diff --git a/llvm/test/BugPoint/reduce-declarations.ll b/llvm/test/BugPoint/reduce-declarations.ll new file mode 100644 --- /dev/null +++ b/llvm/test/BugPoint/reduce-declarations.ll @@ -0,0 +1,31 @@ +; REQUIRES: plugins +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashname -silence-passes > /dev/null +; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck --check-prefix=NONUKE %s +; +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashname -silence-passes -replace-funcs-with-null > /dev/null +; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck --check-prefix=NUKE %s + +declare i32 @foo() +declare i32 @crashing() +declare dso_local i32 @bar() + +; NONUKE-NOT: @foo +; NONUKE: declare void @crashing +; NONUKE-NOT: @foo +; NONUKE-LABEL: define void @test( +; NONUKE-NEXT: call void @crashing() +; NONUKE-NEXT: ret void + +; NUKE-NOT: @foo +; NUKE-NOT: @crashing +; NUKE-NOT: @foo +; NUKE-LABEL: define void @test( +; NUKE-NEXT: %v2 = call i32 null() +; NUKE-NEXT: ret void + +define i32 @test(i32* %a, i8* %b) { + %v1 = call i32 @foo() + %v2 = call i32 @crashing() + %t = add i32 %v1, %v2 + ret i32 %t +} diff --git a/llvm/tools/bugpoint-passes/TestPasses.cpp b/llvm/tools/bugpoint-passes/TestPasses.cpp --- a/llvm/tools/bugpoint-passes/TestPasses.cpp +++ b/llvm/tools/bugpoint-passes/TestPasses.cpp @@ -185,3 +185,29 @@ C("bugpoint-crashmetadata", "BugPoint Test Pass - Intentionally crash on " "fabs calls with fpmath metadata and an fadd as argument"); + +namespace { +class CrashOnCall : public FunctionPass { +public: + static char ID; // Pass ID, replacement for typeid + CrashOnCall() : FunctionPass(ID) {} + +private: + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + // Crash on any instructions using values name 'crashing'. + bool runOnFunction(Function &F) override { + for (Instruction &I : instructions(F)) + if (isa(&I)) + abort(); + return false; + } +}; +} // namespace + +char CrashOnCall::ID = 0; +static RegisterPass + D("bugpoint-crashname", + "BugPoint Test Pass - Intentionally crash on calls;"); diff --git a/llvm/tools/bugpoint/CrashDebugger.cpp b/llvm/tools/bugpoint/CrashDebugger.cpp --- a/llvm/tools/bugpoint/CrashDebugger.cpp +++ b/llvm/tools/bugpoint/CrashDebugger.cpp @@ -262,9 +262,13 @@ if (!ReplaceFuncsWithNull) { // Loop over and delete any functions which we aren't supposed to be playing // with... - for (Function &I : *M) - if (!I.isDeclaration() && !Functions.count(&I)) + for (Function &I : make_early_inc_range(*M)) { + if (Functions.count(&I)) + continue; + if (!I.isDeclaration()) { DeleteFunctionBody(&I); + } + } } else { std::vector ToRemove; // First, remove aliases to functions we're about to purge. @@ -290,7 +294,7 @@ } for (Function &I : *M) { - if (!I.isDeclaration() && !Functions.count(&I)) { + if (!Functions.count(&I)) { PointerType *Ty = cast(I.getType()); Constant *Replacement = ConstantPointerNull::get(Ty); I.replaceAllUsesWith(Replacement); @@ -1198,7 +1202,6 @@ // Now try to reduce the number of functions in the module to something small. std::vector Functions; for (Function &F : BD.getProgram()) - if (!F.isDeclaration()) Functions.push_back(&F); if (Functions.size() > 1 && !BugpointIsInterrupted) {