aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/LiveIntervalAnalysis.cpp
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-11-30 21:23:43 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-11-30 21:23:43 +0000
commitcddbb83ea82e98658d9f530c50a7b9d23249afc2 (patch)
tree4a95387e7cb0e065698be99469963612be86a669 /lib/CodeGen/LiveIntervalAnalysis.cpp
parentcd883f203d23c7e44b12dff62df2e6d65d8f231c (diff)
Do not fold reload into an instruction with multiple uses. It issues one extra load.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44467 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/LiveIntervalAnalysis.cpp')
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp161
1 files changed, 86 insertions, 75 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 7d627bb6b2..f902f4be96 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -642,13 +642,22 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
/// MI. If it is successul, MI is updated with the newly created MI and
/// returns true.
bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI,
- VirtRegMap &vrm,
- MachineInstr *DefMI,
- unsigned index, unsigned i,
- bool isSS, int slot, unsigned reg) {
+ VirtRegMap &vrm, MachineInstr *DefMI,
+ unsigned InstrIdx, unsigned OpIdx,
+ unsigned NumUses,
+ bool isSS, int Slot, unsigned Reg) {
+ // FIXME: fold subreg use
+ if (MI->getOperand(OpIdx).getSubReg())
+ return false;
+
+ // FIXME: It may be possible to fold load when there are multiple uses.
+ // e.g. On x86, TEST32rr r, r -> CMP32rm [mem], 0
+ if (NumUses > 1)
+ return false;
+
MachineInstr *fmi = isSS
- ? mri_->foldMemoryOperand(MI, i, slot)
- : mri_->foldMemoryOperand(MI, i, DefMI);
+ ? mri_->foldMemoryOperand(MI, OpIdx, Slot)
+ : mri_->foldMemoryOperand(MI, OpIdx, DefMI);
if (fmi) {
// Attempt to fold the memory reference into the instruction. If
// we can do this, we don't need to insert spill code.
@@ -657,15 +666,13 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI,
else
LiveVariables::transferKillDeadInfo(MI, fmi, mri_);
MachineBasicBlock &MBB = *MI->getParent();
- if (isSS) {
- if (!mf_->getFrameInfo()->isFixedObjectIndex(slot))
- vrm.virtFolded(reg, MI, i, fmi);
- }
+ if (isSS && !mf_->getFrameInfo()->isFixedObjectIndex(Slot))
+ vrm.virtFolded(Reg, MI, OpIdx, fmi);
vrm.transferSpillPts(MI, fmi);
vrm.transferRestorePts(MI, fmi);
mi2iMap_.erase(MI);
- i2miMap_[index/InstrSlots::NUM] = fmi;
- mi2iMap_[fmi] = index;
+ i2miMap_[InstrIdx /InstrSlots::NUM] = fmi;
+ mi2iMap_[fmi] = InstrIdx;
MI = MBB.insert(MBB.erase(MI), fmi);
++numFolds;
return true;
@@ -714,8 +721,6 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
unsigned RegI = Reg;
if (Reg == 0 || MRegisterInfo::isPhysicalRegister(Reg))
continue;
- unsigned SubIdx = mop.getSubReg();
- bool isSubReg = SubIdx != 0;
if (Reg != li.reg)
continue;
@@ -726,6 +731,8 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
// If this is the rematerializable definition MI itself and
// all of its uses are rematerialized, simply delete it.
if (MI == ReMatOrigDefMI && CanDelete) {
+ DOUT << "\t\t\t\tErasing re-materlizable def: ";
+ DOUT << MI << '\n';
RemoveMachineInstrFromMaps(MI);
vrm.RemoveMachineInstrFromMaps(MI);
MI->eraseFromParent();
@@ -747,23 +754,6 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
if (TryFold)
TryFold = !TrySplit && NewVReg == 0;
- // FIXME: fold subreg use
- if (!isSubReg && TryFold &&
- tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, i, FoldSS, FoldSlot,
- Reg))
- // Folding the load/store can completely change the instruction in
- // unpredictable ways, rescan it from the beginning.
- goto RestartInstruction;
-
- // Create a new virtual register for the spill interval.
- bool CreatedNewVReg = false;
- if (NewVReg == 0) {
- NewVReg = RegMap->createVirtualRegister(rc);
- vrm.grow();
- CreatedNewVReg = true;
- }
- mop.setReg(NewVReg);
-
// Scan all of the operands of this instruction rewriting operands
// to use NewVReg instead of li.reg as appropriate. We do this for
// two reasons:
@@ -775,9 +765,11 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
//
// Keep track of whether we replace a use and/or def so that we can
// create the spill interval with the appropriate range.
-
+
HasUse = mop.isUse();
HasDef = mop.isDef();
+ unsigned NumUses = HasUse;
+ std::vector<unsigned> UpdateOps;
for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
if (!MI->getOperand(j).isRegister())
continue;
@@ -785,12 +777,37 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
if (RegJ == 0 || MRegisterInfo::isPhysicalRegister(RegJ))
continue;
if (RegJ == RegI) {
- MI->getOperand(j).setReg(NewVReg);
+ UpdateOps.push_back(j);
+ if (MI->getOperand(j).isUse())
+ ++NumUses;
HasUse |= MI->getOperand(j).isUse();
HasDef |= MI->getOperand(j).isDef();
}
}
+ if (TryFold &&
+ tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, i,
+ NumUses, FoldSS, FoldSlot, Reg)) {
+ // Folding the load/store can completely change the instruction in
+ // unpredictable ways, rescan it from the beginning.
+ HasUse = false;
+ HasDef = false;
+ goto RestartInstruction;
+ }
+
+ // Create a new virtual register for the spill interval.
+ bool CreatedNewVReg = false;
+ if (NewVReg == 0) {
+ NewVReg = RegMap->createVirtualRegister(rc);
+ vrm.grow();
+ CreatedNewVReg = true;
+ }
+ mop.setReg(NewVReg);
+
+ // Reuse NewVReg for other reads.
+ for (unsigned j = 0, e = UpdateOps.size(); j != e; ++j)
+ MI->getOperand(UpdateOps[j]).setReg(NewVReg);
+
if (CreatedNewVReg) {
if (DefIsReMat) {
vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI/*, CanDelete*/);
@@ -1197,46 +1214,44 @@ addIntervalsForSpills(const LiveInterval &li,
for (unsigned i = 0, e = spills.size(); i != e; ++i) {
int index = spills[i].index;
unsigned VReg = spills[i].vreg;
- bool DoFold = spills[i].canFold;
bool isReMat = vrm.isReMaterialized(VReg);
MachineInstr *MI = getInstructionFromIndex(index);
int OpIdx = -1;
- bool FoldedLoad = false;
- if (DoFold) {
+ unsigned NumUses = 0;
+ if (spills[i].canFold) {
for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) {
MachineOperand &MO = MI->getOperand(j);
if (!MO.isRegister() || MO.getReg() != VReg)
continue;
- if (MO.isUse()) {
- // Can't fold if it's two-address code and the use isn't the
- // first and only use.
- // If there are more than one uses, a load is still needed.
- if (!isReMat && !FoldedLoad &&
- alsoFoldARestore(Id, index,VReg,RestoreMBBs,RestoreIdxes)) {
- FoldedLoad = true;
- continue;
- } else {
- OpIdx = -1;
- break;
- }
+ if (MO.isDef()) {
+ OpIdx = (int)j;
+ continue;
}
- OpIdx = (int)j;
+ // Can't fold if it's two-address code and the use isn't the
+ // first and only use.
+ if (isReMat ||
+ (NumUses == 0 && !alsoFoldARestore(Id, index, VReg, RestoreMBBs,
+ RestoreIdxes))) {
+ OpIdx = -1;
+ break;
+ }
+ ++NumUses;
}
}
// Fold the store into the def if possible.
- if (OpIdx == -1)
- DoFold = false;
- if (DoFold) {
- if (tryFoldMemoryOperand(MI, vrm, NULL, index,OpIdx,true,Slot,VReg)) {
- if (FoldedLoad)
+ bool Folded = false;
+ if (OpIdx != -1) {
+ if (tryFoldMemoryOperand(MI, vrm, NULL, index, OpIdx, NumUses,
+ true, Slot, VReg)) {
+ if (NumUses)
// Folded a two-address instruction, do not issue a load.
eraseRestoreInfo(Id, index, VReg, RestoreMBBs, RestoreIdxes);
- } else
- DoFold = false;
+ Folded = true;
+ }
}
// Else tell the spiller to issue a store for us.
- if (!DoFold)
+ if (!Folded)
vrm.addSpillPoint(VReg, MI);
}
Id = SpillMBBs.find_next(Id);
@@ -1251,32 +1266,30 @@ addIntervalsForSpills(const LiveInterval &li,
if (index == -1)
continue;
unsigned VReg = restores[i].vreg;
- bool DoFold = restores[i].canFold;
MachineInstr *MI = getInstructionFromIndex(index);
+ unsigned NumUses = 0;
int OpIdx = -1;
- if (DoFold) {
+ if (restores[i].canFold) {
for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) {
MachineOperand &MO = MI->getOperand(j);
if (!MO.isRegister() || MO.getReg() != VReg)
continue;
if (MO.isDef()) {
- // Can't fold if it's two-address code.
+ // Can't fold if it's two-address code and it hasn't already
+ // been folded.
OpIdx = -1;
break;
}
- if (OpIdx != -1) {
- // Multiple uses, do not fold!
- OpIdx = -1;
- break;
- }
- OpIdx = (int)j;
+ if (NumUses == 0)
+ // Use the first use index.
+ OpIdx = (int)j;
+ ++NumUses;
}
}
// Fold the load into the use if possible.
- if (OpIdx == -1)
- DoFold = false;
- if (DoFold) {
+ bool Folded = false;
+ if (OpIdx != -1) {
if (vrm.isReMaterialized(VReg)) {
MachineInstr *ReMatDefMI = vrm.getReMaterializedMI(VReg);
int LdSlot = 0;
@@ -1284,17 +1297,15 @@ addIntervalsForSpills(const LiveInterval &li,
// If the rematerializable def is a load, also try to fold it.
if (isLoadSS ||
(ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG))
- DoFold = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, OpIdx,
- isLoadSS, LdSlot, VReg);
- else
- DoFold = false;
+ Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, OpIdx,
+ NumUses, isLoadSS, LdSlot, VReg);
} else
- DoFold = tryFoldMemoryOperand(MI, vrm, NULL, index, OpIdx,
+ Folded = tryFoldMemoryOperand(MI, vrm, NULL, index, OpIdx, NumUses,
true, Slot, VReg);
}
// If folding is not possible / failed, then tell the spiller to issue a
// load / rematerialization for us.
- if (!DoFold)
+ if (!Folded)
vrm.addRestorePoint(VReg, MI);
}
Id = RestoreMBBs.find_next(Id);