aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-05-29 20:10:28 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-05-29 20:10:28 +0000
commit57903357ee4f9fed47dcad6f3739414301136b0f (patch)
tree7aecb2c8990380407de3412b3473f8b526ae7cce
parent5f8fd54f0891aa47f467498454f6a3df8ae62704 (diff)
Fix PR10046 by updating LiveVariables kill info when splitting live ranges.
This only affects targets like Mips where branch instructions may kill virtual registers. Most other targets branch on flag values, so virtual registers are not involved. The problem is that MachineBasicBlock::updateTerminator deletes branches and inserts new ones while LiveVariables keeps a list of pointers to instructions that kill virtual registers. That list wasn't properly updated in MBB::SplitCriticalEdge. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132298 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/MachineBasicBlock.cpp41
-rw-r--r--test/CodeGen/Mips/2011-05-26-BranchKillsVreg.ll43
2 files changed, 82 insertions, 2 deletions
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp
index 57f3e34d0c..68946a2c9d 100644
--- a/lib/CodeGen/MachineBasicBlock.cpp
+++ b/lib/CodeGen/MachineBasicBlock.cpp
@@ -485,6 +485,30 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
<< " -- BB#" << NMBB->getNumber()
<< " -- BB#" << Succ->getNumber() << '\n');
+ // On some targets like Mips, branches may kill virtual registers. Make sure
+ // that LiveVariables is properly updated after updateTerminator replaces the
+ // terminators.
+ LiveVariables *LV = P->getAnalysisIfAvailable<LiveVariables>();
+
+ // Collect a list of virtual registers killed by the terminators.
+ SmallVector<unsigned, 4> KilledRegs;
+ if (LV)
+ for (iterator I = getFirstTerminator(), E = end(); I != E; ++I) {
+ MachineInstr *MI = I;
+ for (MachineInstr::mop_iterator OI = MI->operands_begin(),
+ OE = MI->operands_end(); OI != OE; ++OI) {
+ if (!OI->isReg() || !OI->isUse() || !OI->isKill() || OI->isUndef())
+ continue;
+ unsigned Reg = OI->getReg();
+ if (TargetRegisterInfo::isVirtualRegister(Reg) &&
+ LV->getVarInfo(Reg).removeKill(MI)) {
+ KilledRegs.push_back(Reg);
+ DEBUG(dbgs() << "Removing terminator kill: " << *MI);
+ OI->setIsKill(false);
+ }
+ }
+ }
+
ReplaceUsesOfBlockWith(Succ, NMBB);
updateTerminator();
@@ -502,9 +526,22 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
if (i->getOperand(ni+1).getMBB() == this)
i->getOperand(ni+1).setMBB(NMBB);
- if (LiveVariables *LV =
- P->getAnalysisIfAvailable<LiveVariables>())
+ // Update LiveVariables.
+ if (LV) {
+ // Restore kills of virtual registers that were killed by the terminators.
+ while (!KilledRegs.empty()) {
+ unsigned Reg = KilledRegs.pop_back_val();
+ for (iterator I = end(), E = begin(); I != E;) {
+ if (!(--I)->addRegisterKilled(Reg, NULL, /* addIfNotFound= */ false))
+ continue;
+ LV->getVarInfo(Reg).Kills.push_back(I);
+ DEBUG(dbgs() << "Restored terminator kill: " << *I);
+ break;
+ }
+ }
+ // Update relevant live-through information.
LV->addNewBlock(NMBB, this, Succ);
+ }
if (MachineDominatorTree *MDT =
P->getAnalysisIfAvailable<MachineDominatorTree>()) {
diff --git a/test/CodeGen/Mips/2011-05-26-BranchKillsVreg.ll b/test/CodeGen/Mips/2011-05-26-BranchKillsVreg.ll
new file mode 100644
index 0000000000..1255949740
--- /dev/null
+++ b/test/CodeGen/Mips/2011-05-26-BranchKillsVreg.ll
@@ -0,0 +1,43 @@
+; RUN: llc < %s -verify-coalescing
+; PR10046
+;
+; PHI elimination splits the critical edge from %while.end415 to %if.end427.
+; This requires updating the BNE-J terminators to a BEQ. The BNE instruction
+; kills a virtual register, and LiveVariables must be updated with the new kill
+; instruction.
+
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32"
+target triple = "mips-ellcc-linux"
+
+define i32 @mergesort(i8* %base, i32 %nmemb, i32 %size, i32 (i8*, i8*)* nocapture %cmp) nounwind {
+entry:
+ br i1 undef, label %return, label %if.end13
+
+if.end13: ; preds = %entry
+ br label %while.body
+
+while.body: ; preds = %while.body, %if.end13
+ %list1.0482 = phi i8* [ %base, %if.end13 ], [ null, %while.body ]
+ br i1 undef, label %while.end415, label %while.body
+
+while.end415: ; preds = %while.body
+ br i1 undef, label %if.then419, label %if.end427
+
+if.then419: ; preds = %while.end415
+ %call425 = tail call i8* @memmove(i8* %list1.0482, i8* undef, i32 undef) nounwind
+ br label %if.end427
+
+if.end427: ; preds = %if.then419, %while.end415
+ %list2.1 = phi i8* [ undef, %if.then419 ], [ %list1.0482, %while.end415 ]
+ tail call void @free(i8* %list2.1)
+ unreachable
+
+return: ; preds = %entry
+ ret i32 -1
+}
+
+
+declare i8* @memmove(i8*, i8*, i32)
+
+declare void @free(i8*)
+