Move lib/Codegen/RegAlloc into lib/Target/Sparc, as it is sparc specific

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10728 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-01-09 06:17:12 +00:00
parent f7703df496
commit 75e260990d
17 changed files with 3 additions and 3355 deletions

View File

@ -7,7 +7,7 @@
#
##===----------------------------------------------------------------------===##
LEVEL = ../..
PARALLEL_DIRS = InstrSelection InstrSched RegAlloc SelectionDAG
PARALLEL_DIRS = InstrSelection InstrSched SelectionDAG
LIBRARYNAME = codegen
include $(LEVEL)/Makefile.common

View File

@ -1,84 +0,0 @@
//===-- AllocInfo.h - Store info about regalloc decisions -------*- 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 header file contains the data structure used to save the state
// of the global, graph-coloring register allocator.
//
//===----------------------------------------------------------------------===//
#ifndef ALLOCINFO_H
#define ALLOCINFO_H
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
namespace llvm {
/// AllocInfo - Structure representing one instruction's operand's-worth of
/// register allocation state. We create tables made out of these data
/// structures to generate mapping information for this register allocator.
///
struct AllocInfo {
unsigned Instruction;
int Operand; // (-1 if Instruction, or 0...n-1 for an operand.)
enum AllocStateTy { NotAllocated = 0, Allocated, Spilled };
AllocStateTy AllocState;
int Placement;
AllocInfo (unsigned Instruction_, unsigned Operand_,
AllocStateTy AllocState_, int Placement_) :
Instruction (Instruction_), Operand (Operand_),
AllocState (AllocState_), Placement (Placement_) { }
/// getConstantType - Return a StructType representing an AllocInfo object.
///
static StructType *getConstantType () {
std::vector<const Type *> TV;
TV.push_back (Type::UIntTy);
TV.push_back (Type::IntTy);
TV.push_back (Type::UIntTy);
TV.push_back (Type::IntTy);
return StructType::get (TV);
}
/// toConstant - Convert this AllocInfo into an LLVM Constant of type
/// getConstantType(), and return the Constant.
///
Constant *toConstant () const {
StructType *ST = getConstantType ();
std::vector<Constant *> CV;
CV.push_back (ConstantUInt::get (Type::UIntTy, Instruction));
CV.push_back (ConstantSInt::get (Type::IntTy, Operand));
CV.push_back (ConstantUInt::get (Type::UIntTy, AllocState));
CV.push_back (ConstantSInt::get (Type::IntTy, Placement));
return ConstantStruct::get (ST, CV);
}
/// AllocInfos compare equal if the allocation placements are equal
/// (i.e., they can be equal even if they refer to operands from two
/// different instructions.)
///
bool operator== (const AllocInfo &X) const {
return (X.AllocState == AllocState) && (X.Placement == Placement);
}
bool operator!= (const AllocInfo &X) const { return !(*this == X); }
/// Returns a human-readable string representation of the AllocState member.
///
const std::string allocStateToString () const {
static const char *AllocStateNames[] =
{ "NotAllocated", "Allocated", "Spilled" };
return std::string (AllocStateNames[AllocState]);
}
};
} // End llvm namespace
#endif // ALLOCINFO_H

View File

@ -1,62 +0,0 @@
//===-- IGNode.cpp --------------------------------------------------------===//
//
// 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 an Interference graph node for coloring-based register
// allocation.
//
//===----------------------------------------------------------------------===//
#include "IGNode.h"
#include <algorithm>
#include <iostream>
namespace llvm {
//-----------------------------------------------------------------------------
// Sets this IGNode on stack and reduce the degree of neighbors
//-----------------------------------------------------------------------------
void IGNode::pushOnStack() {
OnStack = true;
int neighs = AdjList.size();
if (neighs < 0) {
std::cerr << "\nAdj List size = " << neighs;
assert(0 && "Invalid adj list size");
}
for (int i=0; i < neighs; i++)
AdjList[i]->decCurDegree();
}
//-----------------------------------------------------------------------------
// Deletes an adjacency node. IGNodes are deleted when coalescing merges
// two IGNodes together.
//-----------------------------------------------------------------------------
void IGNode::delAdjIGNode(const IGNode *Node) {
std::vector<IGNode *>::iterator It=find(AdjList.begin(), AdjList.end(), Node);
assert(It != AdjList.end() && "The node must be there!");
AdjList.erase(It);
}
//-----------------------------------------------------------------------------
// Get the number of unique neighbors if these two nodes are merged
//-----------------------------------------------------------------------------
unsigned
IGNode::getCombinedDegree(const IGNode* otherNode) const {
std::vector<IGNode*> nbrs(AdjList);
nbrs.insert(nbrs.end(), otherNode->AdjList.begin(), otherNode->AdjList.end());
sort(nbrs.begin(), nbrs.end());
std::vector<IGNode*>::iterator new_end = unique(nbrs.begin(), nbrs.end());
return new_end - nbrs.begin();
}
} // End llvm namespace

View File

@ -1,123 +0,0 @@
//===-- IGNode.h - Represent a node in an interference graph ----*- 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 represents a node in an interference graph.
//
// For efficiency, the AdjList is updated only once - ie. we can add but not
// remove nodes from AdjList.
//
// The removal of nodes from IG is simulated by decrementing the CurDegree.
// If this node is put on stack (that is removed from IG), the CurDegree of all
// the neighbors are decremented and this node is marked OnStack. Hence
// the effective neighbors in the AdjList are the ones that do not have the
// OnStack flag set (therefore, they are in the IG).
//
// The methods that modify/use the CurDegree must be called only
// after all modifications to the IG are over (i.e., all neighbors are fixed).
//
// The vector representation is the most efficient one for adj list.
// Though nodes are removed when coalescing is done, we access it in sequence
// for far many times when coloring (colorNode()).
//
//===----------------------------------------------------------------------===//
#ifndef IGNODE_H
#define IGNODE_H
#include "LiveRange.h"
#include <vector>
namespace llvm {
class RegClass;
//----------------------------------------------------------------------------
// Class IGNode
//
// Represents a node in an interference graph.
//----------------------------------------------------------------------------
class IGNode {
const unsigned Index; // index within IGNodeList
bool OnStack; // this has been pushed on to stack for coloring
std::vector<IGNode *> AdjList;// adjacency list for this live range
int CurDegree;
//
// set by InterferenceGraph::setCurDegreeOfIGNodes() after calculating
// all adjacency lists.
// Decremented when a neighbor is pushed on to the stack.
// After that, never incremented/set again nor used.
LiveRange *const ParentLR;
public:
IGNode(LiveRange *LR, unsigned index) : Index(index), ParentLR(LR) {
OnStack = false;
CurDegree = -1;
ParentLR->setUserIGNode(this);
}
inline unsigned int getIndex() const { return Index; }
// adjLists must be updated only once. However, the CurDegree can be changed
//
inline void addAdjIGNode(IGNode *AdjNode) { AdjList.push_back(AdjNode); }
inline IGNode *getAdjIGNode(unsigned ind) const
{ assert ( ind < AdjList.size()); return AdjList[ind]; }
// delete a node in AdjList - node must be in the list
// should not be called often
//
void delAdjIGNode(const IGNode *Node);
inline unsigned getNumOfNeighbors() const { return AdjList.size(); }
// Get the number of unique neighbors if these two nodes are merged
unsigned getCombinedDegree(const IGNode* otherNode) const;
inline bool isOnStack() const { return OnStack; }
// remove form IG and pushes on to stack (reduce the degree of neighbors)
//
void pushOnStack();
// CurDegree is the effective number of neighbors when neighbors are
// pushed on to the stack during the coloring phase. Must be called
// after all modifications to the IG are over (i.e., all neighbors are
// fixed).
//
inline void setCurDegree() {
assert(CurDegree == -1);
CurDegree = AdjList.size();
}
inline int getCurDegree() const { return CurDegree; }
// called when a neigh is pushed on to stack
//
inline void decCurDegree() { assert(CurDegree > 0); --CurDegree; }
// The following methods call the methods in ParentLR
// They are added to this class for convenience
// If many of these are called within a single scope,
// consider calling the methods directly on LR
inline bool hasColor() const { return ParentLR->hasColor(); }
inline unsigned int getColor() const { return ParentLR->getColor(); }
inline void setColor(unsigned Col) { ParentLR->setColor(Col); }
inline LiveRange *getParentLR() const { return ParentLR; }
};
} // End llvm namespace
#endif

