1//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements bookkeeping for "interesting" users of expressions
11// computed from induction variables.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ANALYSIS_IVUSERS_H
16#define LLVM_ANALYSIS_IVUSERS_H
17
18#include "llvm/Analysis/LoopAnalysisManager.h"
19#include "llvm/Analysis/LoopPass.h"
20#include "llvm/Analysis/ScalarEvolutionNormalization.h"
21#include "llvm/IR/ValueHandle.h"
22
23namespace llvm {
24
25class AssumptionCache;
26class DominatorTree;
27class Instruction;
28class Value;
29class ScalarEvolution;
30class SCEV;
31class IVUsers;
32class DataLayout;
33
34/// IVStrideUse - Keep track of one use of a strided induction variable.
35/// The Expr member keeps track of the expression, User is the actual user
36/// instruction of the operand, and 'OperandValToReplace' is the operand of
37/// the User that is the use.
38class IVStrideUse final : public CallbackVH, public ilist_node<IVStrideUse> {
39  friend class IVUsers;
40public:
41  IVStrideUse(IVUsers *P, Instruction* U, Value *O)
42    : CallbackVH(U), Parent(P), OperandValToReplace(O) {
43  }
44
45  /// getUser - Return the user instruction for this use.
46  Instruction *getUser() const {
47    return cast<Instruction>(getValPtr());
48  }
49
50  /// setUser - Assign a new user instruction for this use.
51  void setUser(Instruction *NewUser) {
52    setValPtr(NewUser);
53  }
54
55  /// getOperandValToReplace - Return the Value of the operand in the user
56  /// instruction that this IVStrideUse is representing.
57  Value *getOperandValToReplace() const {
58    return OperandValToReplace;
59  }
60
61  /// setOperandValToReplace - Assign a new Value as the operand value
62  /// to replace.
63  void setOperandValToReplace(Value *Op) {
64    OperandValToReplace = Op;
65  }
66
67  /// getPostIncLoops - Return the set of loops for which the expression has
68  /// been adjusted to use post-inc mode.
69  const PostIncLoopSet &getPostIncLoops() const {
70    return PostIncLoops;
71  }
72
73  /// transformToPostInc - Transform the expression to post-inc form for the
74  /// given loop.
75  void transformToPostInc(const Loop *L);
76
77private:
78  /// Parent - a pointer to the IVUsers that owns this IVStrideUse.
79  IVUsers *Parent;
80
81  /// OperandValToReplace - The Value of the operand in the user instruction
82  /// that this IVStrideUse is representing.
83  WeakTrackingVH OperandValToReplace;
84
85  /// PostIncLoops - The set of loops for which Expr has been adjusted to
86  /// use post-inc mode. This corresponds with SCEVExpander's post-inc concept.
87  PostIncLoopSet PostIncLoops;
88
89  /// Deleted - Implementation of CallbackVH virtual function to
90  /// receive notification when the User is deleted.
91  void deleted() override;
92};
93
94class IVUsers {
95  friend class IVStrideUse;
96  Loop *L;
97  AssumptionCache *AC;
98  LoopInfo *LI;
99  DominatorTree *DT;
100  ScalarEvolution *SE;
101  SmallPtrSet<Instruction*, 16> Processed;
102
103  /// IVUses - A list of all tracked IV uses of induction variable expressions
104  /// we are interested in.
105  ilist<IVStrideUse> IVUses;
106
107  // Ephemeral values used by @llvm.assume in this function.
108  SmallPtrSet<const Value *, 32> EphValues;
109
110public:
111  IVUsers(Loop *L, AssumptionCache *AC, LoopInfo *LI, DominatorTree *DT,
112          ScalarEvolution *SE);
113
114  IVUsers(IVUsers &&X)
115      : L(std::move(X.L)), AC(std::move(X.AC)), DT(std::move(X.DT)),
116        SE(std::move(X.SE)), Processed(std::move(X.Processed)),
117        IVUses(std::move(X.IVUses)), EphValues(std::move(X.EphValues)) {
118    for (IVStrideUse &U : IVUses)
119      U.Parent = this;
120  }
121  IVUsers(const IVUsers &) = delete;
122  IVUsers &operator=(IVUsers &&) = delete;
123  IVUsers &operator=(const IVUsers &) = delete;
124
125  Loop *getLoop() const { return L; }
126
127  /// AddUsersIfInteresting - Inspect the specified Instruction.  If it is a
128  /// reducible SCEV, recursively add its users to the IVUsesByStride set and
129  /// return true.  Otherwise, return false.
130  bool AddUsersIfInteresting(Instruction *I);
131
132  IVStrideUse &AddUser(Instruction *User, Value *Operand);
133
134  /// getReplacementExpr - Return a SCEV expression which computes the
135  /// value of the OperandValToReplace of the given IVStrideUse.
136  const SCEV *getReplacementExpr(const IVStrideUse &IU) const;
137
138  /// getExpr - Return the expression for the use.
139  const SCEV *getExpr(const IVStrideUse &IU) const;
140
141  const SCEV *getStride(const IVStrideUse &IU, const Loop *L) const;
142
143  typedef ilist<IVStrideUse>::iterator iterator;
144  typedef ilist<IVStrideUse>::const_iterator const_iterator;
145  iterator begin() { return IVUses.begin(); }
146  iterator end()   { return IVUses.end(); }
147  const_iterator begin() const { return IVUses.begin(); }
148  const_iterator end() const   { return IVUses.end(); }
149  bool empty() const { return IVUses.empty(); }
150
151  bool isIVUserOrOperand(Instruction *Inst) const {
152    return Processed.count(Inst);
153  }
154
155  void releaseMemory();
156
157  void print(raw_ostream &OS, const Module * = nullptr) const;
158
159  /// dump - This method is used for debugging.
160  void dump() const;
161
162protected:
163  bool AddUsersImpl(Instruction *I, SmallPtrSetImpl<Loop*> &SimpleLoopNests);
164};
165
166Pass *createIVUsersPass();
167
168class IVUsersWrapperPass : public LoopPass {
169  std::unique_ptr<IVUsers> IU;
170
171public:
172  static char ID;
173
174  IVUsersWrapperPass();
175
176  IVUsers &getIU() { return *IU; }
177  const IVUsers &getIU() const { return *IU; }
178
179  void getAnalysisUsage(AnalysisUsage &AU) const override;
180
181  bool runOnLoop(Loop *L, LPPassManager &LPM) override;
182
183  void releaseMemory() override;
184
185  void print(raw_ostream &OS, const Module * = nullptr) const override;
186};
187
188/// Analysis pass that exposes the \c IVUsers for a loop.
189class IVUsersAnalysis : public AnalysisInfoMixin<IVUsersAnalysis> {
190  friend AnalysisInfoMixin<IVUsersAnalysis>;
191  static AnalysisKey Key;
192
193public:
194  typedef IVUsers Result;
195
196  IVUsers run(Loop &L, LoopAnalysisManager &AM,
197              LoopStandardAnalysisResults &AR);
198};
199
200}
201
202#endif
203