| //===--- LiveRangeEdit.cpp - Basic tools for editing a register live range --===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // The LiveRangeEdit class represents changes done to a virtual register when it |
| // is spilled or split. |
| //===----------------------------------------------------------------------===// |
| |
| #include "LiveRangeEdit.h" |
| #include "VirtRegMap.h" |
| #include "llvm/CodeGen/LiveIntervalAnalysis.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/Target/TargetInstrInfo.h" |
| |
| using namespace llvm; |
| |
| LiveInterval &LiveRangeEdit::create(MachineRegisterInfo &mri, |
| LiveIntervals &lis, |
| VirtRegMap &vrm) { |
| const TargetRegisterClass *RC = mri.getRegClass(parent_.reg); |
| unsigned VReg = mri.createVirtualRegister(RC); |
| vrm.grow(); |
| LiveInterval &li = lis.getOrCreateInterval(VReg); |
| newRegs_.push_back(&li); |
| return li; |
| } |
| |
| void LiveRangeEdit::scanRemattable(LiveIntervals &lis, |
| const TargetInstrInfo &tii, |
| AliasAnalysis *aa) { |
| for (LiveInterval::vni_iterator I = parent_.vni_begin(), |
| E = parent_.vni_end(); I != E; ++I) { |
| VNInfo *VNI = *I; |
| if (VNI->isUnused()) |
| continue; |
| MachineInstr *DefMI = lis.getInstructionFromIndex(VNI->def); |
| if (!DefMI) |
| continue; |
| if (tii.isTriviallyReMaterializable(DefMI, aa)) |
| remattable_.insert(VNI); |
| } |
| scannedRemattable_ = true; |
| } |
| |
| bool LiveRangeEdit::anyRematerializable(LiveIntervals &lis, |
| const TargetInstrInfo &tii, |
| AliasAnalysis *aa) { |
| if (!scannedRemattable_) |
| scanRemattable(lis, tii, aa); |
| return !remattable_.empty(); |
| } |
| |
| /// allUsesAvailableAt - Return true if all registers used by OrigMI at |
| /// OrigIdx are also available with the same value at UseIdx. |
| bool LiveRangeEdit::allUsesAvailableAt(const MachineInstr *OrigMI, |
| SlotIndex OrigIdx, |
| SlotIndex UseIdx, |
| LiveIntervals &lis) { |
| OrigIdx = OrigIdx.getUseIndex(); |
| UseIdx = UseIdx.getUseIndex(); |
| for (unsigned i = 0, e = OrigMI->getNumOperands(); i != e; ++i) { |
| const MachineOperand &MO = OrigMI->getOperand(i); |
| if (!MO.isReg() || !MO.getReg() || MO.getReg() == getReg()) |
| continue; |
| // Reserved registers are OK. |
| if (MO.isUndef() || !lis.hasInterval(MO.getReg())) |
| continue; |
| // We don't want to move any defs. |
| if (MO.isDef()) |
| return false; |
| // We cannot depend on virtual registers in uselessRegs_. |
| for (unsigned ui = 0, ue = uselessRegs_.size(); ui != ue; ++ui) |
| if (uselessRegs_[ui]->reg == MO.getReg()) |
| return false; |
| |
| LiveInterval &li = lis.getInterval(MO.getReg()); |
| const VNInfo *OVNI = li.getVNInfoAt(OrigIdx); |
| if (!OVNI) |
| continue; |
| if (OVNI != li.getVNInfoAt(UseIdx)) |
| return false; |
| } |
| return true; |
| } |
| |
| bool LiveRangeEdit::canRematerializeAt(Remat &RM, |
| SlotIndex UseIdx, |
| bool cheapAsAMove, |
| LiveIntervals &lis) { |
| assert(scannedRemattable_ && "Call anyRematerializable first"); |
| |
| // Use scanRemattable info. |
| if (!remattable_.count(RM.ParentVNI)) |
| return false; |
| |
| // No defining instruction. |
| RM.OrigMI = lis.getInstructionFromIndex(RM.ParentVNI->def); |
| assert(RM.OrigMI && "Defining instruction for remattable value disappeared"); |
| |
| // If only cheap remats were requested, bail out early. |
| if (cheapAsAMove && !RM.OrigMI->getDesc().isAsCheapAsAMove()) |
| return false; |
| |
| // Verify that all used registers are available with the same values. |
| if (!allUsesAvailableAt(RM.OrigMI, RM.ParentVNI->def, UseIdx, lis)) |
| return false; |
| |
| return true; |
| } |
| |
| SlotIndex LiveRangeEdit::rematerializeAt(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, |
| unsigned DestReg, |
| const Remat &RM, |
| LiveIntervals &lis, |
| const TargetInstrInfo &tii, |
| const TargetRegisterInfo &tri) { |
| assert(RM.OrigMI && "Invalid remat"); |
| tii.reMaterialize(MBB, MI, DestReg, 0, RM.OrigMI, tri); |
| rematted_.insert(RM.ParentVNI); |
| return lis.InsertMachineInstrInMaps(--MI).getDefIndex(); |
| } |
| |