liveness assertion problem in llc

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

liveness assertion problem in llc

Bjorn De Sutter
Hi,

I am working on a backend for a CGRA architecture with advanced predicate support (as on EPIC machines and as first used in the OpenIMPACT compiler). Until last month, the backend was working fine, but since the r161643 commit by stoklund, my backend doesn't work anymore. I think I noticed some related commits later on, and the assertion I get on the latest trunk (r164162) differs from what I got on r161643 (where it was the PHIelimination that failed). From the log, I have the impression that the assertion is raised on a dead instruction during the spill weight calculation. The dead instruction (definition of vreg12 in the log below) is an instruction I add during if-conversion for use in a later pass. Previously, such dead instructions did not cause any problem...

Any idea what might be going wrong here? I've noticed that there is now something like a flag that needs to be set by code transformations that destroy existing liveness information. Maybe I should set that flag during if-conversion? Apart from that, I have no clue...

Here is the end of a log I get under gdb (gdb used for getting a more informative backtrace):

# *** IR Dump Before Calculate spill weights ***:
# Machine code for function CGA_kernel_read: Post SSA
Function Live Ins: %P0 in %vreg5, %P1 in %vreg6
Function Live Outs: %P15

0B BB#0: derived from LLVM BB %entry
            Live Ins: %P0 %P1
16B %vreg6<def> = COPY %P1; IntRegs:%vreg6
48B %vreg8<def> = MOV32ri <ga:@fifo>, pred:%noreg; IntRegs:%vreg8 dbg:../src/getbits.c:46:1
64B %vreg9<def> = LDUBri %vreg8, 1, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 1)] IntRegs:%vreg9,%vreg8 dbg:../src/getbits.c:46:1
80B %vreg10<def> = CMPEQI %vreg9<kill>, 0, pred:%noreg; PredRegs:%vreg10 IntRegs:%vreg9 dbg:../src/getbits.c:46:1
96B JUMP <BB#2>, pred:%vreg10<kill>; PredRegs:%vreg10
            Successors according to CFG: BB#2(12) BB#1(20)

112B BB#1:
            Predecessors according to CFG: BB#0
128B %vreg27<def> = MOV32ri -1, pred:%noreg; IntRegs:%vreg27
160B JUMP <BB#5>, pred:%noreg
            Successors according to CFG: BB#5

176B BB#2: derived from LLVM BB %while.cond.preheader
            Predecessors according to CFG: BB#0
192B %vreg27<def> = MOV32ri 0, pred:%noreg; IntRegs:%vreg27
208B %vreg24<def> = CMPNEI %vreg6, 0, pred:%noreg; PredRegs:%vreg24 IntRegs:%vreg6 dbg:../src/getbits.c:53:3
224B %vreg12<def> = CMPEQI %vreg6, 0, pred:%noreg; PredRegs:%vreg12 IntRegs:%vreg6 dbg:../src/getbits.c:53:3    <---- THIS IS THE DEAD INSTRUCTION
240B JUMP <BB#3>, pred:%vreg24; PredRegs:%vreg24
            Successors according to CFG: BB#6(12) BB#3(20)

256B BB#6:
            Predecessors according to CFG: BB#2
288B JUMP <BB#5>, pred:%noreg
            Successors according to CFG: BB#5

304B BB#3:
            Predecessors according to CFG: BB#2
336B %vreg26<def> = COPY %P0; IntRegs:%vreg26
            Successors according to CFG: BB#4

352B BB#4: derived from LLVM BB %while.body
            Predecessors according to CFG: BB#4 BB#3
400B %vreg14<def> = LDUBrr %vreg8, 0, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 0)] IntRegs:%vreg14,%vreg8 dbg:../src/getbits.c:56:5
416B STBrr %vreg26, 0, %vreg14<kill>, pred:%noreg; mem:ST1[%p.04] IntRegs:%vreg26,%vreg14 dbg:../src/getbits.c:56:5
432B %vreg27<def> = ADDri %vreg27<kill>, 1, pred:%noreg; IntRegs:%vreg27 dbg:../src/getbits.c:55:5
448B %vreg17<def> = CMPLT_U %vreg27, %vreg6, pred:%noreg; PredRegs:%vreg17 IntRegs:%vreg27,%vreg6 dbg:../src/getbits.c:53:3
464B ADJCALLSTACKDOWN 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
480B CALL <ga:@CGA_kernel_advance>, 0, 0, pred:%noreg, 0, %noreg, %P0<imp-def>, %P1<imp-def>, %P2<imp-def>, %P3<imp-def>, %P15<imp-def>, %RT<imp-def>, %P0<imp-use>, %P1<imp-use>, %P2<imp-use>, %P3<imp-use>; dbg:../src/getbits.c:57:5
496B ADJCALLSTACKUP 0, 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
512B %vreg16<def> = LDUBri %vreg8, 1, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 1)] IntRegs:%vreg16,%vreg8 dbg:../src/getbits.c:53:3
544B %vreg17<def,tied1> = CMPEQANDri %vreg17<tied0>, %vreg16<kill>, 0, pred:%noreg; PredRegs:%vreg17 IntRegs:%vreg16 dbg:../src/getbits.c:53:3
560B %vreg26<def> = ADDri %vreg26<kill>, 1, pred:%noreg; IntRegs:%vreg26 dbg:../src/getbits.c:56:5
624B JUMP <BB#4>, pred:%vreg17<kill>; PredRegs:%vreg17 dbg:../src/getbits.c:53:3
640B JUMP <BB#5>, pred:%noreg; dbg:../src/getbits.c:53:3
            Successors according to CFG: BB#4(124) BB#5(4)

