X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLLVMTargetMachine.cpp;h=1234cb7fd9ab5e53552e7ec7c38797fedba7335b;hb=9f476e3179713a1e93bbf634855b85a93f8653cd;hp=4004cf1e1800a3e5b0f8eca818262089f6a64bf2;hpb=b013f5094c3bdb36472da996d63d5c0f75b6d4d3;p=oota-llvm.git diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 4004cf1e180..1234cb7fd9a 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -15,15 +15,22 @@ #include "llvm/PassManager.h" #include "llvm/Pass.h" #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Analysis/LoopPass.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/Collector.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/TargetRegistry.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; +namespace llvm { + bool EnableFastISel; +} + static cl::opt PrintLSR("print-lsr-output", cl::Hidden, cl::desc("Print LLVM IR produced by the loop-reduce pass")); static cl::opt PrintISelInput("print-isel-input", cl::Hidden, @@ -32,122 +39,52 @@ static cl::opt PrintEmittedAsm("print-emitted-asm", cl::Hidden, cl::desc("Dump emitter generated instructions as assembly")); static cl::opt PrintGCInfo("print-gc", cl::Hidden, cl::desc("Dump garbage collector data")); +static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, + cl::desc("Verify generated machine code"), + cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); + +// Enable or disable FastISel. Both options are needed, because +// FastISel is enabled by default with -fast, and we wish to be +// able to enable or disable fast-isel independently from -O0. +static cl::opt +EnableFastISelOption("fast-isel", cl::Hidden, + cl::desc("Enable the \"fast\" instruction selector")); + + +LLVMTargetMachine::LLVMTargetMachine(const Target &T, + const std::string &TargetTriple) + : TargetMachine(T) { + AsmInfo = T.createAsmInfo(TargetTriple); +} + -// Hidden options to help debugging -static cl::opt -EnableSinking("enable-sinking", cl::init(false), cl::Hidden, - cl::desc("Perform sinking on machine code")); -static cl::opt -AlignLoops("align-loops", cl::init(true), cl::Hidden, - cl::desc("Align loop headers")); -static cl::opt -PerformLICM("machine-licm", - cl::init(false), cl::Hidden, - cl::desc("Perform loop-invariant code motion on machine code")); - -// When this works it will be on by default. -static cl::opt -DisablePostRAScheduler("disable-post-RA-scheduler", - cl::desc("Disable scheduling after register allocation"), - cl::init(true)); FileModel::Model LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - std::ostream &Out, + formatted_raw_ostream &Out, CodeGenFileType FileType, - bool Fast) { - // Standard LLVM-Level Passes. - - // Run loop strength reduction before anything else. - if (!Fast) { - PM.add(createLoopStrengthReducePass(getTargetLowering())); - if (PrintLSR) - PM.add(new PrintFunctionPass("\n\n*** Code after LSR ***\n", &cerr)); - } - - PM.add(createGCLoweringPass()); - - if (!getTargetAsmInfo()->doesSupportExceptionHandling()) - PM.add(createLowerInvokePass(getTargetLowering())); - - // Make sure that no unreachable blocks are instruction selected. - PM.add(createUnreachableBlockEliminationPass()); - - if (!Fast) - PM.add(createCodeGenPreparePass(getTargetLowering())); - - if (PrintISelInput) - PM.add(new PrintFunctionPass("\n\n*** Final LLVM Code input to ISel ***\n", - &cerr)); - - // Ask the target for an isel. - if (addInstSelector(PM, Fast)) + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) return FileModel::Error; - // Print the instruction selected machine code... - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - if (PerformLICM) - PM.add(createMachineLICMPass()); - - if (EnableSinking) - PM.add(createMachineSinkingPass()); - - // Run pre-ra passes. - if (addPreRegAlloc(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - // Perform register allocation to convert to a concrete x86 representation - PM.add(createRegisterAllocator()); - - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - PM.add(createLowerSubregsPass()); - - if (PrintMachineCode) // Print the subreg lowered code - PM.add(createMachineFunctionPrinterPass(cerr)); - - // Run post-ra passes. - if (addPostRegAlloc(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - // Insert prolog/epilog code. Eliminate abstract frame index references... - PM.add(createPrologEpilogCodeInserter()); - - // Second pass scheduler. - if (!Fast && !DisablePostRAScheduler) - PM.add(createPostRAScheduler()); - - // Branch folding must be run after regalloc and prolog/epilog insertion. - if (!Fast) - PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); - - PM.add(createGCMachineCodeAnalysisPass()); - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - if (PrintGCInfo) - PM.add(createCollectorMetadataPrinter(*cerr)); - // Fold redundant debug labels. PM.add(createDebugLabelFoldingPass()); - - if (PrintMachineCode) // Print the register-allocated code - PM.add(createMachineFunctionPrinterPass(cerr)); - if (addPreEmitPass(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs())); + + if (addPreEmitPass(PM, OptLevel) && PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs())); - if (AlignLoops && !OptimizeForSize) - PM.add(createLoopAlignerPass()); + if (OptLevel != CodeGenOpt::None) + PM.add(createCodePlacementOptPass()); switch (FileType) { default: break; case TargetMachine::AssemblyFile: - if (addAssemblyEmitter(PM, Fast, Out)) + if (addAssemblyEmitter(PM, OptLevel, getAsmVerbosityDefault(), Out)) return FileModel::Error; return FileModel::AsmFile; case TargetMachine::ObjectFile: @@ -159,20 +96,64 @@ LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, return FileModel::Error; } - + +bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool Verbose, + formatted_raw_ostream &Out) { + FunctionPass *Printer = + getTarget().createAsmPrinter(Out, *this, getMCAsmInfo(), Verbose); + if (!Printer) + return true; + + PM.add(Printer); + return false; +} + /// addPassesToEmitFileFinish - If the passes to emit the specified file had to /// be split up (e.g., to add an object writer pass), this method can be used to /// finish up adding passes to emit the file, if necessary. bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, MachineCodeEmitter *MCE, - bool Fast) { + CodeGenOpt::Level OptLevel) { if (MCE) - addSimpleCodeEmitter(PM, Fast, PrintEmittedAsm, *MCE); - - PM.add(createCollectorMetadataDeleter()); + addSimpleCodeEmitter(PM, OptLevel, *MCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + JITCodeEmitter *JCE, + CodeGenOpt::Level OptLevel) { + if (JCE) + addSimpleCodeEmitter(PM, OptLevel, *JCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); - // Delete machine code for this function - PM.add(createMachineCodeDeleter()); + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + ObjectCodeEmitter *OCE, + CodeGenOpt::Level OptLevel) { + if (OCE) + addSimpleCodeEmitter(PM, OptLevel, *OCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); return false; // success! } @@ -185,94 +166,173 @@ bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, /// bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, MachineCodeEmitter &MCE, - bool Fast) { + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) + return true; + + if (addPreEmitPass(PM, OptLevel) && PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs())); + + addCodeEmitter(PM, OptLevel, MCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitMachineCode - Add passes to the specified pass manager to +/// get machine code emitted. This uses a MachineCodeEmitter object to handle +/// actually outputting the machine code and resolving things like the address +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, + JITCodeEmitter &JCE, + CodeGenOpt::Level OptLevel) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel)) + return true; + + if (addPreEmitPass(PM, OptLevel) && PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs())); + + addCodeEmitter(PM, OptLevel, JCE); + if (PrintEmittedAsm) + addAssemblyEmitter(PM, OptLevel, true, ferrs()); + + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +static void printAndVerify(PassManagerBase &PM, + bool allowDoubleDefs = false) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(errs())); + + if (VerifyMachineCode) + PM.add(createMachineVerifierPass(allowDoubleDefs)); +} + +/// addCommonCodeGenPasses - Add standard LLVM codegen passes used for both +/// emitting to assembly files or machine code output. +/// +bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { // Standard LLVM-Level Passes. - + // Run loop strength reduction before anything else. - if (!Fast) { + if (OptLevel != CodeGenOpt::None) { PM.add(createLoopStrengthReducePass(getTargetLowering())); if (PrintLSR) - PM.add(new PrintFunctionPass("\n\n*** Code after LSR ***\n", &cerr)); + PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &errs())); } - - PM.add(createGCLoweringPass()); - - if (!getTargetAsmInfo()->doesSupportExceptionHandling()) + + // Turn exception handling constructs into something the code generators can + // handle. + switch (getMCAsmInfo()->getExceptionHandlingType()) + { + case ExceptionHandling::SjLj: + // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + PM.add(createSjLjEHPass(getTargetLowering())); + break; + case ExceptionHandling::Dwarf: + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + break; + case ExceptionHandling::None: PM.add(createLowerInvokePass(getTargetLowering())); - + break; + } + + PM.add(createGCLoweringPass()); + // Make sure that no unreachable blocks are instruction selected. PM.add(createUnreachableBlockEliminationPass()); - if (!Fast) + if (OptLevel != CodeGenOpt::None) PM.add(createCodeGenPreparePass(getTargetLowering())); + PM.add(createStackProtectorPass(getTargetLowering())); + if (PrintISelInput) - PM.add(new PrintFunctionPass("\n\n*** Final LLVM Code input to ISel ***\n", - &cerr)); + PM.add(createPrintFunctionPass("\n\n" + "*** Final LLVM Code input to ISel ***\n", + &errs())); + + // Standard Lower-Level Passes. + + // Set up a MachineFunction for the rest of CodeGen to work on. + PM.add(new MachineFunctionAnalysis(*this, OptLevel)); + + // Enable FastISel with -fast, but allow that to be overridden. + if (EnableFastISelOption == cl::BOU_TRUE || + (OptLevel == CodeGenOpt::None && EnableFastISelOption != cl::BOU_FALSE)) + EnableFastISel = true; // Ask the target for an isel. - if (addInstSelector(PM, Fast)) + if (addInstSelector(PM, OptLevel)) return true; // Print the instruction selected machine code... - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + printAndVerify(PM, /* allowDoubleDefs= */ true); - if (PerformLICM) + if (OptLevel != CodeGenOpt::None) { PM.add(createMachineLICMPass()); - - if (EnableSinking) PM.add(createMachineSinkingPass()); + printAndVerify(PM, /* allowDoubleDefs= */ true); + } // Run pre-ra passes. - if (addPreRegAlloc(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (addPreRegAlloc(PM, OptLevel)) + printAndVerify(PM, /* allowDoubleDefs= */ true); - // Perform register allocation to convert to a concrete x86 representation + // Perform register allocation. PM.add(createRegisterAllocator()); - - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - PM.add(createLowerSubregsPass()); - - if (PrintMachineCode) // Print the subreg lowered code - PM.add(createMachineFunctionPrinterPass(cerr)); + + // Perform stack slot coloring. + if (OptLevel != CodeGenOpt::None) + // FIXME: Re-enable coloring with register when it's capable of adding + // kill markers. + PM.add(createStackSlotColoringPass(false)); + + printAndVerify(PM); // Print the register-allocated code // Run post-ra passes. - if (addPostRegAlloc(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (addPostRegAlloc(PM, OptLevel)) + printAndVerify(PM); + + PM.add(createLowerSubregsPass()); + printAndVerify(PM); // Insert prolog/epilog code. Eliminate abstract frame index references... PM.add(createPrologEpilogCodeInserter()); - - if (PrintMachineCode) // Print the register-allocated code - PM.add(createMachineFunctionPrinterPass(cerr)); - + printAndVerify(PM); + + // Run pre-sched2 passes. + if (addPreSched2(PM, OptLevel)) + printAndVerify(PM); + // Second pass scheduler. - if (!Fast) - PM.add(createPostRAScheduler()); + if (OptLevel != CodeGenOpt::None) { + PM.add(createPostRAScheduler(OptLevel)); + printAndVerify(PM); + } // Branch folding must be run after regalloc and prolog/epilog insertion. - if (!Fast) + if (OptLevel != CodeGenOpt::None) { PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); + printAndVerify(PM); + } PM.add(createGCMachineCodeAnalysisPass()); - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - + printAndVerify(PM); + if (PrintGCInfo) - PM.add(createCollectorMetadataPrinter(*cerr)); - - if (addPreEmitPass(PM, Fast) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE); - - PM.add(createCollectorMetadataDeleter()); - - // Delete machine code for this function - PM.add(createMachineCodeDeleter()); - - return false; // success! + PM.add(createGCInfoPrinter(errs())); + + return false; }