Assertion failed: "Node emitted out of order - late"

Hi!

I get the error 'Assertion failed: (I != VRBaseMap.end() && "Node emitted out of order - late")' in a simple test function. LLVM dis-assembly looks like this:

; Function Attrs: nounwind
define void @bug(i32* nocapture readnone %result, i32* nocapture readonly %sptr) #0 {
entry:
  %a = alloca [16 x i32], align 8
  %0 = bitcast [16 x i32]* %a to i8*
  call void @llvm.lifetime.start(i64 64, i8* %0) #1
  %arraydecay = getelementptr inbounds [16 x i32]* %a, i16 0, i16 0
  %sptr.addr.010 = getelementptr inbounds i32* %sptr, i16 1
  %v.0 = load i32* %sptr, align 8
  %cmp1 = icmp eq i32 %v.0, 0
  br i1 %cmp1, label %if.end, label %if.then
if.then: ; preds = %entry

After scheduling there is a CopyToReg node and a llvm.lifetime.start node, both have a TargetFrameIndex<0> as operand (it is a TargetFrameIndex from the very first pass - but I expected a FrameIndex). I guess this is %a. The instruction emitter tries to get the virtual register number from the CopyToReg's operand, the TargetFrameIndex. But there is no virtual register number for TargetFrameIndex and that raises the assertion.
Well, I have lots of [Target]FrameIndex operations in other test code, but probably no arrays, and that works as expected.

I do not touch the llvm.lifetime.X intrinsics. I can leave them, right?
What did I miss to do? Why is there no virtual register for that TargetFrameIndex?

Thanks,
Boris

I get the error 'Assertion failed: (I != VRBaseMap.end() && "Node emitted out of order - late")' in a simple test function. LLVM dis-assembly looks like this:

[full disassembly and original code at the end]

After scheduling there is a CopyToReg node and a llvm.lifetime.start node, both have a TargetFrameIndex<0> as operand (it is a TargetFrameIndex from the very first pass - but I expected a FrameIndex). I guess this is %a. The instruction emitter tries to get the virtual register number from the CopyToReg's operand, the TargetFrameIndex. But there is no virtual register number for TargetFrameIndex and that raises the assertion.
Well, I have lots of [Target]FrameIndex operations in other test code, but probably no arrays, and that works as expected.

I do not touch the llvm.lifetime.X intrinsics. I can leave them, right?
What did I miss to do? Why is there no virtual register for that TargetFrameIndex?

I worked on that a little bit more: the TargetFrameIndex is only used by CopToReg and llvm.lifetime.start; it seems that these operations do not trigger the generation of virtual registers? If I add some access/write to that array a[0]=0; in the entry block, then the generation of the virtual register is triggered.

I compared "my" IR graphs to the IR graphs generated by the ARM backend: the ARM backend generates an extra "ADD #0" and gets a virtual register number.

I'm really stuck and need some help.
Boris

--8<--

void bug_no190 (int* result, int *sptr, int end_index)
{
  int a[16];
  int *cptr = a;
  int v = *sptr++;

  //a[0] = 0; // this avoids the crash
  for(int i = 1; i < 3; i++) {
    if(v != 0) {
      *cptr++ = 0;
    }
    v = *sptr++;
  }
}

--8<--

; Function Attrs: nounwind
define void @bug_no190(i32* nocapture readnone %result, i32* nocapture readonly %sptr, i32 %end_index) #0 {
entry:
  %a = alloca [16 x i32], align 8
  %0 = bitcast [16 x i32]* %a to i8*
  call void @llvm.lifetime.start(i64 64, i8* %0) #1
  %arraydecay = getelementptr inbounds [16 x i32]* %a, i16 0, i16 0
  %sptr.addr.010 = getelementptr inbounds i32* %sptr, i16 1
  %v.0 = load i32* %sptr, align 8
  %cmp1 = icmp eq i32 %v.0, 0
  br i1 %cmp1, label %if.end, label %if.then

if.then: ; preds = %entry
  %incdec.ptr2 = getelementptr inbounds [16 x i32]* %a, i16 0, i16 1
  store i32 0, i32* %arraydecay, align 8, !tbaa !1
  br label %if.end

if.end: ; preds = %if.then, %entry
  %cptr.1 = phi i32* [ %incdec.ptr2, %if.then ], [ %arraydecay, %entry ]
  %v.0.1 = load i32* %sptr.addr.010, align 8
  %cmp1.1 = icmp eq i32 %v.0.1, 0
  br i1 %cmp1.1, label %if.end.1, label %if.then.1

if.then.1: ; preds = %if.end
  store i32 0, i32* %cptr.1, align 8, !tbaa !1
  br label %if.end.1

if.end.1: ; preds = %if.then.1, %if.end
  call void @llvm.lifetime.end(i64 64, i8* %0) #1
  ret void
}

; Function Attrs: nounwind
declare void @llvm.lifetime.start(i64, i8* nocapture) #1

; Function Attrs: nounwind
declare void @llvm.lifetime.end(i64, i8* nocapture) #1

attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }

!llvm.ident = !{!0}

!0 = metadata !{metadata !"clang version 3.4.2 (tags/RELEASE_34/dot2-final)"}
!1 = metadata !{metadata !2, metadata !2, i64 0}
!2 = metadata !{metadata !"int", metadata !3, i64 0}
!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0}
!4 = metadata !{metadata !"Simple C/C++ TBAA"}