656B BB#5: derived from LLVM BB %if.end
            Predecessors according to CFG: BB#4 BB#1 BB#6
688B %P15<def> = COPY %vreg27<kill>; IntRegs:%vreg27 dbg:../src/getbits.c:60:1
704B RET pred:%noreg, %RT<imp-use>, %P15<imp-use,kill>; dbg:../src/getbits.c:60:1

# End machine code for function CGA_kernel_read.

llc: /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:76: static llvm::MachineOperand* llvm::MachineRegisterInfo::getNextOperandForReg(const llvm::MachineOperand*): Assertion `MO && MO->isReg() && "This is not a register operand!"' failed.

Program received signal SIGABRT, Aborted.
0xb7fdd424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fdd424 in __kernel_vsyscall ()
#1  0xb7cfe1ef in __GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7d01835 in __GI_abort () at abort.c:91
#3  0xb7cf7095 in __assert_fail_base (fmt=0xb7e308b8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x8d27b14 "MO && MO->isReg() && \"This is not a register operand!\"",
    file=0x8d27ad0 "/work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h", line=76,
    function=0x8d2b600 "static llvm::MachineOperand* llvm::MachineRegisterInfo::getNextOperandForReg(const llvm::MachineOperand*)") at assert.c:94
#4  0xb7cf7147 in __GI___assert_fail (assertion=0x8d27b14 "MO && MO->isReg() && \"This is not a register operand!\"", file=0x8d27ad0 "/work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h",
    line=76, function=0x8d2b600 "static llvm::MachineOperand* llvm::MachineRegisterInfo::getNextOperandForReg(const llvm::MachineOperand*)") at assert.c:103
#5  0x084faa91 in llvm::MachineRegisterInfo::getNextOperandForReg (MO=0xbfffee8c) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:76
#6  0x086a8118 in llvm::MachineRegisterInfo::defusechain_iterator<true, true, false>::operator++ (this=0xbffff068) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:514
#7  0x08803f51 in llvm::MachineRegisterInfo::defusechain_iterator<true, true, false>::skipInstruction (this=0xbffff068) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:543
#8  0x0896d5bf in llvm::VirtRegAuxInfo::CalculateWeightAndHint (this=0xbffff0d8, li=...) at /work/llvm/trunk/llvm/lib/CodeGen/CalcSpillWeights.cpp:131
#9  0x0896d22e in llvm::CalculateSpillWeights::runOnMachineFunction (this=0x937f0a8, MF=...) at /work/llvm/trunk/llvm/lib/CodeGen/CalcSpillWeights.cpp:53
#10 0x08847e95 in llvm::MachineFunctionPass::runOnFunction (this=0x937f0a8, F=...) at /work/llvm/trunk/llvm/lib/CodeGen/MachineFunctionPass.cpp:33
#11 0x08bcdbec in llvm::FPPassManager::runOnFunction (this=0x9348038, F=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1498
#12 0x08bcdda8 in llvm::FPPassManager::runOnModule (this=0x9348038, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1518
#13 0x08bce086 in llvm::MPPassManager::runOnModule (this=0x9347130, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1572
#14 0x08bce578 in llvm::PassManagerImpl::run (this=0x9347690, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1655
#15 0x08bce715 in llvm::PassManager::run (this=0xbffff400, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1684
#16 0x083ad0a6 in main (argc=13, argv=0xbffff584) at /work/llvm/trunk/llvm/tools/llc/llc.cpp:559
(gdb)

By the way, when I try to add a pass before register allocation to remove the inserted dead instruction with the following code, I get a similar assertion on the MRI.use_empty. This code also used to work until before r161643.

bool ADRESUselessPredicateCleanup::eliminateUselessPredicate(MachineInstr *MI){
 
  // find destination operand and check it is a register
  MachineOperand MO = MI->getOperand(0);
  if (!MO.isReg()) return false;
 
  unsigned reg = MO.getReg();
  MachineRegisterInfo &MRI=MI->getParent()->getParent()->getRegInfo();

  //  MI->dump();

  // if the produced register is not used anywhere in the method and it is a predicate register
  // eliminate the instruction
  // TODO: fix the ugly check for PredicateRegisters
  if (MRI.use_empty(reg)) {
    if ( !TargetRegisterInfo::isPhysicalRegister(reg) || (reg >= ADRES::p0 && reg <= ADRES::p387)) {
      MI->eraseFromParent();
      return true;
    }
  }
  return false;
}

Thanks a lot,

Bjorn De Sutter
Computer Systems Lab
Ghent University





_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: liveness assertion problem in llc

Jakob Stoklund Olesen-2

On Sep 18, 2012, at 1:45 PM, Bjorn De Sutter <[hidden email]> wrote:

> I am working on a backend for a CGRA architecture with advanced predicate support (as on EPIC machines and as first used in the OpenIMPACT compiler). Until last month, the backend was working fine, but since the r161643 commit by stoklund, my backend doesn't work anymore. I think I noticed some related commits later on, and the assertion I get on the latest trunk (r164162) differs from what I got on r161643 (where it was the PHIelimination that failed). From the log, I have the impression that the assertion is raised on a dead instruction during the spill weight calculation. The dead instruction (definition of vreg12 in the log below) is an instruction I add during if-conversion for use in a later pass. Previously, such dead instructions did not cause any problem...
>
> Any idea what might be going wrong here? I've noticed that there is now something like a flag that needs to be set by code transformations that destroy existing liveness information. Maybe I should set that flag during if-conversion? Apart from that, I have no clue…

Hi Bjorn,

It looks like the linked list of operands for a register has been corrupted. Every (non-null) register operand belongs to a doubly linked list of MachineOperands referencing the same register.

I couldn't say how those lists got corrupted based on your debug dumps. The lists are maintained by code in MachineInstr.cpp and MachineRegisterInfo.cpp.

/jakob


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: liveness assertion problem in llc

Bjorn De Sutter
Hi Jacob,

thanks for the fast response. Could you have a quick look at the assertion I get with r161643? Before that last commit, i.e., with r161642, everything went fine for my backend, but after this commit, with no other changes, PHI-elimination suddenly broke as follows:

# *** IR Dump Before Eliminate PHI nodes for register allocation ***:
# Machine code for function CGA_kernel_read: SSA
Function Live Ins: %P0 in %vreg5, %P1 in %vreg6
Function Live Outs: %P15

BB#0: derived from LLVM BB %entry
    Live Ins: %P0 %P1
        DBG_VALUE %P0, 0, !"buf"; line no:42
        DBG_VALUE %P1, 0, !"count"; line no:42
        DBG_VALUE %P0, 0, !"p"; line no:44
        %vreg6<def> = COPY %P1; IntRegs:%vreg6
        DBG_VALUE %vreg6, 0, !"count"; IntRegs:%vreg6 line no:42
        %vreg5<def> = COPY %P0; IntRegs:%vreg5
        DBG_VALUE %vreg5, 0, !"buf"; IntRegs:%vreg5 line no:42
        DBG_VALUE %vreg5, 0, !"p"; IntRegs:%vreg5 line no:44
        %vreg8<def> = MOV32ri <ga:@fifo>, pred:%noreg; IntRegs:%vreg8 dbg:../src/getbits.c:46:1
        %vreg9<def> = LDUBri %vreg8, 1, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 1)] IntRegs:%vreg9,%vreg8 dbg:../src/getbits.c:46:1
        %vreg10<def> = CMPEQI %vreg9<kill>, 0, pred:%noreg; PredRegs:%vreg10 IntRegs:%vreg9 dbg:../src/getbits.c:46:1
        JUMP <BB#2>, pred:%vreg10<kill>; PredRegs:%vreg10
    Successors according to CFG: BB#2 BB#1

BB#1:
    Predecessors according to CFG: BB#0
        %vreg7<def> = MOV32ri -1, pred:%noreg; IntRegs:%vreg7
        JUMP <BB#5>, pred:%noreg
    Successors according to CFG: BB#5

BB#2: derived from LLVM BB %while.cond.preheader
    Predecessors according to CFG: BB#0
        %vreg11<def> = MOV32ri 0, pred:%noreg; IntRegs:%vreg11
        %vreg12<def> = CMPEQI %vreg6, 0, pred:%noreg; PredRegs:%vreg12 IntRegs:%vreg6 dbg:../src/getbits.c:53:3
        JUMP <BB#5>, pred:%vreg12<kill>; PredRegs:%vreg12
    Successors according to CFG: BB#5 BB#3

BB#3:
    Predecessors according to CFG: BB#2
    Successors according to CFG: BB#4

BB#4: derived from LLVM BB %while.body
    Predecessors according to CFG: BB#4 BB#3
        %vreg0<def> = PHI %vreg11, <BB#3>, %vreg2, <BB#4>; IntRegs:%vreg0,%vreg11,%vreg2
        %vreg1<def> = PHI %vreg5, <BB#3>, %vreg3, <BB#4>; IntRegs:%vreg1,%vreg5,%vreg3
        %vreg14<def> = LDUBrr %vreg8, 0, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 0)] IntRegs:%vreg14,%vreg8 dbg:../src/getbits.c:56:5
        STBrr %vreg1, 0, %vreg14<kill>, pred:%noreg; mem:ST1[%p.04] IntRegs:%vreg1,%vreg14 dbg:../src/getbits.c:56:5
        %vreg2<def> = ADDri %vreg0<kill>, 1, pred:%noreg; IntRegs:%vreg2,%vreg0 dbg:../src/getbits.c:55:5
        DBG_VALUE %vreg2, 0, !"r"; IntRegs:%vreg2 line no:45
        %vreg15<def> = CMPLT_U %vreg2, %vreg6, pred:%noreg; PredRegs:%vreg15 IntRegs:%vreg2,%vreg6 dbg:../src/getbits.c:53:3
        ADJCALLSTACKDOWN 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
        CALL <ga:@CGA_kernel_advance>, 0, 0, pred:%noreg, 0, %noreg, %P0<imp-def>, %P1<imp-def>, %P2<imp-def>, %P3<imp-def>, %P15<imp-def>, %RT<imp-def>, %P0<imp-use>, %P1<imp-use>, %P2<imp-use>, %P3<imp-use>; dbg:../src/getbits.c:57:5
        ADJCALLSTACKUP 0, 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
        %vreg16<def> = LDUBri %vreg8, 1, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 1)] IntRegs:%vreg16,%vreg8 dbg:../src/getbits.c:53:3
        %vreg17<def> = CMPEQANDri %vreg15<kill>, %vreg16<kill>, 0, pred:%noreg; PredRegs:%vreg17,%vreg15 IntRegs:%vreg16 dbg:../src/getbits.c:53:3
        %vreg3<def> = ADDri %vreg1<kill>, 1, pred:%noreg; IntRegs:%vreg3,%vreg1 dbg:../src/getbits.c:56:5
        DBG_VALUE %vreg3, 0, !"p"; IntRegs:%vreg3 line no:44
        JUMP <BB#4>, pred:%vreg17<kill>; PredRegs:%vreg17 dbg:../src/getbits.c:53:3
        JUMP <BB#5>, pred:%noreg; dbg:../src/getbits.c:53:3
    Successors according to CFG: BB#4 BB#5

BB#5: derived from LLVM BB %if.end
    Predecessors according to CFG: BB#2 BB#4 BB#1
        %vreg4<def> = PHI %vreg7, <BB#1>, %vreg11, <BB#2>, %vreg2, <BB#4>; IntRegs:%vreg4,%vreg7,%vreg11,%vreg2
        %P15<def> = COPY %vreg4<kill>; IntRegs:%vreg4 dbg:../src/getbits.c:60:1
        RET pred:%noreg, %RT<imp-use>, %P15<imp-use,kill>; dbg:../src/getbits.c:60:1

# End machine code for function CGA_kernel_read.

llc: /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineOperand.h:252: bool llvm::MachineOperand::isUse() const: Assertion `isReg() && "Wrong MachineOperand accessor"' failed.

Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".

