diff --git a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp --- a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -16,18 +16,24 @@ #define DEBUG_TYPE "forceattrs" -static cl::list - 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-attribute=foo:noinline. This " - "option can be specified multiple times.")); +static cl::list ForceAttributes( + "force-attribute", cl::Hidden, + cl::desc( + "Add an attribute to a function. This can be a " + "pair of 'function-name:attribute-name', to apply an attribute to a " + "specific function. For " + "example -force-attribute=foo:noinline. Specifying only an attribute " + "will apply the attribute to every function in the module. This " + "option can be specified multiple times.")); static cl::list ForceRemoveAttributes( "force-remove-attribute", cl::Hidden, - cl::desc("Remove an attribute from a function. This should be a " - "pair of 'function-name:attribute-name', for " - "example -force-remove-attribute=foo:noinline. This " + cl::desc("Remove an attribute from a function. This can be a " + "pair of 'function-name:attribute-name' to remove an attribute " + "from a specific function. For " + "example -force-remove-attribute=foo:noinline. Specifying only an " + "attribute will remove the attribute from all functions in the " + "module. This " "option can be specified multiple times.")); /// If F has any forced attributes given on the command line, add them. @@ -36,13 +42,18 @@ /// takes precedence. static void forceAttributes(Function &F) { auto ParseFunctionAndAttr = [&](StringRef S) { - auto Kind = Attribute::None; - auto KV = StringRef(S).split(':'); - if (KV.first != F.getName()) - return Kind; - Kind = Attribute::getAttrKindFromName(KV.second); + StringRef AttributeText; + if (S.contains(':')) { + auto KV = StringRef(S).split(':'); + if (KV.first != F.getName()) + return Attribute::None; + AttributeText = KV.second; + } else { + AttributeText = S; + } + auto Kind = Attribute::getAttrKindFromName(AttributeText); if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) { - LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second + LLVM_DEBUG(dbgs() << "ForcedAttribute: " << AttributeText << " unknown or not a function attribute!\n"); } return Kind; diff --git a/llvm/test/Transforms/ForcedFunctionAttrs/forced.ll b/llvm/test/Transforms/ForcedFunctionAttrs/forced.ll --- a/llvm/test/Transforms/ForcedFunctionAttrs/forced.ll +++ b/llvm/test/Transforms/ForcedFunctionAttrs/forced.ll @@ -4,6 +4,8 @@ ; RUN: opt < %s -S -passes=forceattrs -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=REMOVE-NOINLINE ; RUN: opt < %s -S -passes=forceattrs -force-attribute goo:cold -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=ADD-COLD-REMOVE-NOINLINE ; RUN: opt < %s -S -passes=forceattrs -force-attribute goo:noinline -force-remove-attribute goo:noinline | FileCheck %s --check-prefix=ADD-NOINLINE-REMOVE-NOINLINE +; RUN: opt < %s -S -passes=forceattrs -force-attribute optsize | FileCheck %s --check-prefix=CHECK-ADD-ALL +; RUN: opt < %s -S -passes=forceattrs -force-remove-attribute noinline | FileCheck %s --check-prefix=CHECK-REMOVE-ALL ; CHECK-CONTROL: define void @foo() { ; CHECK-FOO: define void @foo() #0 { @@ -32,3 +34,18 @@ ; CHECK-FOO: attributes #0 = { noinline } ; REMOVE-COLD: attributes #0 = { noinline } ; ADD-COLD-REMOVE-NOINLINE: attributes #0 = { cold } + +; When passing an attribute without specifying a function, the attribute +; should be added to all functions in the module. +; CHECK-ADD-ALL: define void @foo() #0 { +; CHECK-ADD-ALL: define void @goo() #1 { +; CHECK-ADD-ALL: attributes #0 = { optsize } +; CHECK-ADD-ALL: attributes #1 = { noinline optsize } + +; When passing an attribute to be removed without specifying a function, +; the attribute should be removed from all functions in the module that +; have it. +; CHECK-REMOVE-ALL: define void @foo() { +; CHECK-REMOVE-ALL: define void @goo() { +; CHECK-REMOVE-ALL-NOT: attributes #0 +