18bb63479SFlorian Hahn //===-- AnnotationRemarks.cpp - Generate remarks for annotated instrs. ----===//
28bb63479SFlorian Hahn //
38bb63479SFlorian Hahn // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bb63479SFlorian Hahn // See https://llvm.org/LICENSE.txt for license information.
58bb63479SFlorian Hahn // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bb63479SFlorian Hahn //
78bb63479SFlorian Hahn //===----------------------------------------------------------------------===//
88bb63479SFlorian Hahn //
98bb63479SFlorian Hahn // Generate remarks for instructions marked with !annotation.
108bb63479SFlorian Hahn //
118bb63479SFlorian Hahn //===----------------------------------------------------------------------===//
128bb63479SFlorian Hahn
138bb63479SFlorian Hahn #include "llvm/Transforms/Scalar/AnnotationRemarks.h"
148bb63479SFlorian Hahn #include "llvm/ADT/MapVector.h"
158bb63479SFlorian Hahn #include "llvm/Analysis/OptimizationRemarkEmitter.h"
168bb63479SFlorian Hahn #include "llvm/Analysis/TargetLibraryInfo.h"
178bb63479SFlorian Hahn #include "llvm/IR/Function.h"
188bb63479SFlorian Hahn #include "llvm/IR/InstIterator.h"
198bb63479SFlorian Hahn #include "llvm/InitializePasses.h"
208bb63479SFlorian Hahn #include "llvm/Pass.h"
218bb63479SFlorian Hahn #include "llvm/Transforms/Scalar.h"
22*095e91c9SJon Roelofs #include "llvm/Transforms/Utils/MemoryOpRemark.h"
238bb63479SFlorian Hahn
248bb63479SFlorian Hahn using namespace llvm;
258bb63479SFlorian Hahn using namespace llvm::ore;
268bb63479SFlorian Hahn
278bb63479SFlorian Hahn #define DEBUG_TYPE "annotation-remarks"
288bb63479SFlorian Hahn #define REMARK_PASS DEBUG_TYPE
298bb63479SFlorian Hahn
tryEmitAutoInitRemark(ArrayRef<Instruction * > Instructions,OptimizationRemarkEmitter & ORE,const TargetLibraryInfo & TLI)30c49b600bSFrancis Visoiu Mistrih static void tryEmitAutoInitRemark(ArrayRef<Instruction *> Instructions,
31fee9abe6SFrancis Visoiu Mistrih OptimizationRemarkEmitter &ORE,
32fee9abe6SFrancis Visoiu Mistrih const TargetLibraryInfo &TLI) {
33c49b600bSFrancis Visoiu Mistrih // For every auto-init annotation generate a separate remark.
34c49b600bSFrancis Visoiu Mistrih for (Instruction *I : Instructions) {
35*095e91c9SJon Roelofs if (!AutoInitRemark::canHandle(I))
36c49b600bSFrancis Visoiu Mistrih continue;
37c49b600bSFrancis Visoiu Mistrih
384753a69aSFrancis Visoiu Mistrih Function &F = *I->getParent()->getParent();
394753a69aSFrancis Visoiu Mistrih const DataLayout &DL = F.getParent()->getDataLayout();
40fee9abe6SFrancis Visoiu Mistrih AutoInitRemark Remark(ORE, REMARK_PASS, DL, TLI);
41*095e91c9SJon Roelofs Remark.visit(I);
42c49b600bSFrancis Visoiu Mistrih }
43c49b600bSFrancis Visoiu Mistrih }
44c49b600bSFrancis Visoiu Mistrih
runImpl(Function & F,const TargetLibraryInfo & TLI)45fee9abe6SFrancis Visoiu Mistrih static void runImpl(Function &F, const TargetLibraryInfo &TLI) {
468bb63479SFlorian Hahn if (!OptimizationRemarkEmitter::allowExtraAnalysis(F, REMARK_PASS))
478bb63479SFlorian Hahn return;
488bb63479SFlorian Hahn
49c49b600bSFrancis Visoiu Mistrih // Track all annotated instructions aggregated based on their debug location.
50c49b600bSFrancis Visoiu Mistrih DenseMap<MDNode *, SmallVector<Instruction *, 4>> DebugLoc2Annotated;
51c49b600bSFrancis Visoiu Mistrih
528bb63479SFlorian Hahn OptimizationRemarkEmitter ORE(&F);
53c49b600bSFrancis Visoiu Mistrih // First, generate a summary of the annotated instructions.
548bb63479SFlorian Hahn MapVector<StringRef, unsigned> Mapping;
558bb63479SFlorian Hahn for (Instruction &I : instructions(F)) {
568bb63479SFlorian Hahn if (!I.hasMetadata(LLVMContext::MD_annotation))
578bb63479SFlorian Hahn continue;
58c49b600bSFrancis Visoiu Mistrih auto Iter = DebugLoc2Annotated.insert({I.getDebugLoc().getAsMDNode(), {}});
59c49b600bSFrancis Visoiu Mistrih Iter.first->second.push_back(&I);
60c49b600bSFrancis Visoiu Mistrih
618bb63479SFlorian Hahn for (const MDOperand &Op :
628bb63479SFlorian Hahn I.getMetadata(LLVMContext::MD_annotation)->operands()) {
638bb63479SFlorian Hahn auto Iter = Mapping.insert({cast<MDString>(Op.get())->getString(), 0});
648bb63479SFlorian Hahn Iter.first->second++;
658bb63479SFlorian Hahn }
668bb63479SFlorian Hahn }
678bb63479SFlorian Hahn
688bb63479SFlorian Hahn for (const auto &KV : Mapping)
69e43e8e91SFlorian Hahn ORE.emit(OptimizationRemarkAnalysis(REMARK_PASS, "AnnotationSummary",
70e43e8e91SFlorian Hahn F.getSubprogram(), &F.front())
718bb63479SFlorian Hahn << "Annotated " << NV("count", KV.second) << " instructions with "
728bb63479SFlorian Hahn << NV("type", KV.first));
73c49b600bSFrancis Visoiu Mistrih
74c49b600bSFrancis Visoiu Mistrih // For each debug location, look for all the instructions with annotations and
75c49b600bSFrancis Visoiu Mistrih // generate more detailed remarks to be displayed at that location.
76c49b600bSFrancis Visoiu Mistrih for (auto &KV : DebugLoc2Annotated) {
77c49b600bSFrancis Visoiu Mistrih // Don't generate remarks with no debug location.
78c49b600bSFrancis Visoiu Mistrih if (!KV.first)
79c49b600bSFrancis Visoiu Mistrih continue;
80c49b600bSFrancis Visoiu Mistrih
81fee9abe6SFrancis Visoiu Mistrih tryEmitAutoInitRemark(KV.second, ORE, TLI);
82c49b600bSFrancis Visoiu Mistrih }
838bb63479SFlorian Hahn }
848bb63479SFlorian Hahn
858bb63479SFlorian Hahn namespace {
868bb63479SFlorian Hahn
878bb63479SFlorian Hahn struct AnnotationRemarksLegacy : public FunctionPass {
888bb63479SFlorian Hahn static char ID;
898bb63479SFlorian Hahn
AnnotationRemarksLegacy__anon074bf4f30111::AnnotationRemarksLegacy908bb63479SFlorian Hahn AnnotationRemarksLegacy() : FunctionPass(ID) {
918bb63479SFlorian Hahn initializeAnnotationRemarksLegacyPass(*PassRegistry::getPassRegistry());
928bb63479SFlorian Hahn }
938bb63479SFlorian Hahn
runOnFunction__anon074bf4f30111::AnnotationRemarksLegacy948bb63479SFlorian Hahn bool runOnFunction(Function &F) override {
95fee9abe6SFrancis Visoiu Mistrih const TargetLibraryInfo &TLI =
96fee9abe6SFrancis Visoiu Mistrih getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
97fee9abe6SFrancis Visoiu Mistrih runImpl(F, TLI);
988bb63479SFlorian Hahn return false;
998bb63479SFlorian Hahn }
1008bb63479SFlorian Hahn
getAnalysisUsage__anon074bf4f30111::AnnotationRemarksLegacy1018bb63479SFlorian Hahn void getAnalysisUsage(AnalysisUsage &AU) const override {
1028bb63479SFlorian Hahn AU.setPreservesAll();
103fee9abe6SFrancis Visoiu Mistrih AU.addRequired<TargetLibraryInfoWrapperPass>();
1048bb63479SFlorian Hahn }
1058bb63479SFlorian Hahn };
1068bb63479SFlorian Hahn
1078bb63479SFlorian Hahn } // end anonymous namespace
1088bb63479SFlorian Hahn
1098bb63479SFlorian Hahn char AnnotationRemarksLegacy::ID = 0;
1108bb63479SFlorian Hahn
1118bb63479SFlorian Hahn INITIALIZE_PASS_BEGIN(AnnotationRemarksLegacy, "annotation-remarks",
1128bb63479SFlorian Hahn "Annotation Remarks", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)113fee9abe6SFrancis Visoiu Mistrih INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
1148bb63479SFlorian Hahn INITIALIZE_PASS_END(AnnotationRemarksLegacy, "annotation-remarks",
1158bb63479SFlorian Hahn "Annotation Remarks", false, false)
1168bb63479SFlorian Hahn
1178bb63479SFlorian Hahn FunctionPass *llvm::createAnnotationRemarksLegacyPass() {
1188bb63479SFlorian Hahn return new AnnotationRemarksLegacy();
1198bb63479SFlorian Hahn }
1208bb63479SFlorian Hahn
run(Function & F,FunctionAnalysisManager & AM)1218bb63479SFlorian Hahn PreservedAnalyses AnnotationRemarksPass::run(Function &F,
1228bb63479SFlorian Hahn FunctionAnalysisManager &AM) {
123fee9abe6SFrancis Visoiu Mistrih auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
124fee9abe6SFrancis Visoiu Mistrih runImpl(F, TLI);
1258bb63479SFlorian Hahn return PreservedAnalyses::all();
1268bb63479SFlorian Hahn }
127