Skip to content

Commit

Permalink
allow override of :nonoverlayed
Browse files Browse the repository at this point in the history
  • Loading branch information
aviatesk committed May 1, 2024
1 parent 018b066 commit 385d2e2
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 39 deletions.
3 changes: 2 additions & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ macro _foldable_meta()
#=:notaskstate=#true,
#=:inaccessiblememonly=#true,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end

macro inline() Expr(:meta, :inline) end
Expand Down
3 changes: 2 additions & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2826,7 +2826,8 @@ function override_effects(effects::Effects, override::EffectsOverride)
inaccessiblememonly = override.inaccessiblememonly ? ALWAYS_TRUE : effects.inaccessiblememonly,
noub = override.noub ? ALWAYS_TRUE :
override.noub_if_noinbounds && effects.noub !== ALWAYS_TRUE ? NOUB_IF_NOINBOUNDS :
effects.noub)
effects.noub,
nonoverlayed = override.nonoverlayed ? true : effects.nonoverlayed)
end

isdefined_globalref(g::GlobalRef) = !iszero(ccall(:jl_globalref_boundp, Cint, (Any,), g))
Expand Down
11 changes: 7 additions & 4 deletions base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ struct EffectsOverride
inaccessiblememonly::Bool
noub::Bool
noub_if_noinbounds::Bool
nonoverlayed::Bool
end
function EffectsOverride(
override::EffectsOverride =
EffectsOverride(false, false, false, false, false, false, false, false, false);
EffectsOverride(false, false, false, false, false, false, false, false, false, false);
consistent::Bool = override.consistent,
effect_free::Bool = override.effect_free,
nothrow::Bool = override.nothrow,
Expand All @@ -59,7 +60,8 @@ function EffectsOverride(
notaskstate::Bool = override.notaskstate,
inaccessiblememonly::Bool = override.inaccessiblememonly,
noub::Bool = override.noub,
noub_if_noinbounds::Bool = override.noub_if_noinbounds)
noub_if_noinbounds::Bool = override.noub_if_noinbounds,
nonoverlayed::Bool = override.nonoverlayed)
return EffectsOverride(
consistent,
effect_free,
Expand All @@ -69,9 +71,10 @@ function EffectsOverride(
notaskstate,
inaccessiblememonly,
noub,
noub_if_noinbounds)
noub_if_noinbounds,
nonoverlayed)
end
const NUM_EFFECTS_OVERRIDES = 9 # sync with julia.h
const NUM_EFFECTS_OVERRIDES = 10 # sync with julia.h

# essential files and libraries
include("essentials.jl")
Expand Down
4 changes: 3 additions & 1 deletion base/compiler/effects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ function encode_effects_override(eo::EffectsOverride)
eo.inaccessiblememonly && (e |= (0x0001 << 6))
eo.noub && (e |= (0x0001 << 7))
eo.noub_if_noinbounds && (e |= (0x0001 << 8))
eo.nonoverlayed && (e |= (0x0001 << 9))
return e
end

Expand All @@ -342,7 +343,8 @@ function decode_effects_override(e::UInt16)
!iszero(e & (0x0001 << 5)),
!iszero(e & (0x0001 << 6)),
!iszero(e & (0x0001 << 7)),
!iszero(e & (0x0001 << 8)))
!iszero(e & (0x0001 << 8)),
!iszero(e & (0x0001 << 9)))
end

decode_statement_effects_override(ssaflag::UInt32) =
Expand Down
3 changes: 3 additions & 0 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ function adjust_effects(ipo_effects::Effects, def::Method)
elseif is_effect_overridden(override, :noub_if_noinbounds) && ipo_effects.noub !== ALWAYS_TRUE
ipo_effects = Effects(ipo_effects; noub=NOUB_IF_NOINBOUNDS)
end
if is_effect_overridden(override, :nonoverlayed)
ipo_effects = Effects(ipo_effects; nonoverlayed=true)
end
return ipo_effects
end

