diff options
Diffstat (limited to 'llvm/lib/CodeGen/LiveRangeEdit.cpp')
-rw-r--r-- | llvm/lib/CodeGen/LiveRangeEdit.cpp | 108 |
1 files changed, 40 insertions, 68 deletions
diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp index 59bc82d..5b0365d 100644 --- a/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -68,41 +68,12 @@ Register LiveRangeEdit::createFrom(Register OldReg) { return VReg; } -void LiveRangeEdit::scanRemattable() { - for (VNInfo *VNI : getParent().valnos) { - if (VNI->isUnused()) - continue; - Register Original = VRM->getOriginal(getReg()); - LiveInterval &OrigLI = LIS.getInterval(Original); - VNInfo *OrigVNI = OrigLI.getVNInfoAt(VNI->def); - if (!OrigVNI) - continue; - MachineInstr *DefMI = LIS.getInstructionFromIndex(OrigVNI->def); - if (!DefMI) - continue; - if (TII.isReMaterializable(*DefMI)) - Remattable.insert(OrigVNI); - } - ScannedRemattable = true; -} - -bool LiveRangeEdit::anyRematerializable() { - if (!ScannedRemattable) - scanRemattable(); - return !Remattable.empty(); -} - -bool LiveRangeEdit::canRematerializeAt(Remat &RM, VNInfo *OrigVNI, - SlotIndex UseIdx) { - assert(ScannedRemattable && "Call anyRematerializable first"); +bool LiveRangeEdit::canRematerializeAt(Remat &RM, SlotIndex UseIdx) { + assert(RM.OrigMI && "No defining instruction for remattable value"); - // Use scanRemattable info. - if (!Remattable.count(OrigVNI)) + if (!TII.isReMaterializable(*RM.OrigMI)) return false; - // No defining instruction provided. - assert(RM.OrigMI && "No defining instruction for remattable value"); - // Verify that all used registers are available with the same values. if (!VirtRegAuxInfo::allUsesAvailableAt(RM.OrigMI, UseIdx, LIS, MRI, TII)) return false; @@ -303,6 +274,37 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { } } + // If the dest of MI is an original reg and MI is reMaterializable, + // don't delete the inst. Replace the dest with a new reg, and keep + // the inst for remat of other siblings. The inst is saved in + // LiveRangeEdit::DeadRemats and will be deleted after all the + // allocations of the func are done. Note that if we keep the + // instruction with the original operands, that handles the physreg + // operand case (described just below) as well. + // However, immediately delete instructions which have unshrunk virtual + // register uses. That may provoke RA to split an interval at the KILL + // and later result in an invalid live segment end. + if (isOrigDef && DeadRemats && !HasLiveVRegUses && + TII.isReMaterializable(*MI)) { + LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false); + VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator(); + VNInfo *VNI = NewLI.getNextValue(Idx, Alloc); + NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI)); + + if (DestSubReg) { + const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); + auto *SR = + NewLI.createSubRange(Alloc, TRI->getSubRegIndexLaneMask(DestSubReg)); + SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), + SR->getNextValue(Idx, Alloc))); + } + + pop_back(); + DeadRemats->insert(MI); + const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); + MI->substituteRegister(Dest, NewLI.reg(), 0, TRI); + assert(MI->registerDefIsDead(NewLI.reg(), &TRI)); + } // 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 @@ -310,7 +312,7 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { // 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) { + else if (ReadsPhysRegs) { MI->setDesc(TII.get(TargetOpcode::KILL)); // Remove all operands that aren't physregs. for (unsigned i = MI->getNumOperands(); i; --i) { @@ -322,41 +324,11 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { MI->dropMemRefs(*MI->getMF()); LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI); } else { - // If the dest of MI is an original reg and MI is reMaterializable, - // don't delete the inst. Replace the dest with a new reg, and keep - // the inst for remat of other siblings. The inst is saved in - // LiveRangeEdit::DeadRemats and will be deleted after all the - // allocations of the func are done. - // However, immediately delete instructions which have unshrunk virtual - // register uses. That may provoke RA to split an interval at the KILL - // and later result in an invalid live segment end. - if (isOrigDef && DeadRemats && !HasLiveVRegUses && - TII.isReMaterializable(*MI)) { - LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false); - VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator(); - VNInfo *VNI = NewLI.getNextValue(Idx, Alloc); - NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI)); - - if (DestSubReg) { - const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); - auto *SR = NewLI.createSubRange( - Alloc, TRI->getSubRegIndexLaneMask(DestSubReg)); - SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), - SR->getNextValue(Idx, Alloc))); - } - - pop_back(); - DeadRemats->insert(MI); - const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); - MI->substituteRegister(Dest, NewLI.reg(), 0, TRI); - assert(MI->registerDefIsDead(NewLI.reg(), &TRI)); - } else { - if (TheDelegate) - TheDelegate->LRE_WillEraseInstruction(MI); - LIS.RemoveMachineInstrFromMaps(*MI); - MI->eraseFromParent(); - ++NumDCEDeleted; - } + 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> |