diff --git a/llvm/test/Reduce/remove-funcs.ll b/llvm/test/Reduce/remove-funcs.ll
--- a/llvm/test/Reduce/remove-funcs.ll
+++ b/llvm/test/Reduce/remove-funcs.ll
@@ -1,7 +1,7 @@
 ; Test that llvm-reduce can remove uninteresting functions as well as
 ; their InstCalls.
 ;
-; RUN: llvm-reduce --test %p/Inputs/interestingness-test.sh --test-arg %lli %s
+; RUN: llvm-reduce --run-only functions --test %p/Inputs/interestingness-test.sh --test-arg %lli %s
 ; RUN: cat reduced.ll | FileCheck %s
 ; REQUIRES: plugins, shell
 
diff --git a/llvm/test/Reduce/remove-global-vars.ll b/llvm/test/Reduce/remove-global-vars.ll
--- a/llvm/test/Reduce/remove-global-vars.ll
+++ b/llvm/test/Reduce/remove-global-vars.ll
@@ -1,7 +1,7 @@
 ; Test that llvm-reduce can remove uninteresting Global Variables as well as
 ; their uses (both direct and derived).
 ;
-; RUN: llvm-reduce --test %p/Inputs/interestingness-test.sh --test-arg %lli %s
+; RUN: llvm-reduce --run-only globals --test %p/Inputs/interestingness-test.sh --test-arg %lli %s
 ; RUN: cat reduced.ll | FileCheck %s
 ; REQUIRES: plugins, shell
 
