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