llvm.org GIT mirror llvm / 6a1ce8e
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256465 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 3 years ago
11 changed file(s) with 182 addition(s) and 80 deletion(s). Raw diff Collapse all Expand all
130130 void initializeEarlyCSELegacyPassPass(PassRegistry &);
131131 void initializeEliminateAvailableExternallyPass(PassRegistry&);
132132 void initializeExpandISelPseudosPass(PassRegistry&);
133 void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&);
133134 void initializeFunctionAttrsPass(PassRegistry&);
134135 void initializeGCMachineCodeAnalysisPass(PassRegistry&);
135136 void initializeGCModuleInfoPass(PassRegistry&);
0 //===-- ForceFunctionAttrs.h - Force function attrs for debugging ---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// Super simple passes to force specific function attrs from the commandline
10 /// into the IR for debugging purposes.
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
14 #define LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
15
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/PassManager.h"
18
19 namespace llvm {
20
21 /// Pass which forces specific function attributes into the IR, primarily as
22 /// a debugging tool.
23 class ForceFunctionAttrsPass {
24 public:
25 static StringRef name() { return "ForceFunctionAttrsPass"; }
26 PreservedAnalyses run(Module &M);
27 };
28
29 /// Create a legacy pass manager instance of a pass to force function attrs.
30 Pass *createForceFunctionAttrsLegacyPass();
31
32 }
33
34 #endif // LLVM_TRANSFORMS_IPO_FORCEFUNCTIONATTRS_H
2828 #include "llvm/IR/Verifier.h"
2929 #include "llvm/Support/Debug.h"
3030 #include "llvm/Target/TargetMachine.h"
31 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
32 #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
3133 #include "llvm/Transforms/InstCombine/InstCombine.h"
32 #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
3334 #include "llvm/Transforms/Scalar/ADCE.h"
3435 #include "llvm/Transforms/Scalar/EarlyCSE.h"
3536 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
37 #include "llvm/Transforms/Scalar/SROA.h"
3638 #include "llvm/Transforms/Scalar/SimplifyCFG.h"
37 #include "llvm/Transforms/Scalar/SROA.h"
3839
3940 using namespace llvm;
4041
2626 #ifndef MODULE_PASS
2727 #define MODULE_PASS(NAME, CREATE_PASS)
2828 #endif
29 MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
2930 MODULE_PASS("invalidate", InvalidateAllAnalysesPass())
3031 MODULE_PASS("no-op-module", NoOpModulePass())
3132 MODULE_PASS("print", PrintModulePass(dbgs()))
55 DeadArgumentElimination.cpp
66 ElimAvailExtern.cpp
77 ExtractGV.cpp
8 ForceFunctionAttrs.cpp
89 FunctionAttrs.cpp
910 FunctionImport.cpp
1011 GlobalDCE.cpp
0 //===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
10 #include "llvm/ADT/StringSwitch.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/raw_ostream.h"
16 using namespace llvm;
17
18 #define DEBUG_TYPE "forceattrs"
19
20 static cl::list
21 ForceAttributes("force-attribute", cl::Hidden,
22 cl::desc("Add an attribute to a function. This should be a "
23 "pair of 'function-name:attribute-name', for "
24 "example -force-add-attribute=foo:noinline. This "
25 "option can be specified multiple times."));
26
27 static Attribute::AttrKind parseAttrKind(StringRef Kind) {
28 return StringSwitch(Kind)
29 .Case("alwaysinline", Attribute::AlwaysInline)
30 .Case("builtin", Attribute::Builtin)
31 .Case("cold", Attribute::Cold)
32 .Case("convergent", Attribute::Convergent)
33 .Case("inlinehint", Attribute::InlineHint)
34 .Case("jumptable", Attribute::JumpTable)
35 .Case("minsize", Attribute::MinSize)
36 .Case("naked", Attribute::Naked)
37 .Case("nobuiltin", Attribute::NoBuiltin)
38 .Case("noduplicate", Attribute::NoDuplicate)
39 .Case("noimplicitfloat", Attribute::NoImplicitFloat)
40 .Case("noinline", Attribute::NoInline)
41 .Case("nonlazybind", Attribute::NonLazyBind)
42 .Case("noredzone", Attribute::NoRedZone)
43 .Case("noreturn", Attribute::NoReturn)
44 .Case("norecurse", Attribute::NoRecurse)
45 .Case("nounwind", Attribute::NoUnwind)
46 .Case("optnone", Attribute::OptimizeNone)
47 .Case("optsize", Attribute::OptimizeForSize)
48 .Case("readnone", Attribute::ReadNone)
49 .Case("readonly", Attribute::ReadOnly)
50 .Case("argmemonly", Attribute::ArgMemOnly)
51 .Case("returns_twice", Attribute::ReturnsTwice)
52 .Case("safestack", Attribute::SafeStack)
53 .Case("sanitize_address", Attribute::SanitizeAddress)
54 .Case("sanitize_memory", Attribute::SanitizeMemory)
55 .Case("sanitize_thread", Attribute::SanitizeThread)
56 .Case("ssp", Attribute::StackProtect)
57 .Case("sspreq", Attribute::StackProtectReq)
58 .Case("sspstrong", Attribute::StackProtectStrong)
59 .Case("uwtable", Attribute::UWTable)
60 .Default(Attribute::None);
61 }
62
63 /// If F has any forced attributes given on the command line, add them.
64 static void addForcedAttributes(Function &F) {
65 for (auto &S : ForceAttributes) {
66 auto KV = StringRef(S).split(':');
67 if (KV.first != F.getName())
68 continue;
69
70 auto Kind = parseAttrKind(KV.second);
71 if (Kind == Attribute::None) {
72 DEBUG(dbgs() << "ForcedAttribute: " << KV.second
73 << " unknown or not handled!\n");
74 continue;
75 }
76 if (F.hasFnAttribute(Kind))
77 continue;
78 F.addFnAttr(Kind);
79 }
80 }
81
82 PreservedAnalyses ForceFunctionAttrsPass::run(Module &M) {
83 if (ForceAttributes.empty())
84 return PreservedAnalyses::all();
85
86 for (Function &F : M.functions())
87 addForcedAttributes(F);
88
89 // Just conservatively invalidate analyses, this isn't likely to be important.
90 return PreservedAnalyses::none();
91 }
92
93 namespace {
94 struct ForceFunctionAttrsLegacyPass : public ModulePass {
95 static char ID; // Pass identification, replacement for typeid
96 ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
97 initializeForceFunctionAttrsLegacyPassPass(
98 *PassRegistry::getPassRegistry());
99 }
100
101 bool runOnModule(Module &M) override {
102 if (ForceAttributes.empty())
103 return false;
104
105 for (Function &F : M.functions())
106 addForcedAttributes(F);
107
108 // Conservatively assume we changed something.
109 return true;
110 }
111 };
112 }
113
114 char ForceFunctionAttrsLegacyPass::ID = 0;
115 INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
116 "Force set function attributes", false, false)
117
118 Pass *llvm::createForceFunctionAttrsLegacyPass() {
119 return new ForceFunctionAttrsLegacyPass();
120 }
5151 STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
5252 STATISTIC(NumAnnotated, "Number of attributes added to library functions");
5353 STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
54
55 static cl::list
56 ForceAttributes("force-attribute", cl::Hidden,
57 cl::desc("Add an attribute to a function. This should be a "
58 "pair of 'function-name:attribute-name', for "
59 "example -force-add-attribute=foo:noinline. This "
60 "option can be specified multiple times."));
6154
6255 namespace {
6356 typedef SmallSetVector SCCNodeSet;
18501843 return false;
18511844 }
18521845
1853 static Attribute::AttrKind parseAttrKind(StringRef Kind) {
1854 return StringSwitch(Kind)
1855 .Case("alwaysinline", Attribute::AlwaysInline)
1856 .Case("builtin", Attribute::Builtin)
1857 .Case("cold", Attribute::Cold)
1858 .Case("convergent", Attribute::Convergent)
1859 .Case("inlinehint", Attribute::InlineHint)
1860 .Case("jumptable", Attribute::JumpTable)
1861 .Case("minsize", Attribute::MinSize)
1862 .Case("naked", Attribute::Naked)
1863 .Case("nobuiltin", Attribute::NoBuiltin)
1864 .Case("noduplicate", Attribute::NoDuplicate)
1865 .Case("noimplicitfloat", Attribute::NoImplicitFloat)
1866 .Case("noinline", Attribute::NoInline)
1867 .Case("nonlazybind", Attribute::NonLazyBind)
1868 .Case("noredzone", Attribute::NoRedZone)
1869 .Case("noreturn", Attribute::NoReturn)
1870 .Case("norecurse", Attribute::NoRecurse)
1871 .Case("nounwind", Attribute::NoUnwind)
1872 .Case("optnone", Attribute::OptimizeNone)
1873 .Case("optsize", Attribute::OptimizeForSize)
1874 .Case("readnone", Attribute::ReadNone)
1875 .Case("readonly", Attribute::ReadOnly)
1876 .Case("argmemonly", Attribute::ArgMemOnly)
1877 .Case("returns_twice", Attribute::ReturnsTwice)
1878 .Case("safestack", Attribute::SafeStack)
1879 .Case("sanitize_address", Attribute::SanitizeAddress)
1880 .Case("sanitize_memory", Attribute::SanitizeMemory)
1881 .Case("sanitize_thread", Attribute::SanitizeThread)
1882 .Case("ssp", Attribute::StackProtect)
1883 .Case("sspreq", Attribute::StackProtectReq)
1884 .Case("sspstrong", Attribute::StackProtectStrong)
1885 .Case("uwtable", Attribute::UWTable)
1886 .Default(Attribute::None);
1887 }
1888
1889 /// If F has any forced attributes given on the command line, add them.
1890 static bool addForcedAttributes(Function *F) {
1891 bool Changed = false;
1892 for (auto &S : ForceAttributes) {
1893 auto KV = StringRef(S).split(':');
1894 if (KV.first != F->getName())
1895 continue;
1896
1897 auto Kind = parseAttrKind(KV.second);
1898 if (Kind == Attribute::None) {
1899 DEBUG(dbgs() << "ForcedAttribute: " << KV.second
1900 << " unknown or not handled!\n");
1901 continue;
1902 }
1903 if (F->hasFnAttribute(Kind))
1904 continue;
1905 Changed = true;
1906 F->addFnAttr(Kind);
1907 }
1908 return Changed;
1909 }
1910
19111846 bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
19121847 TLI = &getAnalysis().getTLI();
19131848 bool Changed = false;
19431878 if (F->isDeclaration())
19441879 Changed |= inferPrototypeAttributes(*F, *TLI);
19451880
1946 Changed |= addForcedAttributes(F);
19471881 SCCNodes.insert(F);
19481882 }
19491883
2626 initializeCrossDSOCFIPass(Registry);
2727 initializeDAEPass(Registry);
2828 initializeDAHPass(Registry);
29 initializeForceFunctionAttrsLegacyPassPass(Registry);
2930 initializeFunctionAttrsPass(Registry);
3031 initializeGlobalDCEPass(Registry);
3132 initializeGlobalOptPass(Registry);
3030 #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
3131 #include "llvm/Target/TargetMachine.h"
3232 #include "llvm/Transforms/IPO.h"
33 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
3334 #include "llvm/Transforms/Scalar.h"
3435 #include "llvm/Transforms/Vectorize.h"
3536
186187
187188 void PassManagerBuilder::populateModulePassManager(
188189 legacy::PassManagerBase &MPM) {
190 // Allow forcing function attributes as a debugging and tuning aid.
191 MPM.add(createForceFunctionAttrsLegacyPass());
192
189193 // If all optimizations are disabled, just run the always-inline pass and,
190194 // if enabled, the function merging pass.
191195 if (OptLevel == 0) {
482486 if (FunctionIndex)
483487 PM.add(createFunctionImportPass(FunctionIndex));
484488
489 // Allow forcing function attributes as a debugging and tuning aid.
490 PM.add(createForceFunctionAttrsLegacyPass());
491
485492 // Propagate constants at call sites into the functions they call. This
486493 // opens opportunities for globalopt (and inlining) by substituting function
487494 // pointers passed as arguments to direct uses of functions.
0 ; RUN: opt < %s -S -forceattrs | FileCheck %s --check-prefix=CHECK-CONTROL
1 ; RUN: opt < %s -S -forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
2 ; RUN: opt < %s -S -passes=forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
3
4 ; CHECK-CONTROL: define void @foo() {
5 ; CHECK-FOO: define void @foo() #0 {
6 define void @foo() {
7 ret void
8 }
9
10
11 ; CHECK-FOO: attributes #0 = { noinline }
+0
-12
test/Transforms/FunctionAttrs/forced.ll less more
None ; RUN: opt < %s -S -functionattrs | FileCheck %s --check-prefix=CHECK-CONTROL
1 ; RUN: opt < %s -S -functionattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
2
3 ; CHECK-CONTROL: define void @foo() #0 {
4 ; CHECK-FOO: define void @foo() #0 {
5 define void @foo() {
6 ret void
7 }
8
9
10 ; CHECK-CONTROL: attributes #0 = { norecurse readnone }
11 ; CHECK-FOO: attributes #0 = { noinline norecurse readnone }