Convert sparc backend over to use pass based compilation structure.

Convert some stages into passes in preparation for more splitting up.
Try to decouple stuff as much as possible.

llvm-svn: 1663
This commit is contained in:
Chris Lattner 2002-02-03 23:41:51 +00:00
parent d682045227
commit 84fa1e7801
1 changed files with 120 additions and 97 deletions

View File

@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/PhyRegAlloc.h"
#include "llvm/Method.h"
#include "llvm/PassManager.h"
#include <iostream>
using std::cerr;
@ -43,71 +44,81 @@ 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
return;
class RegisterAllocation : public MethodPass {
TargetMachine &Target;
public:
inline RegisterAllocation(TargetMachine &T) : Target(T) {}
bool runOnMethod(Method *M) {
if (DEBUG_RA)
cerr << "\n******************** Method "<< M->getName()
<< " ********************\n";
if( DEBUG_RA )
cerr << "\n******************** Method "<< M->getName()
<< " ********************\n";
MethodLiveVarInfo LVI(M ); // Analyze live varaibles
LVI.analyze();
PhyRegAlloc PRA(M, target, &LVI); // allocate registers
PRA.allocateRegisters();
MethodLiveVarInfo LVI(M ); // Analyze live varaibles
LVI.analyze();
PhyRegAlloc PRA(M, Target, &LVI); // allocate registers
PRA.allocateRegisters();
if( DEBUG_RA ) cerr << "\nRegister allocation complete!\n";
}
if (DEBUG_RA) cerr << "\nRegister allocation complete!\n";
return false;
}
};
static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
//---------------------------------------------------------------------------
// Function InsertPrologCode
// Function InsertEpilogCode
// Function InsertPrologEpilog
//
// class InsertPrologEpilogCode
//
// Insert SAVE/RESTORE instructions for the method
//
// 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];
class InsertPrologEpilogCode : public MethodPass {
TargetMachine &Target;
public:
inline InsertPrologEpilogCode(TargetMachine &T) : Target(T) {}
bool runOnMethod(Method *M) {
MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(M);
if (!mcodeInfo.isCompiledAsLeafMethod()) {
InsertPrologCode(M);
InsertEpilogCode(M);
}
return false;
}
static void
InsertPrologCode(Method* method, TargetMachine& target)
void InsertPrologCode(Method *M);
void InsertEpilogCode(Method *M);
};
void InsertPrologEpilogCode::InsertPrologCode(Method* method)
{
BasicBlock* entryBB = method->getEntryNode();
unsigned N = GetInstructionsForProlog(entryBB, target, minstrVec);
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);
}
MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N);
}
static void
InsertEpilogCode(Method* method, TargetMachine& target)
void InsertPrologEpilogCode::InsertEpilogCode(Method* method)
{
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);
unsigned N = GetInstructionsForEpilog(exitBB, Target, minstrVec);
MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec();
MachineCodeForInstruction &termMvec =
MachineCodeForInstruction::get(exitBB->getTerminator());
// Remove the NOPs in the delay slots of the return instruction
const MachineInstrInfo &mii = target.getInstrInfo();
const MachineInstrInfo &mii = Target.getInstrInfo();
unsigned numNOPs = 0;
while (termMvec.back()->getOpCode() == NOP)
{
@ -130,17 +141,7 @@ InsertEpilogCode(Method* method, TargetMachine& target)
}
// Insert SAVE/RESTORE instructions for the method
static void
InsertPrologEpilog(Method *method, TargetMachine &target)
{
MachineCodeForMethod& mcodeInfo = MachineCodeForMethod::get(method);
if (mcodeInfo.isCompiledAsLeafMethod())
return; // nothing to do
InsertPrologCode(method, target);
InsertEpilogCode(method, target);
}
//---------------------------------------------------------------------------
@ -267,63 +268,85 @@ UltraSparc::UltraSparc()
}
void
ApplyPeepholeOptimizations(Method *method, TargetMachine &target)
{
return;
// OptimizeLeafProcedures();
// DeleteFallThroughBranches();
// RemoveChainedBranches(); // should be folded with previous
// RemoveRedundantOps(); // operations with %g0, NOP, etc.
}
//===---------------------------------------------------------------------===//
// GenerateCodeForTarget Pass
//
// Native code generation for a specified target.
//===---------------------------------------------------------------------===//
class ConstructMachineCodeForMethod : public MethodPass {
TargetMachine &Target;
public:
inline ConstructMachineCodeForMethod(TargetMachine &T) : Target(T) {}
bool runOnMethod(Method *M) {
MachineCodeForMethod::construct(M, Target);
return false;
}
};
class InstructionSelection : public MethodPass {
TargetMachine &Target;
public:
inline InstructionSelection(TargetMachine &T) : Target(T) {}
bool runOnMethod(Method *M) {
if (SelectInstructionsForMethod(M, Target))
cerr << "Instr selection failed for method " << M->getName() << "\n";
return false;
}
};
class InstructionScheduling : public MethodPass {
TargetMachine &Target;
public:
inline InstructionScheduling(TargetMachine &T) : Target(T) {}
bool runOnMethod(Method *M) {
if (ScheduleInstructionsWithSSA(M, Target))
cerr << "Instr scheduling failed for method " << M->getName() << "\n\n";
return false;
}
};
struct FreeMachineCodeForMethod : public MethodPass {
static void freeMachineCode(Instruction *I) {
MachineCodeForInstruction::destroy(I);
}
bool runOnMethod(Method *M) {
for_each(M->inst_begin(), M->inst_end(), freeMachineCode);
// Don't destruct MachineCodeForMethod - The global printer needs it
//MachineCodeForMethod::destruct(M);
return false;
}
};
bool
UltraSparc::compileMethod(Method *method)
{
void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) {
// Construct and initialize the MachineCodeForMethod object for this method.
MachineCodeForMethod::construct(method, *this);
if (SelectInstructionsForMethod(method, *this))
{
cerr << "Instruction selection failed for method " << method->getName()
<< "\n\n";
return true;
}
PM.add(new ConstructMachineCodeForMethod(*this));
/*
if (ScheduleInstructionsWithSSA(method, *this))
{
cerr << "Instruction scheduling before allocation failed for method "
<< method->getName() << "\n\n";
return true;
}
*/
PM.add(new InstructionSelection(*this));
AllocateRegisters(method, *this); // allocate registers
//PM.add(new InstructionScheduling(*this));
PM.add(new RegisterAllocation(*this));
ApplyPeepholeOptimizations(method, *this); // machine-dependent peephole opts
//PM.add(new OptimizeLeafProcedures());
//PM.add(new DeleteFallThroughBranches());
//PM.add(new RemoveChainedBranches()); // should be folded with previous
//PM.add(new RemoveRedundantOps()); // operations with %g0, NOP, etc.
InsertPrologEpilog(method, *this);
PM.add(new InsertPrologEpilogCode(*this));
return false;
}
static void freeMachineCode(Instruction *I) {
MachineCodeForInstruction::destroy(I);
}
//
// freeCompiledMethod - Release all memory associated with the compiled image
// for this method.
//
void
UltraSparc::freeCompiledMethod(Method *M)
{
for_each(M->inst_begin(), M->inst_end(), freeMachineCode);
// Don't destruct MachineCodeForMethod - The global printer needs it
//MachineCodeForMethod::destruct(M);
// Output assembly language to the .s file. Assembly emission is split into
// two parts: Method output and Global value output. This is because method
// output is pipelined with all of the rest of code generation stuff,
// allowing machine code representations for methods to be free'd after the
// method has been emitted.
//
PM.add(getMethodAsmPrinterPass(PM, Out));
PM.add(new FreeMachineCodeForMethod()); // Free stuff no longer needed
// Emit Module level assembly after all of the methods have been processed.
PM.add(getModuleAsmPrinterPass(PM, Out));
}