Expand Down
36 changes: 24 additions & 12 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ macro _total_meta()
#=:notaskstate=#true,
#=:inaccessiblememonly=#true,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :foldable` (supposed to be used for bootstrapping)
macro _foldable_meta()
Expand All @@ -214,7 +215,8 @@ macro _foldable_meta()
#=:notaskstate=#true,
#=:inaccessiblememonly=#true,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :terminates_locally` (supposed to be used for bootstrapping)
macro _terminates_locally_meta()
Expand All @@ -227,7 +229,8 @@ macro _terminates_locally_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :terminates_globally` (supposed to be used for bootstrapping)
macro _terminates_globally_meta()
Expand All @@ -240,7 +243,8 @@ macro _terminates_globally_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :terminates_globally :notaskstate` (supposed to be used for bootstrapping)
macro _terminates_globally_notaskstate_meta()
Expand All @@ -253,7 +257,8 @@ macro _terminates_globally_notaskstate_meta()
#=:notaskstate=#true,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :terminates_globally :noub` (supposed to be used for bootstrapping)
macro _terminates_globally_noub_meta()
Expand All @@ -266,7 +271,8 @@ macro _terminates_globally_noub_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :effect_free :terminates_locally` (supposed to be used for bootstrapping)
macro _effect_free_terminates_locally_meta()
Expand All @@ -279,7 +285,8 @@ macro _effect_free_terminates_locally_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :nothrow :noub` (supposed to be used for bootstrapping)
macro _nothrow_noub_meta()
Expand All @@ -292,7 +299,8 @@ macro _nothrow_noub_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :nothrow` (supposed to be used for bootstrapping)
macro _nothrow_meta()
Expand All @@ -305,7 +313,8 @@ macro _nothrow_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :nothrow` (supposed to be used for bootstrapping)
macro _noub_meta()
Expand All @@ -318,7 +327,8 @@ macro _noub_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#true,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :notaskstate` (supposed to be used for bootstrapping)
macro _notaskstate_meta()
Expand All @@ -331,7 +341,8 @@ macro _notaskstate_meta()
#=:notaskstate=#true,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#false))
#=:noub_if_noinbounds=#false,
#=:nonoverlayed=#false))
end
# can be used in place of `@assume_effects :noub_if_noinbounds` (supposed to be used for bootstrapping)
macro _noub_if_noinbounds_meta()
Expand All @@ -344,7 +355,8 @@ macro _noub_if_noinbounds_meta()
#=:notaskstate=#false,
#=:inaccessiblememonly=#false,
#=:noub=#false,
#=:noub_if_noinbounds=#true))
#=:noub_if_noinbounds=#true,
#=:nonoverlayed=#false))
end

