X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLLVMTargetMachine.cpp;h=51e538ef46496daede3c87b4ae4631a3d6fea972;hb=5ef31a039dbb9c36cfd78442b3554d1b6974ec4c;hp=8757c9f0ae3ee9227a29b590efe1fad59a3cd660;hpb=541e9ae3ad39f6ebca7649ce0c640ff2c64bfb84;p=oota-llvm.git diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 8757c9f0ae3..51e538ef464 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -14,6 +14,7 @@ #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" @@ -21,8 +22,12 @@ #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.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/Debug.h" #include "llvm/Support/FormattedStream.h" @@ -38,6 +43,8 @@ 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, @@ -54,14 +61,25 @@ 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)); +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 -O0. @@ -75,174 +93,127 @@ 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; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify)) + return true; + + const MCAsmInfo &MAI = *getMCAsmInfo(); + OwningPtr Context(new MCContext(MAI)); + OwningPtr AsmStreamer; + formatted_raw_ostream *LegacyOutput; switch (FileType) { - default: + default: return true; + case CGFT_AssemblyFile: { + MCInstPrinter *InstPrinter = + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, Out); + AsmStreamer.reset(createAsmStreamer(*Context, Out, + getTargetData()->isLittleEndian(), + getVerboseAsm(), InstPrinter, + /*codeemitter*/0)); + // Set the AsmPrinter's "O" to the output file. + LegacyOutput = &Out; 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; -} - -bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - bool Verbose, - formatted_raw_ostream &Out) { + 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)); + + // Any output to the asmprinter's "O" stream is bad and needs to be fixed, + // force it to come out stderr. + // FIXME: this is horrible and leaks, eventually remove the raw_ostream from + // asmprinter. + LegacyOutput = new formatted_raw_ostream(errs()); + break; + } + case CGFT_Null: + // The Null output is intended for use for performance analysis and testing, + // not real users. + AsmStreamer.reset(createNullStreamer(*Context)); + // Any output to the asmprinter's "O" stream is bad and needs to be fixed, + // force it to come out stderr. + // FIXME: this is horrible and leaks, eventually remove the raw_ostream from + // asmprinter. + LegacyOutput = new formatted_raw_ostream(errs()); + break; + } + + // Create the AsmPrinter, which takes ownership of Context and AsmStreamer + // if successful. FunctionPass *Printer = - getTarget().createAsmPrinter(Out, *this, getMCAsmInfo(), Verbose); - if (!Printer) + getTarget().createAsmPrinter(*LegacyOutput, *this, *Context, *AsmStreamer, + getMCAsmInfo()); + if (Printer == 0) 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, - 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 successful, createAsmPrinter took ownership of AsmStreamer and Context. + Context.take(); AsmStreamer.take(); - if (JCE) - addSimpleCodeEmitter(PM, OptLevel, *JCE); - 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, - ObjectCodeEmitter *OCE, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForStatic(); + PM.add(Printer); - if (OCE) - addSimpleCodeEmitter(PM, OptLevel, *OCE); - 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, - MachineCodeEmitter &MCE, - CodeGenOpt::Level OptLevel) { // Make sure the code model is set. - setCodeModelForJIT(); - - // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) - return true; - - addCodeEmitter(PM, OptLevel, MCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - + setCodeModelForStatic(); 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, JITCodeEmitter &JCE, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Make sure the code model is set. setCodeModelForJIT(); // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify)) return true; addCodeEmitter(PM, OptLevel, JCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - PM.add(createGCInfoDeleter()); 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) { @@ -257,13 +228,19 @@ static void printAndVerify(PassManagerBase &PM, /// emitting to assembly files or machine code output. /// bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // 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(/*NoPRE=*/false, /*NoLoads=*/true)); + PM.add(createGVNPass(/*NoLoads=*/true)); } // Run loop strength reduction before anything else. @@ -279,8 +256,13 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, { 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())); + PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); break; case ExceptionHandling::Dwarf: PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None)); @@ -305,6 +287,11 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, "*** 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. // Set up a MachineFunction for the rest of CodeGen to work on. @@ -323,18 +310,29 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, 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(createOptimizeExtsPass()); if (!DisableMachineLICM) PM.add(createMachineLICMPass()); + PM.add(createMachineCSEPass()); if (!DisableMachineSink) PM.add(createMachineSinkingPass()); - printAndVerify(PM, "After MachineLICM and MachineSinking", + printAndVerify(PM, "After Machine LICM, CSE and Sinking passes", /* allowDoubleDefs= */ true); } // 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); @@ -381,13 +379,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()); @@ -397,11 +395,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; }