Factor live variable analysis so it does not do register coalescing

simultaneously.  Move that pass to SimpleRegisterCoalescing.

This makes it easier to implement alternative register allocation and
coalescing strategies while maintaining reuse of the existing live
interval analysis.

llvm-svn: 37520
This commit is contained in:
David Greene 2007-06-08 17:18:56 +00:00
parent a59fb10de8
commit 02f6e9b621
6 changed files with 1337 additions and 1169 deletions

View File

@ -54,31 +54,12 @@ namespace llvm {
typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; typedef std::map<unsigned, LiveInterval> Reg2IntervalMap;
Reg2IntervalMap r2iMap_; Reg2IntervalMap r2iMap_;
typedef IndexedMap<unsigned> Reg2RegMap;
Reg2RegMap r2rMap_;
BitVector allocatableRegs_; BitVector allocatableRegs_;
DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_;
/// JoinedLIs - Keep track which register intervals have been coalesced
/// with other intervals.
BitVector JoinedLIs;
public: public:
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {}
struct CopyRec {
MachineInstr *MI;
unsigned SrcReg, DstReg;
};
CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) {
CopyRec R;
R.MI = MI;
R.SrcReg = SrcReg;
R.DstReg = DstReg;
return R;
}
struct InstrSlots { struct InstrSlots {
enum { enum {
LOAD = 0, LOAD = 0,
@ -159,28 +140,30 @@ namespace llvm {
return i2miMap_[index]; return i2miMap_[index];
} }
std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, // Interval creation
VirtRegMap& vrm,
int slot); LiveInterval &getOrCreateInterval(unsigned reg) {
Reg2IntervalMap::iterator I = r2iMap_.find(reg);
if (I == r2iMap_.end())
I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg)));
return I->second;
}
/// CreateNewLiveInterval - Create a new live interval with the given live /// CreateNewLiveInterval - Create a new live interval with the given live
/// ranges. The new live interval will have an infinite spill weight. /// ranges. The new live interval will have an infinite spill weight.
LiveInterval &CreateNewLiveInterval(const LiveInterval *LI, LiveInterval &CreateNewLiveInterval(const LiveInterval *LI,
const std::vector<LiveRange> &LRs); const std::vector<LiveRange> &LRs);
virtual void getAnalysisUsage(AnalysisUsage &AU) const; std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i,
virtual void releaseMemory(); VirtRegMap& vrm,
int slot);
/// runOnMachineFunction - pass entry point // Interval removal
virtual bool runOnMachineFunction(MachineFunction&);
/// print - Implement the dump method. void removeInterval(unsigned Reg) {
virtual void print(std::ostream &O, const Module* = 0) const; r2iMap_.erase(Reg);
void print(std::ostream *O, const Module* M = 0) const {
if (O) print(*O, M);
} }
private:
/// isRemoved - returns true if the specified machine instr has been /// isRemoved - returns true if the specified machine instr has been
/// removed. /// removed.
bool isRemoved(MachineInstr* instr) const { bool isRemoved(MachineInstr* instr) const {
@ -199,40 +182,22 @@ namespace llvm {
} }
} }
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual void releaseMemory();
/// runOnMachineFunction - pass entry point
virtual bool runOnMachineFunction(MachineFunction&);
/// print - Implement the dump method.
virtual void print(std::ostream &O, const Module* = 0) const;
void print(std::ostream *O, const Module* M = 0) const {
if (O) print(*O, M);
}
private:
/// computeIntervals - Compute live intervals. /// computeIntervals - Compute live intervals.
void computeIntervals(); void computeIntervals();
/// joinIntervals - join compatible live intervals
void joinIntervals();
/// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting
/// copies that cannot yet be coallesced into the "TryAgain" list.
void CopyCoallesceInMBB(MachineBasicBlock *MBB,
std::vector<CopyRec> *TryAgain, bool PhysOnly = false);
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
/// which are the src/dst of the copy instruction CopyMI. This returns true
/// if the copy was successfully coallesced away, or if it is never possible
/// to coallesce these this copy, due to register constraints. It returns
/// false if it is not currently possible to coallesce this interval, but
/// it may be possible if other things get coallesced.
bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg,
bool PhysOnly = false);
/// JoinIntervals - Attempt to join these two intervals. On failure, this
/// returns false. Otherwise, if one of the intervals being joined is a
/// physreg, this method always canonicalizes DestInt to be it. The output
/// "SrcInt" will not have been modified, so we can use this information
/// below to update aliases.
bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS);
/// SimpleJoin - Attempt to join the specified interval into this one. The
/// caller of this method must guarantee that the RHS only contains a single
/// value number and that the RHS is not defined by a copy from this
/// interval. This returns false if the intervals are not joinable, or it
/// joins them and returns true.
bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
/// handleRegisterDef - update intervals for a register def /// handleRegisterDef - update intervals for a register def
/// (calls handlePhysicalRegisterDef and /// (calls handlePhysicalRegisterDef and
/// handleVirtualRegisterDef) /// handleVirtualRegisterDef)
@ -260,57 +225,8 @@ namespace llvm {
unsigned MIIdx, unsigned MIIdx,
LiveInterval &interval, bool isAlias = false); LiveInterval &interval, bool isAlias = false);
/// Return true if the two specified registers belong to different
/// register classes. The registers may be either phys or virt regs.
bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB,
MachineInstr *CopyMI);
/// lastRegisterUse - Returns the last use of the specific register between
/// cycles Start and End. It also returns the use operand by reference. It
/// returns NULL if there are no uses.
MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg,
MachineOperand *&MOU);
/// findDefOperand - Returns the MachineOperand that is a def of the specific
/// register. It returns NULL if the def is not found.
MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg);
/// unsetRegisterKill - Unset IsKill property of all uses of the specific
/// register of the specific instruction.
void unsetRegisterKill(MachineInstr *MI, unsigned Reg);
/// unsetRegisterKills - Unset IsKill property of all uses of specific register
/// between cycles Start and End.
void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg);
/// hasRegisterDef - True if the instruction defines the specific register.
///
bool hasRegisterDef(MachineInstr *MI, unsigned Reg);
static LiveInterval createInterval(unsigned Reg); static LiveInterval createInterval(unsigned Reg);
void removeInterval(unsigned Reg) {
r2iMap_.erase(Reg);
}
LiveInterval &getOrCreateInterval(unsigned reg) {
Reg2IntervalMap::iterator I = r2iMap_.find(reg);
if (I == r2iMap_.end())
I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg)));
return I->second;
}
/// rep - returns the representative of this register
unsigned rep(unsigned Reg) {
unsigned Rep = r2rMap_[Reg];
if (Rep)
return r2rMap_[Reg] = rep(Rep);
return Reg;
}
void printRegName(unsigned reg) const; void printRegName(unsigned reg) const;
}; };

