Skip to content

Commit e945dbd

Browse files
committed
optimizer: don't insert :throw_undef_if_not for defined slots
As an application of #55545, this commit avoids the insertion of `:throw_undef_if_not` nodes when the defined-ness of a slot is guaranteed by abstract interpretation. ```julia julia> function isdefined_nothrow(c, x) local val if c val = x end if @isdefined val return val end return zero(Int) end; julia> @code_typed isdefined_nothrow(true, 42) ``` ```diff diff --git a/old b/new index c4980a5c9c..3d1d6d30f0 100644 --- a/old +++ b/new @@ -4,7 +4,6 @@ CodeInfo( 3 ┄ %3 = φ (#2 => x, #1 => #undef)::Int64 │ %4 = φ (#2 => true, #1 => false)::Bool └── goto #5 if not %4 -4 ─ $(Expr(:throw_undef_if_not, :val, :(%4)))::Any -└── return %3 +4 ─ return %3 5 ─ return 0 ) => Int64 ```
1 parent 78b0b74 commit e945dbd

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

base/compiler/ssair/slot2ssa.jl

+6-3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ function fixup_slot!(ir::IRCode, ci::CodeInfo, idx::Int, slot::Int, @nospecializ
8888
insert_node!(ir, idx, NewInstruction(
8989
Expr(:throw_undef_if_not, ci.slotnames[slot], false), Any))
9090
return UNDEF_TOKEN
91+
elseif has_flag(ir.stmts[idx], IR_FLAG_NOTHROW)
92+
# if the `isdefined`-ness of this slot is guaranteed by abstract interpretation,
93+
# there is no need to form a `:throw_undef_if_not`
9194
elseif def_ssa !== true
9295
insert_node!(ir, idx, NewInstruction(
9396
Expr(:throw_undef_if_not, ci.slotnames[slot], def_ssa), Any))
@@ -153,12 +156,12 @@ end
153156

154157
function fixup_uses!(ir::IRCode, ci::CodeInfo, code::Vector{Any}, uses::Vector{Int}, slot::Int, @nospecialize(ssa))
155158
for use in uses
156-
code[use] = fixemup!(x::SlotNumber->slot_id(x)==slot, stmt::SlotNumber->(ssa, true), ir, ci, use, code[use])
159+
code[use] = fixemup!(x::SlotNumber->slot_id(x)==slot, ::SlotNumber->Pair{Any,Any}(ssa, true), ir, ci, use, code[use])
157160
end
158161
end
159162

160163
function rename_uses!(ir::IRCode, ci::CodeInfo, idx::Int, @nospecialize(stmt), renames::Vector{Pair{Any, Any}})
161-
return fixemup!(stmt::SlotNumber->true, stmt::SlotNumber->renames[slot_id(stmt)], ir, ci, idx, stmt)
164+
return fixemup!(::SlotNumber->true, x::SlotNumber->renames[slot_id(x)], ir, ci, idx, stmt)
162165
end
163166

164167
# maybe use expr_type?
@@ -656,7 +659,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
656659
visited = BitSet()
657660
new_nodes = ir.new_nodes
658661
@timeit "SSA Rename" while !isempty(worklist)
659-
(item::Int, pred, incoming_vals) = pop!(worklist)
662+
(item, pred, incoming_vals) = pop!(worklist)
660663
if sv.bb_vartables[item] === nothing
661664
continue
662665
end

test/compiler/inference.jl

+6-2
Original file line numberDiff line numberDiff line change
@@ -6051,7 +6051,7 @@ end |> Core.Compiler.is_nothrow
60516051
end |> Core.Compiler.is_nothrow
60526052

60536053
# refine `undef` information from `@isdefined` check
6054-
@test Base.infer_effects((Bool,Int)) do c, x
6054+
function isdefined_nothrow(c, x)
60556055
local val
60566056
if c
60576057
val = x
@@ -6060,7 +6060,11 @@ end |> Core.Compiler.is_nothrow
60606060
return val
60616061
end
60626062
return zero(Int)
6063-
end |> Core.Compiler.is_nothrow
6063+
end
6064+
@test Core.Compiler.is_nothrow(Base.infer_effects(isdefined_nothrow, (Bool,Int)))
6065+
@test !any(first(only(code_typed(isdefined_nothrow, (Bool,Int)))).code) do @nospecialize x
6066+
Meta.isexpr(x, :throw_undef_if_not)
6067+
end
60646068

60656069
# End to end test case for the partially initialized struct with `PartialStruct`
60666070
@noinline broadcast_noescape1(a) = (broadcast(identity, a); nothing)

0 commit comments

Comments
 (0)