Skip to content

Commit 126e201

Browse files
authored
Merge pull request #182 from JuliaGPU/tb/1.13
Support for 1.13
2 parents df5a821 + 6eae13d commit 126e201

8 files changed

Lines changed: 61 additions & 26 deletions

File tree

.buildkite/pipeline.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ steps:
1919
julia:
2020
- "1.11"
2121
- "1.12"
22+
- "1.13-nightly"

.github/workflows/CI.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
version:
1818
- '1.11'
1919
- '1.12'
20+
- '1.13-nightly'
2021
os:
2122
- Linux
2223
- Windows

src/compiler/codegen/expressions.jl

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ In Tile IR codegen, only ghost types (zero-size immutables like `Val{V}`,
3939
function emit_new!(ctx::CGCtx, expr::Expr, @nospecialize(result_type))
4040
T = CC.widenconst(result_type)
4141
is_ghost_type(T) && return ghost_value(T)
42+
# On older Julia versions, method errors are emitted as
43+
# %new(MethodError, func, args_tuple, world) instead of Core.throw_methoderror
44+
if T === MethodError
45+
# expr.args: (MethodError, func, args_tuple, world)
46+
_throw_method_error(ctx, expr.args[2:end-1])
47+
end
4248
throw(IRError("Struct construction not supported in Tile IR: $T"))
4349
end
4450

@@ -103,7 +109,7 @@ function emit_call!(ctx::CGCtx, expr::Expr, @nospecialize(result_type))
103109
end
104110

105111
result = emit_intrinsic!(ctx, func, call_args)
106-
result === missing && _unsupported_call(ctx, func, call_args)
112+
result === missing && _throw_method_error(ctx, [func; call_args])
107113
validate_result_type(result, result_type, func)
108114
return result
109115
end
@@ -125,7 +131,7 @@ function emit_invoke!(ctx::CGCtx, expr::Expr, @nospecialize(result_type))
125131
end
126132

127133
result = emit_intrinsic!(ctx, func, call_args)
128-
result === missing && _unsupported_call(ctx, func, call_args)
134+
result === missing && _throw_method_error(ctx, [func; call_args])
129135
validate_result_type(result, result_type, func)
130136
return result
131137
end
@@ -138,7 +144,6 @@ Assert that the intrinsic returned a type compatible with what the IR expects.
138144
function validate_result_type(@nospecialize(result), @nospecialize(expected_type), @nospecialize(func))
139145
result === nothing && return # void return
140146
result isa CGVal || return
141-
142147
actual = CC.widenconst(result.jltype)
143148
expected = CC.widenconst(expected_type)
144149

@@ -151,13 +156,15 @@ end
151156
"""
152157
_throw_method_error(ctx, call_args)
153158
154-
Provide a clear error message when Julia inserts a `throw_methoderror` call,
155-
indicating that type inference found no matching method for a function call.
159+
Provide a clear error message when an unsupported function is encountered during
160+
Tile IR compilation, either from an explicit `throw_methoderror` / `MethodError`
161+
construction, or from a function call with no Tile IR intrinsic mapping.
162+
163+
`call_args` contains `(function, arg1, arg2, ...)`.
156164
"""
157165
function _throw_method_error(ctx::CGCtx, call_args)
158-
# call_args typically contains: (function, arg1, arg2, ...)
159166
if isempty(call_args)
160-
throw(IRError("MethodError during Tile IR compilation"))
167+
throw(IRError("Unsupported function call during Tile IR compilation"))
161168
end
162169

163170
func_val = try
@@ -168,18 +175,7 @@ function _throw_method_error(ctx::CGCtx, call_args)
168175

169176
argtypes = argextype.(Ref(ctx), call_args[2:end])
170177
typestr = isempty(argtypes) ? "" : " with argument types ($(join(argtypes, ", ")))"
171-
throw(IRError("MethodError during Tile IR compilation: no matching method for $func_val$typestr"))
172-
end
173-
174-
"""
175-
_unsupported_call(ctx, func, call_args)
176-
177-
Provide a clear error message when a function has no Tile IR intrinsic mapping.
178-
"""
179-
function _unsupported_call(ctx::CGCtx, @nospecialize(func), call_args)
180-
argtypes = argextype.(Ref(ctx), call_args)
181-
typestr = isempty(argtypes) ? "" : " with argument types ($(join(argtypes, ", ")))"
182-
throw(IRError("Unsupported function call during Tile IR compilation: $func$typestr has no Tile IR equivalent"))
178+
throw(IRError("Unsupported function call during Tile IR compilation: $func_val$typestr has no Tile IR equivalent"))
183179
end
184180

185181
"""

src/compiler/interpreter.jl

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ This is necessary because NativeInterpreter has a fixed method_table type parame
1414
struct cuTileInterpreter <: CC.AbstractInterpreter
1515
cache::CacheView
1616
method_table::CC.CachedMethodTable{CC.OverlayMethodTable}
17-
inf_cache::Vector{CC.InferenceResult}
17+
inf_cache::@static isdefined(CC, :InferenceCache) ? CC.InferenceCache : Vector{CC.InferenceResult}
1818
inf_params::CC.InferenceParams
1919
opt_params::CC.OptimizationParams
2020
end
2121

2222
function cuTileInterpreter(cache::CacheView; always_inline::Bool=true)
2323
method_table = get_method_table_view(cache.world)
24-
inf_cache = Vector{CC.InferenceResult}()
24+
@static if isdefined(CC, :InferenceCache)
25+
inf_cache = CC.InferenceCache()
26+
else
27+
inf_cache = Vector{CC.InferenceResult}()
28+
end
2529
inf_params = CC.InferenceParams()
2630
opt_params = if always_inline
2731
CC.OptimizationParams(; inline_cost_threshold=typemax(Int))
@@ -237,6 +241,28 @@ else # 1.11: synchronous, edges auto-tracked via stmt_edges
237241
end
238242
end
239243

244+
# Force inlining of all functions with source code.
245+
#
246+
# Julia 1.13+ changed inlining cost storage to encode costs into a UInt8 via
247+
# jl_encode_inlining_cost. This lossy encoding saturates costs above ~5000 to
248+
# MAX_INLINE_COST, making functions permanently non-inlineable regardless of the
249+
# caller's inline_cost_threshold. Each cuTile intrinsic call is penalized at
250+
# inline_nonleaf_penalty (1000), so functions with ≥5 intrinsic calls hit the
251+
# ceiling.
252+
#
253+
# This override tells the inliner to always consider functions with available
254+
# source code as inlineable, matching the behavior that our typemax(Int)
255+
# inline_cost_threshold intends.
256+
@static if VERSION >= v"1.13-"
257+
function CC.src_inlining_policy(interp::cuTileInterpreter,
258+
@nospecialize(src), @nospecialize(info::CC.CallInfo), stmt_flag::UInt32)
259+
isa(src, CC.OptimizationState) && (src = src.src)
260+
isa(src, CC.MaybeCompressed) && return true
261+
isa(src, CC.IRCode) && return true
262+
return false
263+
end
264+
end
265+
240266
# Disable semi-concrete interpretation (broken with overlays per JuliaLang/julia#47349)
241267
function CC.concrete_eval_eligible(interp::cuTileInterpreter,
242268
@nospecialize(f), result::CC.MethodCallResult, arginfo::CC.ArgInfo, sv::CC.InferenceState)

src/compiler/intrinsics/julia.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@
1111
# built-in: tuple (ghost — no runtime representation)
1212
emit_intrinsic!(ctx::CGCtx, ::typeof(Core.tuple), args) = nothing
1313

14-
# built-in: isa (compile-time type narrowing)
15-
emit_intrinsic!(ctx::CGCtx, ::typeof(isa), args) = nothing
14+
# built-in: isa (compile-time type check, emitted as a tile constant)
15+
function emit_intrinsic!(ctx::CGCtx, ::typeof(isa), args)
16+
length(args) >= 2 || return nothing
17+
T = @something get_constant(ctx, args[2]) return nothing
18+
val_type = CC.widenconst(argextype(ctx, args[1]))
19+
emit_constant!(ctx, val_type <: T, Tile{Bool, Tuple{}})
20+
end
1621

1722
# built-in: donotdelete (keep-alive barrier — no Tile IR emission)
1823
emit_intrinsic!(ctx::CGCtx, ::typeof(donotdelete), args) = nothing

src/compiler/passes/canonicalize.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ function scalar_elim_block!(block::Block)
122122
for inst in instructions(block)
123123
call = resolve_call(block, stmt(inst))
124124
call === nothing && continue
125-
_, ops = call
125+
func, ops = call
126+
127+
# isa is a scalar type check, not a tile operation — its result shape
128+
# should not inherit from operands. (On Julia nightly, InferenceCache
129+
# interactions can leave isa unresolved in the IR; see _combine_masks.)
130+
func === isa && continue
126131

127132
current_type = value_type(inst)
128133
current_type === nothing && continue

src/language/arithmetic.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
# mul_hi (high bits of integer multiply — no Core.Intrinsic equivalent)
5454
@static if VERSION >= v"1.13-"
55+
using Base: mul_hi
5556
@overlay Base.mul_hi(x::T, y::T) where {T <: Signed} = Intrinsics.mulhii(x, y, Signedness.Signed)
5657
@overlay Base.mul_hi(x::T, y::T) where {T <: Unsigned} = Intrinsics.mulhii(x, y, Signedness.Unsigned)
5758
else

test/codegen/integration.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ end
560560
isdefined(Core, :throw_methoderror) &&
561561
@testset "mismatched tile shapes with + produces MethodError" begin
562562
spec2d = ct.ArraySpec{2}(16, true)
563-
@test_throws "MethodError during Tile IR compilation" begin
563+
@test_throws "Unsupported function call during Tile IR compilation" begin
564564
code_tiled(Tuple{ct.TileArray{Float32,2,spec2d}}) do a
565565
pid = ct.bid(1)
566566
tile_a = ct.load(a, pid, (4, 8))
@@ -574,7 +574,7 @@ end
574574
isdefined(Core, :throw_methoderror) &&
575575
@testset "no matching method produces MethodError" begin
576576
only_ints(x::Int) = x
577-
@test_throws "MethodError during Tile IR compilation" begin
577+
@test_throws "Unsupported function call during Tile IR compilation" begin
578578
code_tiled(Tuple{ct.TileArray{Float32,1,spec}}) do a
579579
tile = ct.load(a, ct.bid(1), (16,))
580580
only_ints(tile)

0 commit comments

Comments
 (0)