blob: edc6375804b7f9f4f961e449e962b6a7f94d44ea [file] [log] [blame]
David Blaikie477c1df2019-09-10 22:09:58 +00001//===- ReduceMetadata.cpp - Specialized Delta Pass ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements two functions used by the Generic Delta Debugging
10// Algorithm, which are used to reduce Metadata nodes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ReduceMetadata.h"
15#include "Delta.h"
16#include "llvm/ADT/SmallVector.h"
17#include <set>
18#include <vector>
19
20using namespace llvm;
21
22/// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set
23template <class T>
24static void getChunkMetadataNodes(T &MDUser, unsigned &I,
25 const std::vector<Chunk> &ChunksToKeep,
26 std::set<MDNode *> &SeenNodes,
27 std::set<MDNode *> &NodesToKeep) {
28 SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
29 MDUser.getAllMetadata(MDs);
30 for (auto &MD : MDs) {
31 SeenNodes.insert(MD.second);
32 if (I < ChunksToKeep.size()) {
33 if (ChunksToKeep[I].contains(SeenNodes.size()))
34 NodesToKeep.insert(MD.second);
35 if (ChunksToKeep[I].end == SeenNodes.size())
36 ++I;
37 }
38 }
39}
40
41/// Erases out-of-chunk unnamed metadata nodes from its user
42template <class T>
43static void eraseMetadataIfOutsideChunk(T &MDUser,
44 const std::set<MDNode *> &NodesToKeep) {
45 SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
46 MDUser.getAllMetadata(MDs);
47 for (int I = 0, E = MDs.size(); I != E; ++I)
48 if (!NodesToKeep.count(MDs[I].second))
49 MDUser.setMetadata(I, NULL);
50}
51
52/// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
53/// functions that aren't inside the desired Chunks.
54/// @returns the Module stripped of out-of-chunk MDNodes
55static void extractMetadataFromModule(const std::vector<Chunk> &ChunksToKeep,
56 Module *Program) {
57 std::set<MDNode *> SeenNodes;
58 std::set<MDNode *> NodesToKeep;
59 unsigned I = 0;
60
61 // Add chunk MDNodes used by GVs, Functions, and Instructions to set
62 for (auto &GV : Program->globals())
63 getChunkMetadataNodes(GV, I, ChunksToKeep, SeenNodes, NodesToKeep);
64
65 for (auto &F : *Program) {
66 getChunkMetadataNodes(F, I, ChunksToKeep, SeenNodes, NodesToKeep);
67 for (auto &BB : F)
68 for (auto &Inst : BB)
69 getChunkMetadataNodes(Inst, I, ChunksToKeep, SeenNodes, NodesToKeep);
70 }
71
72 // Once more, go over metadata nodes, but deleting the ones outside chunks
73 for (auto &GV : Program->globals())
74 eraseMetadataIfOutsideChunk(GV, NodesToKeep);
75
76 for (auto &F : *Program) {
77 eraseMetadataIfOutsideChunk(F, NodesToKeep);
78 for (auto &BB : F)
79 for (auto &Inst : BB)
80 eraseMetadataIfOutsideChunk(Inst, NodesToKeep);
81 }
82
83
84 // Get out-of-chunk Named metadata nodes
85 unsigned MetadataCount = SeenNodes.size();
86 std::vector<NamedMDNode *> NamedNodesToDelete;
87 for (auto &MD : Program->named_metadata()) {
88 if (I < ChunksToKeep.size()) {
89 if (!ChunksToKeep[I].contains(++MetadataCount))
90 NamedNodesToDelete.push_back(&MD);
91 if (ChunksToKeep[I].end == SeenNodes.size())
92 ++I;
93 } else
94 NamedNodesToDelete.push_back(&MD);
95 }
96
97 for (auto *NN : NamedNodesToDelete) {
98 for (int I = 0, E = NN->getNumOperands(); I != E; ++I)
99 NN->setOperand(I, NULL);
100 NN->eraseFromParent();
101 }
102}
103
104// Gets unnamed metadata nodes used by a given instruction/GV/function and adds
105// them to the set of seen nodes
106template <class T>
107static void addMetadataToSet(T &MDUser, std::set<MDNode *> &UnnamedNodes) {
108 SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
109 MDUser.getAllMetadata(MDs);
110 for (auto &MD : MDs)
111 UnnamedNodes.insert(MD.second);
112}
113
114/// Returns the amount of Named and Unnamed Metadata Nodes
115static unsigned countMetadataTargets(Module *Program) {
116 std::set<MDNode *> UnnamedNodes;
117 int NamedMetadataNodes = Program->named_metadata_size();
118
119 // Get metadata nodes used by globals
120 for (auto &GV : Program->globals())
121 addMetadataToSet(GV, UnnamedNodes);
122
123 // Do the same for nodes used by functions & instructions
124 for (auto &F : *Program) {
125 addMetadataToSet(F, UnnamedNodes);
126 for (auto &BB : F)
127 for (auto &I : BB)
128 addMetadataToSet(I, UnnamedNodes);
129 }
130
131 return UnnamedNodes.size() + NamedMetadataNodes;
132}
133
134void llvm::reduceMetadataDeltaPass(TestRunner &Test) {
135 outs() << "*** Reducing Metadata...\n";
136 unsigned MDCount = countMetadataTargets(Test.getProgram());
137 runDeltaPass(Test, MDCount, extractMetadataFromModule);
138 outs() << "----------------------------\n";
139}