Move all the code that creates code generation passes from Sparc.cpp to

TargetMachine.cpp, since it is entirely machine-independent.
Also, add options to disable optional back-end passes (preselection and
instr. scheduling).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3740 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vikram S. Adve 2002-09-16 15:39:26 +00:00
parent 00020d3d01
commit e1f7280bf8
4 changed files with 201 additions and 106 deletions

View File

@ -21,8 +21,6 @@ class UltraSparc;
class PhyRegAlloc;
class Pass;
Pass *createPrologEpilogCodeInserter(TargetMachine &TM);
// OpCodeMask definitions for the Sparc V9
//
const OpCodeMask Immed = 0x00002000; // immed or reg operand?
@ -88,7 +86,7 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
//
// All immediate constants are in position 1 except the
// store instructions.
// store instructions and SETxx.
//
virtual int getImmedConstantPos(MachineOpCode opCode) const {
bool ignore;
@ -96,7 +94,11 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
{
assert(! this->isStore((MachineOpCode) STB - 1)); // 1st store opcode
assert(! this->isStore((MachineOpCode) STXFSR+1));// last store opcode
return (opCode >= STB && opCode <= STXFSR)? 2 : 1;
if (opCode==SETSW || opCode==SETUW || opCode==SETX || opCode==SETHI)
return 0;
if (opCode >= STB && opCode <= STXFSR)
return 2;
return 1;
}
else
return -1;
@ -113,6 +115,13 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
return (opCode == FCMPS || opCode == FCMPD || opCode == FCMPQ);
}
//-------------------------------------------------------------------------
// Queries about representation of LLVM quantities (e.g., constants)
//-------------------------------------------------------------------------
virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
const Instruction* I) const;
//-------------------------------------------------------------------------
// Code generation support for creating individual machine instructions
//-------------------------------------------------------------------------
@ -538,13 +547,22 @@ public:
UltraSparcFrameInfo(const TargetMachine &tgt) : MachineFrameInfo(tgt) {}
public:
// These methods provide constant parameters of the frame layout.
//
int getStackFrameSizeAlignment() const { return StackFrameSizeAlignment;}
int getMinStackFrameSize() const { return MinStackFrameSize; }
int getNumFixedOutgoingArgs() const { return NumFixedOutgoingArgs; }
int getSizeOfEachArgOnStack() const { return SizeOfEachArgOnStack; }
bool argsOnStackHaveFixedSize() const { return true; }
//
// This method adjusts a stack offset to meet alignment rules of target.
// The fixed OFFSET (0x7ff) must be subtracted and the result aligned.
virtual int adjustAlignment (int unalignedOffset,
bool growUp,
unsigned int align) const {
return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align);
}
// These methods compute offsets using the frame contents for a
// particular function. The frame contents are obtained from the
// MachineCodeInfoForMethod object for the given function.
@ -601,15 +619,58 @@ public:
}
private:
/*----------------------------------------------------------------------
This diagram shows the stack frame layout used by llc on Sparc V9.
Note that only the location of automatic variables, spill area,
temporary storage, and dynamically allocated stack area are chosen
by us. The rest conform to the Sparc V9 ABI.
All stack addresses are offset by OFFSET = 0x7ff (2047).
Alignment assumpteions and other invariants:
(1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary
(2) Variables in automatic, spill, temporary, or dynamic regions
are aligned according to their size as in all memory accesses.
(3) Everything below the dynamically allocated stack area is only used
during a call to another function, so it is never needed when
the current function is active. This is why space can be allocated
dynamically by incrementing %sp any time within the function.
STACK FRAME LAYOUT:
...
%fp+OFFSET+176 Optional extra incoming arguments# 1..N
%fp+OFFSET+168 Incoming argument #6
... ...
%fp+OFFSET+128 Incoming argument #1
... ...
---%fp+OFFSET-0--------Bottom of caller's stack frame--------------------
%fp+OFFSET-8 Automatic variables <-- ****TOP OF STACK FRAME****
Spill area
Temporary storage
...
%sp+OFFSET+176+8N Bottom of dynamically allocated stack area
%sp+OFFSET+168+8N Optional extra outgoing argument# N
... ...
%sp+OFFSET+176 Optional extra outgoing argument# 1
%sp+OFFSET+168 Outgoing argument #6
... ...
%sp+OFFSET+128 Outgoing argument #1
%sp+OFFSET+120 Save area for %i7
... ...
%sp+OFFSET+0 Save area for %l0 <-- ****BOTTOM OF STACK FRAME****
*----------------------------------------------------------------------*/
// All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
static const int OFFSET = (int) 0x7ff;
static const int StackFrameSizeAlignment = 16;
static const int MinStackFrameSize = 176;
static const int NumFixedOutgoingArgs = 6;
static const int SizeOfEachArgOnStack = 8;
static const int StaticAreaOffsetFromFP = 0 + OFFSET;
static const int FirstIncomingArgOffsetFromFP = 128 + OFFSET;
static const int FirstOptionalIncomingArgOffsetFromFP = 176 + OFFSET;
static const int StaticAreaOffsetFromFP = 0 + OFFSET;
static const int FirstOutgoingArgOffsetFromSP = 128 + OFFSET;
static const int FirstOptionalOutgoingArgOffsetFromSP = 176 + OFFSET;
};
@ -655,16 +716,17 @@ public:
virtual const MachineFrameInfo &getFrameInfo() const { return frameInfo; }
virtual const MachineCacheInfo &getCacheInfo() const { return cacheInfo; }
//
// addPassesToEmitAssembly - Add passes to the specified pass manager to get
// assembly langage code emited. For sparc, we have to do ...
//
virtual void addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
// getPrologEpilogCodeInserter - Inserts prolog/epilog code.
virtual Pass* getPrologEpilogInsertionPass();
private:
Pass *getFunctionAsmPrinterPass(PassManager &PM, std::ostream &Out);
Pass *getModuleAsmPrinterPass(PassManager &PM, std::ostream &Out);
Pass *getEmitBytecodeToAsmPass(std::ostream &Out);
// getFunctionAsmPrinterPass - Writes out machine code for a single function
virtual Pass* getFunctionAsmPrinterPass(std::ostream &Out);
// getModuleAsmPrinterPass - Writes generated machine code to assembly file.
virtual Pass* getModuleAsmPrinterPass(std::ostream &Out);
// getEmitBytecodeToAsmPass - Emits final LLVM bytecode to assembly file.
virtual Pass* getEmitBytecodeToAsmPass(std::ostream &Out);
};
#endif