View File

@ -1,252 +0,0 @@
//===-- InterferenceGraph.cpp ---------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Interference graph for coloring-based register allocation for LLVM.
//
//===----------------------------------------------------------------------===//
#include "IGNode.h"
#include "InterferenceGraph.h"
#include "RegAllocCommon.h"
#include "Support/STLExtras.h"
#include <algorithm>
namespace llvm {
// for asserting this IG node is infact in the IGNodeList of this class
inline static void assertIGNode(const InterferenceGraph *IG,
const IGNode *Node) {
assert(IG->getIGNodeList()[Node->getIndex()] == Node);
}
//-----------------------------------------------------------------------------
// Constructor: Records the RegClass and initalizes IGNodeList.
// The matrix is NOT yet created by the constructor. Call createGraph()
// to create it after adding all IGNodes to the IGNodeList.
//-----------------------------------------------------------------------------
InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC) {
IG = NULL;
Size = 0;
if( DEBUG_RA >= RA_DEBUG_Interference)
std::cerr << "Interference graph created!\n";
}
//-----------------------------------------------------------------------------
// destructor. Deletes the bit matrix and all IGNodes
//-----------------------------------------------------------------------------
InterferenceGraph:: ~InterferenceGraph() {
// delete the matrix
for(unsigned int r=0; r < IGNodeList.size(); ++r)
delete[] IG[r];
delete[] IG;
// delete all IGNodes in the IGNodeList
for_each(IGNodeList.begin(), IGNodeList.end(), deleter<IGNode>);
}
//-----------------------------------------------------------------------------
// Creates (dynamically allocates) the bit matrix necessary to hold the
// interference graph.
//-----------------------------------------------------------------------------
void InterferenceGraph::createGraph()
{
Size = IGNodeList.size();
IG = new char*[Size];
for( unsigned int r=0; r < Size; ++r)
IG[r] = new char[Size];
// init IG matrix
for(unsigned int i=0; i < Size; i++)
for(unsigned int j=0; j < Size; j++)
IG[i][j] = 0;
}
//-----------------------------------------------------------------------------
// creates a new IGNode for the given live range and add to IG
//-----------------------------------------------------------------------------
void InterferenceGraph::addLRToIG(LiveRange *const LR)
{
IGNodeList.push_back(new IGNode(LR, IGNodeList.size()));
}
//-----------------------------------------------------------------------------
// set interference for two live ranges
// update both the matrix and AdjLists of nodes.
// If there is already an interference between LR1 and LR2, adj lists
// are not updated. LR1 and LR2 must be distinct since if not, it suggests
// that there is some wrong logic in some other method.
//-----------------------------------------------------------------------------
void InterferenceGraph::setInterference(const LiveRange *const LR1,
const LiveRange *const LR2 ) {
assert(LR1 != LR2);
IGNode *IGNode1 = LR1->getUserIGNode();
IGNode *IGNode2 = LR2->getUserIGNode();
assertIGNode(this, IGNode1);
assertIGNode(this, IGNode2);
unsigned row = IGNode1->getIndex();
unsigned col = IGNode2->getIndex();
char *val;
if( DEBUG_RA >= RA_DEBUG_Interference)
std::cerr << "setting intf for: [" << row << "][" << col << "]\n";
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
if( ! (*val) ) { // if this interf is not previously set
*val = 1; // add edges between nodes
IGNode1->addAdjIGNode( IGNode2 );
IGNode2->addAdjIGNode( IGNode1 );
}
}
//----------------------------------------------------------------------------
// return whether two live ranges interfere
//----------------------------------------------------------------------------
unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
const LiveRange *const LR2) const {
assert(LR1 != LR2);
assertIGNode(this, LR1->getUserIGNode());
assertIGNode(this, LR2->getUserIGNode());
const unsigned int row = LR1->getUserIGNode()->getIndex();
const unsigned int col = LR2->getUserIGNode()->getIndex();
char ret;
if (row > col)
ret = IG[row][col];
else
ret = IG[col][row];
return ret;
}
//----------------------------------------------------------------------------
// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
// Then the IGNode2L will be deleted. Necessary for coalescing.
// IMPORTANT: The live ranges are NOT merged by this method. Use
// LiveRangeInfo::unionAndUpdateLRs for that purpose.
//----------------------------------------------------------------------------
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
LiveRange *LR2) {
assert( LR1 != LR2); // cannot merge the same live range
IGNode *const DestNode = LR1->getUserIGNode();
IGNode *SrcNode = LR2->getUserIGNode();
assertIGNode(this, DestNode);
assertIGNode(this, SrcNode);
if( DEBUG_RA >= RA_DEBUG_Interference) {
std::cerr << "Merging LRs: \""; printSet(*LR1);
std::cerr << "\" and \""; printSet(*LR2);
std::cerr << "\"\n";
}
unsigned SrcDegree = SrcNode->getNumOfNeighbors();
const unsigned SrcInd = SrcNode->getIndex();
// for all neighs of SrcNode
for(unsigned i=0; i < SrcDegree; i++) {
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
LiveRange *const LROfNeigh = NeighNode->getParentLR();
// delete edge between src and neigh - even neigh == dest
NeighNode->delAdjIGNode(SrcNode);
// set the matrix posn to 0 betn src and neigh - even neigh == dest
const unsigned NInd = NeighNode->getIndex();
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
if( LR1 != LROfNeigh) { // if the neigh != dest
// add edge betwn Dest and Neigh - if there is no current edge
setInterference(LR1, LROfNeigh );
}
}
IGNodeList[ SrcInd ] = NULL;
// SrcNode is no longer necessary - LR2 must be deleted by the caller
delete( SrcNode );
}
//----------------------------------------------------------------------------
// must be called after modifications to the graph are over but before
// pushing IGNodes on to the stack for coloring.
//----------------------------------------------------------------------------
void InterferenceGraph::setCurDegreeOfIGNodes()
{
unsigned Size = IGNodeList.size();
for( unsigned i=0; i < Size; i++) {
IGNode *Node = IGNodeList[i];
if( Node )
Node->setCurDegree();
}
}
//--------------------- debugging (Printing) methods -----------------------
//----------------------------------------------------------------------------
// Print the IGnodes
//----------------------------------------------------------------------------
void InterferenceGraph::printIG() const {
for(unsigned i=0; i < Size; i++) {
const IGNode *const Node = IGNodeList[i];
if(Node) {
std::cerr << " [" << i << "] ";
for( unsigned int j=0; j < Size; j++)
if(IG[i][j])
std::cerr << "(" << i << "," << j << ") ";
std::cerr << "\n";
}
}
}
//----------------------------------------------------------------------------
// Print the IGnodes in the IGNode List
//----------------------------------------------------------------------------
void InterferenceGraph::printIGNodeList() const {
for(unsigned i=0; i < IGNodeList.size() ; ++i) {
const IGNode *const Node = IGNodeList[i];
if (Node) {
std::cerr << " [" << Node->getIndex() << "] ";
printSet(*Node->getParentLR());
//int Deg = Node->getCurDegree();
std::cerr << "\t <# of Neighs: " << Node->getNumOfNeighbors() << ">\n";
}
}
}
} // End llvm namespace

