[llvm] d9562a8 - [llvm-reduce] Reduce metadata references.

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 29 09:25:42 PDT 2021


Author: Michael Kruse
Date: 2021-09-29T11:25:35-05:00
New Revision: d9562a8e4528411aa22bd960a6487c0e2708dd4e

URL: https://github.com/llvm/llvm-project/commit/d9562a8e4528411aa22bd960a6487c0e2708dd4e
DIFF: https://github.com/llvm/llvm-project/commit/d9562a8e4528411aa22bd960a6487c0e2708dd4e.diff

LOG: [llvm-reduce] Reduce metadata references.

The ReduceMetadata pass before this patch removed metadata on a per-MDNode (or NamedMDNode) basis. Either all references to an MDNode are kept, or all of them are removed. However, MDNodes are uniqued, meaning that references to MDNodes with the same data become references to the same MDNodes. As a consequence, e.g. tbaa references to the same type will all have the same MDNode reference and hence make it impossible to reduce only keeping metadata on those memory access for which they are interesting.
Moreover, MDNodes can also be referenced by some intrinsics or other MDNodes. These references were not considered for removal leading to the possibility that MDNodes are not actually removed even if selected to be removed by the oracle.

This patch changes ReduceMetadata to reduces based on removable metadata references instead. MDNodes without references implicitly dropped anyway. References by intrinsic calls should be removed by ReduceOperands or ReduceInstructions. References in other MDNodes cannot be removed as it would violate the immutability of MDNodes.

Additionally, ReduceMetadata pass before this patch used `setMetadata(I, NULL)` to remove references, where `I` is the index in the array returned by `getAllMetadata`. However, `setMetadata` expects a MDKind (such as `MD_tbaa`) as first argument. `getAllMetadata` does not return those in consecutive order (otherwise it would not need to be a `std::pair` with `first` representing the MDKind).

Reviewed By: aeubanks, swamulism

Differential Revision: https://reviews.llvm.org/D110534

Added: 
    llvm/test/tools/llvm-reduce/remove-metadata-args.ll

Modified: 
    llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-reduce/remove-metadata-args.ll b/llvm/test/tools/llvm-reduce/remove-metadata-args.ll
new file mode 100644
index 0000000000000..817f1eb8defe0
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/remove-metadata-args.ll
@@ -0,0 +1,29 @@
+; RUN: llvm-reduce %s -o %t --delta-passes=metadata --test FileCheck --test-arg %s --test-arg --check-prefix=EXCITING --test-arg --input-file
+; RUN: FileCheck %s --input-file %t --check-prefix=REDUCED
+
+; All exciting stuff must remain in the reduced file.
+; EXCITING-DAG: ExcitingGlobal = global i32 0, !md !0
+; EXCITING-DAG: define void @ExcitingFunc() !md !0
+; EXCITING-DAG: store i32 0, i32* @ExcitingGlobal, align 4, !md !0
+; EXCITING-DAG: !ExcitingNamedMD = !{!0}
+
+; Boring stuff's metadata must have been removed.
+; REDUCED-NOT: Boring{{.*}} !md !0
+; REDUCED-NOT: !md !0 {{.*}}Boring
+
+
+ at ExcitingGlobal = global i32 0, !md !0
+ at BoringGlobal = global i32 0, !md !0
+
+define void @ExcitingFunc() !md !0 {
+   store i32 0, i32* @ExcitingGlobal, align 4, !md !0
+   store i32 0, i32* @BoringGlobal, align 4, !md !0
+   ret void
+}
+
+declare !md !0 void @BoringFunc()
+
+!ExcitingNamedMD = !{!0}
+!BoringNamedMD = !{!0}
+
+!0 = !{!"my metadata"}

diff  --git a/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
index 4587295a00bee..8eb4533848d92 100644
--- a/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
+++ b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
@@ -13,110 +13,83 @@
 
 #include "ReduceMetadata.h"
 #include "Delta.h"
+#include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallVector.h"
-#include <set>
+#include "llvm/IR/InstIterator.h"
 #include <vector>
 
 using namespace llvm;
 
