summaryrefslogtreecommitdiff
path: root/lib/CodeGen/LiveRangeEdit.cpp
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2012-08-02 16:36:47 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2012-08-02 16:36:47 +0000
commite2b83ab056836067e2c86ef22223a4c29fe267ce (patch)
treef0b8958b61d67b64aa67ba60dad7fc30f64861a7 /lib/CodeGen/LiveRangeEdit.cpp
parent28897ca434892340f2e188a0331db92d5899409b (diff)
downloadllvm-e2b83ab056836067e2c86ef22223a4c29fe267ce.tar.gz
llvm-e2b83ab056836067e2c86ef22223a4c29fe267ce.tar.bz2
llvm-e2b83ab056836067e2c86ef22223a4c29fe267ce.tar.xz
Avoid creating dangling physreg live ranges during DCE.
LiveRangeEdit::eliminateDeadDefs() can delete a dead instruction that reads unreserved physregs. This would leave the corresponding regunit live interval dangling because we don't have shrinkToUses() for physical registers. Fix this problem by turning the instruction into a KILL instead of deleting it. This happens in a landing pad in test/CodeGen/X86/2012-05-19-CoalescerCrash.ll: %vreg27<def,dead> = COPY %EDX<kill>; GR32:%vreg27 becomes: KILL %EDX<kill> An upcoming fix to the machine verifier will catch problems like this by verifying regunit live intervals. This fixes PR13498. I am not including the test case from the PR since we already have one exposing the problem once the verifier is fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161182 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/LiveRangeEdit.cpp')
-rw-r--r--lib/CodeGen/LiveRangeEdit.cpp36
1 files changed, 30 insertions, 6 deletions
diff --git a/lib/CodeGen/LiveRangeEdit.cpp b/lib/CodeGen/LiveRangeEdit.cpp
index 896fdbfbe2..b4ce9aa8c1 100644
--- a/lib/CodeGen/LiveRangeEdit.cpp
+++ b/lib/CodeGen/LiveRangeEdit.cpp
@@ -239,6 +239,7 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
// Collect virtual registers to be erased after MI is gone.
SmallVector<unsigned, 8> RegsToErase;
+ bool ReadsPhysRegs = false;
// Check for live intervals that may shrink
for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
@@ -246,8 +247,12 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
if (!MOI->isReg())
continue;
unsigned Reg = MOI->getReg();
- if (!TargetRegisterInfo::isVirtualRegister(Reg))
+ if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
+ // Check if MI reads any unreserved physregs.
+ if (Reg && MOI->readsReg() && !LIS.isReserved(Reg))
+ ReadsPhysRegs = true;
continue;
+ }
LiveInterval &LI = LIS.getInterval(Reg);
// Shrink read registers, unless it is likely to be expensive and
@@ -271,11 +276,30 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
}
}
- if (TheDelegate)
- TheDelegate->LRE_WillEraseInstruction(MI);
- LIS.RemoveMachineInstrFromMaps(MI);
- MI->eraseFromParent();
- ++NumDCEDeleted;
+ // Currently, we don't support DCE of physreg live ranges. If MI reads
+ // any unreserved physregs, don't erase the instruction, but turn it into
+ // a KILL instead. This way, the physreg live ranges don't end up
+ // dangling.
+ // FIXME: It would be better to have something like shrinkToUses() for
+ // physregs. That could potentially enable more DCE and it would free up
+ // the physreg. It would not happen often, though.
+ if (ReadsPhysRegs) {
+ MI->setDesc(TII.get(TargetOpcode::KILL));
+ // Remove all operands that aren't physregs.
+ for (unsigned i = MI->getNumOperands(); i; --i) {
+ const MachineOperand &MO = MI->getOperand(i-1);
+ if (MO.isReg() && TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+ continue;
+ MI->RemoveOperand(i-1);
+ }
+ DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
+ } else {
+ if (TheDelegate)
+ TheDelegate->LRE_WillEraseInstruction(MI);
+ LIS.RemoveMachineInstrFromMaps(MI);
+ MI->eraseFromParent();
+ ++NumDCEDeleted;
+ }
// Erase any virtregs that are now empty and unused. There may be <undef>
// uses around. Keep the empty live range in that case.