summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/IPO/CMakeLists.txt1
-rw-r--r--llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp121
-rw-r--r--llvm/lib/Transforms/IPO/FunctionAttrs.cpp66
-rw-r--r--llvm/lib/Transforms/IPO/IPO.cpp1
-rw-r--r--llvm/lib/Transforms/IPO/PassManagerBuilder.cpp7
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.
OpenPOWER on IntegriCloud