diff --git a/llvm/test/tools/llvm-reduce/remove-metadata-args.ll b/llvm/test/tools/llvm-reduce/remove-metadata-args.ll new file mode 100644 index 00000000000000..817f1eb8defe04 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/remove-metadata-args.ll @@ -0,0 +1,29 @@ +; RUN: llvm-reduce %s -o %t --delta-passes=metadata --test FileCheck --test-arg %s --test-arg --check-prefix=EXCITING --test-arg --input-file +; RUN: FileCheck %s --input-file %t --check-prefix=REDUCED + +; All exciting stuff must remain in the reduced file. +; EXCITING-DAG: ExcitingGlobal = global i32 0, !md !0 +; EXCITING-DAG: define void @ExcitingFunc() !md !0 +; EXCITING-DAG: store i32 0, i32* @ExcitingGlobal, align 4, !md !0 +; EXCITING-DAG: !ExcitingNamedMD = !{!0} + +; Boring stuff's metadata must have been removed. +; REDUCED-NOT: Boring{{.*}} !md !0 +; REDUCED-NOT: !md !0 {{.*}}Boring + + +@ExcitingGlobal = global i32 0, !md !0 +@BoringGlobal = global i32 0, !md !0 + +define void @ExcitingFunc() !md !0 { + store i32 0, i32* @ExcitingGlobal, align 4, !md !0 + store i32 0, i32* @BoringGlobal, align 4, !md !0 + ret void +} + +declare !md !0 void @BoringFunc() + +!ExcitingNamedMD = !{!0} +!BoringNamedMD = !{!0} + +!0 = !{!"my metadata"} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp index 4587295a00bee6..8eb4533848d920 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp @@ -13,110 +13,83 @@ #include "ReduceMetadata.h" #include "Delta.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" -#include +#include "llvm/IR/InstIterator.h" #include using namespace llvm; -/// Adds all Unnamed Metadata Nodes that are inside desired Chunks to set -template -static void getChunkMetadataNodes(T &MDUser, Oracle &O, - std::set &SeenNodes, - std::set &NodesToKeep) { - SmallVector, 4> MDs; - MDUser.getAllMetadata(MDs); - for (auto &MD : MDs) { - SeenNodes.insert(MD.second); - if (O.shouldKeep()) - NodesToKeep.insert(MD.second); - } -} - -/// Erases out-of-chunk unnamed metadata nodes from its user -template -static void eraseMetadataIfOutsideChunk(T &MDUser, - const std::set &NodesToKeep) { - SmallVector, 4> MDs; - MDUser.getAllMetadata(MDs); - for (int I = 0, E = MDs.size(); I != E; ++I) - if (!NodesToKeep.count(MDs[I].second)) - MDUser.setMetadata(I, NULL); -} - /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug /// functions that aren't inside the desired Chunks. static void extractMetadataFromModule(const std::vector &ChunksToKeep, Module *Program) { Oracle O(ChunksToKeep); - std::set SeenNodes; - std::set NodesToKeep; - - // Add chunk MDNodes used by GVs, Functions, and Instructions to set - for (auto &GV : Program->globals()) - getChunkMetadataNodes(GV, O, SeenNodes, NodesToKeep); - - for (auto &F : *Program) { - getChunkMetadataNodes(F, O, SeenNodes, NodesToKeep); - for (auto &BB : F) - for (auto &Inst : BB) - getChunkMetadataNodes(Inst, O, SeenNodes, NodesToKeep); - } - - // Once more, go over metadata nodes, but deleting the ones outside chunks - for (auto &GV : Program->globals()) - eraseMetadataIfOutsideChunk(GV, NodesToKeep); - - for (auto &F : *Program) { - eraseMetadataIfOutsideChunk(F, NodesToKeep); - for (auto &BB : F) - for (auto &Inst : BB) - eraseMetadataIfOutsideChunk(Inst, NodesToKeep); - } - - // Get out-of-chunk Named metadata nodes - std::vector NamedNodesToDelete; - for (auto &MD : Program->named_metadata()) + SmallVector NamedNodesToDelete; + for (NamedMDNode &MD : Program->named_metadata()) if (!O.shouldKeep()) NamedNodesToDelete.push_back(&MD); - for (auto *NN : NamedNodesToDelete) { - for (int I = 0, E = NN->getNumOperands(); I != E; ++I) + for (NamedMDNode *NN : NamedNodesToDelete) { + for (auto I : seq(0, NN->getNumOperands())) NN->setOperand(I, NULL); NN->eraseFromParent(); } -} -// Gets unnamed metadata nodes used by a given instruction/GV/function and adds -// them to the set of seen nodes -template -static void addMetadataToSet(T &MDUser, std::set &UnnamedNodes) { - SmallVector, 4> MDs; - MDUser.getAllMetadata(MDs); - for (auto &MD : MDs) - UnnamedNodes.insert(MD.second); + // Delete out-of-chunk metadata attached to globals. + SmallVector> MDs; + for (GlobalVariable &GV : Program->globals()) { + GV.getAllMetadata(MDs); + for (std::pair &MD : MDs) + if (!O.shouldKeep()) + GV.setMetadata(MD.first, NULL); + } + + for (Function &F : *Program) { + // Delete out-of-chunk metadata attached to functions. + F.getAllMetadata(MDs); + for (std::pair &MD : MDs) + if (!O.shouldKeep()) + F.setMetadata(MD.first, NULL); + + // Delete out-of-chunk metadata attached to instructions. + for (Instruction &I : instructions(F)) { + I.getAllMetadata(MDs); + for (std::pair &MD : MDs) + if (!O.shouldKeep()) + I.setMetadata(MD.first, NULL); + } + } } -/// Returns the amount of Named and Unnamed Metadata Nodes static int countMetadataTargets(Module *Program) { - std::set UnnamedNodes; int NamedMetadataNodes = Program->named_metadata_size(); - // Get metadata nodes used by globals - for (auto &GV : Program->globals()) - addMetadataToSet(GV, UnnamedNodes); + // Get metadata attached to globals. + int GlobalMetadataArgs = 0; + SmallVector> MDs; + for (GlobalVariable &GV : Program->globals()) { + GV.getAllMetadata(MDs); + GlobalMetadataArgs += MDs.size(); + } - // Do the same for nodes used by functions & instructions - for (auto &F : *Program) { - addMetadataToSet(F, UnnamedNodes); - for (auto &BB : F) - for (auto &I : BB) - addMetadataToSet(I, UnnamedNodes); + // Get metadata attached to functions & instructions. + int FunctionMetadataArgs = 0; + int InstructionMetadataArgs = 0; + for (Function &F : *Program) { + F.getAllMetadata(MDs); + FunctionMetadataArgs += MDs.size(); + + for (Instruction &I : instructions(F)) { + I.getAllMetadata(MDs); + InstructionMetadataArgs += MDs.size(); + } } - return UnnamedNodes.size() + NamedMetadataNodes; + return NamedMetadataNodes + GlobalMetadataArgs + FunctionMetadataArgs + + InstructionMetadataArgs; } void llvm::reduceMetadataDeltaPass(TestRunner &Test) {