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