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