Program received signal SIGABRT, Aborted.
0xb7fdd424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fdd424 in __kernel_vsyscall ()
#1  0xb7cfe1ef in __GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7d01835 in __GI_abort () at abort.c:91
#3  0xb7cf7095 in __assert_fail_base (fmt=0xb7e308b8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x8c9d818 "isReg() && \"Wrong MachineOperand accessor\"",
    file=0x8c9d7ac "/work/llvm/trunk/llvm/include/llvm/CodeGen/MachineOperand.h", line=252, function=0x8c9f7c0 "bool llvm::MachineOperand::isUse() const")
    at assert.c:94
#4  0xb7cf7147 in __GI___assert_fail (assertion=0x8c9d818 "isReg() && \"Wrong MachineOperand accessor\"",
    file=0x8c9d7ac "/work/llvm/trunk/llvm/include/llvm/CodeGen/MachineOperand.h", line=252, function=0x8c9f7c0 "bool llvm::MachineOperand::isUse() const")
    at assert.c:103
#5  0x08450f78 in llvm::MachineOperand::isUse (this=0xbfffee68) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineOperand.h:252
#6  0x084f4039 in llvm::MachineRegisterInfo::defusechain_iterator<false, true, false>::operator++ (this=0xbfffee50)
    at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:521
