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