Skip to content

Commit

Permalink
post-opt: add more test cases for visit_conditional_successors (#53642
Browse files Browse the repository at this point in the history
)

This commit fixes the first problem that was found while digging into
#53613. It turns out that the post-domtree constructed
from regular `IRCode` doesn't work for visiting conditional successors
for post-opt analysis in cases like:
```julia
julia> let code = Any[
               # block 1
               GotoIfNot(Argument(2), 3),
               # block 2
               ReturnNode(Argument(3)),
               # block 3 (we should visit this block)
               Expr(:call, throw, "potential throw"),
               ReturnNode(), # unreachable
           ]
           ir = make_ircode(code; slottypes=Any[Any,Bool,Bool])
           visited = BitSet()
           @test !Core.Compiler.visit_conditional_successors(CC.LazyPostDomtree(ir), ir, #=bb=#1) do succ::Int
               push!(visited, succ)
               return false
           end
           @test 2 ∉ visited
           @test 3 ∈ visited
       end
Test Failed at REPL[14]:16
  Expression: 2 ∉ visited
   Evaluated: 2 ∉ BitSet([2])
```

This might mean that we need to fix on the `postdominates` end, but for
now, this commit tries to get around it by using the augmented post
domtree in `visit_conditional_successors`. Since the augmented post
domtree is enforced to have a single return, we can keep using the
current `postdominates` to fix the issue.

However, this commit isn't enough to fix the NeuralNetworkReachability
segfault as reported in #53613, and we need to tackle the second issue
reported there too
(#53613 (comment)).
  • Loading branch information
aviatesk committed Apr 23, 2024
1 parent eb9c9b8 commit 678fe46
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 11 deletions.
2 changes: 2 additions & 0 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ function any_stmt_may_throw(ir::IRCode, bb::Int)
return false
end

visit_conditional_successors(callback, ir::IRCode, bb::Int) = # used for test
visit_conditional_successors(callback, LazyPostDomtree(ir), ir, bb)
function visit_conditional_successors(callback, lazypostdomtree::LazyPostDomtree, ir::IRCode, bb::Int)
visited = BitSet((bb,))
worklist = Int[bb]
Expand Down
10 changes: 10 additions & 0 deletions test/compiler/effects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1387,3 +1387,13 @@ let; Base.Experimental.@force_compile; func52843(); end
# https://github.com/JuliaLang/julia/issues/53508
@test !Core.Compiler.is_consistent(Base.infer_effects(getindex, (UnitRange{Int},Int)))
@test !Core.Compiler.is_consistent(Base.infer_effects(getindex, (Base.OneTo{Int},Int)))

@noinline f53613() = @assert isdefined(@__MODULE__, :v53613)
g53613() = f53613()
@test !Core.Compiler.is_consistent(Base.infer_effects(f53613))
@test_broken !Core.Compiler.is_consistent(Base.infer_effects(g53613))
@test_throws AssertionError f53613()
@test_throws AssertionError g53613()
global v53613 = nothing
@test f53613() === nothing
@test g53613() === nothing
66 changes: 55 additions & 11 deletions test/compiler/ssair.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,35 +233,79 @@ let code = Any[
end

# issue #37919
let ci = code_lowered(()->@isdefined(_not_def_37919_), ())[1]
let ci = only(code_lowered(()->@isdefined(_not_def_37919_), ()))
ir = Core.Compiler.inflate_ir(ci)
@test Core.Compiler.verify_ir(ir) === nothing
end

let code = Any[
# block 1
GotoIfNot(Argument(2), 4),
GotoIfNot(Argument(2), 4)
# block 2
GotoNode(3),
Expr(:call, throw, "potential throw")
ReturnNode() # unreachable
# block 3
Expr(:call, throw, "potential throw"),
ReturnNode(Argument(3))
]
ir = make_ircode(code; slottypes=Any[Any,Bool,Int])
visited = BitSet()
@test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int
push!(visited, succ)
return false
end
@test 2 visited
@test 3 visited
oc = Core.OpaqueClosure(ir)
@test oc(false, 1) == 1
@test_throws "potential throw" oc(true, 1)
end

let code = Any[
# block 1
GotoIfNot(Argument(2), 3)
# block 2
ReturnNode(Argument(3))
# block 3
Expr(:call, throw, "potential throw")
ReturnNode() # unreachable
]
ir = make_ircode(code; slottypes=Any[Any,Bool,Int])
visited = BitSet()
@test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int
push!(visited, succ)
return false
end
@test 2 visited
@test 3 visited
oc = Core.OpaqueClosure(ir)
@test oc(true, 1) == 1
@test_throws "potential throw" oc(false, 1)
end

let code = Any[
# block 1
GotoIfNot(Argument(2), 5)
# block 2
GotoNode(3)
# block 3
Expr(:call, throw, "potential throw")
ReturnNode()
# block 4
Expr(:call, Core.Intrinsics.add_int, Argument(3), Argument(4)),
GotoNode(6),
Expr(:call, Core.Intrinsics.add_int, Argument(3), Argument(4))
GotoNode(7)
# block 5
ReturnNode(SSAValue(4))
ReturnNode(SSAValue(5))
]
ir = make_ircode(code; slottypes=Any[Any,Bool,Int,Int])
lazypostdomtree = Core.Compiler.LazyPostDomtree(ir)
visited = BitSet()
@test !Core.Compiler.visit_conditional_successors(lazypostdomtree, ir, #=bb=#1) do succ::Int
@test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int
push!(visited, succ)
return false
end
@test 2 visited
@test 3 visited
@test 4 visited
@test 5 visited
@test 4 visited
@test 5 visited
oc = Core.OpaqueClosure(ir)
@test oc(false, 1, 1) == 2
@test_throws "potential throw" oc(true, 1, 1)
Expand Down

0 comments on commit 678fe46

Please sign in to comment.