X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLLVMTargetMachine.cpp;h=80dfc763af6977c4a7efcb30d370bc11f534942a;hb=463b3c2a9974acf7586d1e6a4416aa7cc004ff0e;hp=733995f82be8dd4cd070c2b9d68c326c1cba6c9e;hpb=81d22d87de93f501f90f55b6bbc63f5dd286797a;p=oota-llvm.git diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 733995f82be..80dfc763af6 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -13,19 +13,26 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/PassManager.h" -#include "llvm/Pass.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/StandardPasses.h" using namespace llvm; namespace llvm { @@ -38,12 +45,17 @@ static cl::opt DisableBranchFold("disable-branch-fold", cl::Hidden, cl::desc("Disable branch folding")); static cl::opt DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, cl::desc("Disable tail duplication")); +static cl::opt DisableEarlyTailDup("disable-early-taildup", cl::Hidden, + cl::desc("Disable pre-register allocation tail duplication")); static cl::opt DisableCodePlace("disable-code-place", cl::Hidden, cl::desc("Disable code placement")); static cl::opt DisableSSC("disable-ssc", cl::Hidden, cl::desc("Disable Stack Slot Coloring")); static cl::opt DisableMachineLICM("disable-machine-licm", cl::Hidden, cl::desc("Disable Machine LICM")); +static cl::opt DisablePostRAMachineLICM("disable-postra-machine-licm", + cl::Hidden, + cl::desc("Disable Machine LICM")); static cl::opt DisableMachineSink("disable-machine-sink", cl::Hidden, cl::desc("Disable Machine Sinking")); static cl::opt DisableLSR("disable-lsr", cl::Hidden, @@ -54,14 +66,30 @@ 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, cl::desc("Print LLVM IR input to isel pass")); -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 ShowMCEncoding("show-mc-encoding", cl::Hidden, + cl::desc("Show encoding in .s output")); +static cl::opt ShowMCInst("show-mc-inst", cl::Hidden, + cl::desc("Show instruction structure in .s output")); +static cl::opt EnableMCLogging("enable-mc-api-logging", cl::Hidden, + cl::desc("Enable MC API logging")); static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); +static cl::opt +AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), + cl::init(cl::BOU_UNSET)); + +static bool getVerboseAsm() { + switch (AsmVerbose) { + default: + case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault(); + case cl::BOU_TRUE: return true; + case cl::BOU_FALSE: return false; + } +} // Enable or disable FastISel. Both options are needed, because // FastISel is enabled by default with -fast, and we wish to be @@ -76,195 +104,178 @@ EnableFastISelOption("fast-isel", cl::Hidden, static cl::opt EnableSplitGEPGVN("split-gep-gvn", cl::Hidden, cl::desc("Split GEPs and run no-load GVN")); -static cl::opt PreAllocTailDup("pre-regalloc-taildup", cl::Hidden, - cl::desc("Pre-register allocation tail duplication")); - LLVMTargetMachine::LLVMTargetMachine(const Target &T, - const std::string &TargetTriple) - : TargetMachine(T) { + const std::string &Triple) + : TargetMachine(T), TargetTriple(Triple) { AsmInfo = T.createAsmInfo(TargetTriple); } // Set the default code model for the JIT for a generic target. // FIXME: Is small right here? or .is64Bit() ? Large : Small? -void -LLVMTargetMachine::setCodeModelForJIT() { +void LLVMTargetMachine::setCodeModelForJIT() { setCodeModel(CodeModel::Small); } // Set the default code model for static compilation for a generic target. -void -LLVMTargetMachine::setCodeModelForStatic() { +void LLVMTargetMachine::setCodeModelForStatic() { setCodeModel(CodeModel::Small); } -FileModel::Model -LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - formatted_raw_ostream &Out, - CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { +bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) - return FileModel::Error; + MCContext *Context = 0; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Context)) + return true; + assert(Context != 0 && "Failed to get MCContext"); + + const MCAsmInfo &MAI = *getMCAsmInfo(); + OwningPtr AsmStreamer; switch (FileType) { - default: + default: return true; + case CGFT_AssemblyFile: { + MCInstPrinter *InstPrinter = + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); + + // Create a code emitter if asked to show the encoding. + MCCodeEmitter *MCE = 0; + TargetAsmBackend *TAB = 0; + if (ShowMCEncoding) { + MCE = getTarget().createCodeEmitter(*this, *Context); + TAB = getTarget().createAsmBackend(TargetTriple); + } + + MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, + getVerboseAsm(), + hasMCUseLoc(), + InstPrinter, + MCE, TAB, + ShowMCInst); + AsmStreamer.reset(S); + break; + } + case CGFT_ObjectFile: { + // Create the code emitter for the target if it exists. If not, .o file + // emission fails. + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Context); + TargetAsmBackend *TAB = getTarget().createAsmBackend(TargetTriple); + if (MCE == 0 || TAB == 0) + return true; + + AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Context, + *TAB, Out, MCE, + hasMCRelaxAll(), + hasMCNoExecStack())); + AsmStreamer.get()->InitSections(); + break; + } + case CGFT_Null: + // The Null output is intended for use for performance analysis and testing, + // not real users. + AsmStreamer.reset(createNullStreamer(*Context)); break; - case TargetMachine::AssemblyFile: - if (addAssemblyEmitter(PM, OptLevel, getAsmVerbosityDefault(), Out)) - return FileModel::Error; - return FileModel::AsmFile; - case TargetMachine::ObjectFile: - if (getMachOWriterInfo()) - return FileModel::MachOFile; - else if (getELFWriterInfo()) - return FileModel::ElfFile; } - return FileModel::Error; -} + if (EnableMCLogging) + AsmStreamer.reset(createLoggingStreamer(AsmStreamer.take(), errs())); -bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - bool Verbose, - formatted_raw_ostream &Out) { - FunctionPass *Printer = - getTarget().createAsmPrinter(Out, *this, getMCAsmInfo(), Verbose); - if (!Printer) + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); + if (Printer == 0) return true; - PM.add(Printer); - return false; -} + // If successful, createAsmPrinter took ownership of AsmStreamer. + AsmStreamer.take(); -/// 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, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForStatic(); - - if (MCE) - 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) { - // Make sure the code model is set. - setCodeModelForJIT(); - - if (JCE) - addSimpleCodeEmitter(PM, OptLevel, *JCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - - PM.add(createGCInfoDeleter()); - - return false; // success! -} + PM.add(Printer); -/// 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) { // Make sure the code model is set. setCodeModelForStatic(); - - if (OCE) - addSimpleCodeEmitter(PM, OptLevel, *OCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - PM.add(createGCInfoDeleter()); - - return false; // success! + return false; } /// addPassesToEmitMachineCode - Add passes to the specified pass manager to -/// get machine code emitted. This uses a MachineCodeEmitter object to handle +/// get machine code emitted. This uses a JITCodeEmitter 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, - MachineCodeEmitter &MCE, - CodeGenOpt::Level OptLevel) { + JITCodeEmitter &JCE, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Make sure the code model is set. setCodeModelForJIT(); - + // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) + MCContext *Ctx = 0; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) return true; - addCodeEmitter(PM, OptLevel, MCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - + addCodeEmitter(PM, OptLevel, JCE); 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. +/// addPassesToEmitMC - Add passes to the specified pass manager to get +/// machine code emitted with the MCJIT. This method returns true if machine +/// code is not supported. It fills the MCContext Ctx pointer which can be +/// used to build custom MCStreamer. /// -bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, - JITCodeEmitter &JCE, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForJIT(); - +bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, + MCContext *&Ctx, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) return true; - - addCodeEmitter(PM, OptLevel, JCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - - PM.add(createGCInfoDeleter()); + // Make sure the code model is set. + setCodeModelForJIT(); return false; // success! } +static void printNoVerify(PassManagerBase &PM, const char *Banner) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); +} + static void printAndVerify(PassManagerBase &PM, - const char *Banner, - bool allowDoubleDefs = false) { + const char *Banner) { if (PrintMachineCode) PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); if (VerifyMachineCode) - PM.add(createMachineVerifierPass(allowDoubleDefs)); + PM.add(createMachineVerifierPass(Banner)); } /// 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) { + CodeGenOpt::Level OptLevel, + bool DisableVerify, + MCContext *&OutContext) { // Standard LLVM-Level Passes. + // Basic AliasAnalysis support. + createStandardAliasAnalysisPasses(&PM); + + // Before running any passes, run the verifier to determine if the input + // coming from the front-end and/or optimizer is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + // Optionally, tun split-GEPs and no-load GVN. if (EnableSplitGEPGVN) { PM.add(createGEPSplitterPass()); - PM.add(createGVNPass(/*NoPRE=*/false, /*NoLoads=*/true)); + PM.add(createGVNPass(/*NoLoads=*/true)); } // Run loop strength reduction before anything else. @@ -274,40 +285,61 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs())); } + PM.add(createGCLoweringPass()); + + // Make sure that no unreachable blocks are instruction selected. + PM.add(createUnreachableBlockEliminationPass()); + // Turn exception handling constructs into something the code generators can // handle. - switch (getMCAsmInfo()->getExceptionHandlingType()) - { + 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)); + // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, + // catch info can get misplaced when a selector ends up more than one block + // removed from the parent invoke(s). This could happen when a landing + // pad is shared by multiple invokes and is also a target of a normal + // edge from elsewhere. PM.add(createSjLjEHPass(getTargetLowering())); - break; - case ExceptionHandling::Dwarf: - PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + // FALLTHROUGH + case ExceptionHandling::DwarfCFI: + case ExceptionHandling::DwarfTable: + PM.add(createDwarfEHPass(this)); break; case ExceptionHandling::None: PM.add(createLowerInvokePass(getTargetLowering())); + + // The lower invoke pass may create unreachable code. Remove it. + PM.add(createUnreachableBlockEliminationPass()); break; } - PM.add(createGCLoweringPass()); - - // Make sure that no unreachable blocks are instruction selected. - PM.add(createUnreachableBlockEliminationPass()); - if (OptLevel != CodeGenOpt::None && !DisableCGP) PM.add(createCodeGenPreparePass(getTargetLowering())); PM.add(createStackProtectorPass(getTargetLowering())); + addPreISel(PM, OptLevel); + if (PrintISelInput) PM.add(createPrintFunctionPass("\n\n" "*** Final LLVM Code input to ISel ***\n", &dbgs())); + // All passes which modify the LLVM IR are now complete; run the verifier + // to ensure that the IR is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + // Standard Lower-Level Passes. + // Install a MachineModuleInfo class, which is an immutable pass that holds + // all the per-module stuff we're generating, including MCContext. + TargetAsmInfo *TAI = new TargetAsmInfo(*this); + MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(), TAI); + PM.add(MMI); + OutContext = &MMI->getContext(); // Return the MCContext specifically by-ref. + // Set up a MachineFunction for the rest of CodeGen to work on. PM.add(new MachineFunctionAnalysis(*this, OptLevel)); @@ -321,42 +353,65 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, return true; // Print the instruction selected machine code... - printAndVerify(PM, "After Instruction Selection", - /* allowDoubleDefs= */ true); + printAndVerify(PM, "After Instruction Selection"); + + // Expand pseudo-instructions emitted by ISel. + PM.add(createExpandISelPseudosPass()); + + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + if (OptLevel != CodeGenOpt::None) + PM.add(createOptimizePHIsPass()); + + // If the target requests it, assign local variables to stack slots relative + // to one another and simplify frame index references where possible. + PM.add(createLocalStackSlotAllocationPass()); if (OptLevel != CodeGenOpt::None) { - PM.add(createOptimizeExtsPass()); + // With optimization, dead code should already be eliminated. However + // there is one known exception: lowered code for arguments that are only + // used by tail calls, where the tail calls reuse the incoming stack + // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). + PM.add(createDeadMachineInstructionElimPass()); + printAndVerify(PM, "After codegen DCE pass"); + if (!DisableMachineLICM) PM.add(createMachineLICMPass()); + PM.add(createMachineCSEPass()); if (!DisableMachineSink) PM.add(createMachineSinkingPass()); - printAndVerify(PM, "After MachineLICM and MachineSinking", - /* allowDoubleDefs= */ true); + printAndVerify(PM, "After Machine LICM, CSE and Sinking passes"); + + PM.add(createPeepholeOptimizerPass()); + printAndVerify(PM, "After codegen peephole optimization pass"); } // Pre-ra tail duplication. - if (OptLevel != CodeGenOpt::None && - !DisableTailDuplicate && PreAllocTailDup) { + if (OptLevel != CodeGenOpt::None && !DisableEarlyTailDup) { PM.add(createTailDuplicatePass(true)); - printAndVerify(PM, "After Pre-RegAlloc TailDuplicate", - /* allowDoubleDefs= */ true); + printAndVerify(PM, "After Pre-RegAlloc TailDuplicate"); } // Run pre-ra passes. if (addPreRegAlloc(PM, OptLevel)) - printAndVerify(PM, "After PreRegAlloc passes", - /* allowDoubleDefs= */ true); + printAndVerify(PM, "After PreRegAlloc passes"); // Perform register allocation. - PM.add(createRegisterAllocator()); + PM.add(createRegisterAllocator(OptLevel)); printAndVerify(PM, "After Register Allocation"); - // Perform stack slot coloring. - if (OptLevel != CodeGenOpt::None && !DisableSSC) { + // Perform stack slot coloring and post-ra machine LICM. + if (OptLevel != CodeGenOpt::None) { // FIXME: Re-enable coloring with register when it's capable of adding // kill markers. - PM.add(createStackSlotColoringPass(false)); - printAndVerify(PM, "After StackSlotColoring"); + if (!DisableSSC) + PM.add(createStackSlotColoringPass(false)); + + // Run post-ra machine LICM to hoist reloads / remats. + if (!DisablePostRAMachineLICM) + PM.add(createMachineLICMPass(false)); + + printAndVerify(PM, "After StackSlotColoring and postra Machine LICM"); } // Run post-ra passes. @@ -383,13 +438,13 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // Branch folding must be run after regalloc and prolog/epilog insertion. if (OptLevel != CodeGenOpt::None && !DisableBranchFold) { PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); - printAndVerify(PM, "After BranchFolding"); + printNoVerify(PM, "After BranchFolding"); } // Tail duplication. if (OptLevel != CodeGenOpt::None && !DisableTailDuplicate) { PM.add(createTailDuplicatePass(false)); - printAndVerify(PM, "After TailDuplicate"); + printNoVerify(PM, "After TailDuplicate"); } PM.add(createGCMachineCodeAnalysisPass()); @@ -399,11 +454,11 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, if (OptLevel != CodeGenOpt::None && !DisableCodePlace) { PM.add(createCodePlacementOptPass()); - printAndVerify(PM, "After CodePlacementOpt"); + printNoVerify(PM, "After CodePlacementOpt"); } if (addPreEmitPass(PM, OptLevel)) - printAndVerify(PM, "After PreEmit passes"); + printNoVerify(PM, "After PreEmit passes"); return false; }