Newer
Older
// $Id$
//***************************************************************************
// File:
// Sparc.cpp
//
// Purpose:
//
// History:
// 7/15/01 - Vikram Adve - Created
//**************************************************************************/
#include "llvm/Target/Sparc.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
#include "llvm/Method.h"
// 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"
};
//----------------------------------------------------------------------------
// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
//----------------------------------------------------------------------------
//
TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
//----------------------------------------------------------------------------
// Entry point for register allocation for a module
//----------------------------------------------------------------------------
void AllocateRegisters(Method *M, TargetMachine &target)
{
if ( (M)->isExternal() ) // don't process prototypes
if( DEBUG_RA ) {
Chris Lattner
committed
cerr << endl << "******************** Method "<< (M)->getName();
cerr << " ********************" <<endl;
}
MethodLiveVarInfo LVI(M ); // Analyze live varaibles
LVI.analyze();
PhyRegAlloc PRA(M, target, &LVI); // allocate registers
PRA.allocateRegisters();
Chris Lattner
committed
if( DEBUG_RA ) cerr << endl << "Register allocation complete!" << endl;
}
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Initialize the required area of the stack frame.
static void
InitializeFrameLayout(Method *method, TargetMachine &target)
{
int minFrameSize = ((UltraSparc&) target).getFrameInfo().MinStackFrameSize;
method->getMachineCode().incrementStackSize(minFrameSize);
}
//---------------------------------------------------------------------------
// Function InsertPrologCode
// Function InsertEpilogCode
// Function InsertPrologEpilog
//
// Insert prolog code at the unique method entry point.
// Insert epilog code at each method exit point.
// InsertPrologEpilog invokes these only if the method is not compiled
// with the leaf method optimization.
//---------------------------------------------------------------------------
static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
static void
InsertPrologCode(Method* method, TargetMachine& target)
{
BasicBlock* entryBB = method->getEntryNode();
unsigned N = GetInstructionsForProlog(entryBB, target, minstrVec);
assert(N <= MAX_INSTR_PER_VMINSTR);
if (N > 0)
{
MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N);
}
}
static void
InsertEpilogCode(Method* method, TargetMachine& target)
{
for (Method::iterator I=method->begin(), E=method->end(); I != E; ++I)
if ((*I)->getTerminator()->getOpcode() == Instruction::Ret)
{
BasicBlock* exitBB = *I;
unsigned N = GetInstructionsForEpilog(exitBB, target, minstrVec);
MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec();
MachineCodeForVMInstr& termMvec =
exitBB->getTerminator()->getMachineInstrVec();
// Remove the NOPs in the delay slots of the return instruction
const MachineInstrInfo& mii = target.getInstrInfo();
unsigned numNOPs = 0;
while (termMvec.back()->getOpCode() == NOP)
{
assert( termMvec.back() == bbMvec.back());
termMvec.pop_back();
bbMvec.pop_back();
++numNOPs;
}
assert(termMvec.back() == bbMvec.back());
// Check that we found the right number of NOPs and have the right
// number of instructions to replace them.
unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode());
assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
assert(N == ndelays && "Cannot use epilog code for delay slots?");
// Append the epilog code to the end of the basic block.
bbMvec.push_back(minstrVec[0]);
}
}
// Insert SAVE/RESTORE instructions for the method
static void
InsertPrologEpilog(Method *method, TargetMachine &target)
{
MachineCodeForMethod& mcodeInfo = method->getMachineCode();
if (mcodeInfo.isCompiledAsLeafMethod())
return; // nothing to do
InsertPrologCode(method, target);
InsertEpilogCode(method, target);
}
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//---------------------------------------------------------------------------
// 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.
}
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//---------------------------------------------------------------------------
// class UltraSparcFrameInfo
//
// Purpose:
// Interface to stack frame layout info for the UltraSPARC.
// Note that there is no machine-independent interface to this information
//---------------------------------------------------------------------------
int
UltraSparcFrameInfo::getFirstAutomaticVarOffsetFromFP (const Method* method)
{
return StaticStackAreaOffsetFromFP;
}
int
UltraSparcFrameInfo::getRegSpillAreaOffsetFromFP(const Method* method)
{
unsigned int autoVarsSize = method->getMachineCode().getAutomaticVarsSize();
return StaticStackAreaOffsetFromFP + autoVarsSize;
}
int
UltraSparcFrameInfo::getFrameSizeBelowDynamicArea(const Method* method)
{
unsigned int optArgsSize =
method->getMachineCode().getOptionalOutgoingArgsSize();
return optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
}
//---------------------------------------------------------------------------
// 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.
//
//---------------------------------------------------------------------------
UltraSparc::UltraSparc()
: TargetMachine("UltraSparc-Native"),
instrInfo(),
schedInfo(&instrInfo),
regInfo( this ),
frameInfo()
{
optSizeForSubWordData = 4;
minMemOpWordSize = 8;
maxAtomicMemOpWordSize = 8;
}
void
ApplyPeepholeOptimizations(Method *method, TargetMachine &target)
{
return;
// OptimizeLeafProcedures();
// DeleteFallThroughBranches();
// RemoveChainedBranches(); // should be folded with previous
// RemoveRedundantOps(); // operations with %g0, NOP, etc.
}
bool
UltraSparc::compileMethod(Method *M)
{
InitializeFrameLayout(M, *this); // initialize the required area of
// the stack frame
if (SelectInstructionsForMethod(M, *this))
{
cerr << "Instruction selection failed for method " << M->getName()
<< "\n\n";
return true;
}
if (ScheduleInstructionsWithSSA(M, *this))
{
cerr << "Instruction scheduling before allocation failed for method "
<< M->getName() << "\n\n";
return true;
}
AllocateRegisters(M, *this); // allocate registers
ApplyPeepholeOptimizations(M, *this); // machine-dependent peephole opts
InsertPrologEpilog(M, *this);