EnableJoining("join-liveintervals",
cl::desc("Coallesce copies (default=true)"),
cl::init(true));
-
- static cl::opt<bool>
- EnableReMat("enable-rematerialization",
- cl::desc("Perform trivial re-materialization"),
- cl::init(false));
}
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
unsigned reg = rep(mop.getReg());
mii->getOperand(i).setReg(reg);
- // If the definition instruction is re-materializable, its spill
- // weight is zero.
LiveInterval &RegInt = getInterval(reg);
- if (!RegInt.remat) {
- RegInt.weight +=
- (mop.isUse() + mop.isDef()) * pow(10.0F, (int)loopDepth);
- }
+ float w = (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth);
+ // If the definition instruction is re-materializable, its spill
+ // weight is half of what it would have been normally unless it's
+ // a load from fixed stack slot.
+ int Dummy;
+ if (RegInt.remat && !tii_->isLoadFromStackSlot(RegInt.remat, Dummy))
+ w /= 2;
+ RegInt.weight += w;
}
}
++mii;
// done once for the vreg. We use an empty interval to detect the first
// time we see a vreg.
if (interval.empty()) {
- // Remember if the definition can be rematerialized.
- if (EnableReMat &&
- vi.DefInst && tii_->isReMaterializable(vi.DefInst->getOpcode()))
+ // Remember if the definition can be rematerialized. All load's from fixed
+ // stack slots are re-materializable.
+ int FrameIdx = 0;
+ if (vi.DefInst &&
+ (tii_->isReMaterializable(vi.DefInst->getOpcode()) ||
+ (tii_->isLoadFromStackSlot(vi.DefInst, FrameIdx) &&
+ mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))))
interval.remat = vi.DefInst;
// Get the Idx of the defining instructions.
}
} else {
- // Can't safely assume definition is rematierializable anymore.
+ // Can no longer safely assume definition is rematerializable.
interval.remat = NULL;
// If this is the second time we see a virtual register definition, it
// Check if it is necessary to propagate "isDead" property before intervals
// are joined.
+ MachineBasicBlock *CopyBB = CopyMI->getParent();
MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg);
bool isDead = mopd->isDead();
bool isShorten = false;
isShorten = true;
RemoveStart = getDefIndex(getInstructionIndex(LastUse));
RemoveEnd = SrcEnd;
- } else if (RemoveStart > 0)
- // A dead def should have a single cycle interval.
- ++RemoveStart;
+ } else {
+ MachineInstr *SrcMI = getInstructionFromIndex(SrcStart);
+ if (SrcMI) {
+ MachineOperand *mops = findDefOperand(SrcMI, repSrcReg);
+ if (mops)
+ // A dead def should have a single cycle interval.
+ ++RemoveStart;
+ }
+ }
}
}
LiveVariables::VarInfo& dvi = lv_->getVarInfo(repDstReg);
// Is the value used in the current BB or any immediate successroe BB?
- MachineBasicBlock *CopyBB = CopyMI->getParent();
if (dvi.UsedBlocks[CopyBB->getNumber()])
goto TryJoin;
for (MachineBasicBlock::succ_iterator SI = CopyBB->succ_begin(),
} else {
MachineInstr *SrcMI = getInstructionFromIndex(SrcStart);
if (SrcMI) {
- MachineOperand *mops = SrcMI->findRegisterDefOperand(SrcReg);
+ MachineOperand *mops = findDefOperand(SrcMI, repSrcReg);
if (mops)
- // FIXME: mops == NULL means SrcMI defines a subregister?
mops->setIsDead();
}
}
return NULL;
}
+
+/// findDefOperand - Returns the MachineOperand that is a def of the specific
+/// register. It returns NULL if the def is not found.
+MachineOperand *LiveIntervals::findDefOperand(MachineInstr *MI, unsigned Reg) {
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI->getOperand(i);
+ if (MO.isReg() && MO.isDef() &&
+ mri_->regsOverlap(rep(MO.getReg()), Reg))
+ return &MO;
+ }
+ return NULL;
+}
+
/// unsetRegisterKill - Unset IsKill property of all uses of specific register
/// of the specific instruction.
void LiveIntervals::unsetRegisterKill(MachineInstr *MI, unsigned Reg) {