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/Sequence.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/IR/InstIterator.h"
19 #include "llvm/IR/IntrinsicInst.h"
24 static bool shouldKeepDebugIntrinsicMetadata(Instruction
&I
, MDNode
&MD
) {
25 return isa
<DILocation
>(MD
) && isa
<DbgInfoIntrinsic
>(I
);
28 static bool shouldKeepDebugNamedMetadata(NamedMDNode
&MD
) {
29 return MD
.getName() == "llvm.dbg.cu" && MD
.getNumOperands() != 0;
32 // Named metadata with simple list-like behavior, so that it's valid to remove
33 // operands individually.
34 static constexpr StringLiteral ListNamedMetadata
[] = {
37 "opencl.spir.version",
39 "opencl.used.extensions",
40 "opencl.used.optional.core.features",
41 "opencl.compiler.options"
44 /// Remove unneeded arguments to named metadata.
45 static void reduceNamedMetadataOperands(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
46 Module
&M
= WorkItem
.getModule();
48 for (StringRef MDName
: ListNamedMetadata
) {
49 NamedMDNode
*NamedNode
= M
.getNamedMetadata(MDName
);
53 bool MadeChange
= false;
54 SmallVector
<MDNode
*, 16> KeptOperands
;
55 for (auto I
: seq
<unsigned>(0, NamedNode
->getNumOperands())) {
57 KeptOperands
.push_back(NamedNode
->getOperand(I
));
63 NamedNode
->clearOperands();
64 for (MDNode
*KeptOperand
: KeptOperands
)
65 NamedNode
->addOperand(KeptOperand
);
70 /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
71 /// functions that aren't inside the desired Chunks.
72 static void extractMetadataFromModule(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
73 Module
&Program
= WorkItem
.getModule();
75 // Get out-of-chunk Named metadata nodes
76 SmallVector
<NamedMDNode
*> NamedNodesToDelete
;
77 for (NamedMDNode
&MD
: Program
.named_metadata())
78 if (!shouldKeepDebugNamedMetadata(MD
) && !O
.shouldKeep())
79 NamedNodesToDelete
.push_back(&MD
);
81 for (NamedMDNode
*NN
: NamedNodesToDelete
) {
82 for (auto I
: seq
<unsigned>(0, NN
->getNumOperands()))
83 NN
->setOperand(I
, nullptr);
84 NN
->eraseFromParent();
87 // Delete out-of-chunk metadata attached to globals.
88 for (GlobalVariable
&GV
: Program
.globals()) {
89 SmallVector
<std::pair
<unsigned, MDNode
*>> MDs
;
90 GV
.getAllMetadata(MDs
);
91 for (std::pair
<unsigned, MDNode
*> &MD
: MDs
)
93 GV
.setMetadata(MD
.first
, nullptr);
96 for (Function
&F
: Program
) {
98 SmallVector
<std::pair
<unsigned, MDNode
*>> MDs
;
99 // Delete out-of-chunk metadata attached to functions.
100 F
.getAllMetadata(MDs
);
101 for (std::pair
<unsigned, MDNode
*> &MD
: MDs
)
103 F
.setMetadata(MD
.first
, nullptr);
106 // Delete out-of-chunk metadata attached to instructions.
107 for (Instruction
&I
: instructions(F
)) {
108 SmallVector
<std::pair
<unsigned, MDNode
*>> MDs
;
109 I
.getAllMetadata(MDs
);
110 for (std::pair
<unsigned, MDNode
*> &MD
: MDs
) {
111 if (!shouldKeepDebugIntrinsicMetadata(I
, *MD
.second
) && !O
.shouldKeep())
112 I
.setMetadata(MD
.first
, nullptr);
118 void llvm::reduceMetadataDeltaPass(TestRunner
&Test
) {
119 runDeltaPass(Test
, extractMetadataFromModule
, "Reducing Metadata");
122 void llvm::reduceNamedMetadataDeltaPass(TestRunner
&Test
) {
123 runDeltaPass(Test
, reduceNamedMetadataOperands
, "Reducing Named Metadata");