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