#7  0x084f3f9d in llvm::MachineRegisterInfo::defusechain_iterator<false, true, false>::defusechain_iterator (this=0xbfffee50, op=0x9326204)
    at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:492
#8  0x084f3c8f in llvm::MachineRegisterInfo::def_begin (this=0x931c800, RegNo=2147483672) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineRegisterInfo.h:196
#9  0x0884b4f5 in llvm::MachineRegisterInfo::getVRegDef (this=0x931c800, Reg=2147483672) at /work/llvm/trunk/llvm/lib/CodeGen/MachineRegisterInfo.cpp:201
#10 0x087ebded in llvm::LiveVariables::VarInfo::isLiveIn (this=0x932b3b8, MBB=..., Reg=2147483672, MRI=...) at /work/llvm/trunk/llvm/lib/CodeGen/LiveVariables.cpp:748
#11 0x087ec2dd in llvm::LiveVariables::addNewBlock (this=0x92ca380, BB=0x931d4fc, DomBB=0x931cae4, SuccBB=0x931cbec)
    at /work/llvm/trunk/llvm/lib/CodeGen/LiveVariables.cpp:820
#12 0x087f7bd6 in llvm::MachineBasicBlock::SplitCriticalEdge (this=0x931cae4, Succ=0x931cbec, P=0x92ff5c0)
    at /work/llvm/trunk/llvm/lib/CodeGen/MachineBasicBlock.cpp:699
