--- /dev/null
+; 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
+
+
+@ExcitingGlobal = global i32 0, !md !0
+@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"}
#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) {