2001-09-18 13:01:29 +00:00
|
|
|
// $Id$
|
2001-09-14 03:47:57 +00:00
|
|
|
//***************************************************************************
|
|
|
|
// File:
|
|
|
|
// Sparc.cpp
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
// History:
|
|
|
|
// 7/15/01 - Vikram Adve - Created
|
|
|
|
//**************************************************************************/
|
|
|
|
|
2001-09-14 16:56:32 +00:00
|
|
|
#include "llvm/Target/Sparc.h"
|
2001-09-14 03:47:57 +00:00
|
|
|
#include "SparcInternals.h"
|
|
|
|
#include "llvm/Method.h"
|
|
|
|
#include "llvm/CodeGen/InstrScheduling.h"
|
|
|
|
#include "llvm/CodeGen/InstrSelection.h"
|
|
|
|
|
2001-09-15 00:30:44 +00:00
|
|
|
#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
|
|
|
|
#include "llvm/CodeGen/PhyRegAlloc.h"
|
|
|
|
|
2001-09-19 15:56:23 +00:00
|
|
|
// Build the MachineInstruction Description Array...
|
|
|
|
const MachineInstrDescriptor SparcMachineInstrDesc[] = {
|
|
|
|
#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
|
|
|
|
NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS) \
|
|
|
|
{ OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
|
|
|
|
NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS },
|
|
|
|
#include "SparcInstr.def"
|
|
|
|
};
|
2001-09-18 13:01:29 +00:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2001-09-14 16:56:32 +00:00
|
|
|
// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
|
|
|
|
// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
|
2001-09-18 13:01:29 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2001-09-14 16:56:32 +00:00
|
|
|
//
|
2001-10-15 16:25:28 +00:00
|
|
|
|
2001-09-14 16:56:32 +00:00
|
|
|
TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
|
2001-09-14 03:47:57 +00:00
|
|
|
|
|
|
|
|
2001-09-18 13:01:29 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Entry point for register allocation for a module
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
2001-09-18 22:52:44 +00:00
|
|
|
void AllocateRegisters(Method *M, TargetMachine &TM)
|
2001-09-18 13:01:29 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
if ( (M)->isExternal() ) // don't process prototypes
|
2001-09-18 22:52:44 +00:00
|
|
|
return;
|
2001-09-18 13:01:29 +00:00
|
|
|
|
|
|
|
if( DEBUG_RA ) {
|
2001-10-15 18:15:27 +00:00
|
|
|
cerr << endl << "******************** Method "<< (M)->getName();
|
|
|
|
cerr << " ********************" <<endl;
|
2001-09-18 13:01:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MethodLiveVarInfo LVI(M ); // Analyze live varaibles
|
|
|
|
LVI.analyze();
|
|
|
|
|
|
|
|
|
|
|
|
PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
|
|
|
|
PRA.allocateRegisters();
|
|
|
|
|
|
|
|
|
2001-10-15 18:15:27 +00:00
|
|
|
if( DEBUG_RA ) cerr << endl << "Register allocation complete!" << endl;
|
2001-09-18 13:01:29 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-09-18 22:52:44 +00:00
|
|
|
|
|
|
|
|
2001-09-14 03:47:57 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// class UltraSparcInstrInfo
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
// Information about individual instructions.
|
|
|
|
// Most information is stored in the SparcMachineInstrDesc array above.
|
|
|
|
// Other information is computed on demand, and most such functions
|
|
|
|
// default to member functions in base class MachineInstrInfo.
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*ctor*/
|
|
|
|
UltraSparcInstrInfo::UltraSparcInstrInfo()
|
|
|
|
: MachineInstrInfo(SparcMachineInstrDesc,
|
|
|
|
/*descSize = */ NUM_TOTAL_OPCODES,
|
|
|
|
/*numRealOpCodes = */ NUM_REAL_OPCODES)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// class UltraSparcSchedInfo
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
// Scheduling information for the UltraSPARC.
|
|
|
|
// Primarily just initializes machine-dependent parameters in
|
|
|
|
// class MachineSchedInfo.
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*ctor*/
|
|
|
|
UltraSparcSchedInfo::UltraSparcSchedInfo(const MachineInstrInfo* mii)
|
|
|
|
: MachineSchedInfo((unsigned int) SPARC_NUM_SCHED_CLASSES,
|
|
|
|
mii,
|
|
|
|
SparcRUsageDesc,
|
|
|
|
SparcInstrUsageDeltas,
|
|
|
|
SparcInstrIssueDeltas,
|
|
|
|
sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
|
|
|
|
sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
|
|
|
|
{
|
|
|
|
maxNumIssueTotal = 4;
|
|
|
|
longestIssueConflict = 0; // computed from issuesGaps[]
|
|
|
|
|
|
|
|
branchMispredictPenalty = 4; // 4 for SPARC IIi
|
|
|
|
branchTargetUnknownPenalty = 2; // 2 for SPARC IIi
|
|
|
|
l1DCacheMissPenalty = 8; // 7 or 9 for SPARC IIi
|
|
|
|
l1ICacheMissPenalty = 8; // ? for SPARC IIi
|
|
|
|
|
|
|
|
inOrderLoads = true; // true for SPARC IIi
|
|
|
|
inOrderIssue = true; // true for SPARC IIi
|
|
|
|
inOrderExec = false; // false for most architectures
|
|
|
|
inOrderRetire= true; // true for most architectures
|
|
|
|
|
|
|
|
// must be called after above parameters are initialized.
|
|
|
|
this->initializeResources();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
UltraSparcSchedInfo::initializeResources()
|
|
|
|
{
|
|
|
|
// Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps
|
|
|
|
MachineSchedInfo::initializeResources();
|
|
|
|
|
|
|
|
// Machine-dependent fixups go here. None for now.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-15 00:30:44 +00:00
|
|
|
|
|
|
|
|
2001-09-14 03:47:57 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// class UltraSparcMachine
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
// Primary interface to machine description for the UltraSPARC.
|
|
|
|
// Primarily just initializes machine-dependent parameters in
|
|
|
|
// class TargetMachine, and creates machine-dependent subclasses
|
|
|
|
// for classes such as MachineInstrInfo.
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2001-09-18 13:01:29 +00:00
|
|
|
UltraSparc::UltraSparc()
|
|
|
|
: TargetMachine("UltraSparc-Native"),
|
|
|
|
instrInfo(),
|
|
|
|
schedInfo(&instrInfo),
|
|
|
|
regInfo( this )
|
|
|
|
{
|
2001-09-14 03:47:57 +00:00
|
|
|
optSizeForSubWordData = 4;
|
|
|
|
minMemOpWordSize = 8;
|
|
|
|
maxAtomicMemOpWordSize = 8;
|
|
|
|
}
|
|
|
|
|
2001-09-15 00:30:44 +00:00
|
|
|
|
2001-09-18 22:52:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UltraSparc::compileMethod(Method *M) {
|
|
|
|
|
2001-09-18 13:01:29 +00:00
|
|
|
if (SelectInstructionsForMethod(M, *this))
|
|
|
|
{
|
|
|
|
cerr << "Instruction selection failed for method " << M->getName()
|
|
|
|
<< "\n\n";
|
|
|
|
return true;
|
|
|
|
}
|
2001-09-15 00:30:44 +00:00
|
|
|
|
2001-09-18 13:01:29 +00:00
|
|
|
if (ScheduleInstructionsWithSSA(M, *this))
|
|
|
|
{
|
|
|
|
cerr << "Instruction scheduling before allocation failed for method "
|
|
|
|
<< M->getName() << "\n\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2001-09-18 22:52:44 +00:00
|
|
|
AllocateRegisters(M, *this); // allocate registers
|
|
|
|
|
|
|
|
|
2001-09-14 03:47:57 +00:00
|
|
|
return false;
|
|
|
|
}
|
2001-09-14 04:32:55 +00:00
|
|
|
|
2001-09-18 22:52:44 +00:00
|
|
|
|
|
|
|
|