#13 0x0887285e in (anonymous namespace)::PHIElimination::SplitPHIEdges (this=0x92ff5c0, MF=..., MBB=..., LV=..., MLI=0x92ff138)
    at /work/llvm/trunk/llvm/lib/CodeGen/PHIElimination.cpp:485
#14 0x08871264 in (anonymous namespace)::PHIElimination::runOnMachineFunction (this=0x92ff5c0, MF=...) at /work/llvm/trunk/llvm/lib/CodeGen/PHIElimination.cpp:124
#15 0x0881de19 in llvm::MachineFunctionPass::runOnFunction (this=0x92ff5c0, F=...) at /work/llvm/trunk/llvm/lib/CodeGen/MachineFunctionPass.cpp:33
#16 0x08b76c96 in llvm::FPPassManager::runOnFunction (this=0x92e2bb8, F=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1498
#17 0x08b76e52 in llvm::FPPassManager::runOnModule (this=0x92e2bb8, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1518
#18 0x08b77130 in llvm::MPPassManager::runOnModule (this=0x92cb660, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1572
#19 0x08b775f4 in llvm::PassManagerImpl::run (this=0x92cb118, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1655
#20 0x08b77791 in llvm::PassManager::run (this=0xbffff410, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1684
#21 0x083a44f4 in main (argc=13, argv=0xbffff594) at /work/llvm/trunk/llvm/tools/llc/llc.cpp:553

I enabled the printing of additional debug information in PHIelimination, but that did not produce output before the assertion got raised.

With r161642, the PHI-elimination produced this (correct) result:

