1 //===- ReduceMetadata.cpp - Specialized Delta Pass ------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements two functions used by the Generic Delta Debugging
10 // Algorithm, which are used to reduce Metadata nodes.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceMetadata.h"
16 #include "llvm/ADT/SmallVector.h"
22 /// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set
24 static void getChunkMetadataNodes(T
&MDUser
, int &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
< (int)ChunksToKeep
.size()) {
33 if (ChunksToKeep
[I
].contains(SeenNodes
.size()))
34 NodesToKeep
.insert(MD
.second
);
35 if (ChunksToKeep
[I
].end
== (int)SeenNodes
.size())
41 /// Erases out-of-chunk unnamed metadata nodes from its user
43 static 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
);
52 /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
53 /// functions that aren't inside the desired Chunks.
54 static void extractMetadataFromModule(const std::vector
<Chunk
> &ChunksToKeep
,
56 std::set
<MDNode
*> SeenNodes
;
57 std::set
<MDNode
*> NodesToKeep
;
60 // Add chunk MDNodes used by GVs, Functions, and Instructions to set
61 for (auto &GV
: Program
->globals())
62 getChunkMetadataNodes(GV
, I
, ChunksToKeep
, SeenNodes
, NodesToKeep
);
64 for (auto &F
: *Program
) {
65 getChunkMetadataNodes(F
, I
, ChunksToKeep
, SeenNodes
, NodesToKeep
);
68 getChunkMetadataNodes(Inst
, I
, ChunksToKeep
, SeenNodes
, NodesToKeep
);
71 // Once more, go over metadata nodes, but deleting the ones outside chunks
72 for (auto &GV
: Program
->globals())
73 eraseMetadataIfOutsideChunk(GV
, NodesToKeep
);
75 for (auto &F
: *Program
) {
76 eraseMetadataIfOutsideChunk(F
, NodesToKeep
);
79 eraseMetadataIfOutsideChunk(Inst
, NodesToKeep
);
83 // Get out-of-chunk Named metadata nodes
84 unsigned MetadataCount
= SeenNodes
.size();
85 std::vector
<NamedMDNode
*> NamedNodesToDelete
;
86 for (auto &MD
: Program
->named_metadata()) {
87 if (I
< (int)ChunksToKeep
.size()) {
88 if (!ChunksToKeep
[I
].contains(++MetadataCount
))
89 NamedNodesToDelete
.push_back(&MD
);
90 if (ChunksToKeep
[I
].end
== (int)SeenNodes
.size())
93 NamedNodesToDelete
.push_back(&MD
);
96 for (auto *NN
: NamedNodesToDelete
) {
97 for (int I
= 0, E
= NN
->getNumOperands(); I
!= E
; ++I
)
98 NN
->setOperand(I
, NULL
);
99 NN
->eraseFromParent();
103 // Gets unnamed metadata nodes used by a given instruction/GV/function and adds
104 // them to the set of seen nodes
106 static void addMetadataToSet(T
&MDUser
, std::set
<MDNode
*> &UnnamedNodes
) {
107 SmallVector
<std::pair
<unsigned, MDNode
*>, 4> MDs
;
108 MDUser
.getAllMetadata(MDs
);
110 UnnamedNodes
.insert(MD
.second
);
113 /// Returns the amount of Named and Unnamed Metadata Nodes
114 static int countMetadataTargets(Module
*Program
) {
115 std::set
<MDNode
*> UnnamedNodes
;
116 int NamedMetadataNodes
= Program
->named_metadata_size();
118 // Get metadata nodes used by globals
119 for (auto &GV
: Program
->globals())
120 addMetadataToSet(GV
, UnnamedNodes
);
122 // Do the same for nodes used by functions & instructions
123 for (auto &F
: *Program
) {
124 addMetadataToSet(F
, UnnamedNodes
);
127 addMetadataToSet(I
, UnnamedNodes
);
130 return UnnamedNodes
.size() + NamedMetadataNodes
;
133 void llvm::reduceMetadataDeltaPass(TestRunner
&Test
) {
134 outs() << "*** Reducing Metadata...\n";
135 int MDCount
= countMetadataTargets(Test
.getProgram());
136 runDeltaPass(Test
, MDCount
, extractMetadataFromModule
);
137 outs() << "----------------------------\n";