diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-05-19 23:34:59 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-05-19 23:34:59 +0000 |
commit | 7ebed91fddbcd259d03c4b438719ac1ce2a4fc87 (patch) | |
tree | ad2dfa847de2a06219ea704c33e2ae5c49b11cac | |
parent | 9012c57e18d76d562b1f3e60bf19cccefa7b793e (diff) | |
download | external_llvm-7ebed91fddbcd259d03c4b438719ac1ce2a4fc87.zip external_llvm-7ebed91fddbcd259d03c4b438719ac1ce2a4fc87.tar.gz external_llvm-7ebed91fddbcd259d03c4b438719ac1ce2a4fc87.tar.bz2 |
Fix 12892.
Dead code elimination during coalescing could cause a virtual register
to be split into connected components. The following rewriting would be
confused about the already joined copies present in the code, but
without a corresponding value number in the live range.
Erase all joined copies instantly when joining intervals such that the
MI and LiveInterval representations are always in sync.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157135 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/LiveRangeEdit.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/RegisterCoalescer.cpp | 24 | ||||
-rw-r--r-- | test/CodeGen/X86/2012-05-19-CoalescerCrash.ll | 122 |
3 files changed, 146 insertions, 4 deletions
diff --git a/lib/CodeGen/LiveRangeEdit.cpp b/lib/CodeGen/LiveRangeEdit.cpp index 8bdad5a..4c2b0bf 100644 --- a/lib/CodeGen/LiveRangeEdit.cpp +++ b/lib/CodeGen/LiveRangeEdit.cpp @@ -308,6 +308,10 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, TheDelegate->LRE_DidCloneVirtReg(Dups.back()->reg, LI->reg); } ConEQ.Distribute(&Dups[0], MRI); + DEBUG({ + for (unsigned i = 0; i != NumComp; ++i) + dbgs() << '\t' << *Dups[i] << '\n'; + }); } } diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 74d0454..ca5d280 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -1081,9 +1081,10 @@ bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) { if (!CP.isPhys() && RegClassInfo.isProperSubClass(CP.getNewRC())) InflateRegs.push_back(CP.getDstReg()); - // Remember to delete the copy instruction. - LIS->RemoveMachineInstrFromMaps(CopyMI); - CopyMI->eraseFromParent(); + // CopyMI has been erased by joinIntervals at this point. Remove it from + // ErasedInstrs since copyCoalesceWorkList() won't add a successful join back + // to the work list. This keeps ErasedInstrs from growing needlessly. + ErasedInstrs.erase(CopyMI); // Rewrite all SrcReg operands to DstReg. // Also update DstReg operands to include DstIdx if it is set. @@ -1285,6 +1286,7 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) { SmallVector<VNInfo*, 16> NewVNInfo; SmallVector<MachineInstr*, 8> DupCopies; + SmallVector<MachineInstr*, 8> DeadCopies; LiveInterval &LHS = LIS->getOrCreateInterval(CP.getDstReg()); DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), TRI); dbgs() << "\n"; }); @@ -1313,6 +1315,7 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) { continue; LHSValsDefinedFromRHS[VNI] = lr->valno; + DeadCopies.push_back(MI); } // Loop over the value numbers of the RHS, seeing if any are defined from @@ -1339,6 +1342,7 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) { continue; RHSValsDefinedFromLHS[VNI] = lr->valno; + DeadCopies.push_back(MI); } LHSValNoAssignments.resize(LHS.getNumValNums(), -1); @@ -1438,6 +1442,17 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) { if (RHSValNoAssignments.empty()) RHSValNoAssignments.push_back(-1); + // Now erase all the redundant copies. + for (unsigned i = 0, e = DeadCopies.size(); i != e; ++i) { + MachineInstr *MI = DeadCopies[i]; + DEBUG(dbgs() << "\t\terased:\t" << LIS->getInstructionIndex(MI) + << '\t' << *MI); + if (!ErasedInstrs.insert(MI)) + continue; + LIS->RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } + SmallVector<unsigned, 8> SourceRegisters; for (SmallVector<MachineInstr*, 8>::iterator I = DupCopies.begin(), E = DupCopies.end(); I != E; ++I) { @@ -1451,7 +1466,8 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) { // A = X unsigned Src = MI->getOperand(1).getReg(); SourceRegisters.push_back(Src); - ErasedInstrs.insert(MI); + if (!ErasedInstrs.insert(MI)) + continue; LIS->RemoveMachineInstrFromMaps(MI); MI->eraseFromParent(); } diff --git a/test/CodeGen/X86/2012-05-19-CoalescerCrash.ll b/test/CodeGen/X86/2012-05-19-CoalescerCrash.ll new file mode 100644 index 0000000..837fbc0 --- /dev/null +++ b/test/CodeGen/X86/2012-05-19-CoalescerCrash.ll @@ -0,0 +1,122 @@ +; RUN: llc < %s -verify-coalescing +; PR12892 +; +; Dead code elimination during coalesing causes a live range to split into two +; virtual registers. Stale identity copies that had already been joined were +; interfering with the liveness computations. + +target triple = "i386-pc-linux-gnu" + +define void @_ZN4llvm17AsmMatcherEmitter3runERNS_11raw_ostreamE() align 2 { + invoke void @_ZNK4llvm13CodeGenTarget12getAsmParserEv() + to label %1 unwind label %5 + +; <label>:1 ; preds = %0 + invoke void @_ZNK4llvm6Record16getValueAsStringENS_9StringRefE() + to label %4 unwind label %2 + +; <label>:2 ; preds = %1 + %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + unreachable + +; <label>:4 ; preds = %1 + invoke void @_ZN4llvm18isCurrentDebugTypeEPKc() + to label %12 unwind label %7 + +; <label>:5 ; preds = %0 + %6 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + br label %33 + +; <label>:7 ; preds = %4 + %8 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + br label %9 + +; <label>:9 ; preds = %28, %7 + %10 = phi { i8*, i32 } [ %29, %28 ], [ %8, %7 ] + %11 = extractvalue { i8*, i32 } %10, 1 + invoke fastcc void @_ZN12_GLOBAL__N_114AsmMatcherInfoD2Ev() + to label %32 unwind label %35 + +; <label>:12 ; preds = %4 + invoke void @_ZNK4llvm13CodeGenTarget10getRegBankEv() + to label %13 unwind label %16 + +; <label>:13 ; preds = %12 + br label %14 + +; <label>:14 ; preds = %20, %13 + %15 = icmp eq i32 undef, 0 + br i1 %15, label %20, label %18 + +; <label>:16 ; preds = %12 + %17 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + br label %26 + +; <label>:18 ; preds = %14 + invoke void @_ZNSs4_Rep9_S_createEjjRKSaIcE() + to label %19 unwind label %21 + +; <label>:19 ; preds = %18 + unreachable + +; <label>:20 ; preds = %14 + br label %14 + +; <label>:21 ; preds = %18 + %22 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + %23 = extractvalue { i8*, i32 } %22, 1 + br i1 undef, label %26, label %24 + +; <label>:24 ; preds = %21 + br i1 undef, label %25, label %26 + +; <label>:25 ; preds = %24 + unreachable + +; <label>:26 ; preds = %24, %21, %16 + %27 = phi i32 [ 0, %16 ], [ %23, %21 ], [ %23, %24 ] + invoke void @_ZNSt6vectorISt4pairISsSsESaIS1_EED1Ev() + to label %28 unwind label %30 + +; <label>:28 ; preds = %26 + %29 = insertvalue { i8*, i32 } undef, i32 %27, 1 + br label %9 + +; <label>:30 ; preds = %26 + %31 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + unreachable + +; <label>:32 ; preds = %9 + br label %33 + +; <label>:33 ; preds = %32, %5 + %34 = phi i32 [ undef, %5 ], [ %11, %32 ] + unreachable + +; <label>:35 ; preds = %9 + %36 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + unreachable +} + +declare void @_ZNK4llvm13CodeGenTarget12getAsmParserEv() + +declare i32 @__gxx_personality_v0(...) + +declare void @_ZNK4llvm6Record16getValueAsStringENS_9StringRefE() + +declare void @_ZN4llvm18isCurrentDebugTypeEPKc() + +declare fastcc void @_ZN12_GLOBAL__N_114AsmMatcherInfoD2Ev() unnamed_addr inlinehint align 2 + +declare hidden void @_ZNSt6vectorISt4pairISsSsESaIS1_EED1Ev() unnamed_addr align 2 + +declare void @_ZNSs4_Rep9_S_createEjjRKSaIcE() + +declare void @_ZNK4llvm13CodeGenTarget10getRegBankEv() |