View File

@ -44,6 +44,11 @@ namespace llvm {
/// ///
extern const PassInfo *PHIEliminationID; extern const PassInfo *PHIEliminationID;
/// SimpleRegisterCoalescing pass. Aggressively coalesces every register
/// copy it can.
///
extern const PassInfo *SimpleRegisterCoalescingID;
/// TwoAddressInstruction pass - This pass reduces two-address instructions to /// TwoAddressInstruction pass - This pass reduces two-address instructions to
/// use two operands. This destroys SSA information but it is desired by /// use two operands. This destroys SSA information but it is desired by
/// register allocators. /// register allocators.

View File

@ -0,0 +1,160 @@
//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===//
//
// 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 implements a simple register copy coalescing phase.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H
#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
namespace llvm {
class LiveVariables;
class MRegisterInfo;
class TargetInstrInfo;
class VirtRegMap;
class SimpleRegisterCoalescing : public MachineFunctionPass {
MachineFunction* mf_;
const TargetMachine* tm_;
const MRegisterInfo* mri_;
const TargetInstrInfo* tii_;
LiveIntervals *li_;
LiveVariables *lv_;
typedef IndexedMap<unsigned> Reg2RegMap;
Reg2RegMap r2rMap_;
BitVector allocatableRegs_;
DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_;
/// JoinedLIs - Keep track which register intervals have been coalesced
/// with other intervals.
BitVector JoinedLIs;
public:
static char ID; // Pass identifcation, replacement for typeid
SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {};
struct CopyRec {
MachineInstr *MI;
unsigned SrcReg, DstReg;
};
CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) {
CopyRec R;
R.MI = MI;
R.SrcReg = SrcReg;
R.DstReg = DstReg;
return R;
}
struct InstrSlots {
enum {
LOAD = 0,
USE = 1,
DEF = 2,
STORE = 3,
NUM = 4
};
};
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual void releaseMemory();
/// runOnMachineFunction - pass entry point
virtual bool runOnMachineFunction(MachineFunction&);
/// print - Implement the dump method.
virtual void print(std::ostream &O, const Module* = 0) const;
void print(std::ostream *O, const Module* M = 0) const {
if (O) print(*O, M);
}
private:
/// joinIntervals - join compatible live intervals
void joinIntervals();
/// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting
/// copies that cannot yet be coallesced into the "TryAgain" list.
void CopyCoallesceInMBB(MachineBasicBlock *MBB,
std::vector<CopyRec> *TryAgain, bool PhysOnly = false);
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
/// which are the src/dst of the copy instruction CopyMI. This returns true
/// if the copy was successfully coallesced away, or if it is never possible
/// to coallesce these this copy, due to register constraints. It returns
/// false if it is not currently possible to coallesce this interval, but
/// it may be possible if other things get coallesced.
bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg,
bool PhysOnly = false);
/// JoinIntervals - Attempt to join these two intervals. On failure, this
/// returns false. Otherwise, if one of the intervals being joined is a
/// physreg, this method always canonicalizes DestInt to be it. The output
/// "SrcInt" will not have been modified, so we can use this information
/// below to update aliases.
bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS);
/// SimpleJoin - Attempt to join the specified interval into this one. The
/// caller of this method must guarantee that the RHS only contains a single
/// value number and that the RHS is not defined by a copy from this
/// interval. This returns false if the intervals are not joinable, or it
/// joins them and returns true.
bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
/// Return true if the two specified registers belong to different
/// register classes. The registers may be either phys or virt regs.
bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB,
MachineInstr *CopyMI);
/// lastRegisterUse - Returns the last use of the specific register between
/// cycles Start and End. It also returns the use operand by reference. It
/// returns NULL if there are no uses.
MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg,
MachineOperand *&MOU);
/// findDefOperand - Returns the MachineOperand that is a def of the specific
/// register. It returns NULL if the def is not found.
MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg);
/// unsetRegisterKill - Unset IsKill property of all uses of the specific
/// register of the specific instruction.
void unsetRegisterKill(MachineInstr *MI, unsigned Reg);
/// unsetRegisterKills - Unset IsKill property of all uses of specific register
/// between cycles Start and End.
void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg);
/// hasRegisterDef - True if the instruction defines the specific register.
///
bool hasRegisterDef(MachineInstr *MI, unsigned Reg);
/// rep - returns the representative of this register
unsigned rep(unsigned Reg) {
unsigned Rep = r2rMap_[Reg];
if (Rep)
return r2rMap_[Reg] = rep(Rep);
return Reg;
}
void printRegName(unsigned reg) const;
};
} // End llvm namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@ -96,6 +96,7 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage &AU) const { virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveIntervals>(); AU.addRequired<LiveIntervals>();
AU.addRequiredID(SimpleRegisterCoalescingID);
MachineFunctionPass::getAnalysisUsage(AU); MachineFunctionPass::getAnalysisUsage(AU);
} }

File diff suppressed because it is too large Load Diff