X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLLVMTargetMachine.cpp;h=a62f0f6caae663e2a1699d096607da44c4b15681;hb=678d9b7ed030dd79ed5ac749b0b21b6cb0859cd0;hp=b4a0bc2b7ae128da107134b30fe60dfa7d6a1509;hpb=2c1d7726f25b6b219a1518b411351b99d25c1a02;p=oota-llvm.git diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index b4a0bc2b7ae..a62f0f6caae 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -13,148 +13,254 @@ #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/Analysis/LoopPass.h" -#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.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/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" using namespace llvm; namespace llvm { bool EnableFastISel; } +static cl::opt DisablePostRA("disable-post-ra", cl::Hidden, + cl::desc("Disable Post Regalloc")); +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 DisableMachineSink("disable-machine-sink", cl::Hidden, + cl::desc("Disable Machine Sinking")); +static cl::opt DisableLSR("disable-lsr", cl::Hidden, + cl::desc("Disable Loop Strength Reduction Pass")); +static cl::opt DisableCGP("disable-cgp", cl::Hidden, + cl::desc("Disable Codegen Prepare")); 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 VerifyMachineCode("verify-machineinstrs", cl::Hidden, + cl::desc("Verify generated machine code"), + cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); -// 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)); +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 -// able to enable or disable fast-isel independently from -fast. +// able to enable or disable fast-isel independently from -O0. static cl::opt EnableFastISelOption("fast-isel", cl::Hidden, - cl::desc("Enable the experimental \"fast\" instruction selector")); - -FileModel::Model -LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - raw_ostream &Out, - CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { - // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) - return FileModel::Error; + cl::desc("Enable the \"fast\" instruction selector")); + +// Enable or disable an experimental optimization to split GEPs +// and run a special GVN pass which does not examine loads, in +// an effort to factor out redundancy implicit in complex GEPs. +static cl::opt EnableSplitGEPGVN("split-gep-gvn", cl::Hidden, + cl::desc("Split GEPs and run no-load GVN")); + +LLVMTargetMachine::LLVMTargetMachine(const Target &T, + const std::string &Triple) + : TargetMachine(T), TargetTriple(Triple) { + AsmInfo = T.createAsmInfo(TargetTriple); +} - // Fold redundant debug labels. - PM.add(createDebugLabelFoldingPass()); +// Set the default code model for the JIT for a generic target. +// FIXME: Is small right here? or .is64Bit() ? Large : Small? +void LLVMTargetMachine::setCodeModelForJIT() { + setCodeModel(CodeModel::Small); +} - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); +// Set the default code model for static compilation for a generic target. +void LLVMTargetMachine::setCodeModelForStatic() { + setCodeModel(CodeModel::Small); +} - if (addPreEmitPass(PM, OptLevel) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); +bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { + // Add common CodeGen passes. + MCContext *Context = 0; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Context)) + return true; + assert(Context != 0 && "Failed to get MCContext"); - if (OptLevel != CodeGenOpt::None) - PM.add(createLoopAlignerPass()); + const MCAsmInfo &MAI = *getMCAsmInfo(); + OwningPtr AsmStreamer; switch (FileType) { - default: + default: return true; + case CGFT_AssemblyFile: { + MCInstPrinter *InstPrinter = + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); + AsmStreamer.reset(createAsmStreamer(*Context, Out, + getTargetData()->isLittleEndian(), + getVerboseAsm(), InstPrinter, + /*codeemitter*/0)); 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; -} - -/// 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) { - if (MCE) - addSimpleCodeEmitter(PM, OptLevel, PrintEmittedAsm, *MCE); - + 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(createMachOStreamer(*Context, *TAB, Out, MCE)); + break; + } + case CGFT_Null: + // The Null output is intended for use for performance analysis and testing, + // not real users. + AsmStreamer.reset(createNullStreamer(*Context)); + break; + } + + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); + if (Printer == 0) + return true; + + // If successful, createAsmPrinter took ownership of AsmStreamer. + AsmStreamer.take(); + + PM.add(Printer); + + // Make sure the code model is set. + setCodeModelForStatic(); PM.add(createGCInfoDeleter()); - - // Delete machine code for this function - PM.add(createMachineCodeDeleter()); - - 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; - if (addPreEmitPass(PM, OptLevel) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + addCodeEmitter(PM, OptLevel, JCE); + PM.add(createGCInfoDeleter()); - addCodeEmitter(PM, OptLevel, PrintEmittedAsm, MCE); + return false; // success! +} - PM.add(createGCInfoDeleter()); +static void printNoVerify(PassManagerBase &PM, const char *Banner) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); +} - // Delete machine code for this function - PM.add(createMachineCodeDeleter()); +static void printAndVerify(PassManagerBase &PM, + const char *Banner, + bool allowDoubleDefs = false) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); - return false; // success! + 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) { + CodeGenOpt::Level OptLevel, + bool DisableVerify, + MCContext *&OutContext) { // Standard LLVM-Level Passes. + // 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(/*NoLoads=*/true)); + } + // Run loop strength reduction before anything else. - if (OptLevel != CodeGenOpt::None) { + if (OptLevel != CodeGenOpt::None && !DisableLSR) { PM.add(createLoopStrengthReducePass(getTargetLowering())); if (PrintLSR) - PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &errs())); + PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs())); } - 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 + // 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())); + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); + 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 (OptLevel != CodeGenOpt::None) + if (OptLevel != CodeGenOpt::None && !DisableCGP) PM.add(createCodeGenPreparePass(getTargetLowering())); PM.add(createStackProtectorPass(getTargetLowering())); @@ -162,9 +268,24 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, if (PrintISelInput) PM.add(createPrintFunctionPass("\n\n" "*** Final LLVM Code input to ISel ***\n", - &errs())); + &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. + MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo()); + 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)); // Enable FastISel with -fast, but allow that to be overridden. if (EnableFastISelOption == cl::BOU_TRUE || @@ -176,69 +297,102 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, return true; // Print the instruction selected machine code... - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + printAndVerify(PM, "After Instruction Selection", + /* allowDoubleDefs= */ true); + + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + if (OptLevel != CodeGenOpt::None) + PM.add(createOptimizePHIsPass()); + + // Delete dead machine instructions regardless of optimization level. + PM.add(createDeadMachineInstructionElimPass()); + printAndVerify(PM, "After codegen DCE pass", + /* allowDoubleDefs= */ true); if (OptLevel != CodeGenOpt::None) { - PM.add(createMachineLICMPass()); - PM.add(createMachineSinkingPass()); + PM.add(createOptimizeExtsPass()); + if (!DisableMachineLICM) + PM.add(createMachineLICMPass()); + PM.add(createMachineCSEPass()); + if (!DisableMachineSink) + PM.add(createMachineSinkingPass()); + printAndVerify(PM, "After Machine LICM, CSE and Sinking passes", + /* allowDoubleDefs= */ true); + } + + // Pre-ra tail duplication. + if (OptLevel != CodeGenOpt::None && !DisableEarlyTailDup) { + PM.add(createTailDuplicatePass(true)); + printAndVerify(PM, "After Pre-RegAlloc TailDuplicate", + /* allowDoubleDefs= */ true); } // Run pre-ra passes. - if (addPreRegAlloc(PM, OptLevel) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (addPreRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PreRegAlloc passes", + /* allowDoubleDefs= */ true); // Perform register allocation. PM.add(createRegisterAllocator()); + printAndVerify(PM, "After Register Allocation"); // Perform stack slot coloring. - if (OptLevel != CodeGenOpt::None) + if (OptLevel != CodeGenOpt::None && !DisableSSC) { + // FIXME: Re-enable coloring with register when it's capable of adding + // kill markers. PM.add(createStackSlotColoringPass(false)); - /*OptLevel >= CodeGenOpt::Aggressive*/ + printAndVerify(PM, "After StackSlotColoring"); - if (PrintMachineCode) // Print the register-allocated code - PM.add(createMachineFunctionPrinterPass(cerr)); + // Run post-ra machine LICM to hoist reloads / remats. + PM.add(createMachineLICMPass(false)); + } // Run post-ra passes. - if (addPostRegAlloc(PM, OptLevel) && PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (addPostRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PostRegAlloc passes"); PM.add(createLowerSubregsPass()); - - if (PrintMachineCode) // Print the subreg lowered code - PM.add(createMachineFunctionPrinterPass(cerr)); + printAndVerify(PM, "After LowerSubregs"); // Insert prolog/epilog code. Eliminate abstract frame index references... PM.add(createPrologEpilogCodeInserter()); + printAndVerify(PM, "After PrologEpilogCodeInserter"); - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + // Run pre-sched2 passes. + if (addPreSched2(PM, OptLevel)) + printAndVerify(PM, "After PreSched2 passes"); // Second pass scheduler. - if (OptLevel != CodeGenOpt::None && !DisablePostRAScheduler) { - PM.add(createPostRAScheduler()); - - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + if (OptLevel != CodeGenOpt::None && !DisablePostRA) { + PM.add(createPostRAScheduler(OptLevel)); + printAndVerify(PM, "After PostRAScheduler"); } // Branch folding must be run after regalloc and prolog/epilog insertion. - if (OptLevel != CodeGenOpt::None) + if (OptLevel != CodeGenOpt::None && !DisableBranchFold) { PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); + printNoVerify(PM, "After BranchFolding"); + } - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); + // Tail duplication. + if (OptLevel != CodeGenOpt::None && !DisableTailDuplicate) { + PM.add(createTailDuplicatePass(false)); + printNoVerify(PM, "After TailDuplicate"); + } PM.add(createGCMachineCodeAnalysisPass()); - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(cerr)); - if (PrintGCInfo) - PM.add(createGCInfoPrinter(*cerr)); + PM.add(createGCInfoPrinter(dbgs())); + + if (OptLevel != CodeGenOpt::None && !DisableCodePlace) { + PM.add(createCodePlacementOptPass()); + printNoVerify(PM, "After CodePlacementOpt"); + } + + if (addPreEmitPass(PM, OptLevel)) + printNoVerify(PM, "After PreEmit passes"); return false; }