124 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements two functions used by the Generic Delta Debugging10// Algorithm, which are used to reduce Metadata nodes.11//12//===----------------------------------------------------------------------===//13 14#include "ReduceMetadata.h"15#include "llvm/ADT/Sequence.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/IR/InstIterator.h"18#include "llvm/IR/IntrinsicInst.h"19 20using namespace llvm;21 22extern cl::OptionCategory LLVMReduceOptions;23 24static cl::opt<bool> AggressiveMetadataReduction(25 "aggressive-named-md-reduction",26 cl::desc("Reduce named metadata without taking its type into account"),27 cl::cat(LLVMReduceOptions));28 29static bool shouldKeepDebugIntrinsicMetadata(Instruction &I, MDNode &MD) {30 return isa<DILocation>(MD) && isa<DbgInfoIntrinsic>(I);31}32 33static bool shouldKeepDebugNamedMetadata(NamedMDNode &MD) {34 return MD.getName() == "llvm.dbg.cu" && MD.getNumOperands() != 0;35}36 37// Named metadata with simple list-like behavior, so that it's valid to remove38// operands individually.39static constexpr StringLiteral ListNamedMetadata[] = {40 "llvm.module.flags",41 "llvm.ident",42 "opencl.spir.version",43 "opencl.ocl.version",44 "opencl.used.extensions",45 "opencl.used.optional.core.features",46 "opencl.compiler.options"47};48 49/// Remove unneeded arguments to named metadata.50void llvm::reduceNamedMetadataDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {51 Module &M = WorkItem.getModule();52 53 for (NamedMDNode &I : M.named_metadata()) {54 // If we don't want to reduce mindlessly, check if our node is part of55 // ListNamedMetadata before reducing it56 if (!AggressiveMetadataReduction &&57 !is_contained(ListNamedMetadata, I.getName()))58 continue;59 60 bool MadeChange = false;61 SmallVector<MDNode *> KeptOperands;62 for (auto J : seq<unsigned>(0, I.getNumOperands())) {63 if (O.shouldKeep())64 KeptOperands.push_back(I.getOperand(J));65 else66 MadeChange = true;67 }68 69 if (MadeChange) {70 I.clearOperands();71 for (MDNode *KeptOperand : KeptOperands)72 I.addOperand(KeptOperand);73 }74 }75}76 77/// Removes all the Named and Unnamed Metadata Nodes, as well as any debug78/// functions that aren't inside the desired Chunks.79void llvm::reduceMetadataDeltaPass(Oracle &O, ReducerWorkItem &WorkItem) {80 Module &Program = WorkItem.getModule();81 82 // Get out-of-chunk Named metadata nodes83 SmallVector<NamedMDNode *> NamedNodesToDelete;84 for (NamedMDNode &MD : Program.named_metadata())85 if (!shouldKeepDebugNamedMetadata(MD) && !O.shouldKeep())86 NamedNodesToDelete.push_back(&MD);87 88 for (NamedMDNode *NN : NamedNodesToDelete) {89 for (auto I : seq<unsigned>(0, NN->getNumOperands()))90 NN->setOperand(I, nullptr);91 NN->eraseFromParent();92 }93 94 // Delete out-of-chunk metadata attached to globals.95 for (GlobalVariable &GV : Program.globals()) {96 SmallVector<std::pair<unsigned, MDNode *>> MDs;97 GV.getAllMetadata(MDs);98 for (std::pair<unsigned, MDNode *> &MD : MDs)99 if (!O.shouldKeep())100 GV.setMetadata(MD.first, nullptr);101 }102 103 for (Function &F : Program) {104 {105 SmallVector<std::pair<unsigned, MDNode *>> MDs;106 // Delete out-of-chunk metadata attached to functions.107 F.getAllMetadata(MDs);108 for (std::pair<unsigned, MDNode *> &MD : MDs)109 if (!O.shouldKeep())110 F.setMetadata(MD.first, nullptr);111 }112 113 // Delete out-of-chunk metadata attached to instructions.114 for (Instruction &I : instructions(F)) {115 SmallVector<std::pair<unsigned, MDNode *>> MDs;116 I.getAllMetadata(MDs);117 for (std::pair<unsigned, MDNode *> &MD : MDs) {118 if (!shouldKeepDebugIntrinsicMetadata(I, *MD.second) && !O.shouldKeep())119 I.setMetadata(MD.first, nullptr);120 }121 }122 }123}124