Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notasklocal effect #45422

Merged
merged 1 commit into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1998,7 +1998,8 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e),
effects.effect_free ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
effects.nothrow ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
effects.terminates_globally ? ALWAYS_TRUE : TRISTATE_UNKNOWN,
#=nonoverlayed=#true
#=nonoverlayed=#true,
#=notaskstate=#TRISTATE_UNKNOWN
))
else
tristate_merge!(sv, EFFECTS_UNKNOWN)
Expand Down
2 changes: 2 additions & 0 deletions base/compiler/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,8 @@ function Base.show(io::IO, e::Core.Compiler.Effects)
printstyled(io, string(tristate_letter(e.nothrow), 'n'); color=tristate_color(e.nothrow))
print(io, ',')
printstyled(io, string(tristate_letter(e.terminates), 't'); color=tristate_color(e.terminates))
print(io, ',')
printstyled(io, string(tristate_letter(e.notaskstate), 's'); color=tristate_color(e.notaskstate))
print(io, ')')
e.nonoverlayed || printstyled(io, '′'; color=:red)
end
Expand Down
27 changes: 21 additions & 6 deletions base/compiler/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ The effects are composed of the following set of different properties:
- `terminates::TriState`: this method is guaranteed to terminate
- `nonoverlayed::Bool`: indicates that any methods that may be called within this method
are not defined in an [overlayed method table](@ref OverlayMethodTable)
- `notaskstate::TriState`: this method does not access any state bound to the current
task and may thus be moved to a different task without changing observable
behavior. Note that this currently implies that `noyield` as well, since
yielding modifies the state of the current task, though this may be split
in the future.
See [`Base.@assume_effects`](@ref) for more detailed explanation on the definitions of these properties.

Along the abstract interpretation, `Effects` at each statement are analyzed locally and
Expand All @@ -67,6 +72,7 @@ struct Effects
nothrow::TriState
terminates::TriState
nonoverlayed::Bool
notaskstate::TriState
# This effect is currently only tracked in inference and modified
# :consistent before caching. We may want to track it in the future.
inbounds_taints_consistency::Bool
Expand All @@ -76,41 +82,46 @@ function Effects(
effect_free::TriState,
nothrow::TriState,
terminates::TriState,
nonoverlayed::Bool)
nonoverlayed::Bool,
notaskstate::TriState)
return Effects(
consistent,
effect_free,
nothrow,
terminates,
nonoverlayed,
notaskstate,
false)
end

const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true)
const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, TRISTATE_UNKNOWN, ALWAYS_TRUE, true)
const EFFECTS_UNKNOWN = Effects(TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, true) # mostly unknown, but it's not overlayed at least (e.g. it's not a call)
const EFFECTS_UNKNOWN′ = Effects(TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, false) # unknown, really
const EFFECTS_TOTAL = Effects(ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, ALWAYS_TRUE, true, ALWAYS_TRUE)
const EFFECTS_THROWS = Effects(ALWAYS_TRUE, ALWAYS_TRUE, TRISTATE_UNKNOWN, ALWAYS_TRUE, true, ALWAYS_TRUE)
const EFFECTS_UNKNOWN = Effects(TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, true, TRISTATE_UNKNOWN) # mostly unknown, but it's not overlayed at least (e.g. it's not a call)
const EFFECTS_UNKNOWN′ = Effects(TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, TRISTATE_UNKNOWN, false, TRISTATE_UNKNOWN) # unknown, really

function Effects(e::Effects = EFFECTS_UNKNOWN′;
consistent::TriState = e.consistent,
effect_free::TriState = e.effect_free,
nothrow::TriState = e.nothrow,
terminates::TriState = e.terminates,
nonoverlayed::Bool = e.nonoverlayed,
notaskstate::TriState = e.notaskstate,
inbounds_taints_consistency::Bool = e.inbounds_taints_consistency)
return Effects(
consistent,
effect_free,
nothrow,
terminates,
nonoverlayed,
notaskstate,
inbounds_taints_consistency)
end

is_consistent(effects::Effects) = effects.consistent === ALWAYS_TRUE
is_effect_free(effects::Effects) = effects.effect_free === ALWAYS_TRUE
is_nothrow(effects::Effects) = effects.nothrow === ALWAYS_TRUE
is_terminates(effects::Effects) = effects.terminates === ALWAYS_TRUE
is_notaskstate(effects::Effects) = effects.notaskstate === ALWAYS_TRUE
is_nonoverlayed(effects::Effects) = effects.nonoverlayed

is_concrete_eval_eligible(effects::Effects) =
Expand All @@ -132,7 +143,8 @@ function encode_effects(e::Effects)
(e.effect_free.state << 2) |
(e.nothrow.state << 4) |
(e.terminates.state << 6) |
(UInt32(e.nonoverlayed) << 8)
(UInt32(e.nonoverlayed) << 8) |
(UInt32(e.notaskstate.state) << 9)
end
function decode_effects(e::UInt32)
return Effects(
Expand All @@ -141,6 +153,7 @@ function decode_effects(e::UInt32)
TriState((e >> 4) & 0x03),
TriState((e >> 6) & 0x03),
_Bool( (e >> 8) & 0x01),
TriState((e >> 9) & 0x03),
false)
end

Expand All @@ -155,6 +168,8 @@ function tristate_merge(old::Effects, new::Effects)
tristate_merge(
old.terminates, new.terminates),
old.nonoverlayed & new.nonoverlayed,
tristate_merge(
old.notaskstate, new.notaskstate),
old.inbounds_taints_consistency | new.inbounds_taints_consistency)
end

Expand Down