diff options
author | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-09-16 15:39:26 +0000 |
---|---|---|
committer | Vikram S. Adve <vadve@cs.uiuc.edu> | 2002-09-16 15:39:26 +0000 |
commit | e1f7280bf8b54ea263ea146a94e287da8acb3c46 (patch) | |
tree | 58f96c3cd30bf507b780f4923759df4352301a5a | |
parent | 00020d3d01ef91080ca6ba9790b2b198e8543895 (diff) | |
download | external_llvm-e1f7280bf8b54ea263ea146a94e287da8acb3c46.zip external_llvm-e1f7280bf8b54ea263ea146a94e287da8acb3c46.tar.gz external_llvm-e1f7280bf8b54ea263ea146a94e287da8acb3c46.tar.bz2 |
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
-rw-r--r-- | lib/Target/SparcV9/SparcV9Internals.h | 92 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp | 4 | ||||
-rw-r--r-- | lib/Target/SparcV9/SparcV9TargetMachine.cpp | 92 | ||||
-rw-r--r-- | lib/Target/TargetMachine.cpp | 119 |
4 files changed, 201 insertions, 106 deletions
diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h index 1d9641d..4ff6064 100644 --- a/lib/Target/SparcV9/SparcV9Internals.h +++ b/lib/Target/SparcV9/SparcV9Internals.h @@ -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; @@ -114,6 +116,13 @@ struct UltraSparcInstrInfo : public MachineInstrInfo { } //------------------------------------------------------------------------- + // 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 diff --git a/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp b/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp index a355f2f..cfa71f6 100644 --- a/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp +++ b/lib/Target/SparcV9/SparcV9PrologEpilogInserter.cpp @@ -162,6 +162,6 @@ void InsertPrologEpilogCode::InsertEpilogCode(Function &F) } } -Pass *createPrologEpilogCodeInserter(TargetMachine &TM) { - return new InsertPrologEpilogCode(TM); +Pass* UltraSparc::getPrologEpilogInsertionPass() { + return new InsertPrologEpilogCode(*this); } diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.cpp b/lib/Target/SparcV9/SparcV9TargetMachine.cpp index be9159a..98c0131 100644 --- a/lib/Target/SparcV9/SparcV9TargetMachine.cpp +++ b/lib/Target/SparcV9/SparcV9TargetMachine.cpp @@ -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)); -} - diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 69c7cfd..84149f8 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -8,9 +8,31 @@ #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 // // Purpose: @@ -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)) |