X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV9%2FSparcV9TargetMachine.cpp;h=faed36c32a8e18fddde85239bb43f7330f564ab8;hb=601899d196db343670943285c8f989534710937e;hp=cf09734e81b184a977c7caa263a2d344d6d54c35;hpb=f6e0e2813526b4ebea473427ea5ffd88bb1559ac;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.cpp b/lib/Target/SparcV9/SparcV9TargetMachine.cpp index cf09734e81b..faed36c32a8 100644 --- a/lib/Target/SparcV9/SparcV9TargetMachine.cpp +++ b/lib/Target/SparcV9/SparcV9TargetMachine.cpp @@ -1,85 +1,117 @@ -//*************************************************************************** -// File: -// Sparc.cpp -// -// Purpose: -// -// History: -// 7/15/01 - Vikram Adve - Created -//**************************************************************************/ +//===-- Sparc.cpp - General implementation file for the Sparc Target ------===// +// +// This file contains the code for the Sparc Target that does not fit in any of +// the other files in this directory. +// +//===----------------------------------------------------------------------===// -#include "llvm/CodeGen/Sparc.h" #include "SparcInternals.h" -#include "llvm/Method.h" -#include "llvm/CodeGen/InstrScheduling.h" +#include "llvm/Target/TargetMachineImpls.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/PreSelection.h" +#include "llvm/CodeGen/StackSlots.h" +#include "llvm/CodeGen/PeepholeOpts.h" #include "llvm/CodeGen/InstrSelection.h" +#include "llvm/CodeGen/InstrScheduling.h" +#include "llvm/CodeGen/RegisterAllocation.h" +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/Reoptimizer/Mapping/MappingInfo.h" +#include "llvm/Reoptimizer/Mapping/FInfo.h" +#include "Support/CommandLine.h" +using std::cerr; - +// 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, 0 }, +#include "SparcInstr.def" +}; //--------------------------------------------------------------------------- -// 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. +// Command line options to control choice of code generation passes. //--------------------------------------------------------------------------- -/*ctor*/ -UltraSparcInstrInfo::UltraSparcInstrInfo() - : MachineInstrInfo(SparcMachineInstrDesc, - /*descSize = */ NUM_TOTAL_OPCODES, - /*numRealOpCodes = */ NUM_REAL_OPCODES) -{ -} +static cl::opt DisablePreSelect("nopreselect", + cl::desc("Disable preselection pass")); + +static cl::opt DisableSched("nosched", + cl::desc("Disable local scheduling pass")); + +static cl::opt DisablePeephole("nopeephole", + cl::desc("Disable peephole optimization pass")); + +//---------------------------------------------------------------------------- +// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine +// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) +//---------------------------------------------------------------------------- + +TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); } + //--------------------------------------------------------------------------- -// class UltraSparcSchedInfo +// class UltraSparcFrameInfo // // Purpose: -// Scheduling information for the UltraSPARC. -// Primarily just initializes machine-dependent parameters in -// class MachineSchedInfo. +// Interface to stack frame layout info for the UltraSPARC. +// Starting offsets for each area of the stack frame are aligned at +// a multiple of getStackFrameSizeAlignment(). //--------------------------------------------------------------------------- -/*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)) +int +UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction& , + bool& pos) const { - 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 + pos = false; // static stack area grows downwards + return StaticAreaOffsetFromFP; +} + +int +UltraSparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, + bool& pos) const +{ + mcInfo.freezeAutomaticVarsArea(); // ensure no more auto vars are added - // must be called after above parameters are initialized. - this->initializeResources(); + pos = false; // static stack area grows downwards + unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize(); + return StaticAreaOffsetFromFP - autoVarsSize; } -void -UltraSparcSchedInfo::initializeResources() +int +UltraSparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, + bool& pos) const { - // Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps - MachineSchedInfo::initializeResources(); + mcInfo.freezeAutomaticVarsArea(); // ensure no more auto vars are added + mcInfo.freezeSpillsArea(); // ensure no more spill slots are added - // Machine-dependent fixups go here. None for now. + pos = false; // static stack area grows downwards + unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize(); + unsigned int spillAreaSize = mcInfo.getRegSpillsSize(); + int offset = autoVarsSize + spillAreaSize; + return StaticAreaOffsetFromFP - offset; } +int +UltraSparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, + bool& pos) const +{ + // Dynamic stack area grows downwards starting at top of opt-args area. + // The opt-args, required-args, and register-save areas are empty except + // during calls and traps, so they are shifted downwards on each + // 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; +} //--------------------------------------------------------------------------- // class UltraSparcMachine @@ -92,30 +124,66 @@ UltraSparcSchedInfo::initializeResources() // //--------------------------------------------------------------------------- -UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"), - InstSchedulingInfo(&InstInfo) { - optSizeForSubWordData = 4; - minMemOpWordSize = 8; - maxAtomicMemOpWordSize = 8; - zeroRegNum = 0; // %g0 always gives 0 on Sparc +UltraSparc::UltraSparc() + : TargetMachine("UltraSparc-Native", 4), + schedInfo(*this), + regInfo(*this), + frameInfo(*this), + cacheInfo(*this), + optInfo(*this) { } -bool UltraSparc::compileMethod(Method *M) { - if (SelectInstructionsForMethod(M, *this)) { - cerr << "Instruction selection failed for method " << M->getName() - << "\n\n"; - return true; - } - - if (ScheduleInstructionsWithSSA(M, *this, InstSchedulingInfo)) { - cerr << "Instruction scheduling before allocation failed for method " - << M->getName() << "\n\n"; - return true; - } - return false; -} -// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine -// that implements the Sparc backend. +// addPassesToEmitAssembly - This method controls the entire code generation +// process for the ultra sparc. // -TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); } +bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) +{ + // Construct and initialize the MachineFunction object for this fn. + PM.add(createMachineCodeConstructionPass(*this)); + + //Insert empty stackslots in the stack frame of each function + //so %fp+offset-8 and %fp+offset-16 are empty slots now! + PM.add(createStackSlotsPass(*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(createLICMPass()); + PM.add(createGCSEPass()); + } + + PM.add(createInstructionSelectionPass(*this)); + + if (!DisableSched) + PM.add(createInstructionSchedulingWithSSAPass(*this)); + + PM.add(getRegisterAllocator(*this)); + + PM.add(getPrologEpilogInsertionPass()); + + if (!DisablePeephole) + PM.add(createPeepholeOptsPass(*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(Out)); + PM.add(createMachineCodeDestructionPass()); // 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)); + return false; +}