Skip to content

Commit

Permalink
add new :total_but_may_throw utility setting for @assume_effects
Browse files Browse the repository at this point in the history
This setting is particularly useful since it allows the compiler to
evaluate a call of the applied method when all the call arguments are
fully known, no matter if the call results in an error or not.
  • Loading branch information
aviatesk committed Mar 31, 2022
1 parent 82ce311 commit ebad165
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 9 deletions.
2 changes: 1 addition & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ function concrete_eval_eligible(interp::AbstractInterpreter,
isoverlayed(method_table(interp)) && !is_nonoverlayed(result.edge_effects) && return false
return f !== nothing &&
result.edge !== nothing &&
is_total_or_error(result.edge_effects) &&
is_concrete_eval_eligible(result.edge_effects) &&
is_all_const_arg(arginfo)
end

Expand Down
4 changes: 2 additions & 2 deletions base/compiler/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ is_nothrow(effects::Effects) = effects.nothrow === ALWAYS_TRUE
is_terminates(effects::Effects) = effects.terminates === ALWAYS_TRUE
is_nonoverlayed(effects::Effects) = effects.nonoverlayed

is_total_or_error(effects::Effects) =
is_concrete_eval_eligible(effects::Effects) =
is_consistent(effects) &&
is_effect_free(effects) &&
is_terminates(effects)

is_total(effects::Effects) =
is_total_or_error(effects) &&
is_concrete_eval_eligible(effects) &&
is_nothrow(effects)

is_removable_if_unused(effects::Effects) =
Expand Down
21 changes: 18 additions & 3 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -512,11 +512,24 @@ This `setting` combines the following other assertions:
- `:terminates_globally`
and is a convenient shortcut.
---
# `:total_but_may_throw`
This `setting` combines the following other assertions:
- `:consistent`
- `:effect_free`
- `:terminates_globally`
and is a convenient shortcut.
!!! note
`@assume_effects :total` is similar to `@Base.pure` with the primary
This setting is particularly useful since it allows the compiler to evaluate a call of
the applied method when all the call arguments are fully known, no matter if the call
results in an error or not.
`@assume_effects :total_but_may_throw` is similar to `Base.@pure` with the primary
distinction that the `:consistent`-cy requirement applies world-age wise rather
than globally as described above. However, in particular, a method annotated
`@Base.pure` is always `:total`.
`Base.@pure` should always be `:total` or `:total_but_may_throw`.
"""
macro assume_effects(args...)
(consistent, effect_free, nothrow, terminates_globally, terminates_locally) =
Expand All @@ -537,12 +550,14 @@ macro assume_effects(args...)
terminates_locally = true
elseif setting === :total
consistent = effect_free = nothrow = terminates_globally = true
elseif setting === :total_but_may_throw
consistent = effect_free = terminates_globally = true
else
throw(ArgumentError("@assume_effects $setting not supported"))
end
end
ex = args[end]
isa(ex, Expr) || throw(ArgumentError("Bad expression `$ex` in @constprop [settings] ex"))
isa(ex, Expr) || throw(ArgumentError("Bad expression `$ex` in `@assume_effects [settings] ex`"))
if ex.head === :macrocall && ex.args[1] == Symbol("@ccall")
ex.args[1] = GlobalRef(Base, Symbol("@ccall_effects"))
insert!(ex.args, 3, Core.Compiler.encode_effects_override(Core.Compiler.EffectsOverride(
Expand Down
6 changes: 3 additions & 3 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1185,11 +1185,11 @@ recur_termination22(x) = x * recur_termination21(x-1)
recur_termination21(12) + recur_termination22(12)
end

const ___CONST_DICT___ = Dict{Any,Any}(:a => 1, :b => 2)
Base.@assume_effects :consistent :effect_free :terminates_globally consteval(
const ___CONST_DICT___ = Dict{Any,Any}(Symbol(c) => i for (i, c) in enumerate('a':'z'))
Base.@assume_effects :total_but_may_throw concrete_eval(
f, args...; kwargs...) = f(args...; kwargs...)
@test fully_eliminated() do
consteval(getindex, ___CONST_DICT___, :a)
concrete_eval(getindex, ___CONST_DICT___, :a)
end

# https://github.com/JuliaLang/julia/issues/44732
Expand Down

0 comments on commit ebad165

Please sign in to comment.