ReduceDIMetadata.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //===- ReduceDIMetadata.cpp - Specialized Delta pass for DebugInfo --------===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements two functions used by the Generic Delta Debugging
  10. // Algorithm, which are used to reduce DebugInfo metadata nodes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "ReduceDIMetadata.h"
  14. #include "Delta.h"
  15. #include "llvm/ADT/Sequence.h"
  16. #include "llvm/ADT/SetVector.h"
  17. #include "llvm/ADT/SmallSet.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/IR/DebugInfoMetadata.h"
  20. #include "llvm/IR/InstIterator.h"
  21. #include <set>
  22. #include <stack>
  23. #include <tuple>
  24. #include <vector>
  25. using namespace llvm;
  26. using MDNodeList = SmallVector<MDNode *>;
  27. void identifyUninterestingMDNodes(Oracle &O, MDNodeList &MDs) {
  28. SetVector<std::tuple<MDNode *, size_t, MDNode *>> Tuples;
  29. std::vector<MDNode *> ToLook;
  30. SetVector<MDNode *> Visited;
  31. // Start by looking at the attachments we collected
  32. for (const auto &NMD : MDs)
  33. if (NMD)
  34. ToLook.push_back(NMD);
  35. while (!ToLook.empty()) {
  36. MDNode *MD = ToLook.back();
  37. ToLook.pop_back();
  38. if (Visited.count(MD))
  39. continue;
  40. // Determine if the current MDNode is DebugInfo
  41. if (DINode *DIM = dyn_cast_or_null<DINode>(MD)) {
  42. // Scan operands and record attached tuples
  43. for (size_t I = 0; I < DIM->getNumOperands(); ++I)
  44. if (MDTuple *MDT = dyn_cast_or_null<MDTuple>(DIM->getOperand(I)))
  45. if (!Visited.count(MDT) && MDT->getNumOperands())
  46. Tuples.insert({DIM, I, MDT});
  47. }
  48. // Add all of the operands of the current node to the loop's todo list.
  49. for (Metadata *Op : MD->operands())
  50. if (MDNode *OMD = dyn_cast_or_null<MDNode>(Op))
  51. ToLook.push_back(OMD);
  52. Visited.insert(MD);
  53. }
  54. for (auto &T : Tuples) {
  55. auto [DbgNode, OpIdx, Tup] = T;
  56. // Remove the operands of the tuple that are not in the desired chunks.
  57. SmallVector<Metadata *, 16> TN;
  58. for (size_t I = 0; I < Tup->getNumOperands(); ++I) {
  59. // Ignore any operands that are not DebugInfo metadata nodes.
  60. if (isa_and_nonnull<DINode>(Tup->getOperand(I)))
  61. // Don't add uninteresting operands to the tuple.
  62. if (!O.shouldKeep())
  63. continue;
  64. TN.push_back(Tup->getOperand(I));
  65. }
  66. if (TN.size() != Tup->getNumOperands())
  67. DbgNode->replaceOperandWith(OpIdx, DbgNode->get(DbgNode->getContext(), TN));
  68. }
  69. }
  70. static void extractDIMetadataFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
  71. Module &Program = WorkItem.getModule();
  72. MDNodeList MDs;
  73. // Collect all !dbg metadata attachments.
  74. for (const auto &DC : Program.debug_compile_units())
  75. if (DC)
  76. MDs.push_back(DC);
  77. for (GlobalVariable &GV : Program.globals())
  78. GV.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
  79. for (Function &F : Program.functions()) {
  80. F.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
  81. for (Instruction &I : instructions(F))
  82. if (auto *DI = I.getMetadata(llvm::LLVMContext::MD_dbg))
  83. MDs.push_back(DI);
  84. }
  85. identifyUninterestingMDNodes(O, MDs);
  86. }
  87. void llvm::reduceDIMetadataDeltaPass(TestRunner &Test) {
  88. runDeltaPass(Test, extractDIMetadataFromModule, "Reducing DIMetadata");
  89. }