View File

@ -1,75 +0,0 @@
//===-- InterferenceGraph.h - Interference graph for register coloring -*- 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.
//
//===----------------------------------------------------------------------===//
/* Title: InterferenceGraph.h -*- C++ -*-
Author: Ruchira Sasanka
Date: July 20, 01
Purpose: Interference Graph used for register coloring.
Notes:
Adj Info is stored in the lower trangular matrix (i.e., row > col )
This class must be used in the following way:
* Construct class
* call addLRToIG as many times to add ALL LRs to this IG
* call createGraph to create the actual matrix
* Then setInterference, getInterference, mergeIGNodesOfLRs can be
called as desired to modify the graph.
* Once the modifications to the graph are over, call
setCurDegreeOfIGNodes() before pushing IGNodes on to stack for coloring.
*/
#ifndef INTERFERENCEGRAPH_H
#define INTERFERENCEGRAPH_H
#include <vector>
namespace llvm {
class LiveRange;
class RegClass;
class IGNode;
class InterferenceGraph {
char **IG; // a poiner to the interference graph
unsigned int Size; // size of a side of the IG
RegClass *const RegCl; // RegCl contains this IG
std::vector<IGNode *> IGNodeList; // a list of all IGNodes in a reg class
public:
// the matrix is not yet created by the constructor. Call createGraph()
// to create it after adding all IGNodes to the IGNodeList
InterferenceGraph(RegClass *RC);
~InterferenceGraph();
void createGraph();
void addLRToIG(LiveRange *LR);
void setInterference(const LiveRange *LR1,
const LiveRange *LR2);
unsigned getInterference(const LiveRange *LR1,
const LiveRange *LR2) const ;
void mergeIGNodesOfLRs(const LiveRange *LR1, LiveRange *LR2);
std::vector<IGNode *> &getIGNodeList() { return IGNodeList; }
const std::vector<IGNode *> &getIGNodeList() const { return IGNodeList; }
void setCurDegreeOfIGNodes();
void printIG() const;
void printIGNodeList() const;
};
} // End llvm namespace
#endif

View File

@ -1,184 +0,0 @@
//===-- LiveRange.h - Store info about a live range -------------*- 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.
//
//===----------------------------------------------------------------------===//
//
// Implements a live range using a ValueSet. A LiveRange is a simple set
// of Values.
//
// Since the Value pointed by a use is the same as of its def, it is sufficient
// to keep only defs in a LiveRange.
//
//===----------------------------------------------------------------------===//
#ifndef LIVERANGE_H
#define LIVERANGE_H
#include "llvm/Value.h"
#include "llvm/CodeGen/ValueSet.h"
namespace llvm {
class RegClass;
class IGNode;
class LiveRange : public ValueSet {
RegClass *MyRegClass; // register class (e.g., int, FP) for this LR
/// doesSpanAcrossCalls - Does this live range span across calls?
/// This information is used by graph coloring algo to avoid allocating
/// volatile colors to live ranges that span across calls (since they have to
/// be saved/restored)
///
bool doesSpanAcrossCalls;
IGNode *UserIGNode; // IGNode which uses this LR
int Color; // color assigned to this live range
bool mustSpill; // whether this LR must be spilt
/// mustSaveAcrossCalls - whether this LR must be saved accross calls
/// ***TODO REMOVE this
///
bool mustSaveAcrossCalls;
/// SuggestedColor - if this LR has a suggested color, can it be
/// really alloated? A suggested color cannot be allocated when the
/// suggested color is volatile and when there are call
/// interferences.
///
int SuggestedColor; // The suggested color for this LR
/// CanUseSuggestedCol - It is possible that a suggested color for
/// this live range is not available before graph coloring (e.g., it
/// can be allocated to another live range which interferes with
/// this)
///
bool CanUseSuggestedCol;
/// SpilledStackOffsetFromFP - If this LR is spilled, its stack
/// offset from *FP*. The spilled offsets must always be relative to
/// the FP.
///
int SpilledStackOffsetFromFP;
/// HasSpillOffset 0 Whether this live range has a spill offset
///
bool HasSpillOffset;
/// The spill cost of this live range. Calculated using loop depth of
/// each reference to each Value in the live range
///
unsigned SpillCost;
public:
LiveRange() {
Color = SuggestedColor = -1; // not yet colored
mustSpill = mustSaveAcrossCalls = false;
MyRegClass = 0;
UserIGNode = 0;
doesSpanAcrossCalls = false;
CanUseSuggestedCol = true;
HasSpillOffset = false;
SpillCost = 0;
}
void setRegClass(RegClass *RC) { MyRegClass = RC; }
RegClass *getRegClass() const { assert(MyRegClass); return MyRegClass; }
unsigned getRegClassID() const;
bool hasColor() const { return Color != -1; }
unsigned getColor() const { assert(Color != -1); return (unsigned)Color; }
void setColor(unsigned Col) { Color = (int)Col; }
inline void setCallInterference() {
doesSpanAcrossCalls = 1;
}
inline void clearCallInterference() {
doesSpanAcrossCalls = 0;
}
inline bool isCallInterference() const {
return doesSpanAcrossCalls == 1;
}
inline void markForSpill() { mustSpill = true; }
inline bool isMarkedForSpill() const { return mustSpill; }
inline void setSpillOffFromFP(int StackOffset) {
assert(mustSpill && "This LR is not spilled");
SpilledStackOffsetFromFP = StackOffset;
HasSpillOffset = true;
}
inline void modifySpillOffFromFP(int StackOffset) {
assert(mustSpill && "This LR is not spilled");
SpilledStackOffsetFromFP = StackOffset;
HasSpillOffset = true;
}
inline bool hasSpillOffset() const {
return HasSpillOffset;
}
inline int getSpillOffFromFP() const {
assert(HasSpillOffset && "This LR is not spilled");
return SpilledStackOffsetFromFP;
}
inline void markForSaveAcrossCalls() { mustSaveAcrossCalls = true; }
inline void setUserIGNode(IGNode *IGN) {
assert(!UserIGNode); UserIGNode = IGN;
}
// getUserIGNode - NULL if the user is not allocated
inline IGNode *getUserIGNode() const { return UserIGNode; }
inline const Type *getType() const {
return (*begin())->getType(); // set's don't have a front
}
inline void setSuggestedColor(int Col) {
if (SuggestedColor == -1)
SuggestedColor = Col;
}
inline unsigned getSuggestedColor() const {
assert(SuggestedColor != -1); // only a valid color is obtained
return (unsigned)SuggestedColor;
}
inline bool hasSuggestedColor() const {
return SuggestedColor != -1;
}
inline bool isSuggestedColorUsable() const {
assert(hasSuggestedColor() && "No suggested color");
return CanUseSuggestedCol;
}
inline void setSuggestedColorUsable(bool val) {
assert(hasSuggestedColor() && "No suggested color");
CanUseSuggestedCol = val;
}
inline void addSpillCost(unsigned cost) {
SpillCost += cost;
}
inline unsigned getSpillCost() const {
return SpillCost;
}
};
} // End llvm namespace
#endif

