Skip to content

Commit 17b48de

Browse files
[ForceFunctionAttrs] Make options additionally work over entire module
This patch makes the -force-attribute and -force-remove-attribute flags in the forceattrs pass additionally work over all the functions in a module rather than on specific functions. I often find myself dealing with bitcode from projects with arbitrary build systems that have applied the optnone attribute for various reasons and having the ability to do this in opt would be quite convenient. It's possible to remove the attribute by disassembling to textual IR, running sed, and then running opt over the result, but this option makes things just a bit easier. Differential Revision: https://reviews.llvm.org/D158815 Reviewed-By: nikic
1 parent 33b6b67 commit 17b48de

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,24 @@ using namespace llvm;
1616

1717
#define DEBUG_TYPE "forceattrs"
1818

19-
static cl::list<std::string>
20-
ForceAttributes("force-attribute", cl::Hidden,
21-
cl::desc("Add an attribute to a function. This should be a "
22-
"pair of 'function-name:attribute-name', for "
23-
"example -force-attribute=foo:noinline. This "
24-
"option can be specified multiple times."));
19+
static cl::list<std::string> ForceAttributes(
20+
"force-attribute", cl::Hidden,
21+
cl::desc(
22+
"Add an attribute to a function. This can be a "
23+
"pair of 'function-name:attribute-name', to apply an attribute to a "
24+
"specific function. For "
25+
"example -force-attribute=foo:noinline. Specifying only an attribute "
26+
"will apply the attribute to every function in the module. This "
27+
"option can be specified multiple times."));
2528

2629
static cl::list<std::string> ForceRemoveAttributes(
2730
"force-remove-attribute", cl::Hidden,
28-
cl::desc("Remove an attribute from a function. This should be a "
29-
"pair of 'function-name:attribute-name', for "
30-
"example -force-remove-attribute=foo:noinline. This "
31+
cl::desc("Remove an attribute from a function. This can be a "
32+
"pair of 'function-name:attribute-name' to remove an attribute "
33+
"from a specific function. For "
34+
"example -force-remove-attribute=foo:noinline. Specifying only an "
35+
"attribute will remove the attribute from all functions in the "
36+
"module. This "
3137
"option can be specified multiple times."));
3238

3339
/// If F has any forced attributes given on the command line, add them.
@@ -36,13 +42,18 @@ static cl::list<std::string> ForceRemoveAttributes(
3642
/// takes precedence.
3743
static void forceAttributes(Function &F) {
3844
auto ParseFunctionAndAttr = [&](StringRef S) {
39-
auto Kind = Attribute::None;
40-
auto KV = StringRef(S).split(':');
41-
if (KV.first != F.getName())
42-
return Kind;
43-
Kind = Attribute::getAttrKindFromName(KV.second);
45+
StringRef AttributeText;
46+
if (S.contains(':')) {
47+
auto KV = StringRef(S).split(':');
48+
if (KV.first != F.getName())
49+
return Attribute::None;
50+
AttributeText = KV.second;
51+
} else {
52+
AttributeText = S;
53+
}
54+
auto Kind = Attribute::getAttrKindFromName(AttributeText);
4455
if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {
45-
LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
56+
LLVM_DEBUG(dbgs() << "ForcedAttribute: " << AttributeText
4657
<< " unknown or not a function attribute!\n");
4758
}
4859
return Kind;

llvm/test/Transforms/ForcedFunctionAttrs/forced.ll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
; RUN: opt < %s -S -passes=forceattrs -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=REMOVE-NOINLINE
55
; RUN: opt < %s -S -passes=forceattrs -force-attribute goo:cold -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=ADD-COLD-REMOVE-NOINLINE
66
; RUN: opt < %s -S -passes=forceattrs -force-attribute goo:noinline -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=ADD-NOINLINE-REMOVE-NOINLINE
7+
; RUN: opt < %s -S -passes=forceattrs -force-attribute optsize | FileCheck %s --check-prefix=CHECK-ADD-ALL
8+
; RUN: opt < %s -S -passes=forceattrs -force-remove-attribute noinline | FileCheck %s --check-prefix=CHECK-REMOVE-ALL
79

810
; CHECK-CONTROL: define void @foo() {
911
; CHECK-FOO: define void @foo() #0 {
@@ -32,3 +34,18 @@ attributes #0 = { noinline }
3234
; CHECK-FOO: attributes #0 = { noinline }
3335
; REMOVE-COLD: attributes #0 = { noinline }
3436
; ADD-COLD-REMOVE-NOINLINE: attributes #0 = { cold }
37+
38+
; When passing an attribute without specifying a function, the attribute
39+
; should be added to all functions in the module.
40+
; CHECK-ADD-ALL: define void @foo() #0 {
41+
; CHECK-ADD-ALL: define void @goo() #1 {
42+
; CHECK-ADD-ALL: attributes #0 = { optsize }
43+
; CHECK-ADD-ALL: attributes #1 = { noinline optsize }
44+
45+
; When passing an attribute to be removed without specifying a function,
46+
; the attribute should be removed from all functions in the module that
47+
; have it.
48+
; CHECK-REMOVE-ALL: define void @foo() {
49+
; CHECK-REMOVE-ALL: define void @goo() {
50+
; CHECK-REMOVE-ALL-NOT: attributes #0
51+

0 commit comments

Comments
 (0)