12c799b77SMatthew Voss //===- ReduceDIMetadata.cpp - Specialized Delta pass for DebugInfo --------===//
22c799b77SMatthew Voss //
32c799b77SMatthew Voss // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42c799b77SMatthew Voss // See https://llvm.org/LICENSE.txt for license information.
52c799b77SMatthew Voss // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c799b77SMatthew Voss //
72c799b77SMatthew Voss //===----------------------------------------------------------------------===//
82c799b77SMatthew Voss //
92c799b77SMatthew Voss // This file implements two functions used by the Generic Delta Debugging
102c799b77SMatthew Voss // Algorithm, which are used to reduce DebugInfo metadata nodes.
112c799b77SMatthew Voss //
122c799b77SMatthew Voss //===----------------------------------------------------------------------===//
132c799b77SMatthew Voss
142c799b77SMatthew Voss #include "ReduceDIMetadata.h"
152c799b77SMatthew Voss #include "Delta.h"
162c799b77SMatthew Voss #include "llvm/ADT/Sequence.h"
17333ffafbSMatt Arsenault #include "llvm/ADT/SetVector.h"
182c799b77SMatthew Voss #include "llvm/ADT/SmallVector.h"
192c799b77SMatthew Voss #include "llvm/IR/DebugInfoMetadata.h"
202c799b77SMatthew Voss #include "llvm/IR/InstIterator.h"
212c799b77SMatthew Voss #include <tuple>
222c799b77SMatthew Voss #include <vector>
232c799b77SMatthew Voss
242c799b77SMatthew Voss using namespace llvm;
252c799b77SMatthew Voss
262c799b77SMatthew Voss using MDNodeList = SmallVector<MDNode *>;
272c799b77SMatthew Voss
identifyUninterestingMDNodes(Oracle & O,MDNodeList & MDs)282c799b77SMatthew Voss void identifyUninterestingMDNodes(Oracle &O, MDNodeList &MDs) {
29fe50eac8SMatthew Voss SetVector<std::tuple<MDNode *, size_t, MDNode *>> Tuples;
302c799b77SMatthew Voss std::vector<MDNode *> ToLook;
31fe50eac8SMatthew Voss SetVector<MDNode *> Visited;
322c799b77SMatthew Voss
332c799b77SMatthew Voss // Start by looking at the attachments we collected
342c799b77SMatthew Voss for (const auto &NMD : MDs)
35fe50eac8SMatthew Voss if (NMD)
362c799b77SMatthew Voss ToLook.push_back(NMD);
372c799b77SMatthew Voss
382c799b77SMatthew Voss while (!ToLook.empty()) {
392c799b77SMatthew Voss MDNode *MD = ToLook.back();
402c799b77SMatthew Voss ToLook.pop_back();
412c799b77SMatthew Voss
422c799b77SMatthew Voss if (Visited.count(MD))
432c799b77SMatthew Voss continue;
442c799b77SMatthew Voss
452c799b77SMatthew Voss // Determine if the current MDNode is DebugInfo
462c799b77SMatthew Voss if (DINode *DIM = dyn_cast_or_null<DINode>(MD)) {
472c799b77SMatthew Voss // Scan operands and record attached tuples
482c799b77SMatthew Voss for (size_t I = 0; I < DIM->getNumOperands(); ++I)
492c799b77SMatthew Voss if (MDTuple *MDT = dyn_cast_or_null<MDTuple>(DIM->getOperand(I)))
502c799b77SMatthew Voss if (!Visited.count(MDT) && MDT->getNumOperands())
512c799b77SMatthew Voss Tuples.insert({DIM, I, MDT});
522c799b77SMatthew Voss }
532c799b77SMatthew Voss
542c799b77SMatthew Voss // Add all of the operands of the current node to the loop's todo list.
552c799b77SMatthew Voss for (Metadata *Op : MD->operands())
562c799b77SMatthew Voss if (MDNode *OMD = dyn_cast_or_null<MDNode>(Op))
572c799b77SMatthew Voss ToLook.push_back(OMD);
582c799b77SMatthew Voss
592c799b77SMatthew Voss Visited.insert(MD);
602c799b77SMatthew Voss }
612c799b77SMatthew Voss
622c799b77SMatthew Voss for (auto &T : Tuples) {
632c799b77SMatthew Voss auto [DbgNode, OpIdx, Tup] = T;
642c799b77SMatthew Voss // Remove the operands of the tuple that are not in the desired chunks.
652c799b77SMatthew Voss SmallVector<Metadata *, 16> TN;
662c799b77SMatthew Voss for (size_t I = 0; I < Tup->getNumOperands(); ++I) {
672c799b77SMatthew Voss // Ignore any operands that are not DebugInfo metadata nodes.
68*c2e62c74SOrlando Cazalet-Hyams if (Metadata *Op = Tup->getOperand(I).get()) {
69*c2e62c74SOrlando Cazalet-Hyams if (isa<DINode>(Op) || isa<DIGlobalVariableExpression>(Op))
702c799b77SMatthew Voss // Don't add uninteresting operands to the tuple.
712c799b77SMatthew Voss if (!O.shouldKeep())
722c799b77SMatthew Voss continue;
73*c2e62c74SOrlando Cazalet-Hyams TN.push_back(Op);
74*c2e62c74SOrlando Cazalet-Hyams }
752c799b77SMatthew Voss }
762c799b77SMatthew Voss if (TN.size() != Tup->getNumOperands())
772c799b77SMatthew Voss DbgNode->replaceOperandWith(OpIdx, DbgNode->get(DbgNode->getContext(), TN));
782c799b77SMatthew Voss }
792c799b77SMatthew Voss }
802c799b77SMatthew Voss
extractDIMetadataFromModule(Oracle & O,ReducerWorkItem & WorkItem)8123cc36e4SMatt Arsenault static void extractDIMetadataFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
8223cc36e4SMatt Arsenault Module &Program = WorkItem.getModule();
8323cc36e4SMatt Arsenault
842c799b77SMatthew Voss MDNodeList MDs;
852c799b77SMatthew Voss // Collect all !dbg metadata attachments.
862c799b77SMatthew Voss for (const auto &DC : Program.debug_compile_units())
872c799b77SMatthew Voss if (DC)
882c799b77SMatthew Voss MDs.push_back(DC);
892c799b77SMatthew Voss for (GlobalVariable &GV : Program.globals())
902c799b77SMatthew Voss GV.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
912c799b77SMatthew Voss for (Function &F : Program.functions()) {
922c799b77SMatthew Voss F.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
932c799b77SMatthew Voss for (Instruction &I : instructions(F))
942c799b77SMatthew Voss if (auto *DI = I.getMetadata(llvm::LLVMContext::MD_dbg))
952c799b77SMatthew Voss MDs.push_back(DI);
962c799b77SMatthew Voss }
972c799b77SMatthew Voss identifyUninterestingMDNodes(O, MDs);
982c799b77SMatthew Voss }
992c799b77SMatthew Voss
reduceDIMetadataDeltaPass(TestRunner & Test)1002c799b77SMatthew Voss void llvm::reduceDIMetadataDeltaPass(TestRunner &Test) {
1012592ccdeSArthur Eubanks runDeltaPass(Test, extractDIMetadataFromModule, "Reducing DIMetadata");
1022c799b77SMatthew Voss }
103