View File

@ -162,6 +162,6 @@ void InsertPrologEpilogCode::InsertEpilogCode(Function &F)
}
}
Pass *createPrologEpilogCodeInserter(TargetMachine &TM) {
return new InsertPrologEpilogCode(TM);
Pass* UltraSparc::getPrologEpilogInsertionPass() {
return new InsertPrologEpilogCode(*this);
}

View File

@ -7,16 +7,9 @@
#include "SparcInternals.h"
#include "llvm/Target/Sparc.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/RegisterAllocation.h"
#include "llvm/Reoptimizer/Mapping/MappingInfo.h"
#include "llvm/Reoptimizer/Mapping/FInfo.h"
#include "llvm/Function.h"
#include "llvm/BasicBlock.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include <iostream>
using std::cerr;
@ -90,6 +83,8 @@ UltraSparcFrameInfo::getDynamicAreaOffset(MachineCodeForMethod& mcInfo,
// dynamic-size alloca.
pos = false;
unsigned int optArgsSize = mcInfo.getMaxOptionalArgsSize();
if (int extra = optArgsSize % getStackFrameSizeAlignment())
optArgsSize += (getStackFrameSizeAlignment() - extra);
int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
return offset;
@ -120,84 +115,3 @@ UltraSparc::UltraSparc()
maxAtomicMemOpWordSize = 8;
}
//===---------------------------------------------------------------------===//
// GenerateCodeForTarget Pass
//
// Native code generation for a specified target.
//===---------------------------------------------------------------------===//
class ConstructMachineCodeForFunction : public FunctionPass {
TargetMachine &Target;
public:
inline ConstructMachineCodeForFunction(TargetMachine &T) : Target(T) {}
const char *getPassName() const {
return "Sparc ConstructMachineCodeForFunction";
}
bool runOnFunction(Function &F) {
MachineCodeForMethod::construct(&F, Target);
return false;
}
};
struct FreeMachineCodeForFunction : public FunctionPass {
const char *getPassName() const { return "Sparc FreeMachineCodeForFunction"; }
static void freeMachineCode(Instruction &I) {
MachineCodeForInstruction::destroy(&I);
}
bool runOnFunction(Function &F) {
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
MachineCodeForInstruction::get(I).dropAllReferences();
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
for_each(FI->begin(), FI->end(), freeMachineCode);
return false;
}
};
// addPassesToEmitAssembly - This method controls the entire code generation
// process for the ultra sparc.
//
void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) {
// Construct and initialize the MachineCodeForMethod object for this fn.
PM.add(new ConstructMachineCodeForFunction(*this));
PM.add(createInstructionSelectionPass(*this));
PM.add(createInstructionSchedulingWithSSAPass(*this));
PM.add(getRegisterAllocator(*this));
//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.
PM.add(createPrologEpilogCodeInserter(*this));
PM.add(MappingInfoForFunction(Out));
// Output assembly language to the .s file. Assembly emission is split into
// two parts: Function output and Global value output. This is because
// function output is pipelined with all of the rest of code generation stuff,
// allowing machine code representations for functions to be free'd after the
// function has been emitted.
//
PM.add(getFunctionAsmPrinterPass(PM, Out));
PM.add(new FreeMachineCodeForFunction()); // Free stuff no longer needed
// Emit Module level assembly after all of the functions have been processed.
PM.add(getModuleAsmPrinterPass(PM, Out));
// Emit bytecode to the sparc assembly file into its special section next
PM.add(getEmitBytecodeToAsmPass(Out));
PM.add(getFunctionInfo(Out));
}

