diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2015-12-27 08:13:45 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2015-12-27 08:13:45 +0000 |
commit | f49f1a87ef49150c33d0810b3e8b0d56e56f3d1f (patch) | |
tree | 188e517b88a15913e5dcfb59034e582281b34d5f /llvm/lib | |
parent | 48a065d2eaba92c5c1221dc32810522b7aad6745 (diff) | |
download | bcm5719-llvm-f49f1a87ef49150c33d0810b3e8b0d56e56f3d1f.tar.gz bcm5719-llvm-f49f1a87ef49150c33d0810b3e8b0d56e56f3d1f.zip |
[attrs] Split off the forced attributes utility into its own pass that
is (by default) run much earlier than FuncitonAttrs proper.
This allows forcing optnone or other widely impactful attributes. It is
also a bit simpler as the force attribute behavior needs no specific
iteration order.
I've added the pass into the default module pass pipeline and LTO pass
pipeline which mirrors where function attrs itself was being run.
Differential Revision: http://reviews.llvm.org/D15668
llvm-svn: 256465
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Passes/PassRegistry.def | 1 | ||||
-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 |
7 files changed, 134 insertions, 68 deletions
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index b24c615f85f..e8d5459f011 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -29,13 +29,14 @@ #include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/IPO/ForceFunctionAttrs.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Scalar/SROA.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" using namespace llvm; diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 638f606c402..b7683f12393 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -27,6 +27,7 @@ MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) #ifndef MODULE_PASS #define MODULE_PASS(NAME, CREATE_PASS) #endif +MODULE_PASS("forceattrs", ForceFunctionAttrsPass()) MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass()) MODULE_PASS("no-op-module", NoOpModulePass()) MODULE_PASS("print", PrintModulePass(dbgs())) 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. |