From ded2e3b0d02998b3bb99b5089d05fca1e0097868 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 4 Aug 2009 20:01:11 +0000 Subject: [PATCH] LowerSubregsInstructionPass::LowerExtract should not extend the live range of registers. When LowerExtract eliminates an EXTRACT_SUBREG with a kill flag, it moves the kill flag to the place where the sub-register is killed. This can accidentally overlap with the use of a sibling sub-register, and we have trouble. In the test case we have this code: Live Ins: %R0 %R1 %R2 %R2L = EXTRACT_SUBREG %R2, 1 %R2H = LOAD16fi , 0, Mem:LD(2,4) [FixedStack-1 + 0] %R1L = EXTRACT_SUBREG %R1, 1 %R0L = EXTRACT_SUBREG %R0, 1 %R0H = ADD16 %R2H, %R2L, %AZ, %AN, %AC0, %V, %VS subreg: CONVERTING: %R2L = EXTRACT_SUBREG %R2, 1 subreg: eliminated! subreg: killed here: %R0H = ADD16 %R2H, %R2L, %R2, %AZ, %AN, %AC0, %V, %VS The kill flag on %R2 is moved to the last instruction, and the live range overlaps with the definition of %R2H: *** Bad machine code: Redefining a live physical register *** - function: f - basic block: 0x18358c0 (#0) - instruction: %R2H = LOAD16fi , 0, Mem:LD(2,4) [FixedStack-1 + 0] Register R2H was defined but already live. The fix is to replace EXTRACT_SUBREG with IMPLICIT_DEF instead of eliminating it completely: subreg: CONVERTING: %R2L = EXTRACT_SUBREG %R2, 1 subreg: replace by: %R2L = IMPLICIT_DEF %R2 Note that these IMPLICIT_DEF instructions survive to the asm output. It is necessary to fix the stack-color-with-reg test case because of that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78093 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/LowerSubregs.cpp | 25 ++++++++----------- .../Blackfin/2009-08-04-LowerExtract-Live.ll | 15 +++++++++++ test/CodeGen/X86/stack-color-with-reg.ll | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 test/CodeGen/Blackfin/2009-08-04-LowerExtract-Live.ll diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index dfd666f96db..9c23a5ac155 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -103,7 +103,7 @@ bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) { MachineFunction &MF = *MBB->getParent(); const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); - + assert(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && MI->getOperand(1).isReg() && MI->getOperand(1).isUse() && MI->getOperand(2).isImm() && "Malformed extract_subreg"); @@ -117,23 +117,20 @@ bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) { "Extract supperg source must be a physical register"); assert(TargetRegisterInfo::isPhysicalRegister(DstReg) && "Extract destination must be in a physical register"); - + DOUT << "subreg: CONVERTING: " << *MI; if (SrcReg == DstReg) { - // No need to insert an identify copy instruction. + // No need to insert an identity copy instruction. + if (MI->getOperand(1).isKill()) { + // We must make sure the super-register gets killed.Replace the + // instruction with IMPLICIT_DEF. + MI->setDesc(TII.get(TargetInstrInfo::IMPLICIT_DEF)); + MI->RemoveOperand(2); // SubIdx + DOUT << "subreg: replace by: " << *MI; + return true; + } DOUT << "subreg: eliminated!"; - // Find the kill of the destination register's live range, and insert - // a kill of the source register at that point. - if (MI->getOperand(1).isKill() && !MI->getOperand(0).isDead()) - for (MachineBasicBlock::iterator MII = - next(MachineBasicBlock::iterator(MI)); - MII != MBB->end(); ++MII) - if (MII->killsRegister(DstReg, &TRI)) { - MII->addRegisterKilled(SuperReg, &TRI, /*AddIfNotFound=*/true); - DOUT << "\nsubreg: killed here: " << *MII; - break; - } } else { // Insert copy const TargetRegisterClass *TRCS = TRI.getPhysicalRegisterRegClass(DstReg); diff --git a/test/CodeGen/Blackfin/2009-08-04-LowerExtract-Live.ll b/test/CodeGen/Blackfin/2009-08-04-LowerExtract-Live.ll new file mode 100644 index 00000000000..58076f9c2d8 --- /dev/null +++ b/test/CodeGen/Blackfin/2009-08-04-LowerExtract-Live.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llc -march=bfin -join-liveintervals=0 -verify-machineinstrs + +; Provoke an error in LowerSubregsPass::LowerExtract where the live range of a +; super-register is illegally extended. + +define i16 @f(i16 %x1, i16 %x2, i16 %x3, i16 %x4) { + %y1 = add i16 %x1, 1 + %y2 = add i16 %x2, 2 + %y3 = add i16 %x3, 3 + %y4 = add i16 %x4, 4 + %z12 = add i16 %y1, %y2 + %z34 = add i16 %y3, %y4 + %p = add i16 %z12, %z34 + ret i16 %p +} diff --git a/test/CodeGen/X86/stack-color-with-reg.ll b/test/CodeGen/X86/stack-color-with-reg.ll index 4e277c7eb03..832886be756 100644 --- a/test/CodeGen/X86/stack-color-with-reg.ll +++ b/test/CodeGen/X86/stack-color-with-reg.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin10 -relocation-model=pic -disable-fp-elim -color-ss-with-regs -stats -info-output-file - > %t ; RUN: grep stackcoloring %t | grep "loads eliminated" ; RUN: grep stackcoloring %t | grep "stack slot refs replaced with reg refs" | grep 5 -; RUN: grep asm-printer %t | grep 175 +; RUN: grep asm-printer %t | grep 180 type { [62 x %struct.Bitvec*] } ; type %0 type { i8* } ; type %1