| 1 | //===-- AnnotationRemarks.cpp - Generate remarks for annotated instrs. ----===// |
| 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 | // Generate remarks for instructions marked with !annotation. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "llvm/Transforms/Scalar/AnnotationRemarks.h" |
| 14 | #include "llvm/ADT/MapVector.h" |
| 15 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
| 16 | #include "llvm/Analysis/TargetLibraryInfo.h" |
| 17 | #include "llvm/IR/Function.h" |
| 18 | #include "llvm/IR/InstIterator.h" |
| 19 | #include "llvm/Transforms/Utils/MemoryOpRemark.h" |
| 20 | |
| 21 | using namespace llvm; |
| 22 | using namespace llvm::ore; |
| 23 | |
| 24 | #define DEBUG_TYPE "annotation-remarks" |
| 25 | #define DEBUG_TYPE |
| 26 | |
| 27 | static void (ArrayRef<Instruction *> Instructions, |
| 28 | OptimizationRemarkEmitter &ORE, |
| 29 | const TargetLibraryInfo &TLI) { |
| 30 | // For every auto-init annotation generate a separate remark. |
| 31 | for (Instruction *I : Instructions) { |
| 32 | if (!AutoInitRemark::canHandle(I)) |
| 33 | continue; |
| 34 | |
| 35 | Function &F = *I->getParent()->getParent(); |
| 36 | const DataLayout &DL = F.getDataLayout(); |
| 37 | AutoInitRemark (ORE, REMARK_PASS, DL, TLI); |
| 38 | Remark.visit(I); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | static void runImpl(Function &F, const TargetLibraryInfo &TLI) { |
| 43 | if (!OptimizationRemarkEmitter::allowExtraAnalysis(F, REMARK_PASS)) |
| 44 | return; |
| 45 | |
| 46 | // Track all annotated instructions aggregated based on their debug location. |
| 47 | DenseMap<MDNode *, SmallVector<Instruction *, 4>> DebugLoc2Annotated; |
| 48 | |
| 49 | OptimizationRemarkEmitter ORE(&F); |
| 50 | // First, generate a summary of the annotated instructions. |
| 51 | MapVector<StringRef, unsigned> Mapping; |
| 52 | for (Instruction &I : instructions(F)) { |
| 53 | if (!I.hasMetadata(KindID: LLVMContext::MD_annotation)) |
| 54 | continue; |
| 55 | DebugLoc2Annotated[I.getDebugLoc().getAsMDNode()].push_back(Elt: &I); |
| 56 | |
| 57 | for (const MDOperand &Op : |
| 58 | I.getMetadata(KindID: LLVMContext::MD_annotation)->operands()) { |
| 59 | StringRef AnnotationStr = |
| 60 | isa<MDString>(Val: Op.get()) |
| 61 | ? cast<MDString>(Val: Op.get())->getString() |
| 62 | : cast<MDString>(Val: cast<MDTuple>(Val: Op.get())->getOperand(I: 0).get()) |
| 63 | ->getString(); |
| 64 | Mapping[AnnotationStr]++; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | for (const auto &KV : Mapping) |
| 69 | ORE.emit(OptDiag: OptimizationRemarkAnalysis(REMARK_PASS, "AnnotationSummary" , |
| 70 | F.getSubprogram(), &F.front()) |
| 71 | << "Annotated " << NV("count" , KV.second) << " instructions with " |
| 72 | << NV("type" , KV.first)); |
| 73 | |
| 74 | // For each debug location, look for all the instructions with annotations and |
| 75 | // generate more detailed remarks to be displayed at that location. |
| 76 | for (auto &KV : DebugLoc2Annotated) { |
| 77 | // Don't generate remarks with no debug location. |
| 78 | if (!KV.first) |
| 79 | continue; |
| 80 | |
| 81 | tryEmitAutoInitRemark(Instructions: KV.second, ORE, TLI); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | PreservedAnalyses AnnotationRemarksPass::(Function &F, |
| 86 | FunctionAnalysisManager &AM) { |
| 87 | auto &TLI = AM.getResult<TargetLibraryAnalysis>(IR&: F); |
| 88 | runImpl(F, TLI); |
| 89 | return PreservedAnalyses::all(); |
| 90 | } |
| 91 | |