llvm.org GIT mirror llvm / 79550f6
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349601 91177308-0d34-0410-b5e6-96231b3b80d8 Brian Gesiak 8 months ago
4 changed file(s) with 139 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashfuncattr -silence-passes
1 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
2 ; REQUIRES: loadable_module
3
4 ; CHECK: f() #[[ATTRS:[0-9]+]]
5 define void @f() #0 {
6 ret void
7 }
8
9 ; CHECK: attributes #[[ATTRS]] = { "bugpoint-crash"="sure" }
10 attributes #0 = { "bugpoint-crash"="sure" noreturn "no-frame-pointer-elim-non-leaf" }
0 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashfuncattr -silence-passes
1 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
2 ; REQUIRES: loadable_module
3
4 ; CHECK: f() #[[ATTRS:[0-9]+]]
5 define void @f() #0 {
6 ret void
7 }
8
9 ; CHECK: attributes #[[ATTRS]] = { "bugpoint-crash" }
10 attributes #0 = { noinline "bugpoint-crash" "no-frame-pointer-elim-non-leaf" }
314314 }
315315
316316 namespace {
317 /// ReduceCrashingFunctionAttributes reducer - This works by removing
318 /// attributes on a particular function and seeing if the program still crashes.
319 /// If it does, then keep the newer, smaller program.
320 ///
321 class ReduceCrashingFunctionAttributes : public ListReducer {
322 BugDriver &BD;
323 std::string FnName;
324 BugTester TestFn;
325
326 public:
327 ReduceCrashingFunctionAttributes(BugDriver &bd, const std::string &FnName,
328 BugTester testFn)
329 : BD(bd), FnName(FnName), TestFn(testFn) {}
330
331 Expected doTest(std::vector &Prefix,
332 std::vector &Kept) override {
333 if (!Kept.empty() && TestFuncAttrs(Kept))
334 return KeepSuffix;
335 if (!Prefix.empty() && TestFuncAttrs(Prefix))
336 return KeepPrefix;
337 return NoFailure;
338 }
339
340 bool TestFuncAttrs(std::vector &Attrs);
341 };
342 }
343
344 bool ReduceCrashingFunctionAttributes::TestFuncAttrs(
345 std::vector &Attrs) {
346 // Clone the program to try hacking it apart...
347 std::unique_ptr M = CloneModule(BD.getProgram());
348 Function *F = M->getFunction(FnName);
349
350 // Build up an AttributeList from the attributes we've been given by the
351 // reducer.
352 AttrBuilder AB;
353 for (auto A : Attrs)
354 AB.addAttribute(A);
355 AttributeList NewAttrs;
356 NewAttrs =
357 NewAttrs.addAttributes(BD.getContext(), AttributeList::FunctionIndex, AB);
358
359 // Set this new list of attributes on the function.
360 F->setAttributes(NewAttrs);
361
362 // Try running on the hacked up program...
363 if (TestFn(BD, M.get())) {
364 BD.setNewProgram(std::move(M)); // It crashed, keep the trimmed version...
365
366 // Pass along the set of attributes that caused the crash.
367 Attrs.clear();
368 for (Attribute A : NewAttrs.getFnAttributes()) {
369 Attrs.push_back(A);
370 }
371 return true;
372 }
373 return false;
374 }
375
376 namespace {
317377 /// Simplify the CFG without completely destroying it.
318378 /// This is not well defined, but basically comes down to "try to eliminate
319379 /// unreachable blocks and constant fold terminators without deciding that
10551115 BD.EmitProgressBitcode(BD.getProgram(), "reduced-function");
10561116 }
10571117
1118 // For each remaining function, try to reduce that function's attributes.
1119 std::vector FunctionNames;
1120 for (Function &F : BD.getProgram())
1121 FunctionNames.push_back(F.getName());
1122
1123 if (!FunctionNames.empty() && !BugpointIsInterrupted) {
1124 outs() << "\n*** Attempting to reduce the number of function attributes in "
1125 "the testcase\n";
1126
1127 unsigned OldSize = 0;
1128 unsigned NewSize = 0;
1129 for (std::string &Name : FunctionNames) {
1130 Function *Fn = BD.getProgram().getFunction(Name);
1131 assert(Fn && "Could not find funcion?");
1132
1133 std::vector Attrs;
1134 for (Attribute A : Fn->getAttributes().getFnAttributes())
1135 Attrs.push_back(A);
1136
1137 OldSize += Attrs.size();
1138 Expected Result =
1139 ReduceCrashingFunctionAttributes(BD, Name, TestFn).reduceList(Attrs);
1140 if (Error E = Result.takeError())
1141 return E;
1142
1143 NewSize += Attrs.size();
1144 }
1145
1146 if (OldSize < NewSize)
1147 BD.EmitProgressBitcode(BD.getProgram(), "reduced-function-attributes");
1148 }
1149
10581150 // Attempt to change conditional branches into unconditional branches to
10591151 // eliminate blocks.
10601152 if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
122122 static RegisterPass
123123 A("bugpoint-crash-too-many-cus",
124124 "BugPoint Test Pass - Intentionally crash on too many CUs");
125
126 namespace {
127 class CrashOnFunctionAttribute : public FunctionPass {
128 public:
129 static char ID; // Pass ID, replacement for typeid
130 CrashOnFunctionAttribute() : FunctionPass(ID) {}
131
132 private:
133 void getAnalysisUsage(AnalysisUsage &AU) const override {
134 AU.setPreservesAll();
135 }
136
137 bool runOnFunction(Function &F) override {
138 AttributeSet A = F.getAttributes().getFnAttributes();
139 if (A.hasAttribute("bugpoint-crash"))
140 abort();
141 return false;
142 }
143 };
144 } // namespace
145
146 char CrashOnFunctionAttribute::ID = 0;
147 static RegisterPass
148 B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on "
149 "function attribute 'bugpoint-crash'");