View File

@ -1,416 +0,0 @@
//===-- LiveRangeInfo.cpp -------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Live range construction for coloring-based register allocation for LLVM.
//
//===----------------------------------------------------------------------===//
#include "IGNode.h"
#include "LiveRangeInfo.h"
#include "RegAllocCommon.h"
#include "RegClass.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegInfo.h"
#include "Support/SetOperations.h"
namespace llvm {
unsigned LiveRange::getRegClassID() const { return getRegClass()->getID(); }
LiveRangeInfo::LiveRangeInfo(const Function *F, const TargetMachine &tm,
std::vector<RegClass *> &RCL)
: Meth(F), TM(tm), RegClassList(RCL), MRI(tm.getRegInfo()) { }
LiveRangeInfo::~LiveRangeInfo() {
for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
MI != LiveRangeMap.end(); ++MI) {
if (MI->first && MI->second) {
LiveRange *LR = MI->second;
// we need to be careful in deleting LiveRanges in LiveRangeMap
// since two/more Values in the live range map can point to the same
// live range. We have to make the other entries NULL when we delete
// a live range.
for (LiveRange::iterator LI = LR->begin(); LI != LR->end(); ++LI)
LiveRangeMap[*LI] = 0;
delete LR;
}
}
}
//---------------------------------------------------------------------------
// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
// Note: the caller must make sure that L1 and L2 are distinct and both
// LRs don't have suggested colors
//---------------------------------------------------------------------------
void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
assert(L1 != L2 && (!L1->hasSuggestedColor() || !L2->hasSuggestedColor()));
assert(! (L1->hasColor() && L2->hasColor()) ||
L1->getColor() == L2->getColor());
set_union(*L1, *L2); // add elements of L2 to L1
for(ValueSet::iterator L2It = L2->begin(); L2It != L2->end(); ++L2It) {
//assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
L1->insert(*L2It); // add the var in L2 to L1
LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
//to L1
}
// set call interference for L1 from L2
if (L2->isCallInterference())
L1->setCallInterference();
// add the spill costs
L1->addSpillCost(L2->getSpillCost());
// If L2 has a color, give L1 that color. Note that L1 may have had the same
// color or none, but would not have a different color as asserted above.
if (L2->hasColor())
L1->setColor(L2->getColor());
// Similarly, if LROfUse(L2) has a suggested color, the new range
// must have the same color.
if (L2->hasSuggestedColor())
L1->setSuggestedColor(L2->getSuggestedColor());
delete L2; // delete L2 as it is no longer needed
}
//---------------------------------------------------------------------------
// Method for creating a single live range for a definition.
// The definition must be represented by a virtual register (a Value).
// Note: this function does *not* check that no live range exists for def.
//---------------------------------------------------------------------------
LiveRange*
LiveRangeInfo::createNewLiveRange(const Value* Def, bool isCC /* = false*/)
{
LiveRange* DefRange = new LiveRange(); // Create a new live range,
DefRange->insert(Def); // add Def to it,
LiveRangeMap[Def] = DefRange; // and update the map.
// set the register class of the new live range
DefRange->setRegClass(RegClassList[MRI.getRegClassIDOfType(Def->getType(),
isCC)]);
if (DEBUG_RA >= RA_DEBUG_LiveRanges) {
std::cerr << " Creating a LR for def ";
if (isCC) std::cerr << " (CC Register!)";
std::cerr << " : " << RAV(Def) << "\n";
}
return DefRange;
}
LiveRange*
LiveRangeInfo::createOrAddToLiveRange(const Value* Def, bool isCC /* = false*/)
{
LiveRange *DefRange = LiveRangeMap[Def];
// check if the LR is already there (because of multiple defs)
if (!DefRange) {
DefRange = createNewLiveRange(Def, isCC);
} else { // live range already exists
DefRange->insert(Def); // add the operand to the range
LiveRangeMap[Def] = DefRange; // make operand point to merged set
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << " Added to existing LR for def: " << RAV(Def) << "\n";
}
return DefRange;
}
//---------------------------------------------------------------------------
// Method for constructing all live ranges in a function. It creates live
// ranges for all values defined in the instruction stream. Also, it
// creates live ranges for all incoming arguments of the function.
//---------------------------------------------------------------------------
void LiveRangeInfo::constructLiveRanges() {
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << "Constructing Live Ranges ...\n";
// first find the live ranges for all incoming args of the function since
// those LRs start from the start of the function
for (Function::const_aiterator AI = Meth->abegin(); AI != Meth->aend(); ++AI)
createNewLiveRange(AI, /*isCC*/ false);
// Now suggest hardware registers for these function args
MRI.suggestRegs4MethodArgs(Meth, *this);
// Now create LRs for machine instructions. A new LR will be created
// only for defs in the machine instr since, we assume that all Values are
// defined before they are used. However, there can be multiple defs for
// the same Value in machine instructions.
//
// Also, find CALL and RETURN instructions, which need extra work.
//
MachineFunction &MF = MachineFunction::get(Meth);
for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
MachineBasicBlock &MBB = *BBI;
// iterate over all the machine instructions in BB
for(MachineBasicBlock::iterator MInstIterator = MBB.begin();
MInstIterator != MBB.end(); ++MInstIterator) {
MachineInstr *MInst = *MInstIterator;
// If the machine instruction is a call/return instruction, add it to
// CallRetInstrList for processing its args, ret value, and ret addr.
//
if(TM.getInstrInfo().isReturn(MInst->getOpCode()) ||
TM.getInstrInfo().isCall(MInst->getOpCode()))
CallRetInstrList.push_back(MInst);
// iterate over explicit MI operands and create a new LR
// for each operand that is defined by the instruction
for (MachineInstr::val_op_iterator OpI = MInst->begin(),
OpE = MInst->end(); OpI != OpE; ++OpI)
if (OpI.isDef()) {
const Value *Def = *OpI;
bool isCC = (OpI.getMachineOperand().getType()
== MachineOperand::MO_CCRegister);
LiveRange* LR = createOrAddToLiveRange(Def, isCC);
// If the operand has a pre-assigned register,
// set it directly in the LiveRange
if (OpI.getMachineOperand().hasAllocatedReg()) {
unsigned getClassId;
LR->setColor(MRI.getClassRegNum(
OpI.getMachineOperand().getAllocatedRegNum(),
getClassId));
}
}
// iterate over implicit MI operands and create a new LR
// for each operand that is defined by the instruction
for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i)
if (MInst->getImplicitOp(i).isDef()) {
const Value *Def = MInst->getImplicitRef(i);
LiveRange* LR = createOrAddToLiveRange(Def, /*isCC*/ false);
// If the implicit operand has a pre-assigned register,
// set it directly in the LiveRange
if (MInst->getImplicitOp(i).hasAllocatedReg()) {
unsigned getClassId;
LR->setColor(MRI.getClassRegNum(
MInst->getImplicitOp(i).getAllocatedRegNum(),
getClassId));
}
}
} // for all machine instructions in the BB
} // for all BBs in function
// Now we have to suggest clors for call and return arg live ranges.
// Also, if there are implicit defs (e.g., retun value of a call inst)
// they must be added to the live range list
//
suggestRegs4CallRets();
if( DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << "Initial Live Ranges constructed!\n";
}
//---------------------------------------------------------------------------
// If some live ranges must be colored with specific hardware registers
// (e.g., for outgoing call args), suggesting of colors for such live
// ranges is done using target specific function. Those functions are called
// from this function. The target specific methods must:
// 1) suggest colors for call and return args.
// 2) create new LRs for implicit defs in machine instructions
//---------------------------------------------------------------------------
void LiveRangeInfo::suggestRegs4CallRets() {
std::vector<MachineInstr*>::iterator It = CallRetInstrList.begin();
for( ; It != CallRetInstrList.end(); ++It) {
MachineInstr *MInst = *It;
MachineOpCode OpCode = MInst->getOpCode();
if ((TM.getInstrInfo()).isReturn(OpCode))
MRI.suggestReg4RetValue(MInst, *this);
else if ((TM.getInstrInfo()).isCall(OpCode))
MRI.suggestRegs4CallArgs(MInst, *this);
else
assert( 0 && "Non call/ret instr in CallRetInstrList" );
}
}
//--------------------------------------------------------------------------
// The following method coalesces live ranges when possible. This method
// must be called after the interference graph has been constructed.
/* Algorithm:
for each BB in function
for each machine instruction (inst)
for each definition (def) in inst
for each operand (op) of inst that is a use
if the def and op are of the same register type
if the def and op do not interfere //i.e., not simultaneously live
if (degree(LR of def) + degree(LR of op)) <= # avail regs
if both LRs do not have suggested colors
merge2IGNodes(def, op) // i.e., merge 2 LRs
*/
//---------------------------------------------------------------------------
// Checks if live range LR interferes with any node assigned or suggested to
// be assigned the specified color
//
inline bool InterferesWithColor(const LiveRange& LR, unsigned color) {
IGNode* lrNode = LR.getUserIGNode();
for (unsigned n=0, NN = lrNode->getNumOfNeighbors(); n < NN; n++) {
LiveRange *neighLR = lrNode->getAdjIGNode(n)->getParentLR();
if (neighLR->hasColor() && neighLR->getColor() == color)
return true;
if (neighLR->hasSuggestedColor() && neighLR->getSuggestedColor() == color)
return true;
}
return false;
}
// Cannot coalesce if any of the following is true:
// (1) Both LRs have suggested colors (should be "different suggested colors"?)
// (2) Both LR1 and LR2 have colors and the colors are different
// (but if the colors are the same, it is definitely safe to coalesce)
// (3) LR1 has color and LR2 interferes with any LR that has the same color
// (4) LR2 has color and LR1 interferes with any LR that has the same color
//
inline bool InterfsPreventCoalescing(const LiveRange& LROfDef,
const LiveRange& LROfUse) {
// (4) if they have different suggested colors, cannot coalesce
if (LROfDef.hasSuggestedColor() && LROfUse.hasSuggestedColor())
return true;
// if neither has a color, nothing more to do.
if (! LROfDef.hasColor() && ! LROfUse.hasColor())
return false;
// (2, 3) if L1 has color...
if (LROfDef.hasColor()) {
if (LROfUse.hasColor())
return (LROfUse.getColor() != LROfDef.getColor());
return InterferesWithColor(LROfUse, LROfDef.getColor());
}
// (4) else only LROfUse has a color: check if that could interfere
return InterferesWithColor(LROfDef, LROfUse.getColor());
}
void LiveRangeInfo::coalesceLRs()
{
if(DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << "\nCoalescing LRs ...\n";
MachineFunction &MF = MachineFunction::get(Meth);
for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
MachineBasicBlock &MBB = *BBI;
// iterate over all the machine instructions in BB
for(MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII){
const MachineInstr *MI = *MII;
if( DEBUG_RA >= RA_DEBUG_LiveRanges) {
std::cerr << " *Iterating over machine instr ";
MI->dump();
std::cerr << "\n";
}
// iterate over MI operands to find defs
for(MachineInstr::const_val_op_iterator DefI = MI->begin(),
DefE = MI->end(); DefI != DefE; ++DefI) {
if (DefI.isDef()) { // this operand is modified
LiveRange *LROfDef = getLiveRangeForValue( *DefI );
RegClass *RCOfDef = LROfDef->getRegClass();
MachineInstr::const_val_op_iterator UseI = MI->begin(),
UseE = MI->end();
for( ; UseI != UseE; ++UseI) { // for all uses
LiveRange *LROfUse = getLiveRangeForValue( *UseI );
if (!LROfUse) { // if LR of use is not found
//don't warn about labels
if (!isa<BasicBlock>(*UseI) && DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << " !! Warning: No LR for use " << RAV(*UseI)<< "\n";
continue; // ignore and continue
}
if (LROfUse == LROfDef) // nothing to merge if they are same
continue;
if (MRI.getRegTypeForLR(LROfDef) ==
MRI.getRegTypeForLR(LROfUse)) {
// If the two RegTypes are the same
if (!RCOfDef->getInterference(LROfDef, LROfUse) ) {
unsigned CombinedDegree =
LROfDef->getUserIGNode()->getNumOfNeighbors() +
LROfUse->getUserIGNode()->getNumOfNeighbors();
if (CombinedDegree > RCOfDef->getNumOfAvailRegs()) {
// get more precise estimate of combined degree
CombinedDegree = LROfDef->getUserIGNode()->
getCombinedDegree(LROfUse->getUserIGNode());
}
if (CombinedDegree <= RCOfDef->getNumOfAvailRegs()) {
// if both LRs do not have different pre-assigned colors
// and both LRs do not have suggested colors
if (! InterfsPreventCoalescing(*LROfDef, *LROfUse)) {
RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
unionAndUpdateLRs(LROfDef, LROfUse);
}
} // if combined degree is less than # of regs
} // if def and use do not interfere
}// if reg classes are the same
} // for all uses
} // if def
} // for all defs
} // for all machine instructions
} // for all BBs
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
std::cerr << "\nCoalescing Done!\n";
}
/*--------------------------- Debug code for printing ---------------*/
void LiveRangeInfo::printLiveRanges() {
LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
std::cerr << "\nPrinting Live Ranges from Hash Map:\n";
for( ; HMI != LiveRangeMap.end(); ++HMI) {
if (HMI->first && HMI->second) {
std::cerr << " Value* " << RAV(HMI->first) << "\t: ";
if (IGNode* igNode = HMI->second->getUserIGNode())
std::cerr << "LR# " << igNode->getIndex();
else
std::cerr << "LR# " << "<no-IGNode>";
std::cerr << "\t:Values = "; printSet(*HMI->second); std::cerr << "\n";
}
}
}
} // End llvm namespace

