summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Gesiak <modocache@gmail.com>2018-12-19 03:42:19 +0000
committerBrian Gesiak <modocache@gmail.com>2018-12-19 03:42:19 +0000
commit274981eb83440be5359da5efc221416f9ea96e91 (patch)
treefc187d7cd2c957ccfd15ad1b6849f816e64ff767
parent0b832095d7c383e464e51db0a7c86f9e553926ca (diff)
downloadbcm5719-llvm-274981eb83440be5359da5efc221416f9ea96e91.tar.gz
bcm5719-llvm-274981eb83440be5359da5efc221416f9ea96e91.zip
[bugpoint][PR29027] Reduce function attributes
Summary: In addition to reducing the functions in an LLVM module, bugpoint now reduces the function attributes associated with each of the remaining functions. To test this, add a -bugpoint-crashfuncattr test pass, which crashes if a function in the module has a "bugpoint-crash" attribute. A test case demonstrates that the IR is reduced to just that one attribute. Reviewers: MatzeB, silvas, davide, reames Reviewed By: reames Subscribers: reames, llvm-commits Differential Revision: https://reviews.llvm.org/D55216 llvm-svn: 349601
-rw-r--r--llvm/test/BugPoint/func-attrs-keyval.ll11
-rw-r--r--llvm/test/BugPoint/func-attrs.ll11
-rw-r--r--llvm/tools/bugpoint-passes/TestPasses.cpp25
-rw-r--r--llvm/tools/bugpoint/CrashDebugger.cpp92
4 files changed, 139 insertions, 0 deletions
diff --git a/llvm/test/BugPoint/func-attrs-keyval.ll b/llvm/test/BugPoint/func-attrs-keyval.ll
new file mode 100644
index 00000000000..830d0964cde
--- /dev/null
+++ b/llvm/test/BugPoint/func-attrs-keyval.ll
@@ -0,0 +1,11 @@
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashfuncattr -silence-passes
+; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
+; REQUIRES: loadable_module
+
+; CHECK: f() #[[ATTRS:[0-9]+]]
+define void @f() #0 {
+ ret void
+}
+
+; CHECK: attributes #[[ATTRS]] = { "bugpoint-crash"="sure" }
+attributes #0 = { "bugpoint-crash"="sure" noreturn "no-frame-pointer-elim-non-leaf" }
diff --git a/llvm/test/BugPoint/func-attrs.ll b/llvm/test/BugPoint/func-attrs.ll
new file mode 100644
index 00000000000..3941e73c217
--- /dev/null
+++ b/llvm/test/BugPoint/func-attrs.ll
@@ -0,0 +1,11 @@
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashfuncattr -silence-passes
+; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
+; REQUIRES: loadable_module
+
+; CHECK: f() #[[ATTRS:[0-9]+]]
+define void @f() #0 {
+ ret void
+}
+
+; CHECK: attributes #[[ATTRS]] = { "bugpoint-crash" }
+attributes #0 = { noinline "bugpoint-crash" "no-frame-pointer-elim-non-leaf" }
diff --git a/llvm/tools/bugpoint-passes/TestPasses.cpp b/llvm/tools/bugpoint-passes/TestPasses.cpp
index 22ded6261a1..6b1463685b2 100644
--- a/llvm/tools/bugpoint-passes/TestPasses.cpp
+++ b/llvm/tools/bugpoint-passes/TestPasses.cpp
@@ -123,3 +123,28 @@ char CrashOnTooManyCUs::ID = 0;
static RegisterPass<CrashOnTooManyCUs>
A("bugpoint-crash-too-many-cus",
"BugPoint Test Pass - Intentionally crash on too many CUs");
+
+namespace {
+class CrashOnFunctionAttribute : public FunctionPass {
+public:
+ static char ID; // Pass ID, replacement for typeid
+ CrashOnFunctionAttribute() : FunctionPass(ID) {}
+
+private:
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ bool runOnFunction(Function &F) override {
+ AttributeSet A = F.getAttributes().getFnAttributes();
+ if (A.hasAttribute("bugpoint-crash"))
+ abort();
+ return false;
+ }
+};
+} // namespace
+
+char CrashOnFunctionAttribute::ID = 0;
+static RegisterPass<CrashOnFunctionAttribute>
+ B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on "
+ "function attribute 'bugpoint-crash'");
diff --git a/llvm/tools/bugpoint/CrashDebugger.cpp b/llvm/tools/bugpoint/CrashDebugger.cpp
index a50ff4c255b..ef6a214fde2 100644
--- a/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -315,6 +315,66 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function *> &Funcs) {
}
namespace {
+/// ReduceCrashingFunctionAttributes reducer - This works by removing
+/// attributes on a particular function and seeing if the program still crashes.
+/// If it does, then keep the newer, smaller program.
+///
+class ReduceCrashingFunctionAttributes : public ListReducer<Attribute> {
+ BugDriver &BD;
+ std::string FnName;
+ BugTester TestFn;
+
+public:
+ ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,
+ BugTester testFn)
+ : BD(bd), FnName(FnName), TestFn(testFn) {}
+
+ Expected<TestResult> doTest(std::vector<Attribute> &Prefix,
+ std::vector<Attribute> &Kept) override {
+ if (!Kept.empty() && TestFuncAttrs(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestFuncAttrs(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
+
+ bool TestFuncAttrs(std::vector<Attribute> &Attrs);
+};
+}
+
+bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
+ std::vector<Attribute> &Attrs) {
+ // Clone the program to try hacking it apart...
+ std::unique_ptr<Module> M = CloneModule(BD.getProgram());
+ Function *F = M->getFunction(FnName);
+
+ // Build up an AttributeList from the attributes we've been given by the
+ // reducer.
+ AttrBuilder AB;
+ for (auto A : Attrs)
+ AB.addAttribute(A);
+ AttributeList NewAttrs;
+ NewAttrs =
+ NewAttrs.addAttributes(BD.getContext(), AttributeList::FunctionIndex, AB);
+
+ // Set this new list of attributes on the function.
+ F->setAttributes(NewAttrs);
+
+ // Try running on the hacked up program...
+ if (TestFn(BD, M.get())) {
+ BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
+
+ // Pass along the set of attributes that caused the crash.
+ Attrs.clear();
+ for (Attribute A : NewAttrs.getFnAttributes()) {
+ Attrs.push_back(A);
+ }
+ return true;
+ }
+ return false;
+}
+
+namespace {
/// Simplify the CFG without completely destroying it.
/// This is not well defined, but basically comes down to "try to eliminate
/// unreachable blocks and constant fold terminators without deciding that
@@ -1056,6 +1116,38 @@ static Error DebugACrash(BugDriver &BD, BugTester TestFn) {
BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
}
+ // For each remaining function, try to reduce that function's attributes.
+ std::vector<std::string> FunctionNames;
+ for (Function &F : BD.getProgram())
+ FunctionNames.push_back(F.getName());
+
+ if (!FunctionNames.empty() && !BugpointIsInterrupted) {
+ outs() << "\n*** Attempting to reduce the number of function attributes in "
+ "the testcase\n";
+
+ unsigned OldSize = 0;
+ unsigned NewSize = 0;
+ for (std::string &Name : FunctionNames) {
+ Function *Fn = BD.getProgram().getFunction(Name);
+ assert(Fn && "Could not find funcion?");
+
+ std::vector<Attribute> Attrs;
+ for (Attribute A : Fn->getAttributes().getFnAttributes())
+ Attrs.push_back(A);
+
+ OldSize += Attrs.size();
+ Expected<bool> Result =
+ ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);
+ if (Error E = Result.takeError())
+ return E;
+
+ NewSize += Attrs.size();
+ }
+
+ if (OldSize < NewSize)
+ BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");
+ }
+
// Attempt to change conditional branches into unconditional branches to
// eliminate blocks.
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
OpenPOWER on IntegriCloud