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

@time in global while loop causes internal error #45600

Closed
KristofferC opened this issue Jun 7, 2022 · 9 comments · Fixed by #46388
Closed

@time in global while loop causes internal error #45600

KristofferC opened this issue Jun 7, 2022 · 9 comments · Fixed by #46388
Assignees
Labels
bug Indicates an unexpected problem or unintended behavior compiler:inference Type inference regression Regression in behavior compared to a previous version

Comments

@KristofferC
Copy link
Member

julia> while true
           @time 1
       end
Internal error: encountered unexpected error in runtime:
BoundsError(a=Array{Core.Compiler.BasicBlock, (10,)}[Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=1, stop=8), preds=Array{Int64, (1,)}[10], succs=Array{Int64, (1,)}[2]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=9, stop=14), preds=Array{Int64, (1,)}[1], succs=Array{Int64, (2,)}[5, 3]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=15, stop=17), preds=Array{Int64, (1,)}[2], succs=Array{Int64, (1,)}[4]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=18, stop=18), preds=Array{Int64, (1,)}[3], succs=Array{Int64, (1,)}[7]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=19, stop=24), preds=Array{Int64, (1,)}[2], succs=Array{Int64, (1,)}[6]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=25, stop=25), preds=Array{Int64, (1,)}[5], succs=Array{Int64, (1,)}[7]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=26, stop=42), preds=Array{Int64, (2,)}[4, 6], succs=Array{Int64, (2,)}[9, 8]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=43, stop=44), preds=Array{Int64, (1,)}[7], succs=Array{Int64, (0,)}[]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=45, stop=72), preds=Array{Int64, (1,)}[7], succs=Array{Int64, (1,)}[10]), Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(start=73, stop=77), preds=Array{Int64, (1,)}[9], succs=Array{Int64, (1,)}[1])], i=(0,))
ijl_bounds_error_ints at /home/kc/julia/src/rtutils.c:194
getindex at ./essentials.jl:13 [inlined]
getindex at ./abstractarray.jl:1263 [inlined]
replace_code_newstyle! at ./compiler/ssair/legacy.jl:89
ir_to_codeinf! at ./compiler/optimize.jl:154 [inlined]
transform_result_for_cache at ./compiler/typeinfer.jl:364 [inlined]
cache_result! at ./compiler/typeinfer.jl:395
_typeinf at ./compiler/typeinfer.jl:277
typeinf at ./compiler/typeinfer.jl:213
typeinf_ext_toplevel at ./compiler/typeinfer.jl:1073
typeinf_ext_toplevel at ./compiler/typeinfer.jl:1060
jfptr_typeinf_ext_toplevel_18438 at /home/kc/julia/usr/lib/julia/sys.so (unknown line)

Seems to have been introduced in 1.7.

@KristofferC KristofferC added bug Indicates an unexpected problem or unintended behavior compiler:inference Type inference labels Jun 7, 2022
@aviatesk aviatesk self-assigned this Jun 7, 2022
@JeffBezanson JeffBezanson added the regression Regression in behavior compared to a previous version label Jun 16, 2022
@vtjnash
Copy link
Member

vtjnash commented Aug 10, 2022

I think @ianatol had looked into this a few times, and was just deciding how to best fix this?

@ianatol
Copy link
Member

ianatol commented Aug 10, 2022

Ref: #37154

I haven't really worked on it since last year, but happy to check it out soon

@inkydragon
Copy link
Member

versioninfo()
while true
    @time 1
end

@NHDaly
Copy link
Member

NHDaly commented Aug 16, 2022

CC: @IanButterworth alas, this will never end.

Thanks for the careful report, @inkydragon! @IanButterworth: do you have any ideas? That PR was mostly just reopening your old PR; I don't immediately see anything wrong.

@IanButterworth
Copy link
Member

@ianatol from the above I get the impression this is a compiler issue, and so the fix isn't to change the time macro code?

@ianatol
Copy link
Member

ianatol commented Aug 17, 2022

@IanButterworth I can't confirm for sure, but it looks very similar to the issues in #37154. It may be possible to change the @time macro to not trigger it, but the underlying internal error is what really needs to be fixed

@martinholters
Copy link
Member

MWE:

julia> while true
           x = try finally end
       end

@martinholters
Copy link
Member

So what's happening is that we produce IR code where the first instructions are PhiNode with one of their edges being 0.
Indeed, this simple modificiotn of above MWE does not produce the problem:

julia> begin
           nothing
           while true
               x = try finally end
           end
       end

With this patch (which probably is not the right thing to do):

--- a/base/compiler/ssair/legacy.jl
+++ b/base/compiler/ssair/legacy.jl
@@ -86,7 +86,7 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
         elseif isa(stmt, GotoIfNot)
             code[i] = GotoIfNot(stmt.cond, first(ir.cfg.blocks[stmt.dest].stmts))
         elseif isa(stmt, PhiNode)
-            code[i] = PhiNode(Int32[last(ir.cfg.blocks[edge].stmts) for edge in stmt.edges], stmt.values)
+            code[i] = PhiNode(Int32[edge == 0 ? 0 : last(ir.cfg.blocks[edge].stmts) for edge in stmt.edges], stmt.values)
         elseif isexpr(stmt, :enter)
             stmt.args[1] = first(ir.cfg.blocks[stmt.args[1]::Int].stmts)
             code[i] = stmt

I obtain the following:

julia> f() = while true x = try finally end end
f (generic function with 1 method)

julia> @code_typed f()
CodeInfo(
1%1  = φ (#1 => false, #9 => %15)::Bool
└── %2  = φ (#1 => #undef, #9 => %16)::Nothing
2$(Expr(:enter, #5))
3%4  = ϒ (%1)::Bool%5  = ϒ (%2)::Nothing%6  = ϒ (true)::Bool%7  = ϒ (nothing)::Nothing
└──       $(Expr(:leave, 1))
4 ─       goto #7
5%10 = φᶜ (%4, %6)::Bool%11 = φᶜ (%5, %7)::Nothing
└──       $(Expr(:leave, 1))
6nothing::Nothing
7%14 = φ (#4 => -1, #6 => 1)::Int64%15 = φ (#4 => true, #6 => %10)::Bool%16 = φ (#4 => nothing, #6 => %11)::Nothing%17 = (%14 === 1)::Bool
└──       goto #9 if not %17
8 ─       invoke Base.rethrow()::Union{}
└──       unreachable
9$(Expr(:throw_undef_if_not, Symbol(""), :(%15)))::Any
└──       goto #1
) => Union{}

Can our PhiNodes represent "code entry" as an edge, or would we have to synthesize a nothing::Nothing block as first instruction? Like for

julia> g() = (nothing; while true x = try finally end end)
g (generic function with 1 method)

julia> @code_typed g()
CodeInfo(
1 ──       nothing::Nothing
2 ┄─ %2  = φ (#1 => false, #10 => %16)::Bool
└─── %3  = φ (#1 => #undef, #10 => %17)::Nothing
3 ──       $(Expr(:enter, #6))
# ... as above, shifted by one instruction/one block

@martinholters
Copy link
Member

With this patch (which probably is not the right thing to do):

... or maybe it is? I do get the same output with @code_llvm for f() and g(), which is rather promising...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior compiler:inference Type inference regression Regression in behavior compared to a previous version
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants