diff options
Diffstat (limited to 'tools/lto')
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 88 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 1 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 198 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 5 |
4 files changed, 221 insertions, 71 deletions
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 6382a3f..b80bc34 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -46,10 +46,12 @@ #include "llvm/ADT/StringExtras.h" using namespace llvm; -static cl::opt<bool> DisableInline("disable-inlining", cl::init(false), +static cl::opt<bool> +DisableInline("disable-inlining", cl::init(false), cl::desc("Do not run the inliner pass")); -static cl::opt<bool> DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), +static cl::opt<bool> +DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), cl::desc("Do not run the GVN load PRE pass")); const char* LTOCodeGenerator::getVersionString() { @@ -152,7 +154,7 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) { // make unique temp .o file to put generated object file sys::PathWithStatus uniqueObjPath("lto-llvm.o"); - if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) { + if (uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg)) { uniqueObjPath.eraseFromDisk(); return true; } @@ -172,7 +174,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) { } objFile.keep(); - if ( genResult ) { + if (genResult) { uniqueObjPath.eraseFromDisk(); return true; } @@ -202,46 +204,49 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) { sys::Path(_nativeObjectPath).eraseFromDisk(); // return buffer, unless error - if ( _nativeObjectFile == NULL ) + if (_nativeObjectFile == NULL) return NULL; *length = _nativeObjectFile->getBufferSize(); return _nativeObjectFile->getBufferStart(); } bool LTOCodeGenerator::determineTarget(std::string& errMsg) { - if ( _target == NULL ) { - std::string Triple = _linker.getModule()->getTargetTriple(); - if (Triple.empty()) - Triple = sys::getDefaultTargetTriple(); - - // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); - if ( march == NULL ) - return true; - - // The relocation model is actually a static member of TargetMachine and - // needs to be set before the TargetMachine is instantiated. - Reloc::Model RelocModel = Reloc::Default; - switch( _codeModel ) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - } - - // construct LTOModule, hand over ownership of module and target - SubtargetFeatures Features; - Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); - std::string FeatureStr = Features.getString(); - TargetOptions Options; - _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options, - RelocModel); + if (_target != NULL) + return false; + + std::string Triple = _linker.getModule()->getTargetTriple(); + if (Triple.empty()) + Triple = sys::getDefaultTargetTriple(); + + // create target machine from info for merged modules + const Target *march = TargetRegistry::lookupTarget(Triple, errMsg); + if (march == NULL) + return true; + + // The relocation model is actually a static member of TargetMachine and + // needs to be set before the TargetMachine is instantiated. + Reloc::Model RelocModel = Reloc::Default; + switch (_codeModel) { + case LTO_CODEGEN_PIC_MODEL_STATIC: + RelocModel = Reloc::Static; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC: + RelocModel = Reloc::PIC_; + break; + case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: + RelocModel = Reloc::DynamicNoPIC; + break; } + + // construct LTOModule, hand over ownership of module and target + SubtargetFeatures Features; + Features.getDefaultSubtargetFeatures(llvm::Triple(Triple)); + std::string FeatureStr = Features.getString(); + TargetOptions Options; + LTOModule::getTargetOptions(Options); + _target = march->createTargetMachine(Triple, _mCpu, FeatureStr, Options, + RelocModel, CodeModel::Default, + CodeGenOpt::Aggressive); return false; } @@ -333,13 +338,13 @@ void LTOCodeGenerator::applyScopeRestrictions() { /// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, std::string &errMsg) { - if ( this->determineTarget(errMsg) ) + if (this->determineTarget(errMsg)) return true; Module* mergedModule = _linker.getModule(); // if options were requested, set them - if ( !_codegenOptions.empty() ) + if (!_codegenOptions.empty()) cl::ParseCommandLineOptions(_codegenOptions.size(), const_cast<char **>(&_codegenOptions[0])); @@ -372,8 +377,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, formatted_raw_ostream Out(out); if (_target->addPassesToEmitFile(*codeGenPasses, Out, - TargetMachine::CGFT_ObjectFile, - CodeGenOpt::Aggressive)) { + TargetMachine::CGFT_ObjectFile)) { errMsg = "target file type not supported"; return true; } @@ -402,7 +406,7 @@ void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { !o.first.empty(); o = getToken(o.second)) { // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add // that. - if ( _codegenOptions.empty() ) + if (_codegenOptions.empty()) _codegenOptions.push_back(strdup("libLTO")); _codegenOptions.push_back(strdup(o.first.str().c_str())); } diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h index 032dc37..3081b7d 100644 --- a/tools/lto/LTOCodeGenerator.h +++ b/tools/lto/LTOCodeGenerator.h @@ -70,7 +70,6 @@ private: llvm::TargetMachine* _target; bool _emitDwarfDebugInfo; bool _scopeRestrictionsDone; - bool _runInternalizePass; lto_codegen_model _codeModel; StringSet _mustPreserveSymbols; StringSet _asmUndefinedRefs; diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 1dbd64b..c5b3d10 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -37,6 +38,118 @@ #include "llvm/ADT/Triple.h" using namespace llvm; +static cl::opt<bool> +EnableFPMAD("enable-fp-mad", + cl::desc("Enable less precise MAD instructions to be generated"), + cl::init(false)); + +static cl::opt<bool> +DisableFPElim("disable-fp-elim", + cl::desc("Disable frame pointer elimination optimization"), + cl::init(false)); + +static cl::opt<bool> +DisableFPElimNonLeaf("disable-non-leaf-fp-elim", + cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), + cl::init(false)); + +static cl::opt<bool> +EnableUnsafeFPMath("enable-unsafe-fp-math", + cl::desc("Enable optimizations that may decrease FP precision"), + cl::init(false)); + +static cl::opt<bool> +EnableNoInfsFPMath("enable-no-infs-fp-math", + cl::desc("Enable FP math optimizations that assume no +-Infs"), + cl::init(false)); + +static cl::opt<bool> +EnableNoNaNsFPMath("enable-no-nans-fp-math", + cl::desc("Enable FP math optimizations that assume no NaNs"), + cl::init(false)); + +static cl::opt<bool> +EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", + cl::Hidden, + cl::desc("Force codegen to assume rounding mode can change dynamically"), + cl::init(false)); + +static cl::opt<bool> +GenerateSoftFloatCalls("soft-float", + cl::desc("Generate software floating point library calls"), + cl::init(false)); + +static cl::opt<llvm::FloatABI::ABIType> +FloatABIForCalls("float-abi", + cl::desc("Choose float ABI type"), + cl::init(FloatABI::Default), + cl::values( + clEnumValN(FloatABI::Default, "default", + "Target default float ABI type"), + clEnumValN(FloatABI::Soft, "soft", + "Soft float ABI (implied by -soft-float)"), + clEnumValN(FloatABI::Hard, "hard", + "Hard float ABI (uses FP registers)"), + clEnumValEnd)); + +static cl::opt<llvm::FPOpFusion::FPOpFusionMode> +FuseFPOps("fp-contract", + cl::desc("Enable aggresive formation of fused FP ops"), + cl::init(FPOpFusion::Standard), + cl::values( + clEnumValN(FPOpFusion::Fast, "fast", + "Fuse FP ops whenever profitable"), + clEnumValN(FPOpFusion::Standard, "on", + "Only fuse 'blessed' FP ops."), + clEnumValN(FPOpFusion::Strict, "off", + "Only fuse FP ops when the result won't be effected."), + clEnumValEnd)); + +static cl::opt<bool> +DontPlaceZerosInBSS("nozero-initialized-in-bss", + cl::desc("Don't place zero-initialized symbols into bss section"), + cl::init(false)); + +static cl::opt<bool> +EnableGuaranteedTailCallOpt("tailcallopt", + cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."), + cl::init(false)); + +static cl::opt<bool> +DisableTailCalls("disable-tail-calls", + cl::desc("Never emit tail calls"), + cl::init(false)); + +static cl::opt<unsigned> +OverrideStackAlignment("stack-alignment", + cl::desc("Override default stack alignment"), + cl::init(0)); + +static cl::opt<bool> +EnableRealignStack("realign-stack", + cl::desc("Realign stack if needed"), + cl::init(true)); + +static cl::opt<std::string> +TrapFuncName("trap-func", cl::Hidden, + cl::desc("Emit a call to trap function rather than a trap instruction"), + cl::init("")); + +static cl::opt<bool> +EnablePIE("enable-pie", + cl::desc("Assume the creation of a position independent executable."), + cl::init(false)); + +static cl::opt<bool> +SegmentedStacks("segmented-stacks", + cl::desc("Use segmented stacks if possible."), + cl::init(false)); + +static cl::opt<bool> +UseInitArray("use-init-array", + cl::desc("Use .init_array instead of .ctors."), + cl::init(false)); + LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) : _module(m), _target(t), _context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL), @@ -117,6 +230,30 @@ LTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, return makeLTOModule(buffer.take(), errMsg); } +void LTOModule::getTargetOptions(TargetOptions &Options) { + Options.LessPreciseFPMADOption = EnableFPMAD; + Options.NoFramePointerElim = DisableFPElim; + Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf; + Options.AllowFPOpFusion = FuseFPOps; + Options.UnsafeFPMath = EnableUnsafeFPMath; + Options.NoInfsFPMath = EnableNoInfsFPMath; + Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.HonorSignDependentRoundingFPMathOption = + EnableHonorSignDependentRoundingFPMath; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + Options.NoZerosInBSS = DontPlaceZerosInBSS; + Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; + Options.DisableTailCalls = DisableTailCalls; + Options.StackAlignmentOverride = OverrideStackAlignment; + Options.RealignStack = EnableRealignStack; + Options.TrapFuncName = TrapFuncName; + Options.PositionIndependentExecutable = EnablePIE; + Options.EnableSegmentedStacks = SegmentedStacks; + Options.UseInitArray = UseInitArray; +} + LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string &errMsg) { static bool Initialized = false; @@ -150,6 +287,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, std::string FeatureStr = Features.getString(); std::string CPU; TargetOptions Options; + getTargetOptions(Options); TargetMachine *target = march->createTargetMachine(Triple, CPU, FeatureStr, Options); LTOModule *Ret = new LTOModule(m.take(), target); @@ -271,6 +409,9 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // Add to list of defined symbols. addDefinedSymbol(v, false); + if (!v->hasSection() /* || !isTargetDarwin */) + return; + // Special case i386/ppc ObjC data structures in magic sections: // The issue is that the old ObjC object format did some strange // contortions to avoid real linker symbols. For instance, the @@ -290,26 +431,25 @@ void LTOModule::addDefinedDataSymbol(GlobalValue *v) { // a class was missing. // The following synthesizes the implicit .objc_* symbols for the linker // from the ObjC data structures generated by the front end. - if (v->hasSection() /* && isTargetDarwin */) { - // special case if this data blob is an ObjC class definition - if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCClass(gv); - } + + // special case if this data blob is an ObjC class definition + if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { + if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + addObjCClass(gv); } + } - // special case if this data blob is an ObjC category definition - else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCCategory(gv); - } + // special case if this data blob is an ObjC category definition + else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { + if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + addObjCCategory(gv); } + } - // special case if this data blob is the list of referenced classes - else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { - if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { - addObjCClassRef(gv); - } + // special case if this data blob is the list of referenced classes + else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { + if (GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { + addObjCClassRef(gv); } } } @@ -409,7 +549,7 @@ void LTOModule::addAsmGlobalSymbol(const char *name, // much. // fill information structure - info.name = name; + info.name = entry.getKey().data(); info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; info.isFunction = false; @@ -599,7 +739,7 @@ namespace { markGlobal(*Symbol); } virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, - unsigned Size , unsigned ByteAlignment) { + uint64_t Size , unsigned ByteAlignment) { markDefined(*Symbol); } virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, @@ -658,21 +798,20 @@ bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, _context, *Streamer, *_target->getMCAsmInfo())); - OwningPtr<MCSubtargetInfo> STI(_target->getTarget(). - createMCSubtargetInfo(_target->getTargetTriple(), - _target->getTargetCPU(), - _target->getTargetFeatureString())); - OwningPtr<MCTargetAsmParser> - TAP(_target->getTarget().createMCAsmParser(*STI, *Parser.get())); + const Target &T = _target->getTarget(); + OwningPtr<MCSubtargetInfo> + STI(T.createMCSubtargetInfo(_target->getTargetTriple(), + _target->getTargetCPU(), + _target->getTargetFeatureString())); + OwningPtr<MCTargetAsmParser> TAP(T.createMCAsmParser(*STI, *Parser.get())); if (!TAP) { - errMsg = "target " + std::string(_target->getTarget().getName()) + - " does not define AsmParser."; + errMsg = "target " + std::string(T.getName()) + + " does not define AsmParser."; return true; } Parser->setTargetParser(*TAP); - int Res = Parser->Run(false); - if (Res) + if (Parser->Run(false)) return true; for (RecordStreamer::const_iterator i = Streamer->begin(), @@ -687,6 +826,7 @@ bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { Value == RecordStreamer::Used) addAsmGlobalSymbolUndef(Key.data()); } + return false; } @@ -694,8 +834,10 @@ bool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { static bool isDeclaration(const GlobalValue &V) { if (V.hasAvailableExternallyLinkage()) return true; + if (V.isMaterializable()) return false; + return V.isDeclaration(); } diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index cafb927..8e52206 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -29,6 +29,7 @@ namespace llvm { class Function; class GlobalValue; class MemoryBuffer; + class TargetOptions; class Value; } @@ -126,6 +127,10 @@ public: return _asm_undefines; } + /// getTargetOptions - Fill the TargetOptions object with the options + /// specified on the command line. + static void getTargetOptions(llvm::TargetOptions &Options); + private: /// parseSymbols - Parse the symbols from the module and model-level ASM and /// add them to either the defined or undefined lists. |