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

"Not a virtual register" LLVM assertion #13366

Closed
simonster opened this issue Sep 29, 2015 · 5 comments
Closed

"Not a virtual register" LLVM assertion #13366

simonster opened this issue Sep 29, 2015 · 5 comments
Assignees
Labels
bug Indicates an unexpected problem or unintended behavior compiler:codegen Generation of LLVM IR and native code regression Regression in behavior compared to a previous version

Comments

@simonster
Copy link
Member

immutable Take{I}
    xs::I
    n::Int
end
take(xs, n::Int) = Take(xs, n)

eltype{I}(::Type{Take{I}}) = eltype(I)

Base.start(it::Take) = (it.n, start(it.xs))

function Base.next(it::Take, state)
    n, xs_state = state
    v, xs_state = next(it.xs, xs_state)
    return v, (n - 1, xs_state)
end

@inline function Base.done(it::Take, state)
    n, xs_state = state
    return n <= 0 || done(it.xs, xs_state)
end

f() = for j = take(repeated(1), 10) end
f()

Take here is just the code from iterators.jl in Base with done inlined. On release-0.4, this works. On master, when Julia is built with LLVM_ASSERTIONS=1, LLVM reports an assertion failure:

julia> f()
Assertion failed: (isVirtualRegister(Reg) && "Not a virtual register"), function virtReg2Index, file /usr/local/julia/deps/srccache/llvm-3.3/include/llvm/Target/TargetRegisterInfo.h, line 293.

Blocks #13355.

@simonster simonster added bug Indicates an unexpected problem or unintended behavior regression Regression in behavior compared to a previous version compiler:codegen Generation of LLVM IR and native code labels Sep 29, 2015
@Keno
Copy link
Member

Keno commented Sep 30, 2015

On first thought if it works on 0.4 this must have to do with the codegen rewrite. But looking at the assertion closer that's a backend assertion, so it might also be an LLVM bug.

@simonster
Copy link
Member Author

The SROA pass is doing weird things with the [0 x i1] array, which get propagated through all the other passes and may be what's causing the issue. Switching to the new SROA pass (#9060) appears to fix things. IR dump follows:

*** IR Dump After Scalar Replacement of Aggregates (DT) ***
; Function Attrs: sspreq
define void @julia_f_21905() #3 {
top:
  %0 = alloca { i64, { i64, [0 x i1] } }, align 8
  %1 = alloca %Take, align 8
  %2 = alloca { i64, [0 x i1] }, align 8
  %gcrootframe11 = alloca [4 x %jl_value_t*], align 8, !dbg !81
  %gcrootframe11.sub = getelementptr inbounds [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 0
  %locals = getelementptr [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 2, !dbg !81
  %3 = getelementptr inbounds [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 0, !dbg !82
  store %jl_value_t* inttoptr (i64 4 to %jl_value_t*), %jl_value_t** %3, align 8, !dbg !82
  %4 = load %jl_value_t*** @jl_pgcstack, align 8, !dbg !82
  %5 = getelementptr [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 1, !dbg !82
  %.c = bitcast %jl_value_t** %4 to %jl_value_t*, !dbg !82
  store %jl_value_t* %.c, %jl_value_t** %5, align 8, !dbg !82
  store %jl_value_t** %gcrootframe11.sub, %jl_value_t*** @jl_pgcstack, align 8, !dbg !82
  store %jl_value_t* null, %jl_value_t** %locals, align 8, !dbg !82
  %6 = getelementptr [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 3, !dbg !82
  store %jl_value_t* null, %jl_value_t** %6, align 8, !dbg !82
  %7 = insertvalue { i64, [0 x i1] } undef, i64 10, 0, !dbg !82
  %8 = extractvalue { i64, [0 x i1] } %7, 0, !dbg !82
  %9 = extractvalue { i64, [0 x i1] } %7, 1, !dbg !82
  store %jl_value_t* inttoptr (i64 4366139408 to %jl_value_t*), %jl_value_t** %locals, align 8, !dbg !82
  %10 = icmp slt i64 %8, 1, !dbg !82
  br i1 %10, label %if, label %L, !dbg !82

if:                                               ; preds = %top
  br label %L1, !dbg !82

L:                                                ; preds = %top
  br label %L1, !dbg !82

L1:                                               ; preds = %L, %if
  %_var0.0 = phi i1 [ false, %L ], [ %10, %if ]
  br i1 %_var0.0, label %L10, label %L3, !dbg !82

L3:                                               ; preds = %L1, %L8
  %"#s3.0.0" = phi i64 [ %8, %L1 ], [ %16, %L8 ]
  %"#s3.1.0" = phi [0 x i1] [ %9, %L1 ], [ %17, %L8 ]
  %insert24 = insertvalue %Repeated undef, i64 1, 0, !dbg !82
  %insert20 = insertvalue %Take undef, %Repeated %insert24, 0, !dbg !82
  %insert22 = insertvalue %Take %insert20, i64 10, 1, !dbg !82
  store %Take %insert22, %Take* %1, align 8, !dbg !82
  %insert = insertvalue { i64, [0 x i1] } undef, i64 %"#s3.0.0", 0, !dbg !82
  %insert17 = insertvalue { i64, [0 x i1] } %insert, [0 x i1] %"#s3.1.0", 1, !dbg !82
  store { i64, [0 x i1] } %insert17, { i64, [0 x i1] }* %2, align 8, !dbg !82
  call void @julia_next_21906({ i64, { i64, [0 x i1] } }* sret %0, %Take* %1, { i64, [0 x i1] }* %2) #3, !dbg !82
  %11 = load { i64, { i64, [0 x i1] } }* %0, align 8, !dbg !82
  %12 = extractvalue { i64, { i64, [0 x i1] } } %11, 0, !dbg !82
  %13 = extractvalue { i64, { i64, [0 x i1] } } %11, 1, !dbg !82
  %14 = extractvalue { i64, [0 x i1] } %13, 0, !dbg !82
  %15 = extractvalue { i64, [0 x i1] } %13, 1, !dbg !82
  %insert27 = insertvalue { i64, [0 x i1] } undef, i64 %14, 0, !dbg !82
  %insert29 = insertvalue { i64, [0 x i1] } %insert27, [0 x i1] %15, 1, !dbg !82
  %16 = extractvalue { i64, [0 x i1] } %insert29, 0, !dbg !82
  %17 = extractvalue { i64, [0 x i1] } %insert29, 1, !dbg !82
  %18 = getelementptr [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 3, !dbg !82
  store %jl_value_t* inttoptr (i64 4366139408 to %jl_value_t*), %jl_value_t** %18, align 8, !dbg !82
  %19 = icmp slt i64 %16, 1, !dbg !82
  br i1 %19, label %if5, label %L7, !dbg !82

if5:                                              ; preds = %L3
  %phitmp15 = xor i1 %19, true, !dbg !82
  br label %L8, !dbg !82

L7:                                               ; preds = %L3
  br label %L8, !dbg !82

L8:                                               ; preds = %L7, %if5
  %_var1.0 = phi i1 [ true, %L7 ], [ %phitmp15, %if5 ]
  br i1 %_var1.0, label %L3, label %L10, !dbg !82

L10:                                              ; preds = %L8, %L1
  %20 = getelementptr [4 x %jl_value_t*]* %gcrootframe11, i64 0, i64 1, !dbg !82
  %21 = load %jl_value_t** %20, align 8, !dbg !82
  %22 = getelementptr inbounds %jl_value_t* %21, i64 0, i32 0, !dbg !82
  store %jl_value_t** %22, %jl_value_t*** @jl_pgcstack, align 8, !dbg !82
  ret void, !dbg !82
}

@vtjnash
Copy link
Member

vtjnash commented Sep 30, 2015

It's a ghost!

We usually try to avoid emitting instructions that actively use the isGhost type. It looks like there are some places that are still trying to emit loads and stores of them, however. The LLVM SROA pass is creating them when it tries to optimize certain local load/store patterns.

@simonster
Copy link
Member Author

So should we just switch to the new SROA pass, which, as @ArchRobison noted, is the default in LLVM 3.3 anyway? Or should we wait until some perf testing infrastructure is set up?

@JeffBezanson
Copy link
Member

Yes, looks like we should just use the new SROA pass. Any objections @vtjnash @Keno ?

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:codegen Generation of LLVM IR and native code regression Regression in behavior compared to a previous version
Projects
None yet
Development

No branches or pull requests

4 participants