diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index 57f3e34d0c5..68946a2c9d1 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(); + + // Collect a list of virtual registers killed by the terminators. + SmallVector 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()) + // 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()) { 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 00000000000..1255949740f --- /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*) +