//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "VirtRegMap.h"
#include "llvm/Value.h"
-#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
cl::init(false), cl::Hidden);
cl::opt<bool> SplitAtBB("split-intervals-at-bb",
- cl::init(false), cl::Hidden);
+ cl::init(true), cl::Hidden);
cl::opt<int> SplitLimit("split-limit",
cl::init(-1), cl::Hidden);
}
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addPreserved<LiveVariables>();
AU.addRequired<LiveVariables>();
+ AU.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
AU.addPreservedID(PHIEliminationID);
AU.addRequiredID(PHIEliminationID);
AU.addRequiredID(TwoAddressInstructionPassID);
/// isReMaterializable - Returns true if the definition MI of the specified
/// val# of the specified interval is re-materializable.
bool LiveIntervals::isReMaterializable(const LiveInterval &li,
- const VNInfo *ValNo, MachineInstr *MI) {
+ const VNInfo *ValNo, MachineInstr *MI,
+ bool &isLoad) {
if (DisableReMat)
return false;
- if (tii_->isTriviallyReMaterializable(MI))
+ isLoad = false;
+ const TargetInstrDesc &TID = MI->getDesc();
+ if (TID.isImplicitDef() || tii_->isTriviallyReMaterializable(MI)) {
+ isLoad = TID.isSimpleLoad();
return true;
+ }
int FrameIdx = 0;
if (!tii_->isLoadFromStackSlot(MI, FrameIdx) ||
// This is a load from fixed stack slot. It can be rematerialized unless it's
// re-defined by a two-address instruction.
+ isLoad = true;
for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
i != e; ++i) {
const VNInfo *VNI = *i;
continue; // Dead val#.
MachineInstr *DefMI = (DefIdx == ~0u)
? NULL : getInstructionFromIndex(DefIdx);
- if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg))
+ if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg)) {
+ isLoad = false;
+ return false;
+ }
+ }
+ return true;
+}
+
+/// isReMaterializable - Returns true if every definition of MI of every
+/// val# of the specified interval is re-materializable.
+bool LiveIntervals::isReMaterializable(const LiveInterval &li, bool &isLoad) {
+ isLoad = false;
+ for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
+ i != e; ++i) {
+ const VNInfo *VNI = *i;
+ unsigned DefIdx = VNI->def;
+ if (DefIdx == ~1U)
+ continue; // Dead val#.
+ // Is the def for the val# rematerializable?
+ if (DefIdx == ~0u)
+ return false;
+ MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx);
+ bool DefIsLoad = false;
+ if (!ReMatDefMI || !isReMaterializable(li, VNI, ReMatDefMI, DefIsLoad))
return false;
+ isLoad |= DefIsLoad;
}
return true;
}
SmallVector<unsigned, 2> &Ops,
bool isSS, int Slot, unsigned Reg) {
unsigned MRInfo = 0;
- const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
+ const TargetInstrDesc &TID = MI->getDesc();
+ // If it is an implicit def instruction, just delete it.
+ if (TID.isImplicitDef()) {
+ RemoveMachineInstrFromMaps(MI);
+ vrm.RemoveMachineInstrFromMaps(MI);
+ MI->eraseFromParent();
+ ++numFolds;
+ return true;
+ }
+
SmallVector<unsigned, 2> FoldOps;
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
unsigned OpIdx = Ops[i];
MRInfo |= (unsigned)VirtRegMap::isMod;
else {
// Filter out two-address use operand(s).
- if (TID->getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
+ if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
MRInfo = VirtRegMap::isModRef;
continue;
}
FoldOps.push_back(OpIdx);
}
- MachineInstr *fmi = isSS ? mri_->foldMemoryOperand(MI, FoldOps, Slot)
- : mri_->foldMemoryOperand(MI, FoldOps, DefMI);
+ MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(MI, FoldOps, Slot)
+ : tii_->foldMemoryOperand(MI, FoldOps, 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.
FoldOps.push_back(OpIdx);
}
- return mri_->canFoldMemoryOperand(MI, FoldOps);
+ return tii_->canFoldMemoryOperand(MI, FoldOps);
}
bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const {
MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI,
unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, SSARegMap *RegMap,
+ VirtRegMap &vrm, MachineRegisterInfo &RegInfo,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
unsigned &NewVReg, bool &HasDef, bool &HasUse,
- const LoopInfo *loopInfo,
+ const MachineLoopInfo *loopInfo,
std::map<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs) {
bool CanFold = false;
} else {
CanFold = canFoldMemoryOperand(MI, Ops);
}
- } else CanFold = false;
+ } else
+ CanFold = false;
// Create a new virtual register for the spill interval.
bool CreatedNewVReg = false;
if (NewVReg == 0) {
- NewVReg = RegMap->createVirtualRegister(rc);
+ NewVReg = RegInfo.createVirtualRegister(rc);
vrm.grow();
CreatedNewVReg = true;
}
MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI,
unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, SSARegMap *RegMap,
+ VirtRegMap &vrm, MachineRegisterInfo &RegInfo,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
- const LoopInfo *loopInfo,
+ const MachineLoopInfo *loopInfo,
BitVector &SpillMBBs,
std::map<unsigned, std::vector<SRInfo> > &SpillIdxes,
BitVector &RestoreMBBs,
bool CanFold = rewriteInstructionForSpills(li, TrySplit, I->valno->id,
index, end, MI, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- CanDelete, vrm, RegMap, rc, ReMatIds, NewVReg,
+ CanDelete, vrm, RegInfo, rc, ReMatIds, NewVReg,
HasDef, HasUse, loopInfo, MBBVRegsMap, NewLIs);
if (!HasDef && !HasUse)
continue;
}
// Update spill weight.
- unsigned loopDepth = loopInfo->getLoopDepth(MBB->getBasicBlock());
+ unsigned loopDepth = loopInfo->getLoopDepth(MBB);
nI.weight += getSpillWeight(HasDef, HasUse, loopDepth);
}
std::vector<LiveInterval*> LiveIntervals::
addIntervalsForSpills(const LiveInterval &li,
- const LoopInfo *loopInfo, VirtRegMap &vrm) {
+ const MachineLoopInfo *loopInfo, VirtRegMap &vrm) {
// Since this is called after the analysis is done we don't know if
// LiveVariables is available
lv_ = getAnalysisToUpdate<LiveVariables>();
std::map<unsigned, std::vector<SRInfo> > RestoreIdxes;
std::map<unsigned,unsigned> MBBVRegsMap;
std::vector<LiveInterval*> NewLIs;
- SSARegMap *RegMap = mf_->getSSARegMap();
- const TargetRegisterClass* rc = RegMap->getRegClass(li.reg);
+ MachineRegisterInfo &RegInfo = mf_->getRegInfo();
+ const TargetRegisterClass* rc = RegInfo.getRegClass(li.reg);
unsigned NumValNums = li.getNumValNums();
SmallVector<MachineInstr*, 4> ReMatDefs;
// it's also guaranteed to be a single val# / range interval.
if (vrm.getPreSplitReg(li.reg)) {
vrm.setIsSplitFromReg(li.reg, 0);
+ // Unset the split kill marker on the last use.
+ unsigned KillIdx = vrm.getKillPoint(li.reg);
+ if (KillIdx) {
+ MachineInstr *KillMI = getInstructionFromIndex(KillIdx);
+ assert(KillMI && "Last use disappeared?");
+ int KillOp = KillMI->findRegisterUseOperandIdx(li.reg, true);
+ assert(KillOp != -1 && "Last use disappeared?");
+ KillMI->getOperand(KillOp).setIsKill(false);
+ }
+ vrm.removeKillPoint(li.reg);
bool DefIsReMat = vrm.isReMaterialized(li.reg);
Slot = vrm.getStackSlot(li.reg);
assert(Slot != VirtRegMap::MAX_STACK_SLOT);
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
bool isLoad = isLoadSS ||
- (DefIsReMat && (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG));
+ (DefIsReMat && (ReMatDefMI->getDesc().isSimpleLoad()));
bool IsFirstRange = true;
for (LiveInterval::Ranges::const_iterator
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
// Note ReMatOrigDefMI has already been deleted.
rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- false, vrm, RegMap, rc, ReMatIds, loopInfo,
+ false, vrm, RegInfo, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
} else {
rewriteInstructionsForSpills(li, false, I, NULL, 0,
Slot, 0, false, false, false,
- false, vrm, RegMap, rc, ReMatIds, loopInfo,
+ false, vrm, RegInfo, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
// Is the def for the val# rematerializable?
MachineInstr *ReMatDefMI = (DefIdx == ~0u)
? 0 : getInstructionFromIndex(DefIdx);
- if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI)) {
+ bool dummy;
+ if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, dummy)) {
// Remember how to remat the def of this val#.
ReMatOrigDefs[VN] = ReMatDefMI;
// Original def may be modified so we have to make a copy here. vrm must
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
bool isLoad = isLoadSS ||
- (DefIsReMat && (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG));
+ (DefIsReMat && ReMatDefMI->getDesc().isSimpleLoad());
rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- CanDelete, vrm, RegMap, rc, ReMatIds, loopInfo,
+ CanDelete, vrm, RegInfo, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
int LdSlot = 0;
bool isLoadSS = tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
// If the rematerializable def is a load, also try to fold it.
- if (isLoadSS ||
- (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG))
+ if (isLoadSS || ReMatDefMI->getDesc().isSimpleLoad())
Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index,
Ops, isLoadSS, LdSlot, VReg);
}
LI->weight /= LI->getSize();
if (!AddedKill.count(LI)) {
LiveRange *LR = &LI->ranges[LI->ranges.size()-1];
- MachineInstr *LastUse = getInstructionFromIndex(getBaseIndex(LR->end));
+ unsigned LastUseIdx = getBaseIndex(LR->end);
+ MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx);
int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg);
assert(UseIdx != -1);
- if (LastUse->getInstrDescriptor()->
- getOperandConstraint(UseIdx, TOI::TIED_TO) == -1)
+ if (LastUse->getDesc().getOperandConstraint(UseIdx, TOI::TIED_TO) ==
+ -1) {
LastUse->getOperand(UseIdx).setIsKill();
+ vrm.addKillPoint(LI->reg, LastUseIdx);
+ }
}
RetNewLIs.push_back(LI);
}