Reported initially at https://github.com/timholy/Revise.jl/issues/334. Happens reliably on every Julia version tested (1.1, 1.2, and master) with -O1
. Here is a slightly-boiled down version that does not require Revise or very much of LoweredCodeUtils & JuliaInterpreter:
$ julia-master --startup-file=no -O1
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.4.0-DEV.10 (2019-08-19)
_/ |\__'_|_|_|\__'_| | Commit 9a9ce76643* (1 day old master)
|__/ |
julia> include("/tmp/methoddef.jl")
methoddef! (generic function with 1 method)
julia> ex = quote
function test()
println("testing...")
end
end
quote
#= REPL[2]:2 =#
function test()
#= REPL[2]:3 =#
println("testing...")
end
end
julia> module TestModule end
Main.TestModule
julia> frame = JuliaInterpreter.prepare_thunk(TestModule, ex)
Frame for Main.TestModule
1 2 1 ─ $(Expr(:thunk, CodeInfo(
2 2 1 ─ return $(Expr(:method, :test))
3 2 )))
â‹®
julia> recurse = JuliaInterpreter.finish_and_return!
finish_and_return! (generic function with 4 methods)
julia> signatures = Any[]
0-element Array{Any,1}
julia> stmt = JuliaInterpreter.pc_expr(frame, 2)
:($(Expr(:method, :test)))
julia> methoddef!(recurse, signatures, frame, stmt, 2; define=false)
signal (11): Segmentation fault
in expression starting at REPL[8]:1
_ZNK4llvm7PHINode24getIncomingValueForBlockEPKNS_10BasicBlockE at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
_ZN12_GLOBAL__N_114CodeGenPrepare20splitBranchConditionERN4llvm8FunctionE at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
_ZN12_GLOBAL__N_114CodeGenPrepare13runOnFunctionERN4llvm8FunctionE.part.1098 at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
_ZN4llvm13FPPassManager13runOnFunctionERNS_8FunctionE at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
_ZN4llvm13FPPassManager11runOnModuleERNS_6ModuleE at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
_ZN4llvm6legacy15PassManagerImpl3runERNS_6ModuleE at /home/tim/src/julia-master/usr/bin/../lib/libLLVM-6.0.so (unknown line)
operator() at /home/tim/src/julia-master/src/jitlayers.cpp:370
addModule at /home/tim/src/julia-master/usr/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h:57 [inlined]
addModule at /home/tim/src/julia-master/src/jitlayers.cpp:508
jl_add_to_ee at /home/tim/src/julia-master/src/jitlayers.cpp:760 [inlined]
jl_finalize_function at /home/tim/src/julia-master/src/jitlayers.cpp:768
getAddressForFunction at /home/tim/src/julia-master/src/codegen.cpp:1325
jl_generate_fptr at /home/tim/src/julia-master/src/codegen.cpp:1417
jl_compile_method_internal at /home/tim/src/julia-master/src/gf.c:1923
_jl_invoke at /home/tim/src/julia-master/src/gf.c:2159 [inlined]
jl_invoke at /home/tim/src/julia-master/src/gf.c:2167
#methoddef! at ./none:0
unknown function (ip: 0x7f32fe42331c)
_jl_invoke at /home/tim/src/julia-master/src/gf.c:2160 [inlined]
jl_apply_generic at /home/tim/src/julia-master/src/gf.c:2324
jl_apply at /home/tim/src/julia-master/src/julia.h:1631 [inlined]
do_call at /home/tim/src/julia-master/src/interpreter.c:328
eval_value at /home/tim/src/julia-master/src/interpreter.c:417
eval_stmt_value at /home/tim/src/julia-master/src/interpreter.c:368 [inlined]
eval_body at /home/tim/src/julia-master/src/interpreter.c:778
jl_interpret_toplevel_thunk_callback at /home/tim/src/julia-master/src/interpreter.c:888
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f3305b3170f)
unknown function (ip: 0x4)
jl_interpret_toplevel_thunk at /home/tim/src/julia-master/src/interpreter.c:897
jl_toplevel_eval_flex at /home/tim/src/julia-master/src/toplevel.c:814
jl_toplevel_eval_flex at /home/tim/src/julia-master/src/toplevel.c:764
jl_toplevel_eval_in at /home/tim/src/julia-master/src/toplevel.c:843
eval at ./boot.jl:330
_jl_invoke at /home/tim/src/julia-master/src/gf.c:2154 [inlined]
jl_apply_generic at /home/tim/src/julia-master/src/gf.c:2324
eval_user_input at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
macro expansion at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:118 [inlined]
#26 at ./task.jl:333
_jl_invoke at /home/tim/src/julia-master/src/gf.c:2154 [inlined]
jl_apply_generic at /home/tim/src/julia-master/src/gf.c:2324
jl_apply at /home/tim/src/julia-master/src/julia.h:1631 [inlined]
start_task at /home/tim/src/julia-master/src/task.c:655
unknown function (ip: 0xffffffffffffffff)
Allocations: 7954783 (Pool: 7952695; Big: 2088); GC: 9
/home/tim/bin/julia-master: line 2: 1450 Segmentation fault (core dumped) ~/src/julia-master/julia "$@"
$
where the contents of /tmp/methoddef.jl
are
import JuliaInterpreter, LoweredCodeUtils
using JuliaInterpreter: Frame, pc_expr
using Base.Meta: isexpr
function methoddef!(@nospecialize(recurse), signatures, frame::Frame, @nospecialize(stmt), pc::Int; define=true)
framecode = frame.framecode
nextstmt = pc_expr(frame, pc+1)
while true # methods containing inner methods may need multiple trips through this loop
sigt, pc = LoweredCodeUtils.signature(recurse, frame, stmt, pc)
stmt = pc_expr(frame, pc)
while !isexpr(stmt, :method, 3)
pc = LoweredCodeUtils.next_or_nothing(frame, pc)
pc === nothing && return nothing # this was just `function foo end`
stmt = pc_expr(frame, pc)
end
end
end
Both the backtrace and putting @show
debugging into methoddef!
indicate that the method never gets called, it seems to segfault during compilation. Only happens with -O1
.
For reference, this is LoweredCodeUtils v0.3.7 and JuliaInterpreter 0.7.0.
Investigative report.
fast-isel
for x86_64 as wellJULIA_LLVM_ARGS="-disable-cgp-branch-opts=true"
I am working on a fix for LLVM as well, but coming up with minimal test case is hard since bugpoint
crashes.
Reproducing command is:
~/builds/julia-debug/usr/tools/llc -fast-isel=true -O1 -mtriple=x86_64-unkown-linux-gnu -debug-only=codegenprepare -start-before=codegenprepare -stop-after=codegenprepare --filetype=obj
GCP crashes on:
Before branch condition splitting
pass19: ; preds = %idxend17
%244 = icmp eq i8 %166, 2, !dbg !109
%245 = select i1 %244, i8 2, i8 -128, !dbg !109
%246 = and i8 %tindex_phi14, -128, !dbg !109
%247 = or i8 %246, %245, !dbg !109
%248 = icmp sgt i8 %247, -1, !dbg !109
%249 = and i8 %245, 3, !dbg !109
%cond5896 = icmp eq i8 %249, 2, !dbg !109
%cond58 = and i1 %cond5896, %248, !dbg !109
br i1 %cond58, label %L34, label %L34, !dbg !109
Manual reduced example:
; RUN: llc -fast-isel=true -O1 -mtriple=x86_64-unkown-linux-gnu -start-before=codegenprepare -stop-after=codegenprepare < %s | FileCheck %s
define void @foo(i32) {
entry:
br label %for
for:
%I = phi i32 [1, %entry], [%i, %for.cond], [%i, %for.cond]
%i = add i32 %I, 1
%cond0 = icmp eq i32 0, %0
br i1 %cond0, label %exit, label %for.cond
for.cond:
%N = and i32 %0, 127
%cond1 = icmp eq i32 %i, %0
%cond2 = icmp eq i32 %i, %N
%cond = and i1 %cond1, %cond2
br i1 %cond, label %for, label %for
exit:
ret void
}
Filed upstream as https://reviews.llvm.org/D66657
Closed by #34190
Most helpful comment
Filed upstream as https://reviews.llvm.org/D66657