diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/IPO/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp | 121 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 66 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/IPO.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 7 |
5 files changed, 130 insertions, 66 deletions
diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt index d79ce50a1a6..f03f2dc4a72 100644 --- a/llvm/lib/Transforms/IPO/CMakeLists.txt +++ b/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMipo DeadArgumentElimination.cpp ElimAvailExtern.cpp ExtractGV.cpp + ForceFunctionAttrs.cpp FunctionAttrs.cpp FunctionImport.cpp GlobalDCE.cpp diff --git a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp new file mode 100644 index 00000000000..816291dac9e --- /dev/null +++ b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -0,0 +1,121 @@ +//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO/ForceFunctionAttrs.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "forceattrs" + +static cl::list<std::string> + ForceAttributes("force-attribute", cl::Hidden, + cl::desc("Add an attribute to a function. This should be a " + "pair of 'function-name:attribute-name', for " + "example -force-add-attribute=foo:noinline. This " + "option can be specified multiple times.")); + +static Attribute::AttrKind parseAttrKind(StringRef Kind) { + return StringSwitch<Attribute::AttrKind>(Kind) + .Case("alwaysinline", Attribute::AlwaysInline) + .Case("builtin", Attribute::Builtin) + .Case("cold", Attribute::Cold) + .Case("convergent", Attribute::Convergent) + .Case("inlinehint", Attribute::InlineHint) + .Case("jumptable", Attribute::JumpTable) + .Case("minsize", Attribute::MinSize) + .Case("naked", Attribute::Naked) + .Case("nobuiltin", Attribute::NoBuiltin) + .Case("noduplicate", Attribute::NoDuplicate) + .Case("noimplicitfloat", Attribute::NoImplicitFloat) + .Case("noinline", Attribute::NoInline) + .Case("nonlazybind", Attribute::NonLazyBind) + .Case("noredzone", Attribute::NoRedZone) + .Case("noreturn", Attribute::NoReturn) + .Case("norecurse", Attribute::NoRecurse) + .Case("nounwind", Attribute::NoUnwind) + .Case("optnone", Attribute::OptimizeNone) + .Case("optsize", Attribute::OptimizeForSize) + .Case("readnone", Attribute::ReadNone) + .Case("readonly", Attribute::ReadOnly) + .Case("argmemonly", Attribute::ArgMemOnly) + .Case("returns_twice", Attribute::ReturnsTwice) + .Case("safestack", Attribute::SafeStack) + .Case("sanitize_address", Attribute::SanitizeAddress) + .Case("sanitize_memory", Attribute::SanitizeMemory) + .Case("sanitize_thread", Attribute::SanitizeThread) + .Case("ssp", Attribute::StackProtect) + .Case("sspreq", Attribute::StackProtectReq) + .Case("sspstrong", Attribute::StackProtectStrong) + .Case("uwtable", Attribute::UWTable) + .Default(Attribute::None); +} + +/// If F has any forced attributes given on the command line, add them. +static void addForcedAttributes(Function &F) { + for (auto &S : ForceAttributes) { + auto KV = StringRef(S).split(':'); + if (KV.first != F.getName()) + continue; + + auto Kind = parseAttrKind(KV.second); + if (Kind == Attribute::None) { + DEBUG(dbgs() << "ForcedAttribute: " << KV.second + << " unknown or not handled!\n"); + continue; + } + if (F.hasFnAttribute(Kind)) + continue; + F.addFnAttr(Kind); + } +} + +PreservedAnalyses ForceFunctionAttrsPass::run(Module &M) { + if (ForceAttributes.empty()) + return PreservedAnalyses::all(); + + for (Function &F : M.functions()) + addForcedAttributes(F); + + // Just conservatively invalidate analyses, this isn't likely to be important. + return PreservedAnalyses::none(); +} + +namespace { +struct ForceFunctionAttrsLegacyPass : public ModulePass { + static char ID; // Pass identification, replacement for typeid + ForceFunctionAttrsLegacyPass() : ModulePass(ID) { + initializeForceFunctionAttrsLegacyPassPass( + *PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + if (ForceAttributes.empty()) + return false; + + for (Function &F : M.functions()) + addForcedAttributes(F); + + // Conservatively assume we changed something. + return true; + } +}; +} + +char ForceFunctionAttrsLegacyPass::ID = 0; +INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs", + "Force set function attributes", false, false) + +Pass *llvm::createForceFunctionAttrsLegacyPass() { + return new ForceFunctionAttrsLegacyPass(); +} diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index e699c5e0df5..b268eff2592 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -53,13 +53,6 @@ STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull"); STATISTIC(NumAnnotated, "Number of attributes added to library functions"); STATISTIC(NumNoRecurse, "Number of functions marked as norecurse"); -static cl::list<std::string> -ForceAttributes("force-attribute", cl::Hidden, - cl::desc("Add an attribute to a function. This should be a " - "pair of 'function-name:attribute-name', for " - "example -force-add-attribute=foo:noinline. This " - "option can be specified multiple times.")); - namespace { typedef SmallSetVector<Function *, 8> SCCNodeSet; } @@ -1851,64 +1844,6 @@ static bool addNoRecurseAttrsTopDownOnly(Function *F) { return false; } -static Attribute::AttrKind parseAttrKind(StringRef Kind) { - return StringSwitch<Attribute::AttrKind>(Kind) - .Case("alwaysinline", Attribute::AlwaysInline) - .Case("builtin", Attribute::Builtin) - .Case("cold", Attribute::Cold) - .Case("convergent", Attribute::Convergent) - .Case("inlinehint", Attribute::InlineHint) - .Case("jumptable", Attribute::JumpTable) - .Case("minsize", Attribute::MinSize) - .Case("naked", Attribute::Naked) - .Case("nobuiltin", Attribute::NoBuiltin) - .Case("noduplicate", Attribute::NoDuplicate) - .Case("noimplicitfloat", Attribute::NoImplicitFloat) - .Case("noinline", Attribute::NoInline) - .Case("nonlazybind", Attribute::NonLazyBind) - .Case("noredzone", Attribute::NoRedZone) - .Case("noreturn", Attribute::NoReturn) - .Case("norecurse", Attribute::NoRecurse) - .Case("nounwind", Attribute::NoUnwind) - .Case("optnone", Attribute::OptimizeNone) - .Case("optsize", Attribute::OptimizeForSize) - .Case("readnone", Attribute::ReadNone) - .Case("readonly", Attribute::ReadOnly) - .Case("argmemonly", Attribute::ArgMemOnly) - .Case("returns_twice", Attribute::ReturnsTwice) - .Case("safestack", Attribute::SafeStack) - .Case("sanitize_address", Attribute::SanitizeAddress) - .Case("sanitize_memory", Attribute::SanitizeMemory) - .Case("sanitize_thread", Attribute::SanitizeThread) - .Case("ssp", Attribute::StackProtect) - .Case("sspreq", Attribute::StackProtectReq) - .Case("sspstrong", Attribute::StackProtectStrong) - .Case("uwtable", Attribute::UWTable) - .Default(Attribute::None); -} - -/// If F has any forced attributes given on the command line, add them. -static bool addForcedAttributes(Function *F) { - bool Changed = false; - for (auto &S : ForceAttributes) { - auto KV = StringRef(S).split(':'); - if (KV.first != F->getName()) - continue; - - auto Kind = parseAttrKind(KV.second); - if (Kind == Attribute::None) { - DEBUG(dbgs() << "ForcedAttribute: " << KV.second - << " unknown or not handled!\n"); - continue; - } - if (F->hasFnAttribute(Kind)) - continue; - Changed = true; - F->addFnAttr(Kind); - } - return Changed; -} - bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) { TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); bool Changed = false; @@ -1944,7 +1879,6 @@ bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) { if (F->isDeclaration()) Changed |= inferPrototypeAttributes(*F, *TLI); - Changed |= addForcedAttributes(F); SCCNodes.insert(F); } diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index 2984785a4de..54f8de30e28 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -27,6 +27,7 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeCrossDSOCFIPass(Registry); initializeDAEPass(Registry); initializeDAHPass(Registry); + initializeForceFunctionAttrsLegacyPassPass(Registry); initializeFunctionAttrsPass(Registry); initializeGlobalDCEPass(Registry); initializeGlobalOptPass(Registry); diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 0d8982774d9..5978b8f59ca 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -31,6 +31,7 @@ #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/ForceFunctionAttrs.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Vectorize.h" @@ -187,6 +188,9 @@ void PassManagerBuilder::populateFunctionPassManager( void PassManagerBuilder::populateModulePassManager( legacy::PassManagerBase &MPM) { + // Allow forcing function attributes as a debugging and tuning aid. + MPM.add(createForceFunctionAttrsLegacyPass()); + // If all optimizations are disabled, just run the always-inline pass and, // if enabled, the function merging pass. if (OptLevel == 0) { @@ -483,6 +487,9 @@ void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { if (FunctionIndex) PM.add(createFunctionImportPass(FunctionIndex)); + // Allow forcing function attributes as a debugging and tuning aid. + PM.add(createForceFunctionAttrsLegacyPass()); + // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function // pointers passed as arguments to direct uses of functions. |