BB#1:
     Predecessors according to CFG: BB#0
       %vreg7<def> = MOV32ri -1, pred:%noreg; IntRegs:%vreg7
       %vreg27<def> = COPY %vreg7<kill>; IntRegs:%vreg27,%vreg7
       JUMP <BB#5>, pred:%noreg
     Successors according to CFG: BB#5
 
 BB#2: derived from LLVM BB %while.cond.preheader
     Predecessors according to CFG: BB#0
       %vreg11<def> = MOV32ri 0, pred:%noreg; IntRegs:%vreg11
       %vreg24<def> = CMPNEI %vreg6, 0, pred:%noreg; PredRegs:%vreg24 IntRegs:%vreg6 dbg:../src/getbits.c:53:3
       %vreg12<def> = CMPEQI %vreg6, 0, pred:%noreg; PredRegs:%vreg12 IntRegs:%vreg6 dbg:../src/getbits.c:53:3
       JUMP <BB#3>, pred:%vreg24; PredRegs:%vreg24
     Successors according to CFG: BB#3 BB#6
 
 BB#6:
     Predecessors according to CFG: BB#2
       %vreg27<def> = COPY %vreg11<kill>; IntRegs:%vreg27,%vreg11
       JUMP <BB#5>, pred:%noreg
     Successors according to CFG: BB#5
 
 BB#3:
     Predecessors according to CFG: BB#2
       %vreg25<def> = COPY %vreg11<kill>; IntRegs:%vreg25,%vreg11
       %vreg26<def> = COPY %vreg5<kill>; IntRegs:%vreg26,%vreg5
     Successors according to CFG: BB#4
 
 BB#4: derived from LLVM BB %while.body
     Predecessors according to CFG: BB#4 BB#3
       %vreg0<def> = COPY %vreg25<kill>; IntRegs:%vreg0,%vreg25
       %vreg1<def> = COPY %vreg26<kill>; IntRegs:%vreg1,%vreg26
       %vreg14<def> = LDUBrr %vreg8, 0, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 0)] IntRegs:%vreg14,%vreg8 dbg:../src/getbits.c:56:5
       STBrr %vreg1, 0, %vreg14<kill>, pred:%noreg; mem:ST1[%p.04] IntRegs:%vreg1,%vreg14 dbg:../src/getbits.c:56:5
       %vreg2<def> = ADDri %vreg0<kill>, 1, pred:%noreg; IntRegs:%vreg2,%vreg0 dbg:../src/getbits.c:55:5
      DBG_VALUE %vreg2, 0, !"r"; IntRegs:%vreg2 line no:45
       %vreg15<def> = CMPLT_U %vreg2, %vreg6, pred:%noreg; PredRegs:%vreg15 IntRegs:%vreg2,%vreg6 dbg:../src/getbits.c:53:3
       ADJCALLSTACKDOWN 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
       CALL <ga:@CGA_kernel_advance>, 0, 0, pred:%noreg, 0, %noreg, %P0<imp-def>, %P1<imp-def>, %P2<imp-def>, %P3<imp-def>, %P15<imp-def>, %RT<imp-def>, %P0<imp-use>, %P1<imp-use>, %P2<imp-use>, %P3<imp-use>; dbg:../src/getbits.c:57:5
       ADJCALLSTACKUP 0, 0, pred:%noreg, %SP<imp-def>, %SP<imp-use>
       %vreg16<def> = LDUBri %vreg8, 1, pred:%noreg; mem:LD1[getelementptr inbounds (%struct.FIFO* @fifo, i32 0, i32 1)] IntRegs:%vreg16,%vreg8 dbg:../src/getbits.c:53:3
       %vreg17<def> = CMPEQANDri %vreg15<kill>, %vreg16<kill>, 0, pred:%noreg; PredRegs:%vreg17,%vreg15 IntRegs:%vreg16 dbg:../src/getbits.c:53:3
       %vreg3<def> = ADDri %vreg1<kill>, 1, pred:%noreg; IntRegs:%vreg3,%vreg1 dbg:../src/getbits.c:56:5
       DBG_VALUE %vreg3, 0, !"p"; IntRegs:%vreg3 line no:44
      %vreg25<def> = COPY %vreg2; IntRegs:%vreg25,%vreg2
       %vreg26<def> = COPY %vreg3<kill>; IntRegs:%vreg26,%vreg3
       %vreg27<def> = COPY %vreg2<kill>; IntRegs:%vreg27,%vreg2
       JUMP <BB#4>, pred:%vreg17<kill>; PredRegs:%vreg17 dbg:../src/getbits.c:53:3
       JUMP <BB#5>, pred:%noreg; dbg:../src/getbits.c:53:3
     Successors according to CFG: BB#4 BB#5

Thanks,

Bjorn

On 18 Sep 2012, at 22:55, Jakob Stoklund Olesen wrote:

>
> On Sep 18, 2012, at 1:45 PM, Bjorn De Sutter <[hidden email]> wrote:
>
>> I am working on a backend for a CGRA architecture with advanced predicate support (as on EPIC machines and as first used in the OpenIMPACT compiler). Until last month, the backend was working fine, but since the r161643 commit by stoklund, my backend doesn't work anymore. I think I noticed some related commits later on, and the assertion I get on the latest trunk (r164162) differs from what I got on r161643 (where it was the PHIelimination that failed). From the log, I have the impression that the assertion is raised on a dead instruction during the spill weight calculation. The dead instruction (definition of vreg12 in the log below) is an instruction I add during if-conversion for use in a later pass. Previously, such dead instructions did not cause any problem...
>>
>> Any idea what might be going wrong here? I've noticed that there is now something like a flag that needs to be set by code transformations that destroy existing liveness information. Maybe I should set that flag during if-conversion? Apart from that, I have no clue…
>
> Hi Bjorn,
>
> It looks like the linked list of operands for a register has been corrupted. Every (non-null) register operand belongs to a doubly linked list of MachineOperands referencing the same register.
>
> I couldn't say how those lists got corrupted based on your debug dumps. The lists are maintained by code in MachineInstr.cpp and MachineRegisterInfo.cpp.
>
> /jakob
>


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: liveness assertion problem in llc