# another version of inlining that propagates an inbounds context
Expand Down
18 changes: 13 additions & 5 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ CodeInfo(
!!! compat "Julia 1.10"
The usage within a function body requires at least Julia 1.10.
!!! compact "Julia 1.11"
!!! compat "Julia 1.11"
The code block annotation requires at least Julia 1.11.
!!! warning
Expand All @@ -505,6 +505,7 @@ The following `setting`s are supported.
- `:inaccessiblememonly`
- `:noub`
- `:noub_if_noinbounds`
- `:nonoverlayed`
- `:foldable`
- `:removable`
- `:total`
Expand Down Expand Up @@ -673,6 +674,10 @@ The `:noub` setting asserts that the method will not execute any undefined behav
any other effect assertions (such as `:consistent` or `:effect_free`) as well, but we do
not model this, and they assume the absence of undefined behavior.
---
## `:nonoverlayed`
TODO.
---
## `:foldable`
Expand Down Expand Up @@ -793,6 +798,8 @@ function compute_assumed_setting(override::EffectsOverride, @nospecialize(settin
return EffectsOverride(override; noub = val)
elseif setting === :noub_if_noinbounds
return EffectsOverride(override; noub_if_noinbounds = val)
elseif setting === :nonoverlayed
return EffectsOverride(override; nonoverlayed = val)
elseif setting === :foldable
consistent = effect_free = terminates_globally = noub = val
return EffectsOverride(override; consistent, effect_free, terminates_globally, noub)
Expand All @@ -810,10 +817,11 @@ function compute_assumed_setting(override::EffectsOverride, @nospecialize(settin
end

function form_purity_expr(override::EffectsOverride)
return Expr(:purity,
override.consistent, override.effect_free, override.nothrow,
override.terminates_globally, override.terminates_locally, override.notaskstate,
override.inaccessiblememonly, override.noub, override.noub_if_noinbounds)
ex = Expr(:purity)
for i = 1:Core.Compiler.NUM_EFFECTS_OVERRIDES
push!(ex.args, getfield(override, i))
end
return ex
end

"""
Expand Down
3 changes: 2 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,12 @@ typedef union __jl_purity_overrides_t {
uint16_t ipo_inaccessiblememonly : 1;
uint16_t ipo_noub : 1;
uint16_t ipo_noub_if_noinbounds : 1;
uint16_t ipo_nonoverlayed : 1;
} overrides;
uint16_t bits;
} _jl_purity_overrides_t;

#define NUM_EFFECTS_OVERRIDES 9
#define NUM_EFFECTS_OVERRIDES 10
#define NUM_IR_FLAGS 13

// This type describes a single function body
Expand Down
1 change: 1 addition & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ir)
li->purity.overrides.ipo_inaccessiblememonly = jl_unbox_bool(jl_exprarg(ma, 6));
li->purity.overrides.ipo_noub = jl_unbox_bool(jl_exprarg(ma, 7));
li->purity.overrides.ipo_noub_if_noinbounds = jl_unbox_bool(jl_exprarg(ma, 8));
li->purity.overrides.ipo_nonoverlayed = jl_unbox_bool(jl_exprarg(ma, 9));
}
}
else
Expand Down
50 changes: 36 additions & 14 deletions test/compiler/AbstractInterpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ using Base.Experimental: @MethodTable, @overlay
end

@newinterp MTOverlayInterp
@MethodTable OverlayedMT
CC.method_table(interp::MTOverlayInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OverlayedMT)
@MethodTable OVERLAY_MT
CC.method_table(interp::MTOverlayInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OVERLAY_MT)

function CC.add_remark!(interp::MTOverlayInterp, ::CC.InferenceState, remark)
if interp.meta !== nothing
Expand All @@ -44,7 +44,7 @@ end

struct StrangeSinError end
strangesin(x) = sin(x)
@overlay OverlayedMT strangesin(x::Float64) =
@overlay OVERLAY_MT strangesin(x::Float64) =
iszero(x) ? throw(StrangeSinError()) : x < 0 ? nothing : cos(x)

# inference should use the overlayed method table
Expand Down Expand Up @@ -102,7 +102,7 @@ end |> only === Float64

# not fully covered overlay method match
overlay_match(::Any) = nothing
@overlay OverlayedMT overlay_match(::Int) = missing
@overlay OVERLAY_MT overlay_match(::Int) = missing
@test Base.return_types((Any,); interp=MTOverlayInterp()) do x
overlay_match(x)
end |> only === Union{Nothing,Missing}
Expand Down Expand Up @@ -134,11 +134,33 @@ Base.@assume_effects :total totalcall(f, args...) = f(args...)
end
end |> only === Nothing

# override `:native_executable` to allow concrete-eval for overlay-ed methods
Base.@assume_effects :foldable function gpucompiler384(x::Int)
1 < x < 20 || error("x is too big")
return factorial(x)
end
@overlay OVERLAY_MT Base.@assume_effects :foldable :nonoverlayed function gpucompiler384(x::Int)
1 < x < 20 || raise_on_gpu("x is too big")
return factorial(x)
end
@noinline raise_on_gpu(x) = #=do something with GPU=# error(x)
call_gpucompiler384(x) = gpucompiler384(x)

@test Base.infer_effects(gpucompiler384, (Int,); interp=MTOverlayInterp()) |> Core.Compiler.is_nonoverlayed
@test Base.infer_effects(call_gpucompiler384, (Int,); interp=MTOverlayInterp()) |> Core.Compiler.is_nonoverlayed

@test Base.infer_return_type(; interp=MTOverlayInterp()) do
Val(gpucompiler384(3))
end == Val{6}
@test Base.infer_return_type(; interp=MTOverlayInterp()) do
Val(call_gpucompiler384(3))
end == Val{6}

# GPUCompiler needs accurate inference through kwfunc with the overlay of `Core.throw_inexacterror`
# https://github.com/JuliaLang/julia/issues/48097
@newinterp Issue48097Interp
@MethodTable Issue48097MT
CC.method_table(interp::Issue48097Interp) = CC.OverlayMethodTable(CC.get_inference_world(interp), Issue48097MT)
@MethodTable ISSUE_48097_MT
CC.method_table(interp::Issue48097Interp) = CC.OverlayMethodTable(CC.get_inference_world(interp), ISSUE_48097_MT)
CC.InferenceParams(::Issue48097Interp) = CC.InferenceParams(; unoptimize_throw_blocks=false)
function CC.concrete_eval_eligible(interp::Issue48097Interp,
@nospecialize(f), result::CC.MethodCallResult, arginfo::CC.ArgInfo, sv::CC.AbsIntState)
Expand All @@ -150,34 +172,34 @@ function CC.concrete_eval_eligible(interp::Issue48097Interp,
end
return ret
end
@overlay Issue48097MT @noinline Core.throw_inexacterror(f::Symbol, ::Type{T}, val) where {T} = return
@overlay ISSUE_48097_MT @noinline Core.throw_inexacterror(f::Symbol, ::Type{T}, val) where {T} = return
issue48097(; kwargs...) = return 42
@test_broken fully_eliminated(; interp=Issue48097Interp(), retval=42) do
issue48097(; a=1f0, b=1.0)
end

# Should not concrete-eval overlayed methods in semi-concrete interpretation
@newinterp OverlaySinInterp
@MethodTable OverlaySinMT
CC.method_table(interp::OverlaySinInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OverlaySinMT)
@MethodTable OVERLAY_SIN_MT
CC.method_table(interp::OverlaySinInterp) = CC.OverlayMethodTable(CC.get_inference_world(interp), OVERLAY_SIN_MT)
overlay_sin1(x) = error("Not supposed to be called.")
@overlay OverlaySinMT overlay_sin1(x) = cos(x)
@overlay OverlaySinMT Base.sin(x::Union{Float32,Float64}) = overlay_sin1(x)
@overlay OVERLAY_SIN_MT overlay_sin1(x) = cos(x)
@overlay OVERLAY_SIN_MT Base.sin(x::Union{Float32,Float64}) = overlay_sin1(x)
let oc = Base.code_ircode(; interp=OverlaySinInterp()) do
sin(0.)
end |> only |> first |> Core.OpaqueClosure
@test oc() == cos(0.)
end
@overlay OverlaySinMT Base.sin(x::Union{Float32,Float64}) = @noinline overlay_sin1(x)
@overlay OVERLAY_SIN_MT Base.sin(x::Union{Float32,Float64}) = @noinline overlay_sin1(x)
let oc = Base.code_ircode(; interp=OverlaySinInterp()) do
sin(0.)
end |> only |> first |> Core.OpaqueClosure
@test oc() == cos(0.)
end
_overlay_sin2(x) = error("Not supposed to be called.")
@overlay OverlaySinMT _overlay_sin2(x) = cos(x)
@overlay OVERLAY_SIN_MT _overlay_sin2(x) = cos(x)
overlay_sin2(x) = _overlay_sin2(x)
@overlay OverlaySinMT Base.sin(x::Union{Float32,Float64}) = @noinline overlay_sin2(x)
@overlay OVERLAY_SIN_MT Base.sin(x::Union{Float32,Float64}) = @noinline overlay_sin2(x)
let oc = Base.code_ircode(; interp=OverlaySinInterp()) do
sin(0.)
end |> only |> first |> Core.OpaqueClosure
Expand Down

0 comments on commit 385d2e2

Please sign in to comment.