mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-05 13:09:10 +00:00
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:
parent
f7703df496
commit
75e260990d
@ -7,7 +7,7 @@
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../..
|
||||
PARALLEL_DIRS = InstrSelection InstrSched RegAlloc SelectionDAG
|
||||
PARALLEL_DIRS = InstrSelection InstrSched SelectionDAG
|
||||
LIBRARYNAME = codegen
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -8,6 +8,7 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
LIBRARYNAME = sparc
|
||||
DIRS = RegAlloc
|
||||
|
||||
ExtraSource = Sparc.burm.cpp
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
# the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
LEVEL = ../../../..
|
||||
|
||||
DIRS =
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user