1 //===- MemoryOpRemark.h - Memory operation remark analysis -*- C++ ------*-===//
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 // Provide more information about instructions that copy, move, or initialize
10 // memory, including those with a "auto-init" !annotation metadata.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TRANSFORMS_UTILS_MEMORYOPREMARK_H
15 #define LLVM_TRANSFORMS_UTILS_MEMORYOPREMARK_H
16 
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Analysis/TargetLibraryInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include <optional>
21 
22 namespace llvm {
23 
24 class CallInst;
25 class DataLayout;
26 class DiagnosticInfoIROptimization;
27 class Instruction;
28 class IntrinsicInst;
29 class Value;
30 class OptimizationRemarkEmitter;
31 class StoreInst;
32 
33 // FIXME: Once we get to more remarks like this one, we need to re-evaluate how
34 // much of this logic should actually go into the remark emitter.
35 struct MemoryOpRemark {
36   OptimizationRemarkEmitter &ORE;
37   StringRef RemarkPass;
38   const DataLayout &DL;
39   const TargetLibraryInfo &TLI;
40 
41   MemoryOpRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass,
42                  const DataLayout &DL, const TargetLibraryInfo &TLI)
43       : ORE(ORE), RemarkPass(RemarkPass), DL(DL), TLI(TLI) {}
44 
45   virtual ~MemoryOpRemark();
46 
47   /// \return true iff the instruction is understood by MemoryOpRemark.
48   static bool canHandle(const Instruction *I, const TargetLibraryInfo &TLI);
49 
50   void visit(const Instruction *I);
51 
52 protected:
53   virtual std::string explainSource(StringRef Type) const;
54 
55   enum RemarkKind { RK_Store, RK_Unknown, RK_IntrinsicCall, RK_Call };
56   virtual StringRef remarkName(RemarkKind RK) const;
57 
58   virtual DiagnosticKind diagnosticKind() const { return DK_OptimizationRemarkAnalysis; }
59 
60 private:
61   template<typename ...Ts>
62   std::unique_ptr<DiagnosticInfoIROptimization> makeRemark(Ts... Args);
63 
64   /// Emit a remark using information from the store's destination, size, etc.
65   void visitStore(const StoreInst &SI);
66   /// Emit a generic auto-init remark.
67   void visitUnknown(const Instruction &I);
68   /// Emit a remark using information from known intrinsic calls.
69   void visitIntrinsicCall(const IntrinsicInst &II);
70   /// Emit a remark using information from known function calls.
71   void visitCall(const CallInst &CI);
72 
73   /// Add callee information to a remark: whether it's known, the function name,
74   /// etc.
75   template <typename FTy>
76   void visitCallee(FTy F, bool KnownLibCall, DiagnosticInfoIROptimization &R);
77   /// Add operand information to a remark based on knowledge we have for known
78   /// libcalls.
79   void visitKnownLibCall(const CallInst &CI, LibFunc LF,
80                          DiagnosticInfoIROptimization &R);
81   /// Add the memory operation size to a remark.
82   void visitSizeOperand(Value *V, DiagnosticInfoIROptimization &R);
83 
84   struct VariableInfo {
85     std::optional<StringRef> Name;
86     std::optional<uint64_t> Size;
87     bool isEmpty() const { return !Name && !Size; }
88   };
89   /// Gather more information about \p V as a variable. This can be debug info,
90   /// information from the alloca, etc. Since \p V can represent more than a
91   /// single variable, they will all be added to the remark.
92   void visitPtr(Value *V, bool IsSrc, DiagnosticInfoIROptimization &R);
93   void visitVariable(const Value *V, SmallVectorImpl<VariableInfo> &Result);
94 };
95 
96 /// Special case for -ftrivial-auto-var-init remarks.
97 struct AutoInitRemark : public MemoryOpRemark {
98   AutoInitRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass,
99                  const DataLayout &DL, const TargetLibraryInfo &TLI)
100       : MemoryOpRemark(ORE, RemarkPass, DL, TLI) {}
101 
102   /// \return true iff the instruction is understood by AutoInitRemark.
103   static bool canHandle(const Instruction *I);
104 
105 protected:
106   std::string explainSource(StringRef Type) const override;
107   StringRef remarkName(RemarkKind RK) const override;
108   DiagnosticKind diagnosticKind() const override {
109     return DK_OptimizationRemarkMissed;
110   }
111 };
112 
113 } // namespace llvm
114 
115 #endif
116