diff options
author | Brian Gesiak <modocache@gmail.com> | 2018-12-19 03:42:19 +0000 |
---|---|---|
committer | Brian Gesiak <modocache@gmail.com> | 2018-12-19 03:42:19 +0000 |
commit | 274981eb83440be5359da5efc221416f9ea96e91 (patch) | |
tree | fc187d7cd2c957ccfd15ad1b6849f816e64ff767 | |
parent | 0b832095d7c383e464e51db0a7c86f9e553926ca (diff) | |
download | bcm5719-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.ll | 11 | ||||
-rw-r--r-- | llvm/test/BugPoint/func-attrs.ll | 11 | ||||
-rw-r--r-- | llvm/tools/bugpoint-passes/TestPasses.cpp | 25 | ||||
-rw-r--r-- | llvm/tools/bugpoint/CrashDebugger.cpp | 92 |
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) { |