diff --git a/llvm/test/Reduce/remove-function-bodies-used-in-globals.ll b/llvm/test/Reduce/remove-function-bodies-used-in-globals.ll new file mode 100644 index 000000000000..0ad801491c6b --- /dev/null +++ b/llvm/test/Reduce/remove-function-bodies-used-in-globals.ll @@ -0,0 +1,14 @@ +; RUN: llvm-reduce --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +; CHECK-INTERESTINGNESS: @alias = +; CHECK-FINAL: @alias = alias void (i32), void (i32)* undef + +@alias = alias void (i32), void (i32)* @func + +; CHECK-FINAL-NOT: @func() + +define void @func(i32 %arg) { +entry: + ret void +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp index 4dd7b98fca3b..223d6adbd140 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp @@ -14,42 +14,36 @@ #include "ReduceFunctions.h" #include "Delta.h" -#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Instructions.h" -#include <set> +#include <iterator> +#include <vector> using namespace llvm; -/// Removes all the Defined Functions (as well as their calls) +/// Removes all the Defined Functions /// that aren't inside any of the desired Chunks. static void extractFunctionsFromModule(const std::vector<Chunk> &ChunksToKeep, Module *Program) { Oracle O(ChunksToKeep); - // Get functions inside desired chunks - std::set<Function *> FuncsToKeep; - for (auto &F : *Program) - if (O.shouldKeep()) - FuncsToKeep.insert(&F); + // Record all out-of-chunk functions. + std::vector<std::reference_wrapper<Function>> FuncsToRemove; + copy_if(Program->functions(), std::back_inserter(FuncsToRemove), + [&O](auto &unused) { return !O.shouldKeep(); }); - // Delete out-of-chunk functions, and replace their users with undef - std::vector<Function *> FuncsToRemove; - SetVector<Instruction *> InstrsToRemove; - for (auto &F : *Program) - if (!FuncsToKeep.count(&F)) { - for (auto U : F.users()) { - U->replaceAllUsesWith(UndefValue::get(U->getType())); - if (auto *I = dyn_cast<Instruction>(U)) - InstrsToRemove.insert(I); - } - FuncsToRemove.push_back(&F); - } + // Then, drop body of each of them. We want to batch this and do nothing else + // here so that minimal number of remaining exteranal uses will remain. + for (Function &F : FuncsToRemove) + F.dropAllReferences(); - for (auto *I : InstrsToRemove) - I->eraseFromParent(); - - for (auto *F : FuncsToRemove) - F->eraseFromParent(); + // And finally, we can actually delete them. + for (Function &F : FuncsToRemove) { + // Replace all *still* remaining uses with undef. + F.replaceAllUsesWith(UndefValue::get(F.getType())); + // And finally, fully drop it. + F.eraseFromParent(); + } } /// Counts the amount of non-declaration functions and prints their