Skip to content

Commit 4f25e87

Browse files
authored
sroa: Better walk for chained KeyValue (#52542)
This redoes #52369, to put the walk through tothe chained KeyValue into a more logical place (the definition walking). This way, we automatically inherit correct handling of PhiNodes and ifelse.
1 parent ec4745b commit 4f25e87

File tree

2 files changed

+68
-31
lines changed

2 files changed

+68
-31
lines changed

base/compiler/ssair/passes.jl

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,9 @@ function walk_to_defs(compact::IncrementalCompact, @nospecialize(defssa), @nospe
273273
def = compact[defssa][:stmt]
274274
values = predecessors(def, compact)
275275
if values !== nothing
276-
push!(visited_philikes, defssa)
276+
if isa(def, PhiNode) || length(values) > 1
277+
push!(visited_philikes, defssa)
278+
end
277279
possible_predecessors = Int[]
278280

279281
for n in 1:length(values)
@@ -857,38 +859,32 @@ function lift_leaves_keyvalue(compact::IncrementalCompact, @nospecialize(key),
857859
for i = 1:length(leaves)
858860
leaf = leaves[i]
859861
cache_key = leaf
860-
while true
861-
if isa(leaf, AnySSAValue)
862-
(def, leaf) = walk_to_def(compact, leaf)
863-
if is_known_invoke_or_call(def, Core.OptimizedGenerics.KeyValue.set, compact)
864-
@assert isexpr(def, :invoke)
865-
if length(def.args) in (5, 6)
866-
collection = def.args[end-2]
867-
set_key = def.args[end-1]
868-
set_val_idx = length(def.args)
869-
elseif length(def.args) == 4
870-
collection = def.args[end-1]
871-
# Key is deleted
872-
# TODO: Model this
873-
return nothing
874-
elseif length(def.args) == 3
875-
collection = def.args[end]
876-
# The whole collection is deleted
877-
# TODO: Model this
878-
return nothing
879-
else
880-
return nothing
881-
end
882-
if set_key === key || (egal_tfunc(𝕃ₒ, argextype(key, compact), argextype(set_key, compact)) == Const(true))
883-
lift_arg!(compact, leaf, cache_key, def, set_val_idx, lifted_leaves)
884-
break
885-
end
886-
leaf = collection
887-
continue
862+
if isa(leaf, AnySSAValue)
863+
(def, leaf) = walk_to_def(compact, leaf)
864+
if is_known_invoke_or_call(def, Core.OptimizedGenerics.KeyValue.set, compact)
865+
@assert isexpr(def, :invoke)
866+
if length(def.args) in (5, 6)
867+
set_key = def.args[end-1]
868+
set_val_idx = length(def.args)
869+
elseif length(def.args) == 4
870+
# Key is deleted
871+
# TODO: Model this
872+
return nothing
873+
elseif length(def.args) == 3
874+
# The whole collection is deleted
875+
# TODO: Model this
876+
return nothing
877+
else
878+
return nothing
888879
end
880+
if set_key === key || (egal_tfunc(𝕃ₒ, argextype(key, compact), argextype(set_key, compact)) == Const(true))
881+
lift_arg!(compact, leaf, cache_key, def, set_val_idx, lifted_leaves)
882+
break
883+
end
884+
continue
889885
end
890-
return nothing
891886
end
887+
return nothing
892888
end
893889
return lifted_leaves
894890
end
@@ -897,7 +893,36 @@ function lift_keyvalue_get!(compact::IncrementalCompact, idx::Int, stmt::Expr,
897893
collection = stmt.args[end-1]
898894
key = stmt.args[end]
899895

900-
leaves, visited_philikes = collect_leaves(compact, collection, Any, 𝕃ₒ, phi_or_ifelse_predecessors)
896+
function keyvalue_predecessors(@nospecialize(def), compact::IncrementalCompact)
897+
if is_known_invoke_or_call(def, Core.OptimizedGenerics.KeyValue.set, compact)
898+
@assert isexpr(def, :invoke)
899+
if length(def.args) in (5, 6)
900+
collection = def.args[end-2]
901+
set_key = def.args[end-1]
902+
set_val_idx = length(def.args)
903+
elseif length(def.args) == 4
904+
collection = def.args[end-1]
905+
# Key is deleted
906+
# TODO: Model this
907+
return nothing
908+
elseif length(def.args) == 3
909+
collection = def.args[end]
910+
# The whole collection is deleted
911+
# TODO: Model this
912+
return nothing
913+
else
914+
return nothing
915+
end
916+
if set_key === key || (egal_tfunc(𝕃ₒ, argextype(key, compact), argextype(set_key, compact)) == Const(true))
917+
# This is an actual def
918+
return nothing
919+
end
920+
return Any[collection]
921+
end
922+
return phi_or_ifelse_predecessors(def, compact)
923+
end
924+
925+
leaves, visited_philikes = collect_leaves(compact, collection, Any, 𝕃ₒ, keyvalue_predecessors)
901926
isempty(leaves) && return
902927

903928
lifted_leaves = lift_leaves_keyvalue(compact, key, leaves, 𝕃ₒ)

test/compiler/irpasses.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,18 @@ end
15631563
@test_broken fully_eliminated(persistent_dict_elim_multiple)
15641564
@test code_typed(persistent_dict_elim_multiple)[1][1].code[end] == Core.ReturnNode(1)
15651565

1566+
function persistent_dict_elim_multiple_phi(c::Bool)
1567+
if c
1568+
a = Base.PersistentDict(:a => 1)
1569+
else
1570+
a = Base.PersistentDict(:a => 1)
1571+
end
1572+
b = Base.PersistentDict(a, :b => 2)
1573+
return b[:a]
1574+
end
1575+
@test_broken fully_eliminated(persistent_dict_elim_multiple_phi)
1576+
@test code_typed(persistent_dict_elim_multiple_phi)[1][1].code[end] == Core.ReturnNode(1)
1577+
15661578
# Test CFG simplify with try/catch blocks
15671579
let code = Any[
15681580
# Block 1

0 commit comments

Comments
 (0)