MLIR  18.0.0git
DenseAnalysis.h
Go to the documentation of this file.
1 //===- DenseAnalysis.h - Dense data-flow analysis -------------------------===//
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 // This file implements dense data-flow analysis using the data-flow analysis
10 // framework. The analysis is forward and conditional and uses the results of
11 // dead code analysis to prune dead code during the analysis.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef MLIR_ANALYSIS_DENSEDATAFLOWANALYSIS_H
16 #define MLIR_ANALYSIS_DENSEDATAFLOWANALYSIS_H
17 
19 #include "mlir/IR/SymbolTable.h"
22 
23 namespace mlir {
24 namespace dataflow {
25 
26 //===----------------------------------------------------------------------===//
27 // CallControlFlowAction
28 //===----------------------------------------------------------------------===//
29 
30 /// Indicates whether the control enters or exits the callee.
32 
33 //===----------------------------------------------------------------------===//
34 // AbstractDenseLattice
35 //===----------------------------------------------------------------------===//
36 
37 /// This class represents a dense lattice. A dense lattice is attached to
38 /// operations to represent the program state after their execution or to blocks
39 /// to represent the program state at the beginning of the block. A dense
40 /// lattice is propagated through the IR by dense data-flow analysis.
42 public:
43  /// A dense lattice can only be created for operations and blocks.
45 
46  /// Join the lattice across control-flow or callgraph edges.
47  virtual ChangeResult join(const AbstractDenseLattice &rhs) {
49  }
50 
51  virtual ChangeResult meet(const AbstractDenseLattice &rhs) {
53  }
54 };
55 
56 //===----------------------------------------------------------------------===//
57 // AbstractDenseForwardDataFlowAnalysis
58 //===----------------------------------------------------------------------===//
59 
60 /// Base class for dense forward data-flow analyses. Dense data-flow analysis
61 /// attaches a lattice between the execution of operations and implements a
62 /// transfer function from the lattice before each operation to the lattice
63 /// after. The lattice contains information about the state of the program at
64 /// that point.
65 ///
66 /// In this implementation, a lattice attached to an operation represents the
67 /// state of the program after its execution, and a lattice attached to block
68 /// represents the state of the program right before it starts executing its
69 /// body.
71 public:
73 
74  /// Initialize the analysis by visiting every program point whose execution
75  /// may modify the program state; that is, every operation and block.
76  LogicalResult initialize(Operation *top) override;
77 
78  /// Visit a program point that modifies the state of the program. If this is a
79  /// block, then the state is propagated from control-flow predecessors or
80  /// callsites. If this is a call operation or region control-flow operation,
81  /// then the state after the execution of the operation is set by control-flow
82  /// or the callgraph. Otherwise, this function invokes the operation transfer
83  /// function.
84  LogicalResult visit(ProgramPoint point) override;
85 
86 protected:
87  /// Propagate the dense lattice before the execution of an operation to the
88  /// lattice after its execution.
89  virtual void visitOperationImpl(Operation *op,
90  const AbstractDenseLattice &before,
91  AbstractDenseLattice *after) = 0;
92 
93  /// Get the dense lattice after the execution of the given program point.
95 
96  /// Get the dense lattice after the execution of the given program point and
97  /// add it as a dependency to a program point. That is, every time the lattice
98  /// after point is updated, the dependent program point must be visited, and
99  /// the newly triggered visit might update the lattice after dependent.
101  ProgramPoint point);
102 
103  /// Set the dense lattice at control flow entry point and propagate an update
104  /// if it changed.
105  virtual void setToEntryState(AbstractDenseLattice *lattice) = 0;
106 
107  /// Join a lattice with another and propagate an update if it changed.
109  propagateIfChanged(lhs, lhs->join(rhs));
110  }
111 
112  /// Visit an operation. If this is a call operation or region control-flow
113  /// operation, then the state after the execution of the operation is set by
114  /// control-flow or the callgraph. Otherwise, this function invokes the
115  /// operation transfer function.
116  virtual void processOperation(Operation *op);
117 
118  /// Propagate the dense lattice forward along the control flow edge from
119  /// `regionFrom` to `regionTo` regions of the `branch` operation. `nullopt`
120  /// values correspond to control flow branches originating at or targeting the
121  /// `branch` operation itself. Default implementation just joins the states,
122  /// meaning that operations implementing `RegionBranchOpInterface` don't have
123  /// any effect on the lattice that isn't already expressed by the interface
124  /// itself.
126  RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
127  std::optional<unsigned> regionTo, const AbstractDenseLattice &before,
128  AbstractDenseLattice *after) {
129  join(after, before);
130  }
131 
132  /// Propagate the dense lattice forward along the call control flow edge,
133  /// which can be either entering or exiting the callee. Default implementation
134  /// just meets the states, meaning that operations implementing
135  /// `CallOpInterface` don't have any effect on the lattice that isn't already
136  /// expressed by the interface itself.
137  virtual void visitCallControlFlowTransfer(CallOpInterface call,
138  CallControlFlowAction action,
139  const AbstractDenseLattice &before,
140  AbstractDenseLattice *after) {
141  join(after, before);
142  }
143 
144  /// Visit a program point within a region branch operation with predecessors
145  /// in it. This can either be an entry block of one of the regions of the
146  /// parent operation itself.
148  RegionBranchOpInterface branch,
149  AbstractDenseLattice *after);
150 
151 private:
152  /// Visit a block. The state at the start of the block is propagated from
153  /// control-flow predecessors or callsites.
154  void visitBlock(Block *block);
155 
156  /// Visit an operation for which the data flow is described by the
157  /// `CallOpInterface`.
158  void visitCallOperation(CallOpInterface call, AbstractDenseLattice *after);
159 };
160 
161 //===----------------------------------------------------------------------===//
162 // DenseForwardDataFlowAnalysis
163 //===----------------------------------------------------------------------===//
164 
165 /// A dense forward data-flow analysis for propagating lattices before and
166 /// after the execution of every operation across the IR by implementing
167 /// transfer functions for operations.
168 ///
169 /// `LatticeT` is expected to be a subclass of `AbstractDenseLattice`.
170 template <typename LatticeT>
173  static_assert(
174  std::is_base_of<AbstractDenseLattice, LatticeT>::value,
175  "analysis state class expected to subclass AbstractDenseLattice");
176 
177 public:
178  using AbstractDenseForwardDataFlowAnalysis::
179  AbstractDenseForwardDataFlowAnalysis;
180 
181  /// Visit an operation with the dense lattice before its execution. This
182  /// function is expected to set the dense lattice after its execution and
183  /// trigger change propagation in case of change.
184  virtual void visitOperation(Operation *op, const LatticeT &before,
185  LatticeT *after) = 0;
186 
187  /// Hook for customizing the behavior of lattice propagation along the call
188  /// control flow edges. Two types of (forward) propagation are possible here:
189  /// - `action == CallControlFlowAction::Enter` indicates that:
190  /// - `before` is the state before the call operation;
191  /// - `after` is the state at the beginning of the callee entry block;
192  /// - `action == CallControlFlowAction::Exit` indicates that:
193  /// - `before` is the state at the end of a callee exit block;
194  /// - `after` is the state after the call operation.
195  /// By default, the `after` state is simply joined with the `before` state.
196  /// Concrete analyses can override this behavior or delegate to the parent
197  /// call for the default behavior. Specifically, if the `call` op may affect
198  /// the lattice prior to entering the callee, the custom behavior can be added
199  /// for `action == CallControlFlowAction::Enter`. If the `call` op may affect
200  /// the lattice post exiting the callee, the custom behavior can be added for
201  /// `action == CallControlFlowAction::Exit`.
202  virtual void visitCallControlFlowTransfer(CallOpInterface call,
203  CallControlFlowAction action,
204  const LatticeT &before,
205  LatticeT *after) {
207  call, action, before, after);
208  }
209 
210  /// Hook for customizing the behavior of lattice propagation along the control
211  /// flow edges between regions and their parent op. The control flows from
212  /// `regionFrom` to `regionTo`, both of which may be `nullopt` to indicate the
213  /// parent op. The lattice is propagated forward along this edge. The lattices
214  /// are as follows:
215  /// - `before:`
216  /// - if `regionFrom` is a region, this is the lattice at the end of the
217  /// block that exits the region; note that for multi-exit regions, the
218  /// lattices are equal at the end of all exiting blocks, but they are
219  /// associated with different program points.
220  /// - otherwise, this is the lattice before the parent op.
221  /// - `after`:
222  /// - if `regionTo` is a region, this is the lattice at the beginning of
223  /// the entry block of that region;
224  /// - otherwise, this is the lattice after the parent op.
225  /// By default, the `after` state is simply joined with the `before` state.
226  /// Concrete analyses can override this behavior or delegate to the parent
227  /// call for the default behavior. Specifically, if the `branch` op may affect
228  /// the lattice before entering any region, the custom behavior can be added
229  /// for `regionFrom == nullopt`. If the `branch` op may affect the lattice
230  /// after all terminated, the custom behavior can be added for `regionTo ==
231  /// nullptr`. The behavior can be further refined for specific pairs of "from"
232  /// and "to" regions.
234  RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
235  std::optional<unsigned> regionTo, const LatticeT &before,
236  LatticeT *after) {
238  branch, regionFrom, regionTo, before, after);
239  }
240 
241 protected:
242  /// Get the dense lattice after this program point.
243  LatticeT *getLattice(ProgramPoint point) override {
244  return getOrCreate<LatticeT>(point);
245  }
246 
247  /// Set the dense lattice at control flow entry point and propagate an update
248  /// if it changed.
249  virtual void setToEntryState(LatticeT *lattice) = 0;
250  void setToEntryState(AbstractDenseLattice *lattice) override {
251  setToEntryState(static_cast<LatticeT *>(lattice));
252  }
253 
254  /// Type-erased wrappers that convert the abstract dense lattice to a derived
255  /// lattice and invoke the virtual hooks operating on the derived lattice.
257  AbstractDenseLattice *after) final {
258  visitOperation(op, static_cast<const LatticeT &>(before),
259  static_cast<LatticeT *>(after));
260  }
261  void visitCallControlFlowTransfer(CallOpInterface call,
262  CallControlFlowAction action,
263  const AbstractDenseLattice &before,
264  AbstractDenseLattice *after) final {
265  visitCallControlFlowTransfer(call, action,
266  static_cast<const LatticeT &>(before),
267  static_cast<LatticeT *>(after));
268  }
269  void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch,
270  std::optional<unsigned> regionFrom,
271  std::optional<unsigned> regionTo,
272  const AbstractDenseLattice &before,
273  AbstractDenseLattice *after) final {
274  visitRegionBranchControlFlowTransfer(branch, regionFrom, regionTo,
275  static_cast<const LatticeT &>(before),
276  static_cast<LatticeT *>(after));
277  }
278 };
279 
280 //===----------------------------------------------------------------------===//
281 // AbstractDenseBackwardDataFlowAnalysis
282 //===----------------------------------------------------------------------===//
283 
284 /// Base class for dense backward dataflow analyses. Such analyses attach a
285 /// lattice between the execution of operations and implement a transfer
286 /// function from the lattice after the operation ot the lattice before it, thus
287 /// propagating backward.
288 ///
289 /// In this implementation, a lattice attached to an operation represents the
290 /// state of the program before its execution, and a lattice attached to a block
291 /// represents the state of the program before the end of the block, i.e., after
292 /// its terminator.
294 public:
295  /// Construct the analysis in the given solver. Takes a symbol table
296  /// collection that is used to cache symbol resolution in interprocedural part
297  /// of the analysis. The symbol table need not be prefilled.
299  SymbolTableCollection &symbolTable)
300  : DataFlowAnalysis(solver), symbolTable(symbolTable) {}
301 
302  /// Initialize the analysis by visiting every program point whose execution
303  /// may modify the program state; that is, every operation and block.
304  LogicalResult initialize(Operation *top) override;
305 
306  /// Visit a program point that modifies the state of the program. The state is
307  /// propagated along control flow directions for branch-, region- and
308  /// call-based control flow using the respective interfaces. For other
309  /// operations, the state is propagated using the transfer function
310  /// (visitOperation).
311  ///
312  /// Note: the transfer function is currently *not* invoked for operations with
313  /// region or call interface, but *is* invoked for block terminators.
314  LogicalResult visit(ProgramPoint point) override;
315 
316 protected:
317  /// Propagate the dense lattice after the execution of an operation to the
318  /// lattice before its execution.
319  virtual void visitOperationImpl(Operation *op,
320  const AbstractDenseLattice &after,
321  AbstractDenseLattice *before) = 0;
322 
323  /// Get the dense lattice before the execution of the program point. That is,
324  /// before the execution of the given operation or after the execution of the
325  /// block.
327 
328  /// Get the dense lattice before the execution of the program point `point`
329  /// and declare that the `dependent` program point must be updated every time
330  /// `point` is.
332  ProgramPoint point);
333 
334  /// Set the dense lattice before at the control flow exit point and propagate
335  /// the update if it changed.
336  virtual void setToExitState(AbstractDenseLattice *lattice) = 0;
337 
338  /// Meet a lattice with another lattice and propagate an update if it changed.
340  propagateIfChanged(lhs, lhs->meet(rhs));
341  }
342 
343  /// Visit an operation. Dispatches to specialized methods for call or region
344  /// control-flow operations. Otherwise, this function invokes the operation
345  /// transfer function.
346  virtual void processOperation(Operation *op);
347 
348  /// Propagate the dense lattice backwards along the control flow edge from
349  /// `regionFrom` to `regionTo` regions of the `branch` operation. `nullopt`
350  /// values correspond to control flow branches originating at or targeting the
351  /// `branch` operation itself. Default implementation just meets the states,
352  /// meaning that operations implementing `RegionBranchOpInterface` don't have
353  /// any effect on the lattice that isn't already expressed by the interface
354  /// itself.
356  RegionBranchOpInterface branch, RegionBranchPoint regionFrom,
357  RegionBranchPoint regionTo, const AbstractDenseLattice &after,
358  AbstractDenseLattice *before) {
359  meet(before, after);
360  }
361 
362  /// Propagate the dense lattice backwards along the call control flow edge,
363  /// which can be either entering or exiting the callee. Default implementation
364  /// just meets the states, meaning that operations implementing
365  /// `CallOpInterface` don't have any effect on hte lattice that isn't already
366  /// expressed by the interface itself.
367  virtual void visitCallControlFlowTransfer(CallOpInterface call,
368  CallControlFlowAction action,
369  const AbstractDenseLattice &after,
370  AbstractDenseLattice *before) {
371  meet(before, after);
372  }
373 
374 private:
375  /// Visit a block. The state and the end of the block is propagated from
376  /// control-flow successors of the block or callsites.
377  void visitBlock(Block *block);
378 
379  /// Visit a program point within a region branch operation with successors
380  /// (from which the state is propagated) in or after it. `regionNo` indicates
381  /// the region that contains the successor, `nullopt` indicating the successor
382  /// of the branch operation itself.
383  void visitRegionBranchOperation(ProgramPoint point,
384  RegionBranchOpInterface branch,
385  RegionBranchPoint branchPoint,
386  AbstractDenseLattice *before);
387 
388  /// Visit an operation for which the data flow is described by the
389  /// `CallOpInterface`. Performs inter-procedural data flow as follows:
390  ///
391  /// - find the callable (resolve via the symbol table),
392  /// - get the entry block of the callable region,
393  /// - take the state before the first operation if present or at block end
394  /// otherwise,
395  /// - meet that state with the state before the call-like op, or use the
396  /// custom logic if overridden by concrete analyses.
397  void visitCallOperation(CallOpInterface call, AbstractDenseLattice *before);
398 
399  /// Symbol table for call-level control flow.
400  SymbolTableCollection &symbolTable;
401 };
402 
403 //===----------------------------------------------------------------------===//
404 // DenseBackwardDataFlowAnalysis
405 //===----------------------------------------------------------------------===//
406 
407 /// A dense backward dataflow analysis propagating lattices after and before the
408 /// execution of every operation across the IR by implementing transfer
409 /// functions for opreations.
410 ///
411 /// `LatticeT` is expected to be a subclass of `AbstractDenseLattice`.
412 template <typename LatticeT>
415  static_assert(std::is_base_of_v<AbstractDenseLattice, LatticeT>,
416  "analysis state expected to subclass AbstractDenseLattice");
417 
418 public:
421 
422  /// Transfer function. Visits an operation with the dense lattice after its
423  /// execution. This function is expected to set the dense lattice before its
424  /// execution and trigger propagation in case of change.
425  virtual void visitOperation(Operation *op, const LatticeT &after,
426  LatticeT *before) = 0;
427 
428  /// Hook for customizing the behavior of lattice propagation along the call
429  /// control flow edges. Two types of (back) propagation are possible here:
430  /// - `action == CallControlFlowAction::Enter` indicates that:
431  /// - `after` is the state at the top of the callee entry block;
432  /// - `before` is the state before the call operation;
433  /// - `action == CallControlFlowAction::Exit` indicates that:
434  /// - `after` is the state after the call operation;
435  /// - `before` is the state of exit blocks of the callee.
436  /// By default, the `before` state is simply met with the `after` state.
437  /// Concrete analyses can override this behavior or delegate to the parent
438  /// call for the default behavior. Specifically, if the `call` op may affect
439  /// the lattice prior to entering the callee, the custom behavior can be added
440  /// for `action == CallControlFlowAction::Enter`. If the `call` op may affect
441  /// the lattice post exiting the callee, the custom behavior can be added for
442  /// `action == CallControlFlowAction::Exit`.
443  virtual void visitCallControlFlowTransfer(CallOpInterface call,
444  CallControlFlowAction action,
445  const LatticeT &after,
446  LatticeT *before) {
448  call, action, after, before);
449  }
450 
451  /// Hook for customizing the behavior of lattice propagation along the control
452  /// flow edges between regions and their parent op. The control flows from
453  /// `regionFrom` to `regionTo`, both of which may be `nullopt` to indicate the
454  /// parent op. The lattice is propagated back along this edge. The lattices
455  /// are as follows:
456  /// - `after`:
457  /// - if `regionTo` is a region, this is the lattice at the beginning of
458  /// the entry block of that region;
459  /// - otherwise, this is the lattice after the parent op.
460  /// - `before:`
461  /// - if `regionFrom` is a region, this is the lattice at the end of the
462  /// block that exits the region; note that for multi-exit regions, the
463  /// lattices are equal at the end of all exiting blocks, but they are
464  /// associated with different program points.
465  /// - otherwise, this is the lattice before the parent op.
466  /// By default, the `before` state is simply met with the `after` state.
467  /// Concrete analyses can override this behavior or delegate to the parent
468  /// call for the default behavior. Specifically, if the `branch` op may affect
469  /// the lattice before entering any region, the custom behavior can be added
470  /// for `regionFrom == nullopt`. If the `branch` op may affect the lattice
471  /// after all terminated, the custom behavior can be added for `regionTo ==
472  /// nullptr`. The behavior can be further refined for specific pairs of "from"
473  /// and "to" regions.
475  RegionBranchOpInterface branch, RegionBranchPoint regionFrom,
476  RegionBranchPoint regionTo, const LatticeT &after, LatticeT *before) {
478  branch, regionFrom, regionTo, after, before);
479  }
480 
481 protected:
482  /// Get the dense lattice at the given program point.
483  LatticeT *getLattice(ProgramPoint point) override {
484  return getOrCreate<LatticeT>(point);
485  }
486 
487  /// Set the dense lattice at control flow exit point (after the terminator)
488  /// and propagate an update if it changed.
489  virtual void setToExitState(LatticeT *lattice) = 0;
490  void setToExitState(AbstractDenseLattice *lattice) final {
491  setToExitState(static_cast<LatticeT *>(lattice));
492  }
493 
494  /// Type-erased wrappers that convert the abstract dense lattice to a derived
495  /// lattice and invoke the virtual hooks operating on the derived lattice.
497  AbstractDenseLattice *before) final {
498  visitOperation(op, static_cast<const LatticeT &>(after),
499  static_cast<LatticeT *>(before));
500  }
501  void visitCallControlFlowTransfer(CallOpInterface call,
502  CallControlFlowAction action,
503  const AbstractDenseLattice &after,
504  AbstractDenseLattice *before) final {
505  visitCallControlFlowTransfer(call, action,
506  static_cast<const LatticeT &>(after),
507  static_cast<LatticeT *>(before));
508  }
510  RegionBranchOpInterface branch, RegionBranchPoint regionForm,
511  RegionBranchPoint regionTo, const AbstractDenseLattice &after,
512  AbstractDenseLattice *before) final {
513  visitRegionBranchControlFlowTransfer(branch, regionForm, regionTo,
514  static_cast<const LatticeT &>(after),
515  static_cast<LatticeT *>(before));
516  }
517 };
518 
519 } // end namespace dataflow
520 } // end namespace mlir
521 
522 #endif // MLIR_ANALYSIS_DENSEDATAFLOWANALYSIS_H
Base class for generic analysis states.
AnalysisState(ProgramPoint point)
Create the analysis state at the given program point.
Block represents an ordered list of Operations.
Definition: Block.h:30
Base class for all data-flow analyses.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
DataFlowAnalysis(DataFlowSolver &solver)
Create an analysis with a reference to the parent solver.
The general data-flow analysis solver.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class represents a point being branched from in the methods of the RegionBranchOpInterface.
This class represents a collection of SymbolTables.
Definition: SymbolTable.h:283
Base class for dense backward dataflow analyses.
virtual void setToExitState(AbstractDenseLattice *lattice)=0
Set the dense lattice before at the control flow exit point and propagate the update if it changed.
LogicalResult initialize(Operation *top) override
Initialize the analysis by visiting every program point whose execution may modify the program state;...
virtual void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &after, AbstractDenseLattice *before)
Propagate the dense lattice backwards along the call control flow edge, which can be either entering ...
LogicalResult visit(ProgramPoint point) override
Visit a program point that modifies the state of the program.
virtual void visitOperationImpl(Operation *op, const AbstractDenseLattice &after, AbstractDenseLattice *before)=0
Propagate the dense lattice after the execution of an operation to the lattice before its execution.
void meet(AbstractDenseLattice *lhs, const AbstractDenseLattice &rhs)
Meet a lattice with another lattice and propagate an update if it changed.
virtual void processOperation(Operation *op)
Visit an operation.
const AbstractDenseLattice * getLatticeFor(ProgramPoint dependent, ProgramPoint point)
Get the dense lattice before the execution of the program point point and declare that the dependent ...
virtual AbstractDenseLattice * getLattice(ProgramPoint point)=0
Get the dense lattice before the execution of the program point.
AbstractDenseBackwardDataFlowAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable)
Construct the analysis in the given solver.
virtual void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, RegionBranchPoint regionFrom, RegionBranchPoint regionTo, const AbstractDenseLattice &after, AbstractDenseLattice *before)
Propagate the dense lattice backwards along the control flow edge from regionFrom to regionTo regions...
Base class for dense forward data-flow analyses.
Definition: DenseAnalysis.h:70
const AbstractDenseLattice * getLatticeFor(ProgramPoint dependent, ProgramPoint point)
Get the dense lattice after the execution of the given program point and add it as a dependency to a ...
virtual AbstractDenseLattice * getLattice(ProgramPoint point)=0
Get the dense lattice after the execution of the given program point.
void join(AbstractDenseLattice *lhs, const AbstractDenseLattice &rhs)
Join a lattice with another and propagate an update if it changed.
void visitRegionBranchOperation(ProgramPoint point, RegionBranchOpInterface branch, AbstractDenseLattice *after)
Visit a program point within a region branch operation with predecessors in it.
virtual void setToEntryState(AbstractDenseLattice *lattice)=0
Set the dense lattice at control flow entry point and propagate an update if it changed.
LogicalResult initialize(Operation *top) override
Initialize the analysis by visiting every program point whose execution may modify the program state;...
virtual void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
LogicalResult visit(ProgramPoint point) override
Visit a program point that modifies the state of the program.
virtual void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the control flow edge from regionFrom to regionTo regions o...
virtual void processOperation(Operation *op)
Visit an operation.
virtual void visitOperationImpl(Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after)=0
Propagate the dense lattice before the execution of an operation to the lattice after its execution.
This class represents a dense lattice.
Definition: DenseAnalysis.h:41
virtual ChangeResult join(const AbstractDenseLattice &rhs)
Join the lattice across control-flow or callgraph edges.
Definition: DenseAnalysis.h:47
virtual ChangeResult meet(const AbstractDenseLattice &rhs)
Definition: DenseAnalysis.h:51
A dense backward dataflow analysis propagating lattices after and before the execution of every opera...
void visitOperationImpl(Operation *op, const AbstractDenseLattice &after, AbstractDenseLattice *before) final
Type-erased wrappers that convert the abstract dense lattice to a derived lattice and invoke the virt...
void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, RegionBranchPoint regionForm, RegionBranchPoint regionTo, const AbstractDenseLattice &after, AbstractDenseLattice *before) final
Propagate the dense lattice backwards along the control flow edge from regionFrom to regionTo regions...
virtual void setToExitState(LatticeT *lattice)=0
Set the dense lattice at control flow exit point (after the terminator) and propagate an update if it...
LatticeT * getLattice(ProgramPoint point) override
Get the dense lattice at the given program point.
virtual void visitOperation(Operation *op, const LatticeT &after, LatticeT *before)=0
Transfer function.
virtual void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const LatticeT &after, LatticeT *before)
Hook for customizing the behavior of lattice propagation along the call control flow edges.
void setToExitState(AbstractDenseLattice *lattice) final
Set the dense lattice before at the control flow exit point and propagate the update if it changed.
void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &after, AbstractDenseLattice *before) final
Propagate the dense lattice backwards along the call control flow edge, which can be either entering ...
virtual void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, RegionBranchPoint regionFrom, RegionBranchPoint regionTo, const LatticeT &after, LatticeT *before)
Hook for customizing the behavior of lattice propagation along the control flow edges between regions...
A dense forward data-flow analysis for propagating lattices before and after the execution of every o...
LatticeT * getLattice(ProgramPoint point) override
Get the dense lattice after this program point.
virtual void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const LatticeT &before, LatticeT *after)
Hook for customizing the behavior of lattice propagation along the call control flow edges.
void setToEntryState(AbstractDenseLattice *lattice) override
Set the dense lattice at control flow entry point and propagate an update if it changed.
virtual void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const LatticeT &before, LatticeT *after)
Hook for customizing the behavior of lattice propagation along the control flow edges between regions...
virtual void visitOperation(Operation *op, const LatticeT &before, LatticeT *after)=0
Visit an operation with the dense lattice before its execution.
virtual void setToEntryState(LatticeT *lattice)=0
Set the dense lattice at control flow entry point and propagate an update if it changed.
void visitOperationImpl(Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Type-erased wrappers that convert the abstract dense lattice to a derived lattice and invoke the virt...
void visitRegionBranchControlFlowTransfer(RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Propagate the dense lattice forward along the control flow edge from regionFrom to regionTo regions o...
void visitCallControlFlowTransfer(CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
CallControlFlowAction
Indicates whether the control enters or exits the callee.
Definition: DenseAnalysis.h:31
Include the generated interface declarations.
ChangeResult
A result type used to indicate if a change happened.
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
Fundamental IR components are supported as first-class program points.