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 <vector> 20 21 using namespace llvm; 22 23 /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug 24 /// functions that aren't inside the desired Chunks. 25 static void extractMetadataFromModule(Oracle &O, Module &Program) { 26 // Get out-of-chunk Named metadata nodes 27 SmallVector<NamedMDNode *> NamedNodesToDelete; 28 for (NamedMDNode &MD : Program.named_metadata()) 29 if (!O.shouldKeep()) 30 NamedNodesToDelete.push_back(&MD); 31 32 for (NamedMDNode *NN : NamedNodesToDelete) { 33 for (auto I : seq<unsigned>(0, NN->getNumOperands())) 34 NN->setOperand(I, NULL); 35 NN->eraseFromParent(); 36 } 37 38 // Delete out-of-chunk metadata attached to globals. 39 SmallVector<std::pair<unsigned, MDNode *>> MDs; 40 for (GlobalVariable &GV : Program.globals()) { 41 GV.getAllMetadata(MDs); 42 for (std::pair<unsigned, MDNode *> &MD : MDs) 43 if (!O.shouldKeep()) 44 GV.setMetadata(MD.first, NULL); 45 } 46 47 for (Function &F : Program) { 48 // Delete out-of-chunk metadata attached to functions. 49 F.getAllMetadata(MDs); 50 for (std::pair<unsigned, MDNode *> &MD : MDs) 51 if (!O.shouldKeep()) 52 F.setMetadata(MD.first, NULL); 53 54 // Delete out-of-chunk metadata attached to instructions. 55 for (Instruction &I : instructions(F)) { 56 I.getAllMetadata(MDs); 57 for (std::pair<unsigned, MDNode *> &MD : MDs) 58 if (!O.shouldKeep()) 59 I.setMetadata(MD.first, NULL); 60 } 61 } 62 } 63 64 static int countMetadataTargets(Module &Program) { 65 int NamedMetadataNodes = Program.named_metadata_size(); 66 67 // Get metadata attached to globals. 68 int GlobalMetadataArgs = 0; 69 SmallVector<std::pair<unsigned, MDNode *>> MDs; 70 for (GlobalVariable &GV : Program.globals()) { 71 GV.getAllMetadata(MDs); 72 GlobalMetadataArgs += MDs.size(); 73 } 74 75 // Get metadata attached to functions & instructions. 76 int FunctionMetadataArgs = 0; 77 int InstructionMetadataArgs = 0; 78 for (Function &F : Program) { 79 F.getAllMetadata(MDs); 80 FunctionMetadataArgs += MDs.size(); 81 82 for (Instruction &I : instructions(F)) { 83 I.getAllMetadata(MDs); 84 InstructionMetadataArgs += MDs.size(); 85 } 86 } 87 88 return NamedMetadataNodes + GlobalMetadataArgs + FunctionMetadataArgs + 89 InstructionMetadataArgs; 90 } 91 92 void llvm::reduceMetadataDeltaPass(TestRunner &Test) { 93 outs() << "*** Reducing Metadata...\n"; 94 int MDCount = countMetadataTargets(Test.getProgram()); 95 runDeltaPass(Test, MDCount, extractMetadataFromModule); 96 outs() << "----------------------------\n"; 97 } 98