//
// 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.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveInterval analysis pass. Given some numbering of
// each the machine instructions (in this implemention depth-first order) an
// interval [i, j) is said to be a live interval for register v if there is no
-// instruction with number j' > j such that v is live at j' abd there is no
+// instruction with number j' > j such that v is live at j' and there is no
// instruction with number i' < i such that v is live at i'. In this
// implementation intervals can have holes, i.e. an interval might look like
// [1,20), [50,65), [1000,1001).
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include <cmath>
+#include <map>
namespace llvm {
class LiveVariables;
- class MRegisterInfo;
- class SSARegMap;
+ class MachineLoopInfo;
+ class TargetRegisterInfo;
+ class MachineRegisterInfo;
class TargetInstrInfo;
class TargetRegisterClass;
class VirtRegMap;
typedef std::pair<unsigned, MachineBasicBlock*> IdxMBBPair;
+ inline bool operator<(unsigned V, const IdxMBBPair &IM) {
+ return V < IM.first;
+ }
+
+ inline bool operator<(const IdxMBBPair &IM, unsigned V) {
+ return IM.first < V;
+ }
+
+ struct Idx2MBBCompare {
+ bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const {
+ return LHS.first < RHS.first;
+ }
+ };
+
class LiveIntervals : public MachineFunctionPass {
MachineFunction* mf_;
+ MachineRegisterInfo* mri_;
const TargetMachine* tm_;
- const MRegisterInfo* mri_;
+ const TargetRegisterInfo* tri_;
const TargetInstrInfo* tii_;
LiveVariables* lv_;
return getBaseIndex(index) + InstrSlots::STORE;
}
- static float getSpillWeight(const MachineOperand &mop, unsigned loopDepth) {
- return (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth);
+ static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) {
+ return (isDef + isUse) * powf(10.0F, (float)loopDepth);
}
typedef Reg2IntervalMap::iterator iterator;
return MBB2IdxMap[MBBNo].second;
}
+ /// getMBBFromIndex - given an index in any instruction of an
+ /// MBB return a pointer the MBB
+ MachineBasicBlock* getMBBFromIndex(unsigned index) const {
+ std::vector<IdxMBBPair>::const_iterator I =
+ std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), index);
+ // Take the pair containing the index
+ std::vector<IdxMBBPair>::const_iterator J =
+ ((I != Idx2MBBMap.end() && I->first > index) ||
+ (I == Idx2MBBMap.end() && Idx2MBBMap.size()>0)) ? (I-1): I;
+
+ assert(J != Idx2MBBMap.end() && J->first < index+1 &&
+ index <= getMBBEndIdx(J->second) &&
+ "index does not correspond to an MBB");
+ return J->second;
+ }
+
/// getInstructionIndex - returns the base index of instr
unsigned getInstructionIndex(MachineInstr* instr) const {
Mi2IndexMap::const_iterator it = mi2iMap_.find(instr);
}
}
+ /// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in
+ /// maps used by register allocator.
+ void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) {
+ Mi2IndexMap::iterator mi2i = mi2iMap_.find(MI);
+ if (mi2i == mi2iMap_.end())
+ return;
+ i2miMap_[mi2i->second/InstrSlots::NUM] = NewMI;
+ Mi2IndexMap::iterator it = mi2iMap_.find(MI);
+ assert(it != mi2iMap_.end() && "Invalid instruction!");
+ unsigned Index = it->second;
+ mi2iMap_.erase(it);
+ mi2iMap_[NewMI] = Index;
+ }
+
BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; }
+ /// getVNInfoSourceReg - Helper function that parses the specified VNInfo
+ /// copy field and returns the source register that defines it.
+ unsigned getVNInfoSourceReg(const VNInfo *VNI) const;
+
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual void releaseMemory();
/// addIntervalsForSpills - Create new intervals for spilled defs / uses of
/// the given interval.
std::vector<LiveInterval*>
- addIntervalsForSpills(const LiveInterval& i, VirtRegMap& vrm);
+ addIntervalsForSpills(const LiveInterval& i,
+ const MachineLoopInfo *loopInfo, VirtRegMap& vrm);
+
+ /// spillPhysRegAroundRegDefsUses - Spill the specified physical register
+ /// around all defs and uses of the specified interval.
+ void spillPhysRegAroundRegDefsUses(const LiveInterval &li,
+ unsigned PhysReg, VirtRegMap &vrm);
+
+ /// isReMaterializable - Returns true if every definition of MI of every
+ /// val# of the specified interval is re-materializable. Also returns true
+ /// by reference if all of the defs are load instructions.
+ bool isReMaterializable(const LiveInterval &li, bool &isLoad);
+
+ /// getRepresentativeReg - Find the largest super register of the specified
+ /// physical register.
+ unsigned getRepresentativeReg(unsigned Reg) const;
+
+ /// getNumConflictsWithPhysReg - Return the number of uses and defs of the
+ /// specified interval that conflicts with the specified physical register.
+ unsigned getNumConflictsWithPhysReg(const LiveInterval &li,
+ unsigned PhysReg) const;
private:
/// computeIntervals - Compute live intervals.
MachineBasicBlock::iterator mi,
unsigned MIIdx,
LiveInterval &interval,
- unsigned SrcReg);
+ MachineInstr *CopyMI);
/// handleLiveInRegister - Create interval for a livein register.
void handleLiveInRegister(MachineBasicBlock* mbb,
unsigned MIIdx,
LiveInterval &interval, bool isAlias = false);
+ /// getReMatImplicitUse - If the remat definition MI has one (for now, we
+ /// only allow one) virtual register operand, then its uses are implicitly
+ /// using the register. Returns the virtual register.
+ unsigned getReMatImplicitUse(const LiveInterval &li,
+ MachineInstr *MI) const;
+
+ /// isValNoAvailableAt - Return true if the val# of the specified interval
+ /// which reaches the given instruction also reaches the specified use
+ /// index.
+ bool isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI,
+ unsigned UseIdx) const;
+
/// isReMaterializable - Returns true if the definition MI of the specified
- /// val# of the specified interval is re-materializable.
+ /// val# of the specified interval is re-materializable. Also returns true
+ /// by reference if the def is a load.
bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo,
- MachineInstr *MI);
+ MachineInstr *MI, bool &isLoad);
/// tryFoldMemoryOperand - Attempts to fold either a spill / restore from
/// slot / to reg or any rematerialized load into ith operand of specified
/// MI. If it is successul, MI is updated with the newly created MI and
/// returns true.
bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm,
- MachineInstr *DefMI, unsigned index, unsigned i,
- bool isSS, int slot, unsigned reg);
+ MachineInstr *DefMI, unsigned InstrIdx,
+ SmallVector<unsigned, 2> &Ops,
+ bool isSS, int Slot, unsigned Reg);
+
+ /// canFoldMemoryOperand - Return true if the specified load / store
+ /// folding is possible.
+ bool canFoldMemoryOperand(MachineInstr *MI,
+ SmallVector<unsigned, 2> &Ops,
+ bool ReMatLoadSS) const;
+
+ /// anyKillInMBBAfterIdx - Returns true if there is a kill of the specified
+ /// VNInfo that's after the specified index but is within the basic block.
+ bool anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI,
+ MachineBasicBlock *MBB, unsigned Idx) const;
+
+ /// intervalIsInOneMBB - Returns true if the specified interval is entirely
+ /// within a single basic block.
+ bool intervalIsInOneMBB(const LiveInterval &li) const;
+
+ /// hasAllocatableSuperReg - Return true if the specified physical register
+ /// has any super register that's allocatable.
+ bool hasAllocatableSuperReg(unsigned Reg) const;
+
+ /// SRInfo - Spill / restore info.
+ struct SRInfo {
+ int index;
+ unsigned vreg;
+ bool canFold;
+ SRInfo(int i, unsigned vr, bool f) : index(i), vreg(vr), canFold(f) {};
+ };
- /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions
- /// for addIntervalsForSpills to rewrite uses / defs for the given live range.
- void rewriteInstructionForSpills(const LiveInterval &li,
- unsigned id, unsigned index, unsigned end, MachineInstr *MI,
+ bool alsoFoldARestore(int Id, int index, unsigned vr,
+ BitVector &RestoreMBBs,
+ std::map<unsigned,std::vector<SRInfo> >&RestoreIdxes);
+ void eraseRestoreInfo(int Id, int index, unsigned vr,
+ BitVector &RestoreMBBs,
+ std::map<unsigned,std::vector<SRInfo> >&RestoreIdxes);
+
+ /// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of
+ /// interval on to-be re-materialized operands of MI) with new register.
+ void rewriteImplicitOps(const LiveInterval &li,
+ MachineInstr *MI, unsigned NewVReg, VirtRegMap &vrm);
+
+ /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper
+ /// functions for addIntervalsForSpills to rewrite uses / defs for the given
+ /// live range.
+ bool rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
+ bool TrySplit, unsigned index, unsigned end, MachineInstr *MI,
MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, SSARegMap *RegMap, const TargetRegisterClass* rc,
- SmallVector<int, 4> &ReMatIds,
+ VirtRegMap &vrm, const TargetRegisterClass* rc,
+ SmallVector<int, 4> &ReMatIds, const MachineLoopInfo *loopInfo,
+ unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse,
+ std::map<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs);
- void rewriteInstructionsForSpills(const LiveInterval &li,
+ void rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
LiveInterval::Ranges::const_iterator &I,
MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, SSARegMap *RegMap, const TargetRegisterClass* rc,
- SmallVector<int, 4> &ReMatIds,
+ VirtRegMap &vrm, const TargetRegisterClass* rc,
+ SmallVector<int, 4> &ReMatIds, const MachineLoopInfo *loopInfo,
+ BitVector &SpillMBBs,
+ std::map<unsigned,std::vector<SRInfo> > &SpillIdxes,
+ BitVector &RestoreMBBs,
+ std::map<unsigned,std::vector<SRInfo> > &RestoreIdxes,
+ std::map<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs);
static LiveInterval createInterval(unsigned Reg);