View File

@ -1,128 +0,0 @@
//===-- LiveRangeInfo.h - Track all LiveRanges for a Function ----*- 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 contains the class LiveRangeInfo which constructs and keeps
// the LiveRangeMap which contains all the live ranges used in a method.
//
// Assumptions:
//
// All variables (llvm Values) are defined before they are used. However, a
// constant may not be defined in the machine instruction stream if it can be
// used as an immediate value within a machine instruction. However, register
// allocation does not have to worry about immediate constants since they
// do not require registers.
//
// Since an llvm Value has a list of uses associated, it is sufficient to
// record only the defs in a Live Range.
//
//===----------------------------------------------------------------------===//
#ifndef LIVERANGEINFO_H
#define LIVERANGEINFO_H
#include "llvm/CodeGen/ValueSet.h"
#include "Support/hash_map"
namespace llvm {
class LiveRange;
class MachineInstr;
class RegClass;
class TargetRegInfo;
class TargetMachine;
class Value;
class Function;
class Instruction;
typedef hash_map<const Value*, LiveRange*> LiveRangeMapType;
//----------------------------------------------------------------------------
// Class LiveRangeInfo
//
// Constructs and keeps the LiveRangeMap which contains all the live
// ranges used in a method. Also contain methods to coalesce live ranges.
//----------------------------------------------------------------------------
class LiveRangeInfo {
const Function *const Meth; // Func for which live range info is held
LiveRangeMapType LiveRangeMap; // A map from Value * to LiveRange * to
// record all live ranges in a method
// created by constructLiveRanges
const TargetMachine& TM; // target machine description
std::vector<RegClass *> & RegClassList;// vector containing register classess
const TargetRegInfo& MRI; // machine reg info
std::vector<MachineInstr*> CallRetInstrList; // a list of all call/ret instrs
//------------ Private methods (see LiveRangeInfo.cpp for description)-------
LiveRange* createNewLiveRange (const Value* Def,
bool isCC = false);
LiveRange* createOrAddToLiveRange (const Value* Def,
bool isCC = false);
void unionAndUpdateLRs (LiveRange *L1,
LiveRange *L2);
void addInterference (const Instruction *Inst,
const ValueSet *LVSet);
void suggestRegs4CallRets ();
const Function *getMethod () const { return Meth; }
public:
LiveRangeInfo(const Function *F,
const TargetMachine& tm,
std::vector<RegClass *> & RCList);
/// Destructor to destroy all LiveRanges in the LiveRange Map
///
~LiveRangeInfo();
// Main entry point for live range construction
//
void constructLiveRanges();
/// return the common live range map for this method
///
inline const LiveRangeMapType *getLiveRangeMap() const
{ return &LiveRangeMap; }
/// Method used to get the live range containing a Value.
/// This may return NULL if no live range exists for a Value (eg, some consts)
///
inline LiveRange *getLiveRangeForValue(const Value *Val) {
return LiveRangeMap[Val];
}
inline const LiveRange *getLiveRangeForValue(const Value *Val) const {
LiveRangeMapType::const_iterator I = LiveRangeMap.find(Val);
return I->second;
}
/// Method for coalescing live ranges. Called only after interference info
/// is calculated.
///
void coalesceLRs();
/// debugging method to print the live ranges
///
void printLiveRanges();
};
} // End llvm namespace
#endif