Bjorn De Sutter
In reply to this post by Bjorn De Sutter
Hi Jacob,

At this point, I suspect there is a problem with maintaining liveness information during branch folding. Here is what I see:

I have a basic block ready for branch optimization, that computes a predicate p10 on which a conditional branch depends. Notice that this is in the stage with physical registers.

BB#2: derived from LLVM BB %while.cond.preheader
    Live Ins: %R3 %R5
    Predecessors according to CFG: BB#0
        DBG_VALUE %P0, 0, !"buf"; line no:42
        DBG_VALUE %R3, 0, !"count"; line no:42
        DBG_VALUE %P0, 0, !"p"; line no:44
        %R1<def> = MOV32ri 0, pred:%noreg
        %p10<def> = CMPEQI %R3, 0, pred:%noreg; dbg:../src/getbits.c:53:3
        JUMP <BB#6>, pred:%p10<kill>
        JUMP <BB#3>, pred:%noreg
    Successors according to CFG: BB#3 BB#6

Several transformations are performed during branch folding:

1) As part of the branch optimization, the conditional branch is reversed. To do so, an additional instruction is added to the code that computes the complementary predicate p387, and this predicate is then used in the reversed branch. The instruction is built using BuildMI and addReg methods as I do in other parts of the backend and as worked well before r161463. The resulting basic block of this step 0 looks like this:

BB#2: derived from LLVM BB %while.cond.preheader
    Live Ins: %R3 %R5
    Predecessors according to CFG: BB#0
        DBG_VALUE %P0, 0, !"buf"; line no:42
        DBG_VALUE %R3, 0, !"count"; line no:42
        DBG_VALUE %P0, 0, !"p"; line no:44
        %R1<def> = MOV32ri 0, pred:%noreg
        %p387<def> = CMPNEI %R3, 0, pred:%noreg; dbg:../src/getbits.c:53:3
        %p10<def> = CMPEQI %R3, 0, pred:%noreg; dbg:../src/getbits.c:53:3
        JUMP <BB#4>, pred:%p387
    Successors according to CFG: BB#4 BB#6

I should point out that this newly used register p387 was previously not used or defined at all in the function at hand, so I guess no use-def chains will have been computed for it. Until r161462, this posed no problem whatsoever.  Also note that the new jump does not have the <kill> attribute. Might that be a problem?

Later on during branch optimization, llc decides to further change the branches, removing and inserting branches. I don't understand the whole decision process behind this, but specifically this sequence of transformations takes place:

2) remove branch JUMP <BB#4>, pred:%p387 (works fine)

3) insert branches JUMP <BB#4>, pred:%p387 (with the same code that inserted an identical instruction in step 1)
                                 JUMP <BB#3>, pred:%noreg

3) try to remove branches, starting with JUMP <BB#4>, pred:%p387 inserted in step 3).

That is when things go wrong and I get the following assertion (with GDB) backtrace. (Please note that my RemoveBranch code is nothing special, it looks exactly the same as the code in the Mips backend. )

