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/SmallVector.h"
19 #include "llvm/IR/DebugInfoMetadata.h"
20 #include "llvm/IR/InstIterator.h"
26 using MDNodeList
= SmallVector
<MDNode
*>;
28 void identifyUninterestingMDNodes(Oracle
&O
, MDNodeList
&MDs
) {
29 SetVector
<std::tuple
<MDNode
*, size_t, MDNode
*>> Tuples
;
30 std::vector
<MDNode
*> ToLook
;
31 SetVector
<MDNode
*> Visited
;
33 // Start by looking at the attachments we collected
34 for (const auto &NMD
: MDs
)
36 ToLook
.push_back(NMD
);
38 while (!ToLook
.empty()) {
39 MDNode
*MD
= ToLook
.back();
42 if (Visited
.count(MD
))
45 // Determine if the current MDNode is DebugInfo
46 if (DINode
*DIM
= dyn_cast_or_null
<DINode
>(MD
)) {
47 // Scan operands and record attached tuples
48 for (size_t I
= 0; I
< DIM
->getNumOperands(); ++I
)
49 if (MDTuple
*MDT
= dyn_cast_or_null
<MDTuple
>(DIM
->getOperand(I
)))
50 if (!Visited
.count(MDT
) && MDT
->getNumOperands())
51 Tuples
.insert({DIM
, I
, MDT
});
54 // Add all of the operands of the current node to the loop's todo list.
55 for (Metadata
*Op
: MD
->operands())
56 if (MDNode
*OMD
= dyn_cast_or_null
<MDNode
>(Op
))
57 ToLook
.push_back(OMD
);
62 for (auto &T
: Tuples
) {
63 auto [DbgNode
, OpIdx
, Tup
] = T
;
64 // Remove the operands of the tuple that are not in the desired chunks.
65 SmallVector
<Metadata
*, 16> TN
;
66 for (size_t I
= 0; I
< Tup
->getNumOperands(); ++I
) {
67 // Ignore any operands that are not DebugInfo metadata nodes.
68 if (Metadata
*Op
= Tup
->getOperand(I
).get()) {
69 if (isa
<DINode
>(Op
) || isa
<DIGlobalVariableExpression
>(Op
))
70 // Don't add uninteresting operands to the tuple.
76 if (TN
.size() != Tup
->getNumOperands())
77 DbgNode
->replaceOperandWith(OpIdx
, DbgNode
->get(DbgNode
->getContext(), TN
));
81 static void extractDIMetadataFromModule(Oracle
&O
, ReducerWorkItem
&WorkItem
) {
82 Module
&Program
= WorkItem
.getModule();
85 // Collect all !dbg metadata attachments.
86 for (const auto &DC
: Program
.debug_compile_units())
89 for (GlobalVariable
&GV
: Program
.globals())
90 GV
.getMetadata(llvm::LLVMContext::MD_dbg
, MDs
);
91 for (Function
&F
: Program
.functions()) {
92 F
.getMetadata(llvm::LLVMContext::MD_dbg
, MDs
);
93 for (Instruction
&I
: instructions(F
))
94 if (auto *DI
= I
.getMetadata(llvm::LLVMContext::MD_dbg
))
97 identifyUninterestingMDNodes(O
, MDs
);
100 void llvm::reduceDIMetadataDeltaPass(TestRunner
&Test
) {
101 runDeltaPass(Test
, extractDIMetadataFromModule
, "Reducing DIMetadata");