View File

@ -1,17 +0,0 @@
##===- lib/CodeGen/RegAlloc/Makefile -----------------------*- Makefile -*-===##
#
# 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.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
DIRS =
LIBRARYNAME = regalloc
BUILD_ARCHIVE = 1
include $(LEVEL)/Makefile.common

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +0,0 @@
//===-- PhyRegAlloc.h - Graph Coloring Register Allocator -------*- 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 is the main entry point for register allocation.
//
// Notes:
// * RegisterClasses: Each RegClass accepts a
// TargetRegClass which contains machine specific info about that register
// class. The code in the RegClass is machine independent and they use
// access functions in the TargetRegClass object passed into it to get
// machine specific info.
//
// * Machine dependent work: All parts of the register coloring algorithm
// except coloring of an individual node are machine independent.
//
//===----------------------------------------------------------------------===//
#ifndef PHYREGALLOC_H
#define PHYREGALLOC_H
#include "LiveRangeInfo.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegInfo.h"
#include <map>
namespace llvm {
class MachineFunction;
class FunctionLiveVarInfo;
class MachineInstr;
class LoopInfo;
class RegClass;
class Constant;
//----------------------------------------------------------------------------
// Class AddedInstrns:
// When register allocator inserts new instructions in to the existing
// instruction stream, it does NOT directly modify the instruction stream.
// Rather, it creates an object of AddedInstrns and stick it in the
// AddedInstrMap for an existing instruction. This class contains two vectors
// to store such instructions added before and after an existing instruction.
//----------------------------------------------------------------------------
struct AddedInstrns {
std::vector<MachineInstr*> InstrnsBefore;//Insts added BEFORE an existing inst
std::vector<MachineInstr*> InstrnsAfter; //Insts added AFTER an existing inst
inline void clear () { InstrnsBefore.clear (); InstrnsAfter.clear (); }
};
//----------------------------------------------------------------------------
// class PhyRegAlloc:
// Main class the register allocator. Call runOnFunction() to allocate
// registers for a Function.
//----------------------------------------------------------------------------
class PhyRegAlloc : public FunctionPass {
std::vector<RegClass *> RegClassList; // vector of register classes
const TargetMachine &TM; // target machine
const Function *Fn; // name of the function we work on
MachineFunction *MF; // descriptor for method's native code
FunctionLiveVarInfo *LVI; // LV information for this method
// (already computed for BBs)
LiveRangeInfo *LRI; // LR info (will be computed)
const TargetRegInfo &MRI; // Machine Register information
const unsigned NumOfRegClasses; // recorded here for efficiency
// Map to indicate whether operands of each MachineInstr have been
// updated according to their assigned colors. This is only used in
// assertion checking (debug builds).
std::map<const MachineInstr *, bool> OperandsColoredMap;
// AddedInstrMap - Used to store instrns added in this phase
std::map<const MachineInstr *, AddedInstrns> AddedInstrMap;
// ScratchRegsUsed - Contains scratch register uses for a particular MI.
typedef std::multimap<const MachineInstr*, int> ScratchRegsUsedTy;
ScratchRegsUsedTy ScratchRegsUsed;
AddedInstrns AddedInstrAtEntry; // to store instrns added at entry
const LoopInfo *LoopDepthCalc; // to calculate loop depths
PhyRegAlloc(const PhyRegAlloc&); // DO NOT IMPLEMENT
void operator=(const PhyRegAlloc&); // DO NOT IMPLEMENT
public:
typedef std::map<const Function *, std::vector<AllocInfo> > SavedStateMapTy;
inline PhyRegAlloc (const TargetMachine &TM_) :
TM (TM_), MRI (TM.getRegInfo ()),
NumOfRegClasses (MRI.getNumOfRegClasses ()) { }
virtual ~PhyRegAlloc() { }
/// runOnFunction - Main method called for allocating registers.
///
virtual bool runOnFunction (Function &F);
virtual bool doFinalization (Module &M);
virtual void getAnalysisUsage (AnalysisUsage &AU) const;
const char *getPassName () const {
return "Traditional graph-coloring reg. allocator";
}
inline const RegClass* getRegClassByID(unsigned id) const {
return RegClassList[id];
}
inline RegClass *getRegClassByID(unsigned id) { return RegClassList[id]; }
private:
SavedStateMapTy FnAllocState;
void addInterference(const Value *Def, const ValueSet *LVSet,
bool isCallInst);
bool markAllocatedRegs(MachineInstr* MInst);
void addInterferencesForArgs();
void createIGNodeListsAndIGs();
void buildInterferenceGraphs();
void saveStateForValue (std::vector<AllocInfo> &state,
const Value *V, unsigned Insn, int Opnd);
void saveState();
void verifySavedState();
void setCallInterferences(const MachineInstr *MI,
const ValueSet *LVSetAft);
void move2DelayedInstr(const MachineInstr *OrigMI,
const MachineInstr *DelayedMI);
void markUnusableSugColors();
void allocateStackSpace4SpilledLRs();
void insertCode4SpilledLR(const LiveRange *LR,
MachineBasicBlock::iterator& MII,
MachineBasicBlock &MBB, unsigned OpNum);
/// Method for inserting caller saving code. The caller must save all the
/// volatile registers live across a call.
///
void insertCallerSavingCode(std::vector<MachineInstr*>& instrnsBefore,
std::vector<MachineInstr*>& instrnsAfter,
MachineInstr *CallMI,
const BasicBlock *BB);
void colorIncomingArgs();
void colorCallRetArgs();
void updateMachineCode();
void updateInstruction(MachineBasicBlock::iterator& MII,
MachineBasicBlock &MBB);
int getUsableUniRegAtMI(int RegType, const ValueSet *LVSetBef,
MachineInstr *MI,
std::vector<MachineInstr*>& MIBef,
std::vector<MachineInstr*>& MIAft);
/// Callback method used to find unused registers.
/// LVSetBef is the live variable set to search for an unused register.
/// If it is not specified, the LV set before the current MI is used.
/// This is sufficient as long as no new copy instructions are generated
/// to copy the free register to memory.
///
int getUnusedUniRegAtMI(RegClass *RC, int RegType,
const MachineInstr *MI,
const ValueSet *LVSetBef = 0);
void setRelRegsUsedByThisInst(RegClass *RC, int RegType,
const MachineInstr *MI);
int getUniRegNotUsedByThisInst(RegClass *RC, int RegType,
const MachineInstr *MI);
void addInterf4PseudoInstr(const MachineInstr *MI);
};
} // End llvm namespace
#endif