llc: /work/llvm/trunk/llvm/lib/CodeGen/MachineRegisterInfo.cpp:162: void llvm::MachineRegisterInfo::removeRegOperandFromUseList(llvm::MachineOperand*): Assertion `NextOp->getReg() == MO->getReg() && "Corrupt reg use/def chain!"' failed.

Program received signal SIGABRT, Aborted.
0xb7fdd424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fdd424 in __kernel_vsyscall ()
#1  0xb7cfe1ef in __GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7d01835 in __GI_abort () at abort.c:91
#3  0xb7cf7095 in __assert_fail_base (fmt=0xb7e308b8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x8e1699c "NextOp->getReg() == MO->getReg() && \"Corrupt reg use/def chain!\"",
    file=0x8e16760 "/work/llvm/trunk/llvm/lib/CodeGen/MachineRegisterInfo.cpp", line=162, function=0x8e17d60 "void llvm::MachineRegisterInfo::removeRegOperandFromUseList(llvm::MachineOperand*)") at assert.c:94
#4  0xb7cf7147 in __GI___assert_fail (assertion=0x8e1699c "NextOp->getReg() == MO->getReg() && \"Corrupt reg use/def chain!\"", file=0x8e16760 "/work/llvm/trunk/llvm/lib/CodeGen/MachineRegisterInfo.cpp", line=162,
    function=0x8e17d60 "void llvm::MachineRegisterInfo::removeRegOperandFromUseList(llvm::MachineOperand*)") at assert.c:103
#5  0x0884e0e0 in llvm::MachineRegisterInfo::removeRegOperandFromUseList (this=0x931b0c8, MO=0x9329aac) at /work/llvm/trunk/llvm/lib/CodeGen/MachineRegisterInfo.cpp:162
#6  0x08823d7f in llvm::MachineInstr::RemoveRegOperandsFromUseLists (this=0x931b920, MRI=...) at /work/llvm/trunk/llvm/lib/CodeGen/MachineInstr.cpp:638
#7  0x087f7c64 in llvm::ilist_traits<llvm::MachineInstr>::removeNodeFromList (this=0x931b3b4, N=0x931b920) at /work/llvm/trunk/llvm/lib/CodeGen/MachineBasicBlock.cpp:115
#8  0x0856f3d8 in llvm::iplist<llvm::MachineInstr, llvm::ilist_traits<llvm::MachineInstr> >::remove (this=0x931b3b4, IT=...) at /work/llvm/trunk/llvm/include/llvm/ADT/ilist.h:444
#9  0x0856f1e8 in llvm::iplist<llvm::MachineInstr, llvm::ilist_traits<llvm::MachineInstr> >::erase (this=0x931b3b4, where=...) at /work/llvm/trunk/llvm/include/llvm/ADT/ilist.h:463
#10 0x0856f22b in llvm::iplist<llvm::MachineInstr, llvm::ilist_traits<llvm::MachineInstr> >::erase (this=0x931b3b4, first=..., last=...) at /work/llvm/trunk/llvm/include/llvm/ADT/ilist.h:528
#11 0x0856f077 in llvm::MachineBasicBlock::erase (this=0x931b3ac, I=..., E=...) at /work/llvm/trunk/llvm/include/llvm/CodeGen/MachineBasicBlock.h:480
#12 0x08593f60 in llvm::ADRESInstrInfo::RemoveBranch (this=0x92cf50c, MBB=...) at /work/llvm/trunk/llvm/lib/Target/ADRES/ADRESInstrInfo.cpp:364
#13 0x0892d513 in llvm::BranchFolder::OptimizeBlock (this=0xbfffea70, MBB=0x931bd14) at /work/llvm/trunk/llvm/lib/CodeGen/BranchFolding.cpp:1200
#14 0x0892c565 in llvm::BranchFolder::OptimizeBranches (this=0xbfffea70, MF=...) at /work/llvm/trunk/llvm/lib/CodeGen/BranchFolding.cpp:972
#15 0x089298c2 in llvm::BranchFolder::OptimizeFunction (this=0xbfffea70, MF=..., tii=0x92cf50c, tri=0x92cf528, mmi=0x92f1228) at /work/llvm/trunk/llvm/lib/CodeGen/BranchFolding.cpp:208
#16 0x08929150 in (anonymous namespace)::BranchFolderPass::runOnMachineFunction (this=0x9309d28, MF=...) at /work/llvm/trunk/llvm/lib/CodeGen/BranchFolding.cpp:91
#17 0x08820b79 in llvm::MachineFunctionPass::runOnFunction (this=0x9309d28, F=...) at /work/llvm/trunk/llvm/lib/CodeGen/MachineFunctionPass.cpp:33
#18 0x08b7a49a in llvm::FPPassManager::runOnFunction (this=0x92e5bb8, F=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1498
#19 0x08b7a656 in llvm::FPPassManager::runOnModule (this=0x92e5bb8, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1518
#20 0x08b7a934 in llvm::MPPassManager::runOnModule (this=0x92ce660, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1572
#21 0x08b7adf8 in llvm::PassManagerImpl::run (this=0x92ce118, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1655
#22 0x08b7af95 in llvm::PassManager::run (this=0xbfffedc0, M=...) at /work/llvm/trunk/llvm/lib/VMCore/PassManager.cpp:1684
#23 0x083a44f4 in main (argc=13, argv=0xbfffef44) at /work/llvm/trunk/llvm/tools/llc/llc.cpp:553

So at this point, I suspect that the problem is that def-use chains are not maintained well during the branch transformations, and more specifically when new instructions are added to compute complementary predicates in physical registers that were not at all used or defined in the function at hand before, and when these registers are then used. But it is strange that in a sequence InsertBranch - RemoveBranch - InsertBranch - RemoveBranch all operating on an identical instruction, the first removal is successful, while the second asserts ... following the commit of r161643

Can you shed some light on this, on where to look further for example?

Thanks a lot,
   
Bjorn




_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev