Skip to content

Commit acca58b

Browse files
vtjnashaviatesk
andcommitted
[Compiler] fix intrinsic_effects computation
The atomic operators, in particular, where missing from the list, though many others were also in incorrect lists also. Try to deduplicate the lists slightly. Co-authored-by: Shuhei Kadowaki <[email protected]>
1 parent 09ab82c commit acca58b

File tree

1 file changed

+33
-29
lines changed

1 file changed

+33
-29
lines changed

Compiler/src/tfuncs.jl

+33-29
Original file line numberDiff line numberDiff line change
@@ -2407,11 +2407,8 @@ const _ARGMEM_BUILTINS = Any[
24072407
]
24082408

24092409
const _INCONSISTENT_INTRINSICS = Any[
2410-
Intrinsics.pointerref, # this one is volatile
2411-
Intrinsics.sqrt_llvm_fast, # this one may differ at runtime (by a few ulps)
2412-
Intrinsics.have_fma, # this one depends on the runtime environment
2413-
Intrinsics.cglobal, # cglobal lookup answer changes at runtime
2414-
# ... and list fastmath intrinsics:
2410+
# all is_pure_intrinsic_infer plus
2411+
# ... all the unsound fastmath functions which should have been in is_pure_intrinsic_infer
24152412
# join(string.("Intrinsics.", sort(filter(endswith("_fast")∘string, names(Core.Intrinsics)))), ",\n")
24162413
Intrinsics.add_float_fast,
24172414
Intrinsics.div_float_fast,
@@ -2888,41 +2885,48 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Vector{Any})
28882885
return intrinsic_exct(SimpleInferenceLattice.instance, f, argtypes) === Union{}
28892886
end
28902887

2888+
function _is_effect_free_infer(f::IntrinsicFunction)
2889+
return !(f === Intrinsics.pointerset ||
2890+
f === Intrinsics.atomic_pointerref ||
2891+
f === Intrinsics.atomic_pointerset ||
2892+
f === Intrinsics.atomic_pointerswap ||
2893+
# f === Intrinsics.atomic_pointermodify ||
2894+
f === Intrinsics.atomic_pointerreplace ||
2895+
f === Intrinsics.atomic_fence)
2896+
end
2897+
28912898
# whether `f` is pure for inference
2892-
function is_pure_intrinsic_infer(f::IntrinsicFunction)
2893-
return !(f === Intrinsics.pointerref || # this one is volatile
2894-
f === Intrinsics.atomic_pointerref || # this one is volatile
2895-
f === Intrinsics.pointerset || # this one is never effect-free
2896-
f === Intrinsics.atomic_pointerset || # this one is never effect-free
2897-
f === Intrinsics.atomic_pointerswap || # this one is never effect-free
2898-
f === Intrinsics.atomic_pointermodify || # this one is never effect-free
2899-
f === Intrinsics.atomic_pointerreplace || # this one is never effect-free
2900-
f === Intrinsics.llvmcall || # this one is never effect-free
2901-
f === Intrinsics.sqrt_llvm_fast || # this one may differ at runtime (by a few ulps)
2902-
f === Intrinsics.have_fma || # this one depends on the runtime environment
2903-
f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
2904-
end
2905-
2906-
# whether `f` is effect free if nothrow
2907-
function intrinsic_effect_free_if_nothrow(@nospecialize f)
2908-
return f === Intrinsics.pointerref ||
2909-
f === Intrinsics.have_fma ||
2910-
is_pure_intrinsic_infer(f)
2899+
function is_pure_intrinsic_infer(f::IntrinsicFunction, is_effect_free::Union{Nothing,Bool}=nothing)
2900+
if is_effect_free === nothing
2901+
is_effect_free = _is_effect_free_infer(f)
2902+
end
2903+
return is_effect_free && !(
2904+
f === Intrinsics.llvmcall || # can do arbitrary things
2905+
f === Intrinsics.atomic_pointermodify || # can do arbitrary things
2906+
f === Intrinsics.pointerref || # this one is volatile
2907+
f === Intrinsics.sqrt_llvm_fast || # this one may differ at runtime (by a few ulps)
2908+
f === Intrinsics.have_fma || # this one depends on the runtime environment
2909+
f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
29112910
end
29122911

29132912
function intrinsic_effects(f::IntrinsicFunction, argtypes::Vector{Any})
29142913
if f === Intrinsics.llvmcall
29152914
# llvmcall can do arbitrary things
29162915
return Effects()
2916+
elseif f === atomic_pointermodify
2917+
# atomic_pointermodify has memory effects, plus any effects from the ModifyOpInfo
2918+
return Effects()
29172919
end
2918-
if contains_is(_INCONSISTENT_INTRINSICS, f)
2919-
consistent = ALWAYS_FALSE
2920-
else
2920+
is_effect_free = _is_effect_free_infer(f)
2921+
effect_free = is_effect_free ? ALWAYS_TRUE : ALWAYS_FALSE
2922+
if ((is_pure_intrinsic_infer(f, is_effect_free) && !contains_is(_INCONSISTENT_INTRINSICS, f)) ||
2923+
f === Intrinsics.pointerset || f === Intrinsics.atomic_pointerset || f === Intrinsics.atomic_fence)
29212924
consistent = ALWAYS_TRUE
2925+
else
2926+
consistent = ALWAYS_FALSE
29222927
end
2923-
effect_free = !(f === Intrinsics.pointerset) ? ALWAYS_TRUE : ALWAYS_FALSE
29242928
nothrow = intrinsic_nothrow(f, argtypes)
2925-
inaccessiblememonly = ALWAYS_TRUE
2929+
inaccessiblememonly = is_effect_free && !(f === Intrinsics.pointerref) ? ALWAYS_TRUE : ALWAYS_FALSE
29262930
return Effects(EFFECTS_TOTAL; consistent, effect_free, nothrow, inaccessiblememonly)
29272931
end
29282932

0 commit comments

Comments
 (0)