View File

@ -1,32 +0,0 @@
//===-- RegAllocCommon.h --------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Shared declarations for register allocation.
//
//===----------------------------------------------------------------------===//
#ifndef REGALLOCCOMMON_H
#define REGALLOCCOMMON_H
namespace llvm {
enum RegAllocDebugLevel_t {
RA_DEBUG_None = 0,
RA_DEBUG_Results = 1,
RA_DEBUG_Coloring = 2,
RA_DEBUG_Interference = 3,
RA_DEBUG_LiveRanges = 4,
RA_DEBUG_Verbose = 5
};
extern RegAllocDebugLevel_t DEBUG_RA;
} // End llvm namespace
#endif

View File

@ -1,250 +0,0 @@
//===-- RegClass.cpp -----------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// class RegClass for coloring-based register allocation for LLVM.
//
//===----------------------------------------------------------------------===//
#include "IGNode.h"
#include "RegAllocCommon.h"
#include "RegClass.h"
#include "llvm/Target/TargetRegInfo.h"
namespace llvm {
//----------------------------------------------------------------------------
// This constructor inits IG. The actual matrix is created by a call to
// createInterferenceGraph() above.
//----------------------------------------------------------------------------
RegClass::RegClass(const Function *M,
const TargetRegInfo *_MRI_,
const TargetRegClassInfo *_MRC_)
: Meth(M), MRI(_MRI_), MRC(_MRC_),
RegClassID( _MRC_->getRegClassID() ),
IG(this), IGNodeStack() {
if (DEBUG_RA >= RA_DEBUG_Interference)
std::cerr << "Created Reg Class: " << RegClassID << "\n";
IsColorUsedArr.resize(MRC->getNumOfAllRegs());
}
//----------------------------------------------------------------------------
// Main entry point for coloring a register class.
//----------------------------------------------------------------------------
void RegClass::colorAllRegs()
{
if (DEBUG_RA >= RA_DEBUG_Coloring)
std::cerr << "Coloring IG of reg class " << RegClassID << " ...\n";
// pre-color IGNodes
pushAllIGNodes(); // push all IG Nodes
unsigned int StackSize = IGNodeStack.size();
IGNode *CurIGNode;
// for all LRs on stack
for (unsigned int IGN=0; IGN < StackSize; IGN++) {
CurIGNode = IGNodeStack.top(); // pop the IGNode on top of stack
IGNodeStack.pop();
colorIGNode (CurIGNode); // color it
}
}
//----------------------------------------------------------------------------
// The method for pushing all IGNodes on to the stack.
//----------------------------------------------------------------------------
void RegClass::pushAllIGNodes()
{
bool NeedMoreSpills;
IG.setCurDegreeOfIGNodes(); // calculate degree of IGNodes
// push non-constrained IGNodes
bool PushedAll = pushUnconstrainedIGNodes();
if (DEBUG_RA >= RA_DEBUG_Coloring) {
std::cerr << " Puhsed all-unconstrained IGNodes. ";
if( PushedAll ) std::cerr << " No constrained nodes left.";
std::cerr << "\n";
}
if (PushedAll) // if NO constrained nodes left
return;
// now, we have constrained nodes. So, push one of them (the one with min
// spill cost) and try to push the others as unConstrained nodes.
// Repeat this.
do {
//get node with min spill cost
IGNode *IGNodeSpill = getIGNodeWithMinSpillCost();
// push that node on to stack
IGNodeStack.push(IGNodeSpill);
// set its OnStack flag and decrement degree of neighs
IGNodeSpill->pushOnStack();
// now push NON-constrained ones, if any
NeedMoreSpills = !pushUnconstrainedIGNodes();
if (DEBUG_RA >= RA_DEBUG_Coloring)
std::cerr << "\nConstrained IG Node found !@!" << IGNodeSpill->getIndex();
} while(NeedMoreSpills); // repeat until we have pushed all
}
//--------------------------------------------------------------------------
// This method goes thru all IG nodes in the IGNodeList of an IG of a
// register class and push any unconstrained IG node left (that is not
// already pushed)
//--------------------------------------------------------------------------
bool RegClass::pushUnconstrainedIGNodes()
{
// # of LRs for this reg class
unsigned int IGNodeListSize = IG.getIGNodeList().size();
bool pushedall = true;
// a pass over IGNodeList
for (unsigned i =0; i < IGNodeListSize; i++) {
// get IGNode i from IGNodeList
IGNode *IGNode = IG.getIGNodeList()[i];
if (!IGNode ) // can be null due to merging
continue;
// if already pushed on stack, continue. This can happen since this
// method can be called repeatedly until all constrained nodes are
// pushed
if (IGNode->isOnStack() )
continue;
// if the degree of IGNode is lower
if ((unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs()) {
IGNodeStack.push( IGNode ); // push IGNode on to the stack
IGNode->pushOnStack(); // set OnStack and dec deg of neighs
if (DEBUG_RA >= RA_DEBUG_Coloring) {
std::cerr << " pushed un-constrained IGNode " << IGNode->getIndex()
<< " on to stack\n";
}
}
else pushedall = false; // we didn't push all live ranges
} // for
// returns true if we pushed all live ranges - else false
return pushedall;
}
//----------------------------------------------------------------------------
// Get the IGNode with the minimum spill cost
//----------------------------------------------------------------------------
IGNode * RegClass::getIGNodeWithMinSpillCost() {
unsigned int IGNodeListSize = IG.getIGNodeList().size();
double MinSpillCost = 0;
IGNode *MinCostIGNode = NULL;
bool isFirstNode = true;
// pass over IGNodeList to find the IGNode with minimum spill cost
// among all IGNodes that are not yet pushed on to the stack
for (unsigned int i =0; i < IGNodeListSize; i++) {
IGNode *IGNode = IG.getIGNodeList()[i];
if (!IGNode) // can be null due to merging
continue;
if (!IGNode->isOnStack()) {
double SpillCost = (double) IGNode->getParentLR()->getSpillCost() /
(double) (IGNode->getCurDegree() + 1);
if (isFirstNode) { // for the first IG node
MinSpillCost = SpillCost;
MinCostIGNode = IGNode;
isFirstNode = false;
} else if (MinSpillCost > SpillCost) {
MinSpillCost = SpillCost;
MinCostIGNode = IGNode;
}
}
}
assert (MinCostIGNode && "No IGNode to spill");
return MinCostIGNode;
}
//----------------------------------------------------------------------------
// Color the IGNode using the machine specific code.
//----------------------------------------------------------------------------
void RegClass::colorIGNode(IGNode *const Node) {
if (! Node->hasColor()) { // not colored as an arg etc.
// init all elements of to IsColorUsedAr false;
clearColorsUsed();
// initialize all colors used by neighbors of this node to true
LiveRange *LR = Node->getParentLR();
unsigned NumNeighbors = Node->getNumOfNeighbors();
for (unsigned n=0; n < NumNeighbors; n++) {
IGNode *NeighIGNode = Node->getAdjIGNode(n);
LiveRange *NeighLR = NeighIGNode->getParentLR();
// Don't use a color if it is in use by the neighbor,
// or is suggested for use by the neighbor,
// markColorsUsed() should be given the color and the reg type for
// LR, not for NeighLR, because it should mark registers used based on
// the type we are looking for, not on the regType for the neighbour.
if (NeighLR->hasColor())
this->markColorsUsed(NeighLR->getColor(),
MRI->getRegTypeForLR(NeighLR),
MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
else if (NeighLR->hasSuggestedColor() &&
NeighLR->isSuggestedColorUsable())
this->markColorsUsed(NeighLR->getSuggestedColor(),
MRI->getRegTypeForLR(NeighLR),
MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
}
// call the target specific code for coloring
//
MRC->colorIGNode(Node, IsColorUsedArr);
} else {
if (DEBUG_RA >= RA_DEBUG_Coloring) {
std::cerr << " Node " << Node->getIndex();
std::cerr << " already colored with color " << Node->getColor() << "\n";
}
}
if (!Node->hasColor() ) {
if (DEBUG_RA >= RA_DEBUG_Coloring) {
std::cerr << " Node " << Node->getIndex();
std::cerr << " - could not find a color (needs spilling)\n";
}
}
}
void RegClass::printIGNodeList() const {
std::cerr << "IG Nodes for Register Class " << RegClassID << ":" << "\n";
IG.printIGNodeList();
}
void RegClass::printIG() {
std::cerr << "IG for Register Class " << RegClassID << ":" << "\n";
IG.printIG();
}
} // End llvm namespace

View File

@ -1,147 +0,0 @@
//===-- RegClass.h - Machine Independent register coloring ------*- 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.
//
//===----------------------------------------------------------------------===//
/* Title: RegClass.h -*- C++ -*-
Author: Ruchira Sasanka
Date: Aug 20, 01
Purpose: Contains machine independent methods for register coloring.
*/
#ifndef REGCLASS_H
#define REGCLASS_H
#include "llvm/Target/TargetRegInfo.h"
#include "InterferenceGraph.h"
#include <stack>
namespace llvm {
class TargetRegClassInfo;
//-----------------------------------------------------------------------------
// Class RegClass
//
// Implements a machine independent register class.
//
// This is the class that contains all data structures and common algos
// for coloring a particular register class (e.g., int class, fp class).
// This class is hardware independent. This class accepts a hardware
// dependent description of machine registers (TargetRegInfo class) to
// get hardware specific info and to color an individual IG node.
//
// This class contains the InterferenceGraph (IG).
// Also it contains an IGNode stack that can be used for coloring.
// The class provides some easy access methods to the IG methods, since these
// methods are called thru a register class.
//
//-----------------------------------------------------------------------------
class RegClass {
const Function *const Meth; // Function we are working on
const TargetRegInfo *MRI; // Machine register information
const TargetRegClassInfo *const MRC; // Machine reg. class for this RegClass
const unsigned RegClassID; // my int ID
InterferenceGraph IG; // Interference graph - constructed by
// buildInterferenceGraph
std::stack<IGNode *> IGNodeStack; // the stack used for coloring
// IsColorUsedArr - An array used for coloring each node. This array must be
// of size MRC->getNumOfAllRegs(). Allocated once in the constructor for
// efficiency.
//
std::vector<bool> IsColorUsedArr;
//--------------------------- private methods ------------------------------
void pushAllIGNodes();
bool pushUnconstrainedIGNodes();
IGNode * getIGNodeWithMinSpillCost();
void colorIGNode(IGNode *const Node);
// This directly marks the colors used by a particular register number
// within the register class. External users should use the public
// versions of this function below.
inline void markColorUsed(unsigned classRegNum) {
assert(classRegNum < IsColorUsedArr.size() && "Invalid register used?");
IsColorUsedArr[classRegNum] = true;
}
inline bool isColorUsed(unsigned regNum) const {
assert(regNum < IsColorUsedArr.size() && "Invalid register used?");
return IsColorUsedArr[regNum];
}
public:
RegClass(const Function *M,
const TargetRegInfo *_MRI_,
const TargetRegClassInfo *_MRC_);
inline void createInterferenceGraph() { IG.createGraph(); }
inline InterferenceGraph &getIG() { return IG; }
inline const unsigned getID() const { return RegClassID; }
inline const TargetRegClassInfo* getTargetRegClass() const { return MRC; }
// main method called for coloring regs
//
void colorAllRegs();
inline unsigned getNumOfAvailRegs() const
{ return MRC->getNumOfAvailRegs(); }
// --- following methods are provided to access the IG contained within this
// ---- RegClass easilly.
inline void addLRToIG(LiveRange *const LR)
{ IG.addLRToIG(LR); }
inline void setInterference(const LiveRange *const LR1,
const LiveRange *const LR2)
{ IG.setInterference(LR1, LR2); }
inline unsigned getInterference(const LiveRange *const LR1,
const LiveRange *const LR2) const
{ return IG.getInterference(LR1, LR2); }
inline void mergeIGNodesOfLRs(const LiveRange *const LR1,
LiveRange *const LR2)
{ IG.mergeIGNodesOfLRs(LR1, LR2); }
inline void clearColorsUsed() {
IsColorUsedArr.clear();
IsColorUsedArr.resize(MRC->getNumOfAllRegs());
}
inline void markColorsUsed(unsigned ClassRegNum,
int UserRegType,
int RegTypeWanted) {
MRC->markColorsUsed(ClassRegNum, UserRegType, RegTypeWanted,IsColorUsedArr);
}
inline int getUnusedColor(int machineRegType) const {
return MRC->findUnusedColor(machineRegType, IsColorUsedArr);
}
void printIGNodeList() const;
void printIG();
};
} // End llvm namespace
#endif

View File

@ -8,6 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = sparc
DIRS = RegAlloc
ExtraSource = Sparc.burm.cpp

View File

@ -6,7 +6,7 @@
# the University of Illinois Open Source License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LEVEL = ../../../..
DIRS =