1 //===- ReduceDIMetadata.cpp - Specialized Delta pass for DebugInfo --------===//
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 DebugInfo metadata nodes.
12 //===----------------------------------------------------------------------===//
14 #include "ReduceDIMetadata.h"
16 #include "llvm/ADT/Sequence.h"
17 #include "llvm/ADT/SetVector.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
21 #include "llvm/IR/InstIterator.h"
29 using MDNodeList
= SmallVector
<MDNode
*>;
31 void identifyUninterestingMDNodes(Oracle
&O
, MDNodeList
&MDs
) {
32 SetVector
<std::tuple
<MDNode
*, size_t, MDNode
*>> Tuples
;
33 std::vector
<MDNode
*> ToLook
;
34 SetVector
<MDNode
*> Visited
;
36 // Start by looking at the attachments we collected
37 for (const auto &NMD
: MDs
)
39 ToLook
.push_back(NMD
);
41 while (!ToLook
.empty()) {
42 MDNode
*MD
= ToLook
.back();
45 if (Visited
.count(MD
))
48 // Determine if the current MDNode is DebugInfo
49 if (DINode
*DIM
= dyn_cast_or_null
<DINode
>(MD
)) {
50 // Scan operands and record attached tuples
51 for (size_t I
= 0; I
< DIM
->getNumOperands(); ++I
)
52 if (MDTuple
*MDT
= dyn_cast_or_null
<MDTuple
>(DIM
->getOperand(I
)))
53 if (!Visited
.count(MDT
) && MDT
->getNumOperands())
54 Tuples
.insert({DIM
, I
, MDT
});
57 // Add all of the operands of the current node to the loop's todo list.
58 for (Metadata
*Op
: MD
->operands())
59 if (MDNode
*OMD
= dyn_cast_or_null
<MDNode
>(Op
))
60 ToLook
.push_back(OMD
);
65 for (auto &T
: Tuples
) {
66 auto [DbgNode
, OpIdx
, Tup
] = T
;
67 // Remove the operands of the tuple that are not in the desired chunks.
68 SmallVector
<Metadata
*, 16> TN
;
69 for (size_t I
= 0; I
< Tup
->getNumOperands(); ++I
) {
70 // Ignore any operands that are not DebugInfo metadata nodes.
71 if (isa_and_nonnull
<DINode
>(Tup
->getOperand(I
)))
72 // Don't add uninteresting operands to the tuple.
76 TN
.push_back(Tup
->getOperand(I
));
78 if (TN
.size() != Tup
->getNumOperands())
79 DbgNode
->replaceOperandWith(OpIdx
, DbgNode
->get(DbgNode
->getContext(), TN
));
83 static void extractDIMetadataFromModule(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
84 Module
&Program
= WorkItem
.getModule();
87 // Collect all !dbg metadata attachments.
88 for (const auto &DC
: Program
.debug_compile_units())
91 for (GlobalVariable
&GV
: Program
.globals())
92 GV
.getMetadata(llvm::LLVMContext::MD_dbg
, MDs
);
93 for (Function
&F
: Program
.functions()) {
94 F
.getMetadata(llvm::LLVMContext::MD_dbg
, MDs
);
95 for (Instruction
&I
: instructions(F
))
96 if (auto *DI
= I
.getMetadata(llvm::LLVMContext::MD_dbg
))
99 identifyUninterestingMDNodes(O
, MDs
);
102 void llvm::reduceDIMetadataDeltaPass(TestRunner
&Test
) {
103 runDeltaPass(Test
, extractDIMetadataFromModule
, "Reducing DIMetadata");