X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV9%2FSparcV9TargetMachine.cpp;h=71e323918060f2db97cc7f16ee06a61e7ee909b6;hb=20a3be3ba832947d1dc5e6b26ae68335a7914aff;hp=b026ccd67a0d58fd21558cdf2b7991b5e6865ecc;hpb=221d688a5ef21a22c2368c9fff0e92d7966c95e5;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9TargetMachine.cpp b/lib/Target/SparcV9/SparcV9TargetMachine.cpp index b026ccd67a0..71e32391806 100644 --- a/lib/Target/SparcV9/SparcV9TargetMachine.cpp +++ b/lib/Target/SparcV9/SparcV9TargetMachine.cpp @@ -1,134 +1,81 @@ -// $Id$ -//*************************************************************************** -// 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 "SparcInternals.h" -#include "llvm/Target/Sparc.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/MachineFunctionInfo.h" +#include "llvm/CodeGen/PreSelection.h" +#include "llvm/CodeGen/StackSlots.h" +#include "llvm/CodeGen/PeepholeOpts.h" #include "llvm/CodeGen/InstrSelection.h" -#include "llvm/CodeGen/MachineCodeForInstruction.h" -#include "llvm/CodeGen/MachineCodeForMethod.h" +#include "llvm/CodeGen/InstrScheduling.h" #include "llvm/CodeGen/RegisterAllocation.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Method.h" -#include "llvm/BasicBlock.h" -#include "llvm/PassManager.h" -#include -using std::cerr; +#include "llvm/CodeGen/MachineCodeForInstruction.h" +#include "llvm/Reoptimizer/Mapping/MappingInfo.h" +#include "Support/CommandLine.h" +#include "llvm/Assembly/PrintModulePass.h" +static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */ // Build the MachineInstruction Description Array... -const MachineInstrDescriptor SparcMachineInstrDesc[] = { +const TargetInstrDescriptor SparcMachineInstrDesc[] = { #define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \ NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS) \ { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \ - NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS }, + NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0, \ + ImplicitRegUseList, ImplicitRegUseList }, #include "SparcInstr.def" }; -//---------------------------------------------------------------------------- -// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine -// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) -//---------------------------------------------------------------------------- -// +//--------------------------------------------------------------------------- +// Command line options to control choice of code generation passes. +//--------------------------------------------------------------------------- -TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); } +static cl::opt DisablePreOpt("disable-preopt", + cl::desc("Disable optimizations prior to instruction selection")); +static cl::opt DisableSched("disable-sched", + cl::desc("Disable local scheduling pass")); -//--------------------------------------------------------------------------- -// 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 cl::opt DisablePeephole("disable-peephole", + cl::desc("Disable peephole optimization pass")); - void InsertPrologCode(Method *M); - void InsertEpilogCode(Method *M); -}; +static cl::opt EmitMappingInfo("emitmaps", + cl::desc("Emit LLVM-to-MachineCode mapping info to assembly")); -void InsertPrologEpilogCode::InsertPrologCode(Method* method) -{ - BasicBlock* entryBB = method->getEntryNode(); - unsigned N = GetInstructionsForProlog(entryBB, Target, minstrVec); - assert(N <= MAX_INSTR_PER_VMINSTR); - MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec(); - bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N); -} +static cl::opt DisableStrip("disable-strip", + cl::desc("Do not strip the LLVM bytecode included in executable")); +static cl::opt DumpInput("dump-input", + cl::desc("Print bytecode before native code generation"), + cl::Hidden); -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); - - 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(); - 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]); - } -} +//---------------------------------------------------------------------------- +// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine +// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) +//---------------------------------------------------------------------------- +TargetMachine *allocateSparcTargetMachine(unsigned Configuration) { + return new UltraSparc(); +} //--------------------------------------------------------------------------- // class UltraSparcFrameInfo // -// Purpose: // 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(). //--------------------------------------------------------------------------- int -UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineCodeForMethod& , +UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction& , bool& pos) const { pos = false; // static stack area grows downwards @@ -136,41 +83,49 @@ UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineCodeForMethod& , } int -UltraSparcFrameInfo::getRegSpillAreaOffset(MachineCodeForMethod& mcInfo, +UltraSparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, bool& pos) const { + // ensure no more auto vars are added + mcInfo.getInfo()->freezeAutomaticVarsArea(); + pos = false; // static stack area grows downwards - unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize(); - if (int mod = autoVarsSize % getStackFrameSizeAlignment()) - autoVarsSize += (getStackFrameSizeAlignment() - mod); + unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize(); return StaticAreaOffsetFromFP - autoVarsSize; } int -UltraSparcFrameInfo::getTmpAreaOffset(MachineCodeForMethod& mcInfo, +UltraSparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, bool& pos) const { + MachineFunctionInfo *MFI = mcInfo.getInfo(); + MFI->freezeAutomaticVarsArea(); // ensure no more auto vars are added + MFI->freezeSpillsArea(); // ensure no more spill slots are added + pos = false; // static stack area grows downwards - unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize(); - unsigned int spillAreaSize = mcInfo.getRegSpillsSize(); + unsigned autoVarsSize = MFI->getAutomaticVarsSize(); + unsigned spillAreaSize = MFI->getRegSpillsSize(); int offset = autoVarsSize + spillAreaSize; - if (int mod = offset % getStackFrameSizeAlignment()) - offset += (getStackFrameSizeAlignment() - mod); return StaticAreaOffsetFromFP - offset; } int -UltraSparcFrameInfo::getDynamicAreaOffset(MachineCodeForMethod& mcInfo, +UltraSparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, bool& pos) const { - // dynamic stack area grows downwards starting at top of opt-args area - unsigned int optArgsSize = mcInfo.getMaxOptionalArgsSize(); + // 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 optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize(); + if (int extra = optArgsSize % getStackFrameSizeAlignment()) + optArgsSize += (getStackFrameSizeAlignment() - extra); int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP; - assert(offset % getStackFrameSizeAlignment() == 0); + assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0); return offset; } - //--------------------------------------------------------------------------- // class UltraSparcMachine // @@ -178,103 +133,130 @@ UltraSparcFrameInfo::getDynamicAreaOffset(MachineCodeForMethod& mcInfo, // 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. +// for classes such as TargetInstrInfo. // //--------------------------------------------------------------------------- UltraSparc::UltraSparc() - : TargetMachine("UltraSparc-Native"), - instrInfo(*this), + : TargetMachine("UltraSparc-Native", false), schedInfo(*this), regInfo(*this), frameInfo(*this), - cacheInfo(*this) -{ - optSizeForSubWordData = 4; - minMemOpWordSize = 8; - maxAtomicMemOpWordSize = 8; + cacheInfo(*this), + optInfo(*this) { } +// addPassesToEmitAssembly - This method controls the entire code generation +// process for the ultra sparc. +// +bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) +{ + // The following 3 passes used to be inserted specially by llc. + // Replace malloc and free instructions with library calls. + PM.add(createLowerAllocationsPass()); + + // Strip all of the symbols from the bytecode so that it will be smaller... + if (!DisableStrip) + PM.add(createSymbolStrippingPass()); -//===---------------------------------------------------------------------===// -// 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; + // FIXME: implement the switch instruction in the instruction selector. + PM.add(createLowerSwitchPass()); + + // decompose multi-dimensional array references into single-dim refs + PM.add(createDecomposeMultiDimRefsPass()); + + // 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)); + + if (!DisablePreOpt) { + // Specialize LLVM code for this target machine + PM.add(createPreSelectionPass(*this)); + // Run basic dataflow optimizations on LLVM code + PM.add(createReassociatePass()); + PM.add(createLICMPass()); + PM.add(createGCSEPass()); } -}; + + // If LLVM dumping after transformations is requested, add it to the pipeline + if (DumpInput) + PM.add(new PrintFunctionPass("Input code to instsr. selection:\n", + &std::cerr)); -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; - } -}; + PM.add(createInstructionSelectionPass(*this)); -struct FreeMachineCodeForMethod : public MethodPass { - static void freeMachineCode(Instruction *I) { - MachineCodeForInstruction::destroy(I); - } + if (!DisableSched) + PM.add(createInstructionSchedulingWithSSAPass(*this)); - bool runOnMethod(Method *M) { - for (Method::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) - for (BasicBlock::iterator I = (*MI)->begin(), E = (*MI)->end(); - I != E; ++I) - freeMachineCode(*I); + PM.add(getRegisterAllocator(*this)); - // Don't destruct MachineCodeForMethod - The global printer needs it - //MachineCodeForMethod::destruct(M); - return false; - } -}; + PM.add(getPrologEpilogInsertionPass()); + if (!DisablePeephole) + PM.add(createPeepholeOptsPass(*this)); + if (EmitMappingInfo) + PM.add(getMappingInfoCollector(Out)); -// addPassesToEmitAssembly - This method controls the entire code generation -// process for the ultra sparc. + // 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 + if (EmitMappingInfo) { + PM.add(getEmitBytecodeToAsmPass(Out)); + PM.add(getFunctionInfo(Out)); + } + + return false; +} + +// addPassesToJITCompile - This method controls the JIT method of code +// generation for the UltraSparc. // -void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) { - // Construct and initialize the MachineCodeForMethod object for this method. - PM.add(new ConstructMachineCodeForMethod(*this)); +bool UltraSparc::addPassesToJITCompile(PassManager &PM) { + const TargetData &TD = getTargetData(); - PM.add(new InstructionSelection(*this)); + PM.add(new TargetData("lli", TD.isLittleEndian(), TD.getPointerSize(), + TD.getPointerAlignment(), TD.getDoubleAlignment())); - //PM.add(createInstructionSchedulingWithSSAPass(*this)); + // Replace malloc and free instructions with library calls. + // Do this after tracing until lli implements these lib calls. + // For now, it will emulate malloc and free internally. + PM.add(createLowerAllocationsPass()); - 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(new InsertPrologEpilogCode(*this)); + // FIXME: implement the switch instruction in the instruction selector. + PM.add(createLowerSwitchPass()); + + // decompose multi-dimensional array references into single-dim refs + PM.add(createDecomposeMultiDimRefsPass()); - // 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 + // Construct and initialize the MachineFunction object for this fn. + PM.add(createMachineCodeConstructionPass(*this)); + + PM.add(createInstructionSelectionPass(*this)); + + // new pass: convert Value* in MachineOperand to an unsigned register + // this brings it in line with what the X86 JIT's RegisterAllocator expects + //PM.add(createAddRegNumToValuesPass()); + + PM.add(getRegisterAllocator(*this)); + PM.add(getPrologEpilogInsertionPass()); - // Emit Module level assembly after all of the methods have been processed. - PM.add(getModuleAsmPrinterPass(PM, Out)); + if (!DisablePeephole) + PM.add(createPeepholeOptsPass(*this)); - // Emit bytecode to the sparc assembly file into its special section next - PM.add(getEmitBytecodeToAsmPass(Out)); + return false; // success! }