diff --git a/llvm/test/Reduce/remove-metadata.ll b/llvm/test/Reduce/remove-metadata.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Reduce/remove-metadata.ll
@@ -0,0 +1,80 @@
+; Test that llvm-reduce can remove uninteresting metadata from an IR file.
+; The "Reduce Metadata" pass erases named and unnamed metadata nodes, as well as debug functions.
+;
+; RUN: llvm-reduce --run-only metadata --test %p/Inputs/interestingness-test.sh --test-arg %lli %s
+; RUN: cat reduced.ll | FileCheck %s
+; REQUIRES: plugins, shell
+
+; CHECK-NOT: llvm.
+; CHECK-NOT: !dbg
+; CHECK-NOT: !
+
+@x = dso_local global i32 0, align 4, !dbg !0
+@y = dso_local global i32 0, align 4, !dbg !6
+@.str = private unnamed_addr constant [4 x i8] c"%i\0A\00", align 1
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @func(i32 %x) !dbg !13 {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !16, metadata !DIExpression()), !dbg !17
+  %0 = load i32, i32* %x.addr, align 4, !dbg !18
+  %inc = add nsw i32 %0, 1, !dbg !18
+  store i32 %inc, i32* %x.addr, align 4, !dbg !18
+  ret void, !dbg !19
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+; Function Attrs: noinline norecurse optnone uwtable
+define dso_local i32 @main() !dbg !20 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  store i32 10, i32* @x, align 4, !dbg !23
+  %0 = load i32, i32* @x, align 4, !dbg !24
+  %sub = sub nsw i32 %0, 5, !dbg !25
+  store i32 %sub, i32* @y, align 4, !dbg !26
+  %1 = load i32, i32* @x, align 4, !dbg !27
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %1), !dbg !28
+  ret i32 0, !dbg !29
+}
+
+declare dso_local i32 @printf(i8*, ...)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 3, type: !8, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 9.0.0 (https://github.com/llvm/llvm-project.git ff0a72129a3e97bf7fddca38688808cd4f4e8f7b)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "ints.cpp", directory: "")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 4, type: !8, isLocal: false, isDefinition: true)
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{i32 1, !"wchar_size", i32 4}
+!12 = !{!"clang version 9.0.0 (https://github.com/llvm/llvm-project.git ff0a72129a3e97bf7fddca38688808cd4f4e8f7b)"}
+!13 = distinct !DISubprogram(name: "func", linkageName: "func", scope: !3, file: !3, line: 6, type: !14, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
+!14 = !DISubroutineType(types: !15)
+!15 = !{null, !8}
+!16 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !3, line: 6, type: !8)
+!17 = !DILocation(line: 6, column: 15, scope: !13)
+!18 = !DILocation(line: 7, column: 4, scope: !13)
+!19 = !DILocation(line: 8, column: 1, scope: !13)
+!20 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 10, type: !21, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
+!21 = !DISubroutineType(types: !22)
+!22 = !{!8}
+!23 = !DILocation(line: 11, column: 5, scope: !20)
+!24 = !DILocation(line: 12, column: 7, scope: !20)
+!25 = !DILocation(line: 12, column: 9, scope: !20)
+!26 = !DILocation(line: 12, column: 5, scope: !20)
+!27 = !DILocation(line: 13, column: 18, scope: !20)
+!28 = !DILocation(line: 13, column: 3, scope: !20)
+!29 = !DILocation(line: 14, column: 3, scope: !20)
diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt
--- a/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -16,8 +16,9 @@
   llvm-reduce.cpp
   TestRunner.cpp
   deltas/Delta.cpp
-  deltas/RemoveFunctions.cpp
-  deltas/RemoveGlobalVars.cpp
+  deltas/ReduceFunctions.cpp
+  deltas/ReduceGlobalVars.cpp
+  deltas/ReduceMetadata.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/llvm/tools/llvm-reduce/DeltaManager.h b/llvm/tools/llvm-reduce/DeltaManager.h
--- a/llvm/tools/llvm-reduce/DeltaManager.h
+++ b/llvm/tools/llvm-reduce/DeltaManager.h
@@ -13,19 +13,23 @@
 
 #include "TestRunner.h"
 #include "deltas/Delta.h"
-#include "deltas/RemoveFunctions.h"
-#include "deltas/RemoveGlobalVars.h"
-#include "deltas/RemoveMetadata.h"
+#include "deltas/ReduceFunctions.h"
+#include "deltas/ReduceGlobalVars.h"
+#include "deltas/ReduceMetadata.h"
 
 namespace llvm {
 
-inline void runDeltaPasses(TestRunner &Tester) {
-  // TODO: Add option to only call certain delta passes
-  outs() << "Reducing functions...\n";
-  removeFunctionsDeltaPass(Tester);
-  outs() << "Reducing GVs...\n";
-  removeGlobalsDeltaPass(Tester);
-  // TODO: Implement the remaining Delta Passes
+inline void runDeltaPasses(TestRunner &Tester,
+                           std::vector<std::string> DeltaPasses) {
+  for (auto &Pass : DeltaPasses) {
+    if (Pass == "functions")
+      reduceFunctionsDeltaPass(Tester);
+    else if (Pass == "globals")
+      reduceGlobalsDeltaPass(Tester);
+    else if (Pass == "metadata")
+      reduceMetadataDeltaPass(Tester);
+    // TODO: Implement the remaining Delta Passes
+  }
 }
 
 } // namespace llvm
diff --git a/llvm/tools/llvm-reduce/deltas/Delta.h b/llvm/tools/llvm-reduce/deltas/Delta.h
--- a/llvm/tools/llvm-reduce/deltas/Delta.h
+++ b/llvm/tools/llvm-reduce/deltas/Delta.h
@@ -30,6 +30,16 @@
   int begin;
   int end;
 
+  /// Helper function to verify if a given Target-index is inside the Chunk
+  bool contains(int Index) const { return Index >= begin && Index <= end; }
+
+  void print() const {
+    outs() << "[" << begin;
+    if (end - begin != 0)
+      outs() << "," << end;
+    outs() << "]";
+  }
+
   /// Operator when populating CurrentChunks in Generic Delta Pass
   friend bool operator!=(const Chunk &C1, const Chunk &C2) {
     return C1.begin != C2.begin && C1.end != C2.end;
diff --git a/llvm/tools/llvm-reduce/deltas/Delta.cpp b/llvm/tools/llvm-reduce/deltas/Delta.cpp
--- a/llvm/tools/llvm-reduce/deltas/Delta.cpp
+++ b/llvm/tools/llvm-reduce/deltas/Delta.cpp
@@ -53,10 +53,7 @@
   for (auto C : Chunks) {
     if (!Oneline)
       outs() << '\t';
-    outs() << "[" << C.begin;
-    if (C.end - C.begin != 0)
-      outs() << "," << C.end;
-    outs() << "]";
+    C.print();
     if (!Oneline)
       outs() << '\n';
   }
@@ -99,6 +96,9 @@
   return SplitOne;
 }
 
+/// Runs the Delta Debugging algorithm, splits the code into chunks and
+/// reduces the amount of chunks that are considered interesting by the
+/// given test.
 void llvm::runDeltaPass(
     TestRunner &Test, int Targets,
     std::function<std::unique_ptr<Module>(std::vector<Chunk>, Module *)>
@@ -125,9 +125,6 @@
         if (!UninterestingChunks.count(C) && C != Chunks[I])
           CurrentChunks.push_back(C);
 
-      if (CurrentChunks.empty())
-        break;
-
       // Generate Module with only Targets inside Current Chunks
       std::unique_ptr<Module> CurrentProgram =
           ExtractChunksFromModule(CurrentChunks, Test.getProgram());
@@ -136,7 +133,11 @@
           createTmpFile(CurrentProgram.get(), Test.getTmpDir());
 
       outs() << "Testing with: ";
-      printChunks(CurrentChunks, /*Oneline=*/true);
+      if (CurrentChunks.empty())
+        outs() << "No Chunks";
+      else
+        printChunks(CurrentChunks, /*Oneline=*/true);
+
       outs() << " | " << sys::path::filename(CurrentFilepath);
 
       // Current Chunks aren't interesting
diff --git a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
rename from llvm/tools/llvm-reduce/deltas/RemoveFunctions.h
rename to llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
--- a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.h
+++ b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
@@ -1,4 +1,4 @@
-//===- RemoveFunctions.h - Specialized Delta Pass -------------------------===//
+//===- ReduceFunctions.h - Specialized Delta Pass -------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -16,5 +16,5 @@
 #include "llvm/Transforms/Utils/Cloning.h"
 
 namespace llvm {
-void removeFunctionsDeltaPass(TestRunner &Test);
+void reduceFunctionsDeltaPass(TestRunner &Test);
 } // namespace llvm
diff --git a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
rename from llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp
rename to llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
--- a/llvm/tools/llvm-reduce/deltas/RemoveFunctions.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
@@ -1,4 +1,4 @@
-//===- RemoveFunctions.cpp - Specialized Delta Pass -----------------------===//
+//===- ReduceFunctions.cpp - Specialized Delta Pass -----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,7 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "RemoveFunctions.h"
+#include "ReduceFunctions.h"
 
 /// Removes all the Defined Functions (as well as their calls)
 /// that aren't inside any of the desired Chunks.
@@ -23,15 +23,14 @@
 
   // Get functions inside desired chunks
   std::set<Function *> FuncsToKeep;
-  int I = 0, FunctionCount = 1;
+  int I = 0, FunctionCount = 0;
   for (auto &F : *Clone) {
     if (!F.isDeclaration() && I < ChunksToKeep.size()) {
-      if (FunctionCount >= ChunksToKeep[I].begin &&
-          FunctionCount <= ChunksToKeep[I].end)
+      ++FunctionCount;
+      if (ChunksToKeep[I].contains(FunctionCount))
         FuncsToKeep.insert(&F);
       if (FunctionCount == ChunksToKeep[I].end)
         ++I;
-      ++FunctionCount;
     }
   }
 
@@ -66,7 +65,7 @@
 
 /// Counts the amount of non-declaration functions and prints their
 /// respective name & index
-static int countFunctions(Module *Program) {
+static int countDefinedFunctions(Module *Program) {
   // TODO: Silence index with --quiet flag
   outs() << "----------------------------\n";
   outs() << "Function Index Reference:\n";
@@ -80,7 +79,8 @@
   return FunctionCount;
 }
 
-void llvm::removeFunctionsDeltaPass(TestRunner &Test) {
-  int FunctionCount = countFunctions(Test.getProgram());
-  runDeltaPass(Test, FunctionCount, extractFunctionsFromModule);
+void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing Functions...\n";
+  int Functions = countDefinedFunctions(Test.getProgram());
+  runDeltaPass(Test, Functions, extractFunctionsFromModule);
 }
\ No newline at end of file
diff --git a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h b/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
rename from llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h
rename to llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
--- a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h
+++ b/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
@@ -1,4 +1,4 @@
-//===- RemoveGlobalVars.h - Specialized Delta Pass ------------------------===//
+//===- ReduceGlobalVars.h - Specialized Delta Pass ------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -17,5 +17,5 @@
 #include "llvm/Transforms/Utils/Cloning.h"
 
 namespace llvm {
-void removeGlobalsDeltaPass(TestRunner &Test);
+void reduceGlobalsDeltaPass(TestRunner &Test);
 } // namespace llvm
diff --git a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp b/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
rename from llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp
rename to llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
--- a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
@@ -1,4 +1,4 @@
-//===- RemoveGlobalVars.cpp - Specialized Delta Pass ----------------------===//
+//===- ReduceGlobalVars.cpp - Specialized Delta Pass ----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,7 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "RemoveGlobalVars.h"
+#include "ReduceGlobalVars.h"
 
 /// Goes over the users of a given instruction and erases them.
 /// For example, if @x is used by %call1 and %call2, both calls and the
@@ -38,14 +38,14 @@
 
   // Get GVs inside desired chunks
   std::set<GlobalVariable *> GVsToKeep;
-  int I = 0, GVCount = 1;
+  int I = 0, GVCount = 0;
   for (auto &GV : Clone->globals()) {
     if (GV.hasInitializer() && I < ChunksToKeep.size()) {
-      if (GVCount >= ChunksToKeep[I].begin && GVCount <= ChunksToKeep[I].end)
+      ++GVCount;
+      if (ChunksToKeep[I].contains(GVCount))
         GVsToKeep.insert(&GV);
       if (GVCount == ChunksToKeep[I].end)
         ++I;
-      ++GVCount;
     }
   }
 
@@ -88,7 +88,8 @@
   return GVCount;
 }
 
-void llvm::removeGlobalsDeltaPass(TestRunner &Test) {
+void llvm::reduceGlobalsDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing GVs...\n";
   int GVCount = countGVs(Test.getProgram());
   runDeltaPass(Test, GVCount, extractGVsFromModule);
 }
\ No newline at end of file
diff --git a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
rename from llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h
rename to llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
--- a/llvm/tools/llvm-reduce/deltas/RemoveGlobalVars.h
+++ b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
@@ -1,4 +1,4 @@
-//===- RemoveGlobalVars.h - Specialized Delta Pass ------------------------===//
+//===- ReduceMetadata.h - Specialized Delta Pass ------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,16 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements a function which calls the Generic Delta pass in order
-// to reduce initialized Global Variables, as well as any derived uses in the
-// provided Module.
+// This file implements two functions used by the Generic Delta Debugging
+// Algorithm, which are used to reduce Metadata tags, as well as debug
+// functions.
 //
 //===----------------------------------------------------------------------===//
 
 #include "Delta.h"
+#include "llvm/IR/Metadata.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include <set>
+#include <vector>
 
 namespace llvm {
-void removeGlobalsDeltaPass(TestRunner &Test);
+void reduceMetadataDeltaPass(TestRunner &Test);
 } // namespace llvm
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
@@ -0,0 +1,169 @@
+//===- ReduceMetadata.cpp - Specialized Delta Pass ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements two functions used by the Generic Delta Debugging
+// Algorithm, which are used to reduce Metadata tags, as well as debug
+// functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceMetadata.h"
+
+/// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set
+template <class T>
+static void getChunkMetadataNodes(T *MDUser, int &I,
+                                  const std::vector<Chunk> &ChunksToKeep,
+                                  std::set<MDNode *> &SeenNodes,
+                                  std::set<MDNode *> &NodesToKeep) {
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+  MDUser->getAllMetadata(MDs);
+  for (auto &MD : MDs) {
+    SeenNodes.insert(MD.second);
+    if (I < ChunksToKeep.size()) {
+      if (ChunksToKeep[I].contains(SeenNodes.size()))
+        NodesToKeep.insert(MD.second);
+      if (ChunksToKeep[I].end == SeenNodes.size())
+        ++I;
+    }
+  }
+}
+
+/// Adds Nodes to seen, and if one of them is out-of-chunks,
+template <class T>
+static void eraseNodeIfOutsideChunk(T *MDUser,
+                                    std::set<MDNode *> &NodesToKeep) {
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+  MDUser->getAllMetadata(MDs);
+  for (int I = 0, E = MDs.size(); I != E; ++I)
+    if (!NodesToKeep.count(MDs[I].second))
+      MDUser->setMetadata(I, NULL);
+}
+
+/// Erases function and its users. It also replaces the uses of any user with
+/// "undef" (e.g. if a function call is stored somewhere it is )
+static void deleteFunctionAndCallers(Function *F) {
+  for (auto U : F->users()) {
+    U->replaceAllUsesWith(UndefValue::get(U->getType()));
+    if (auto *Inst = dyn_cast<Instruction>(U))
+      Inst->eraseFromParent();
+  }
+  F->eraseFromParent();
+}
+
+/// Removes all the Named and Unnamed Metadata Nodes (as well as any debug
+/// functions) that aren't inside the desired Chunks.
+/// @returns the Module stripped of out-of-chunk MDNodes
+static std::unique_ptr<Module>
+extractMetadataNodesFromModule(const std::vector<Chunk> &ChunksToKeep,
+                               Module *Program) {
+  std::unique_ptr<Module> Clone = CloneModule(*Program);
+
+  std::set<MDNode *> SeenNodes;
+  std::set<MDNode *> NodesToKeep;
+  int I = 0;
+
+  // Add chunk MDNodes used by GVs, Functions, and Instructions to set
+  for (auto &GV : Clone->globals())
+    getChunkMetadataNodes(&GV, I, ChunksToKeep, SeenNodes, NodesToKeep);
+
+  for (auto &F : *Clone) {
+    getChunkMetadataNodes(&F, I, ChunksToKeep, SeenNodes, NodesToKeep);
+    for (auto &BB : F)
+      for (auto &Inst : BB)
+        getChunkMetadataNodes(&Inst, I, ChunksToKeep, SeenNodes, NodesToKeep);
+  }
+
+  // Once more, go over metadata nodes, but deleting the ones outside chunks
+  for (auto &GV : Clone->globals())
+    eraseNodeIfOutsideChunk(&GV, NodesToKeep);
+
+  // And keeping a list of debug functions
+  std::vector<Function *> DebugFuncs;
+  for (auto &F : *Clone) {
+    if (F.getName().startswith("llvm."))
+      DebugFuncs.push_back(&F);
+    else
+      eraseNodeIfOutsideChunk(&F, NodesToKeep);
+    for (auto &BB : F)
+      for (auto &J : BB)
+        eraseNodeIfOutsideChunk(&J, NodesToKeep);
+  }
+
+  // Go over debug functions and erase the ones out-of-chunk
+  int MetadataCount = SeenNodes.size();
+  for (auto F : DebugFuncs) {
+    if (I < ChunksToKeep.size()) {
+      if (!ChunksToKeep[I].contains(MetadataCount))
+        deleteFunctionAndCallers(F);
+      if (ChunksToKeep[I].end == MetadataCount)
+        ++I;
+    } else
+      deleteFunctionAndCallers(F);
+  }
+
+  std::vector<NamedMDNode *> NamedNodesToDelete;
+
+  // Delete any out-of-chunk named metadata nodes
+  for (auto &MD : Clone->named_metadata()) {
+    ++MetadataCount;
+    if (I < ChunksToKeep.size()) {
+      if (!ChunksToKeep[I].contains(MetadataCount))
+        NamedNodesToDelete.push_back(&MD);
+      if (ChunksToKeep[I].end == SeenNodes.size())
+        ++I;
+    } else
+      NamedNodesToDelete.push_back(&MD);
+  }
+  for (auto NN : NamedNodesToDelete) {
+    for (int J = 0, E = NN->getNumOperands(); J != E; ++J)
+      NN->setOperand(J, NULL);
+    NN->eraseFromParent();
+  }
+
+  return Clone;
+}
+
+// Gets unnamed metadata nodes used by a given instruction/GV/function and adds
+// them to the set of seen nodes
+template <class T>
+static void addMetadataToSet(T *MDUser, std::set<MDNode *> &UnnamedNodes) {
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+  MDUser->getAllMetadata(MDs);
+  for (auto &MD : MDs)
+    UnnamedNodes.insert(MD.second);
+}
+
+/// Returns the amount of Named and Unnamed Metadata Nodes, and Debug functions
+/// used in the module
+static int countMetadataTargets(Module *Program) {
+  std::set<MDNode *> UnnamedNodes;
+  int NamedMetadataNodes = Program->named_metadata_size();
+  int DebugFunctionsCount = 0;
+
+  // Get metadata nodes used by globals
+  for (auto &GV : Program->globals())
+    addMetadataToSet(&GV, UnnamedNodes);
+
+  // Do the same for nodes used by functions & instructions
+  for (auto &F : *Program) {
+    if (F.getName().startswith("llvm."))
+      ++DebugFunctionsCount;
+    addMetadataToSet(&F, UnnamedNodes);
+    for (auto &BB : F)
+      for (auto &I : BB)
+        addMetadataToSet(&I, UnnamedNodes);
+  }
+
+  return UnnamedNodes.size() + NamedMetadataNodes + DebugFunctionsCount;
+}
+
+void llvm::reduceMetadataDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing Metadata...\n";
+  int MDCount = countMetadataTargets(Test.getProgram());
+  runDeltaPass(Test, MDCount, extractMetadataNodesFromModule);
+}
diff --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp
--- a/llvm/tools/llvm-reduce/llvm-reduce.cpp
+++ b/llvm/tools/llvm-reduce/llvm-reduce.cpp
@@ -53,6 +53,28 @@
                  cl::desc("WARNING: This option will replace your input file"
                           "with the reduced version!"));
 
+namespace {
+std::vector<std::string> DeltaPasses;
+
+struct DeltaPassOption {
+  void operator=(const std::string &Val) const {
+    if (Val.empty())
+      return;
+    SmallVector<StringRef, 8> PassNames;
+    StringRef(Val).split(PassNames, ',', -1, false);
+    for (auto PassName : PassNames)
+      DeltaPasses.push_back(PassName);
+  }
+};
+} // namespace
+
+static DeltaPassOption DeltaPassOpt;
+
+static cl::opt<DeltaPassOption, true, cl::parser<std::string>> Passes(
+    "run-only",
+    cl::desc("Only run the specified delta passes (comma separated list)"),
+    cl::value_desc("passes"), cl::ZeroOrMore, cl::location(DeltaPassOpt));
+
 // Parses IR into a Module and verifies it
 static std::unique_ptr<Module> parseInputFile(StringRef Filename,
                                               LLVMContext &Ctxt) {
@@ -102,7 +124,7 @@
   Tester.setProgram(std::move(OriginalProgram));
 
   // Try to reduce code
-  runDeltaPasses(Tester);
+  runDeltaPasses(Tester, DeltaPasses);
   StringRef ReducedFilename = sys::path::filename(Tester.getReducedFilepath());
 
   if (ReducedFilename == InputFilename) {