View File

@ -8,8 +8,30 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/MachineCacheInfo.h"
#include "llvm/CodeGen/PreSelection.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/RegisterAllocation.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Reoptimizer/Mapping/MappingInfo.h"
#include "llvm/Reoptimizer/Mapping/FInfo.h"
#include "llvm/Transforms/Scalar.h"
#include "Support/CommandLine.h"
#include "llvm/PassManager.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
//---------------------------------------------------------------------------
// Command line options to control choice of code generation passes.
//---------------------------------------------------------------------------
static cl::opt<bool> DisablePreSelect("nopreselect",
cl::desc("Disable preselection pass"));
static cl::opt<bool> DisableSched("nosched",
cl::desc("Disable local scheduling pass"));
//---------------------------------------------------------------------------
// class TargetMachine
//
@ -44,6 +66,99 @@ TargetMachine::findOptimalStorageSize(const Type* ty) const
}
//===---------------------------------------------------------------------===//
// Default code generation passes.
//
// Native code generation for a specified target.
//===---------------------------------------------------------------------===//
class ConstructMachineCodeForFunction : public FunctionPass {
TargetMachine &Target;
public:
inline ConstructMachineCodeForFunction(TargetMachine &T) : Target(T) {}
const char *getPassName() const {
return "ConstructMachineCodeForFunction";
}
bool runOnFunction(Function &F) {
MachineCodeForMethod::construct(&F, Target);
return false;
}
};
struct FreeMachineCodeForFunction : public FunctionPass {
const char *getPassName() const { return "FreeMachineCodeForFunction"; }
static void freeMachineCode(Instruction &I) {
MachineCodeForInstruction::destroy(&I);
}
bool runOnFunction(Function &F) {
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
MachineCodeForInstruction::get(I).dropAllReferences();
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
for_each(FI->begin(), FI->end(), freeMachineCode);
return false;
}
};
// addPassesToEmitAssembly - This method controls the entire code generation
// process for the ultra sparc.
//
void
TargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
{
// Construct and initialize the MachineCodeForMethod object for this fn.
PM.add(new ConstructMachineCodeForFunction(*this));
// Specialize LLVM code for this target machine and then
// run basic dataflow optimizations on LLVM code.
if (!DisablePreSelect)
{
PM.add(createPreSelectionPass(*this));
PM.add(createReassociatePass());
PM.add(createGCSEPass());
PM.add(createLICMPass());
}
PM.add(createInstructionSelectionPass(*this));
if (!DisableSched)
PM.add(createInstructionSchedulingWithSSAPass(*this));
PM.add(getRegisterAllocator(*this));
//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.
PM.add(getPrologEpilogInsertionPass());
PM.add(MappingInfoForFunction(Out));
// Output assembly language to the .s file. Assembly emission is split into
// two parts: Function output and Global value output. This is because
// function output is pipelined with all of the rest of code generation stuff,
// allowing machine code representations for functions to be free'd after the
// function has been emitted.
//
PM.add(getFunctionAsmPrinterPass(Out));
PM.add(new FreeMachineCodeForFunction()); // Free stuff no longer needed
// Emit Module level assembly after all of the functions have been processed.
PM.add(getModuleAsmPrinterPass(Out));
// Emit bytecode to the assembly file into its special section next
PM.add(getEmitBytecodeToAsmPass(Out));
PM.add(getFunctionInfo(Out));
}
//---------------------------------------------------------------------------
// class MachineInstructionInfo
// Interface to description of machine instructions
@ -79,6 +194,10 @@ MachineInstrInfo::constantFitsInImmedField(MachineOpCode opCode,
uint64_t maxImmedValue = maxImmedConstant(opCode, isSignExtended);
if (maxImmedValue != 0)
{
// NEED TO HANDLE UNSIGNED VALUES SINCE THEY MAY BECOME MUCH
// SMALLER AFTER CASTING TO SIGN-EXTENDED int, short, or char.
// See CreateUIntSetInstruction in SparcInstrInfo.cpp.
// Now check if the constant fits
if (intValue <= (int64_t) maxImmedValue &&
intValue >= -((int64_t) maxImmedValue+1))