-/// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set
-template <class T>
-static void getChunkMetadataNodes(T &MDUser, Oracle &O,
-                                  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 (O.shouldKeep())
-      NodesToKeep.insert(MD.second);
-  }
-}
-
-/// Erases out-of-chunk unnamed metadata nodes from its user
-template <class T>
-static void eraseMetadataIfOutsideChunk(T &MDUser,
-                                        const 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);
-}
-
 /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
 /// functions that aren't inside the desired Chunks.
 static void extractMetadataFromModule(const std::vector<Chunk> &ChunksToKeep,
                                       Module *Program) {
   Oracle O(ChunksToKeep);
 
-  std::set<MDNode *> SeenNodes;
-  std::set<MDNode *> NodesToKeep;
-
-  // Add chunk MDNodes used by GVs, Functions, and Instructions to set
-  for (auto &GV : Program->globals())
-    getChunkMetadataNodes(GV, O, SeenNodes, NodesToKeep);
-
-  for (auto &F : *Program) {
-    getChunkMetadataNodes(F, O, SeenNodes, NodesToKeep);
-    for (auto &BB : F)
-      for (auto &Inst : BB)
-        getChunkMetadataNodes(Inst, O, SeenNodes, NodesToKeep);
-  }
-
-  // Once more, go over metadata nodes, but deleting the ones outside chunks
-  for (auto &GV : Program->globals())
-    eraseMetadataIfOutsideChunk(GV, NodesToKeep);
-
-  for (auto &F : *Program) {
-    eraseMetadataIfOutsideChunk(F, NodesToKeep);
-    for (auto &BB : F)
-      for (auto &Inst : BB)
-        eraseMetadataIfOutsideChunk(Inst, NodesToKeep);
-  }
-
-
   // Get out-of-chunk Named metadata nodes
-  std::vector<NamedMDNode *> NamedNodesToDelete;
-  for (auto &MD : Program->named_metadata())
+  SmallVector<NamedMDNode *> NamedNodesToDelete;
+  for (NamedMDNode &MD : Program->named_metadata())
     if (!O.shouldKeep())
       NamedNodesToDelete.push_back(&MD);
 
-  for (auto *NN : NamedNodesToDelete) {
-    for (int I = 0, E = NN->getNumOperands(); I != E; ++I)
+  for (NamedMDNode *NN : NamedNodesToDelete) {
+    for (auto I : seq<unsigned>(0, NN->getNumOperands()))
       NN->setOperand(I, NULL);
     NN->eraseFromParent();
   }
-}
 
-// 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);
+  // Delete out-of-chunk metadata attached to globals.
+  SmallVector<std::pair<unsigned, MDNode *>> MDs;
+  for (GlobalVariable &GV : Program->globals()) {
+    GV.getAllMetadata(MDs);
+    for (std::pair<unsigned, MDNode *> &MD : MDs)
+      if (!O.shouldKeep())
+        GV.setMetadata(MD.first, NULL);
+  }
+
+  for (Function &F : *Program) {
+    // Delete out-of-chunk metadata attached to functions.
+    F.getAllMetadata(MDs);
+    for (std::pair<unsigned, MDNode *> &MD : MDs)
+      if (!O.shouldKeep())
+        F.setMetadata(MD.first, NULL);
+
+    // Delete out-of-chunk metadata attached to instructions.
+    for (Instruction &I : instructions(F)) {
+      I.getAllMetadata(MDs);
+      for (std::pair<unsigned, MDNode *> &MD : MDs)
+        if (!O.shouldKeep())
+          I.setMetadata(MD.first, NULL);
+    }
+  }
 }
 
-/// Returns the amount of Named and Unnamed Metadata Nodes
 static int countMetadataTargets(Module *Program) {
-  std::set<MDNode *> UnnamedNodes;
   int NamedMetadataNodes = Program->named_metadata_size();
 
-  // Get metadata nodes used by globals
-  for (auto &GV : Program->globals())
-    addMetadataToSet(GV, UnnamedNodes);
+  // Get metadata attached to globals.
+  int GlobalMetadataArgs = 0;
+  SmallVector<std::pair<unsigned, MDNode *>> MDs;
+  for (GlobalVariable &GV : Program->globals()) {
+    GV.getAllMetadata(MDs);
+    GlobalMetadataArgs += MDs.size();
+  }
 
-  // Do the same for nodes used by functions & instructions
-  for (auto &F : *Program) {
-    addMetadataToSet(F, UnnamedNodes);
-    for (auto &BB : F)
-      for (auto &I : BB)
-        addMetadataToSet(I, UnnamedNodes);
+  // Get metadata attached to functions & instructions.
+  int FunctionMetadataArgs = 0;
+  int InstructionMetadataArgs = 0;
+  for (Function &F : *Program) {
+    F.getAllMetadata(MDs);
+    FunctionMetadataArgs += MDs.size();
+
+    for (Instruction &I : instructions(F)) {
+      I.getAllMetadata(MDs);
+      InstructionMetadataArgs += MDs.size();
+    }
   }
 
-  return UnnamedNodes.size() + NamedMetadataNodes;
+  return NamedMetadataNodes + GlobalMetadataArgs + FunctionMetadataArgs +
+         InstructionMetadataArgs;
 }
 
 void llvm::reduceMetadataDeltaPass(TestRunner &Test) {


        


More information about the llvm-commits mailing list