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 | auto Iter = DebugLoc2Annotated.insert(KV: {I.getDebugLoc().getAsMDNode(), {}}); |
56 | Iter.first->second.push_back(Elt: &I); |
57 | |
58 | for (const MDOperand &Op : |
59 | I.getMetadata(KindID: LLVMContext::MD_annotation)->operands()) { |
60 | StringRef AnnotationStr = |
61 | isa<MDString>(Val: Op.get()) |
62 | ? cast<MDString>(Val: Op.get())->getString() |
63 | : cast<MDString>(Val: cast<MDTuple>(Val: Op.get())->getOperand(I: 0).get()) |
64 | ->getString(); |
65 | auto Iter = Mapping.insert(KV: {AnnotationStr, 0}); |
66 | Iter.first->second++; |
67 | } |
68 | } |
69 | |
70 | for (const auto &KV : Mapping) |
71 | ORE.emit(OptDiag&: OptimizationRemarkAnalysis(REMARK_PASS, "AnnotationSummary" , |
72 | F.getSubprogram(), &F.front()) |
73 | << "Annotated " << NV("count" , KV.second) << " instructions with " |
74 | << NV("type" , KV.first)); |
75 | |
76 | // For each debug location, look for all the instructions with annotations and |
77 | // generate more detailed remarks to be displayed at that location. |
78 | for (auto &KV : DebugLoc2Annotated) { |
79 | // Don't generate remarks with no debug location. |
80 | if (!KV.first) |
81 | continue; |
82 | |
83 | tryEmitAutoInitRemark(Instructions: KV.second, ORE, TLI); |
84 | } |
85 | } |
86 | |
87 | PreservedAnalyses AnnotationRemarksPass::(Function &F, |
88 | FunctionAnalysisManager &AM) { |
89 | auto &TLI = AM.getResult<TargetLibraryAnalysis>(IR&: F); |
90 | runImpl(F, TLI); |
91 | return PreservedAnalyses::all(); |
92 | } |
93 | |