1//===- ReduceMetadata.cpp - Specialized Delta Pass ------------------------===// 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 Metadata nodes. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ReduceMetadata.h" 15#include "Delta.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" 20#include <vector> 21 22using namespace llvm; 23 24static bool shouldKeepDebugIntrinsicMetadata(Instruction &I, MDNode &MD) { 25 return isa<DILocation>(MD) && isa<DbgInfoIntrinsic>(I); 26} 27 28static bool shouldKeepDebugNamedMetadata(NamedMDNode &MD) { 29 return MD.getName() == "llvm.dbg.cu" && MD.getNumOperands() != 0; 30} 31 32// Named metadata with simple list-like behavior, so that it's valid to remove 33// operands individually. 34static constexpr StringLiteral ListNamedMetadata[] = { 35 "llvm.module.flags", 36 "llvm.ident", 37 "opencl.spir.version", 38 "opencl.ocl.version", 39 "opencl.used.extensions", 40 "opencl.used.optional.core.features", 41 "opencl.compiler.options" 42}; 43 44/// Remove unneeded arguments to named metadata. 45static void reduceNamedMetadataOperands(Oracle &O, ReducerWorkItem &WorkItem) { 46 Module &M = WorkItem.getModule(); 47 48 for (StringRef MDName : ListNamedMetadata) { 49 NamedMDNode *NamedNode = M.getNamedMetadata(MDName); 50 if (!NamedNode) 51 continue; 52 53 bool MadeChange = false; 54 SmallVector<MDNode *, 16> KeptOperands; 55 for (auto I : seq<unsigned>(0, NamedNode->getNumOperands())) { 56 if (O.shouldKeep()) 57 KeptOperands.push_back(NamedNode->getOperand(I)); 58 else 59 MadeChange = true; 60 } 61 62 if (MadeChange) { 63 NamedNode->clearOperands(); 64 for (MDNode *KeptOperand : KeptOperands) 65 NamedNode->addOperand(KeptOperand); 66 } 67 } 68} 69 70/// Removes all the Named and Unnamed Metadata Nodes, as well as any debug 71/// functions that aren't inside the desired Chunks. 72static void extractMetadataFromModule(Oracle &O, ReducerWorkItem &WorkItem) { 73 Module &Program = WorkItem.getModule(); 74 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); 80 81 for (NamedMDNode *NN : NamedNodesToDelete) { 82 for (auto I : seq<unsigned>(0, NN->getNumOperands())) 83 NN->setOperand(I, nullptr); 84 NN->eraseFromParent(); 85 } 86 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) 92 if (!O.shouldKeep()) 93 GV.setMetadata(MD.first, nullptr); 94 } 95 96 for (Function &F : Program) { 97 { 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) 102 if (!O.shouldKeep()) 103 F.setMetadata(MD.first, nullptr); 104 } 105 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); 113 } 114 } 115 } 116} 117 118void llvm::reduceMetadataDeltaPass(TestRunner &Test) { 119 runDeltaPass(Test, extractMetadataFromModule, "Reducing Metadata"); 120} 121 122void llvm::reduceNamedMetadataDeltaPass(TestRunner &Test) { 123 runDeltaPass(Test, reduceNamedMetadataOperands, "Reducing Named Metadata"); 124} 125