MLIR 23.0.0git
SparseAnalysis.h
Go to the documentation of this file.
1//===- SparseAnalysis.h - Sparse 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 sparse 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_DATAFLOW_SPARSEANALYSIS_H
16#define MLIR_ANALYSIS_DATAFLOW_SPARSEANALYSIS_H
17
19#include "mlir/IR/SymbolTable.h"
22#include "llvm/ADT/SmallPtrSet.h"
23
24namespace mlir {
25namespace dataflow {
26
27//===----------------------------------------------------------------------===//
28// AbstractSparseLattice
29//===----------------------------------------------------------------------===//
30
31/// This class represents an abstract lattice. A lattice contains information
32/// about an SSA value and is what's propagated across the IR by sparse
33/// data-flow analysis.
35public:
36 /// Lattices can only be created for values.
38
39 /// Return the value this lattice is located at.
40 Value getAnchor() const { return cast<Value>(AnalysisState::getAnchor()); }
41
42 /// Join the information contained in 'rhs' into this lattice. Returns
43 /// if the value of the lattice changed.
47
48 /// Meet (intersect) the information in this lattice with 'rhs'. Returns
49 /// if the value of the lattice changed.
53
54 /// When the lattice gets updated, propagate an update to users of the value
55 /// using its use-def chain to subscribed analyses.
56 void onUpdate(DataFlowSolver *solver) const override;
57
58 /// Subscribe an analysis to updates of the lattice. When the lattice changes,
59 /// subscribed analyses are re-invoked on all users of the value. This is
60 /// more efficient than relying on the dependency map.
62 useDefSubscribers.insert(analysis);
63 }
64
65private:
66 /// A set of analyses that should be updated when this lattice changes.
69 useDefSubscribers;
70};
71
72//===----------------------------------------------------------------------===//
73// Lattice
74//===----------------------------------------------------------------------===//
75
76/// This class represents a lattice holding a specific value of type `ValueT`.
77/// Lattice values (`ValueT`) are required to adhere to the following:
78///
79/// * static ValueT join(const ValueT &lhs, const ValueT &rhs);
80/// - This method conservatively joins the information held by `lhs`
81/// and `rhs` into a new value. This method is required to be monotonic.
82/// * bool operator==(const ValueT &rhs) const;
83///
84template <typename ValueT>
86public:
88
89 /// Return the value this lattice is located at.
90 Value getAnchor() const { return cast<Value>(anchor); }
91
92 /// Return the value held by this lattice. This requires that the value is
93 /// initialized.
94 ValueT &getValue() { return value; }
95 const ValueT &getValue() const {
96 return const_cast<Lattice<ValueT> *>(this)->getValue();
97 }
98
100
101 /// Join the information contained in the 'rhs' lattice into this
102 /// lattice. Returns if the state of the current lattice changed.
104 return join(static_cast<const LatticeT &>(rhs).getValue());
105 }
106
107 /// Meet (intersect) the information contained in the 'rhs' lattice with
108 /// this lattice. Returns if the state of the current lattice changed.
110 return meet(static_cast<const LatticeT &>(rhs).getValue());
111 }
112
113 /// Join the information contained in the 'rhs' value into this
114 /// lattice. Returns if the state of the current lattice changed.
115 ChangeResult join(const ValueT &rhs) {
116 // Otherwise, join rhs with the current optimistic value.
117 ValueT newValue = ValueT::join(value, rhs);
118 assert(ValueT::join(newValue, value) == newValue &&
119 "expected `join` to be monotonic");
120 assert(ValueT::join(newValue, rhs) == newValue &&
121 "expected `join` to be monotonic");
122
123 // Update the current optimistic value if something changed.
124 if (newValue == value)
126
127 value = newValue;
129 }
130
131 /// Trait to check if `T` provides a `meet` method. Needed since for forward
132 /// analysis, lattices will only have a `join`, no `meet`, but we want to use
133 /// the same `Lattice` class for both directions.
134 template <typename T, typename... Args>
135 using has_meet = decltype(&T::meet);
136 template <typename T>
137 using lattice_has_meet = llvm::is_detected<has_meet, T>;
138
139 /// Meet (intersect) the information contained in the 'rhs' value with this
140 /// lattice. Returns if the state of the current lattice changed. If the
141 /// lattice elements don't have a `meet` method, this is a no-op.
142 template <typename VT>
143 ChangeResult meet(const VT &rhs) {
144 if constexpr (!lattice_has_meet<VT>::value) {
146 } else {
147 ValueT newValue = ValueT::meet(value, rhs);
148 assert(ValueT::meet(newValue, value) == newValue &&
149 "expected `meet` to be monotonic");
150 assert(ValueT::meet(newValue, rhs) == newValue &&
151 "expected `meet` to be monotonic");
152
153 // Update the current optimistic value if something changed.
154 if (newValue == value)
156
157 value = newValue;
159 }
160 }
161
162 /// Print the lattice element.
163 void print(raw_ostream &os) const override { value.print(os); }
164
165private:
166 /// The currently computed value that is optimistically assumed to be true.
167 ValueT value;
168};
169
170//===----------------------------------------------------------------------===//
171// AbstractSparseForwardDataFlowAnalysis
172//===----------------------------------------------------------------------===//
173
174/// Base class for sparse forward data-flow analyses. A sparse analysis
175/// implements a transfer function on operations from the lattices of the
176/// operands to the lattices of the results. This analysis will propagate
177/// lattices across control-flow edges and the callgraph using liveness
178/// information.
179///
180/// Visit a program point in sparse forward data-flow analysis will invoke the
181/// transfer function of the operation preceding the program point iterator.
182/// Visit a program point at the begining of block will visit the block itself.
184public:
185 /// Initialize the analysis by visiting every owner of an SSA value: all
186 /// operations and blocks.
187 LogicalResult initialize(Operation *top) override;
188
189 /// Visit a program point. If this is at beginning of block and all
190 /// control-flow predecessors or callsites are known, then the arguments
191 /// lattices are propagated from them. If this is after call operation or an
192 /// operation with region control-flow, then its result lattices are set
193 /// accordingly. Otherwise, the operation transfer function is invoked.
194 LogicalResult visit(ProgramPoint *point) override;
195
196protected:
198
199 /// The operation transfer function. Given the operand lattices, this
200 /// function is expected to set the result lattices.
201 virtual LogicalResult
204 ArrayRef<AbstractSparseLattice *> resultLattices) = 0;
205
206 /// The transfer function for calls to external functions.
208 CallOpInterface call,
210 ArrayRef<AbstractSparseLattice *> resultLattices) = 0;
211
212 /// Given an operation with region control-flow, the lattices of the operands,
213 /// and a region successor, compute the lattice values for block arguments
214 /// that are not accounted for by the branching control flow (ex. the bounds
215 /// of loops).
217 Operation *op, const RegionSuccessor &successor,
218 ValueRange successorInputs, ArrayRef<AbstractSparseLattice *> argLattices,
219 unsigned firstIndex) = 0;
220
221 /// Get the lattice element of a value.
223
224 /// Get a read-only lattice element for a value and add it as a dependency to
225 /// a program point.
227 Value value);
228
229 /// Set the given lattice element(s) at control flow entry point(s).
230 virtual void setToEntryState(AbstractSparseLattice *lattice) = 0;
232
233 /// Join the lattice element and propagate and update if it changed.
235
236 /// Visits a call operation. Given the operand lattices, sets the result
237 /// lattices. Performs interprocedural data flow as follows: if the call
238 /// operation targets an external function, or if the solver is not
239 /// interprocedural, attempts to infer the results from the call arguments
240 /// using the user-provided `visitExternalCallImpl`. Otherwise, computes the
241 /// result lattices from the return sites if all return sites are known;
242 /// otherwise, conservatively marks the result lattices as having reached
243 /// their pessimistic fixpoints.
244 /// This method can be overridden to, for example, be less conservative and
245 /// propagate the information even if some return sites are unknown.
246 virtual LogicalResult
247 visitCallOperation(CallOpInterface call,
249 ArrayRef<AbstractSparseLattice *> resultLattices);
250
251 /// Visits a callable operation. Computes the argument lattices from call
252 /// sites if all call sites are known; otherwise, conservatively marks them
253 /// as having reached their pessimistic fixpoints.
254 /// This method can be overridden to, for example, be less conservative and
255 /// propagate the information even if some call sites are unknown.
256 virtual void
257 visitCallableOperation(CallableOpInterface callable,
259
260private:
261 /// Recursively initialize the analysis on nested operations and blocks.
262 LogicalResult initializeRecursively(Operation *op);
263
264 /// Visit an operation. If this is a call operation or an operation with
265 /// region control-flow, then its result lattices are set accordingly.
266 /// Otherwise, the operation transfer function is invoked.
267 LogicalResult visitOperation(Operation *op);
268
269 /// Visit a block to compute the lattice values of its arguments. If this is
270 /// an entry block, then the argument values are determined from the block's
271 /// "predecessors" as set by `PredecessorState`. The predecessors can be
272 /// region terminators or callable callsites. Otherwise, the values are
273 /// determined from block predecessors.
274 void visitBlock(Block *block);
275
276 /// Visit a program point `point` with predecessors within a region branch
277 /// operation `branch`, which can either be the entry block of one of the
278 /// regions or the parent operation itself, and set either the argument or
279 /// parent result lattices.
280 /// This method can be overridden to control precisely how the region
281 /// successors of `branch` are visited. For example in order to precisely
282 /// control the order in which predecessor operand lattices are propagated
283 /// from. An override is responsible for visiting all the known predecessors
284 /// and propagating therefrom.
285 virtual void
286 visitRegionSuccessors(ProgramPoint *point, RegionBranchOpInterface branch,
287 RegionSuccessor successor,
289};
290
291//===----------------------------------------------------------------------===//
292// SparseForwardDataFlowAnalysis
293//===----------------------------------------------------------------------===//
294
295/// A sparse forward data-flow analysis for propagating SSA value lattices
296/// across the IR by implementing transfer functions for operations.
297///
298/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
299template <typename StateT>
302 static_assert(
303 std::is_base_of<AbstractSparseLattice, StateT>::value,
304 "analysis state class expected to subclass AbstractSparseLattice");
305
306public:
309
310 /// Visit an operation with the lattices of its operands. This function is
311 /// expected to set the lattices of the operation's results.
312 virtual LogicalResult visitOperation(Operation *op,
314 ArrayRef<StateT *> results) = 0;
315
316 /// Visit a call operation to an externally defined function given the
317 /// lattices of its arguments.
318 virtual void visitExternalCall(CallOpInterface call,
319 ArrayRef<const StateT *> argumentLattices,
320 ArrayRef<StateT *> resultLattices) {
321 setAllToEntryStates(resultLattices);
322 }
323
324 /// Given an operation with possible region control-flow, the lattices of the
325 /// operands, and a region successor, compute the lattice values for block
326 /// arguments that are not accounted for by the branching control flow (ex.
327 /// the bounds of loops). By default, this method marks all such lattice
328 /// elements as having reached a pessimistic fixpoint. `firstIndex` is the
329 /// index of the first element of `argLattices` that is set by control-flow.
331 const RegionSuccessor &successor,
332 ValueRange successorInputs,
333 ArrayRef<StateT *> argLattices,
334 unsigned firstIndex) {
335 setAllToEntryStates(argLattices.take_front(firstIndex));
337 argLattices.drop_front(firstIndex + successorInputs.size()));
338 }
339
340protected:
341 /// Get the lattice element for a value.
342 StateT *getLatticeElement(Value value) override {
343 return getOrCreate<StateT>(value);
344 }
345
346 /// Get the lattice element for a value and create a dependency on the
347 /// provided program point.
348 const StateT *getLatticeElementFor(ProgramPoint *point, Value value) {
349 return static_cast<const StateT *>(
351 value));
352 }
353
354 /// Set the given lattice element(s) at control flow entry point(s).
355 virtual void setToEntryState(StateT *lattice) = 0;
358 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
359 lattices.size()});
360 }
361
362private:
363 /// Type-erased wrappers that convert the abstract lattice operands to derived
364 /// lattices and invoke the virtual hooks operating on the derived lattices.
365 LogicalResult visitOperationImpl(
367 ArrayRef<AbstractSparseLattice *> resultLattices) override {
368 return visitOperation(
369 op,
370 {reinterpret_cast<const StateT *const *>(operandLattices.begin()),
371 operandLattices.size()},
372 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
373 resultLattices.size()});
374 }
375 void visitExternalCallImpl(
376 CallOpInterface call,
377 ArrayRef<const AbstractSparseLattice *> argumentLattices,
378 ArrayRef<AbstractSparseLattice *> resultLattices) override {
380 call,
381 {reinterpret_cast<const StateT *const *>(argumentLattices.begin()),
382 argumentLattices.size()},
383 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
384 resultLattices.size()});
385 }
386 void visitNonControlFlowArgumentsImpl(
387 Operation *op, const RegionSuccessor &successor,
388 ValueRange successorInputs, ArrayRef<AbstractSparseLattice *> argLattices,
389 unsigned firstIndex) override {
391 op, successor, successorInputs,
392 {reinterpret_cast<StateT *const *>(argLattices.begin()),
393 argLattices.size()},
394 firstIndex);
395 }
396 void setToEntryState(AbstractSparseLattice *lattice) override {
397 return setToEntryState(reinterpret_cast<StateT *>(lattice));
398 }
399};
400
401//===----------------------------------------------------------------------===//
402// AbstractSparseBackwardDataFlowAnalysis
403//===----------------------------------------------------------------------===//
404
405/// Base class for sparse backward data-flow analyses. Similar to
406/// AbstractSparseForwardDataFlowAnalysis, but walks bottom to top.
408public:
409 /// Initialize the analysis by visiting the operation and everything nested
410 /// under it.
411 LogicalResult initialize(Operation *top) override;
412
413 /// Visit a program point. If it is after call operation or an operation with
414 /// block or region control-flow, then operand lattices are set accordingly.
415 /// Otherwise, invokes the operation transfer function (`visitOperationImpl`).
416 LogicalResult visit(ProgramPoint *point) override;
417
418protected:
420 DataFlowSolver &solver, SymbolTableCollection &symbolTable);
421
422 /// The operation transfer function. Given the result lattices, this
423 /// function is expected to set the operand lattices.
424 virtual LogicalResult visitOperationImpl(
425 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
426 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
427
428 /// The transfer function for calls to external functions.
430 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
431 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
432
433 // Visit operands on branch instructions that are not forwarded.
434 virtual void visitBranchOperand(OpOperand &operand) = 0;
435
436 // Visit the non-forwarded arguments of a region, such as the
437 // induction variables of a loop.
438 virtual void
440 ArrayRef<BlockArgument> arguments) = 0;
441
442 // Visit operands on call instructions that are not forwarded.
443 virtual void visitCallOperand(OpOperand &operand) = 0;
444
445 /// Set the given lattice element(s) at control flow exit point(s) and
446 /// propagate the update if it chaned.
447 virtual void setToExitState(AbstractSparseLattice *lattice) = 0;
448
449 /// Set the given lattice element(s) at control flow exit point(s) and
450 /// propagate the update if it chaned.
452
453 /// Get the lattice element for a value.
455
456 /// Get the lattice elements for a range of values.
458
459 /// Join the lattice element and propagate and update if it changed.
461
462 /// Visits a callable operation. If all the call sites are known computes the
463 /// operand lattices of `op` from the result lattices of all the call sites;
464 /// otherwise, conservatively marks them as having reached their pessimistic
465 /// fixpoints.
466 /// This method can be overridden to, for example, be less conservative and
467 /// propagate the information even if some call sites are unknown.
468 virtual LogicalResult
469 visitCallableOperation(Operation *op, CallableOpInterface callable,
470 ArrayRef<AbstractSparseLattice *> operandLattices);
471
472private:
473 /// Recursively initialize the analysis on nested operations and blocks.
474 LogicalResult initializeRecursively(Operation *op);
475
476 /// Visit an operation. If this is a call operation or an operation with
477 /// region control-flow, then its operand lattices are set accordingly.
478 /// Otherwise, the operation transfer function is invoked.
479 LogicalResult visitOperation(Operation *op);
480
481 /// Visit a block.
482 void visitBlock(Block *block);
483
484 /// Visit an op with regions (like e.g. `scf.while`)
485 void visitRegionSuccessors(RegionBranchOpInterface branch,
487
488 /// Visit a `RegionBranchTerminatorOpInterface` to compute the lattice values
489 /// of its operands, given its parent op `branch`. The lattice value of an
490 /// operand is determined based on the corresponding arguments in
491 /// `terminator`'s region successor(s).
492 void visitRegionSuccessorsFromTerminator(
493 RegionBranchTerminatorOpInterface terminator,
494 RegionBranchOpInterface branch);
495
496 /// Get the lattice element for a value, and also set up
497 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
498 /// if the value changes.
499 const AbstractSparseLattice *getLatticeElementFor(ProgramPoint *point,
500 Value value);
501
502 /// Get the lattice elements for a range of values, and also set up
503 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
504 /// if any of the values change.
506 getLatticeElementsFor(ProgramPoint *point, ValueRange values);
507
508 SymbolTableCollection &symbolTable;
509};
510
511//===----------------------------------------------------------------------===//
512// SparseBackwardDataFlowAnalysis
513//===----------------------------------------------------------------------===//
514
515/// A sparse (backward) data-flow analysis for propagating SSA value lattices
516/// backwards across the IR by implementing transfer functions for operations.
517///
518/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
519///
520/// Visit a program point in sparse backward data-flow analysis will invoke the
521/// transfer function of the operation preceding the program point iterator.
522/// Visit a program point at the begining of block will visit the block itself.
523template <typename StateT>
526 static_assert(
527 std::is_base_of<AbstractSparseLattice, StateT>::value,
528 "analysis state class expected to subclass AbstractSparseLattice");
529
530public:
534
535 /// Visit an operation with the lattices of its results. This function is
536 /// expected to set the lattices of the operation's operands.
537 virtual LogicalResult visitOperation(Operation *op,
538 ArrayRef<StateT *> operands,
539 ArrayRef<const StateT *> results) = 0;
540
541 /// Visit a call to an external function. This function is expected to set
542 /// lattice values of the call operands. By default, calls `visitCallOperand`
543 /// for all operands.
544 virtual void visitExternalCall(CallOpInterface call,
545 ArrayRef<StateT *> argumentLattices,
546 ArrayRef<const StateT *> resultLattices) {
547 (void)argumentLattices;
548 (void)resultLattices;
549 for (OpOperand &operand : call->getOpOperands()) {
550 visitCallOperand(operand);
551 }
552 };
553
554protected:
555 /// Get the lattice element for a value.
556 StateT *getLatticeElement(Value value) override {
557 return getOrCreate<StateT>(value);
558 }
559
560 /// Set the given lattice element(s) at control flow exit point(s).
561 virtual void setToExitState(StateT *lattice) = 0;
562 void setToExitState(AbstractSparseLattice *lattice) override {
563 return setToExitState(reinterpret_cast<StateT *>(lattice));
564 }
567 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
568 lattices.size()});
569 }
570
571private:
572 /// Type-erased wrappers that convert the abstract lattice operands to derived
573 /// lattices and invoke the virtual hooks operating on the derived lattices.
574 LogicalResult visitOperationImpl(
575 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
576 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
577 return visitOperation(
578 op,
579 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
580 operandLattices.size()},
581 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
582 resultLattices.size()});
583 }
584
585 void visitExternalCallImpl(
586 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
587 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
589 call,
590 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
591 operandLattices.size()},
592 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
593 resultLattices.size()});
594 }
595};
596
597} // end namespace dataflow
598} // end namespace mlir
599
600#endif // MLIR_ANALYSIS_DATAFLOW_SPARSEANALYSIS_H
lhs
LatticeAnchor getAnchor() const
Returns the lattice anchor this state is located at.
AnalysisState(LatticeAnchor anchor)
Create the analysis state on the given lattice anchor.
LatticeAnchor anchor
The lattice anchor to which the state belongs.
Block represents an ordered list of Operations.
Definition Block.h:33
Base class for all data-flow analyses.
StateT * getOrCreate(AnchorT anchor)
Get the analysis state associated with the lattice anchor.
DataFlowAnalysis(DataFlowSolver &solver)
Create an analysis with a reference to the parent solver.
friend class DataFlowSolver
Allow the data-flow solver to access the internals of this class.
The general data-flow analysis solver.
This class represents an operand of an operation.
Definition Value.h:257
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class represents a successor of a region.
This class represents a collection of SymbolTables.
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
virtual void setToExitState(AbstractSparseLattice *lattice)=0
Set the given lattice element(s) at control flow exit point(s) and propagate the update if it chaned.
SmallVector< AbstractSparseLattice * > getLatticeElements(ValueRange values)
Get the lattice elements for a range of values.
AbstractSparseBackwardDataFlowAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable)
virtual AbstractSparseLattice * getLatticeElement(Value value)=0
Get the lattice element for a value.
virtual void visitBranchOperand(OpOperand &operand)=0
virtual void visitCallOperand(OpOperand &operand)=0
virtual void visitNonControlFlowArguments(RegionSuccessor &successor, ArrayRef< BlockArgument > arguments)=0
LogicalResult visit(ProgramPoint *point) override
Visit a program point.
void meet(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs)
Join the lattice element and propagate and update if it changed.
virtual LogicalResult visitCallableOperation(Operation *op, CallableOpInterface callable, ArrayRef< AbstractSparseLattice * > operandLattices)
Visits a callable operation.
virtual void visitExternalCallImpl(CallOpInterface call, ArrayRef< AbstractSparseLattice * > operandLattices, ArrayRef< const AbstractSparseLattice * > resultLattices)=0
The transfer function for calls to external functions.
LogicalResult initialize(Operation *top) override
Initialize the analysis by visiting the operation and everything nested under it.
void setAllToExitStates(ArrayRef< AbstractSparseLattice * > lattices)
Set the given lattice element(s) at control flow exit point(s) and propagate the update if it chaned.
virtual LogicalResult visitOperationImpl(Operation *op, ArrayRef< AbstractSparseLattice * > operandLattices, ArrayRef< const AbstractSparseLattice * > resultLattices)=0
The operation transfer function.
LogicalResult visit(ProgramPoint *point) override
Visit a program point.
LogicalResult initialize(Operation *top) override
Initialize the analysis by visiting every owner of an SSA value: all operations and blocks.
virtual void visitExternalCallImpl(CallOpInterface call, ArrayRef< const AbstractSparseLattice * > argumentLattices, ArrayRef< AbstractSparseLattice * > resultLattices)=0
The transfer function for calls to external functions.
void setAllToEntryStates(ArrayRef< AbstractSparseLattice * > lattices)
virtual void setToEntryState(AbstractSparseLattice *lattice)=0
Set the given lattice element(s) at control flow entry point(s).
const AbstractSparseLattice * getLatticeElementFor(ProgramPoint *point, Value value)
Get a read-only lattice element for a value and add it as a dependency to a program point.
virtual LogicalResult visitCallOperation(CallOpInterface call, ArrayRef< const AbstractSparseLattice * > operandLattices, ArrayRef< AbstractSparseLattice * > resultLattices)
Visits a call operation.
virtual void visitCallableOperation(CallableOpInterface callable, ArrayRef< AbstractSparseLattice * > argLattices)
Visits a callable operation.
virtual AbstractSparseLattice * getLatticeElement(Value value)=0
Get the lattice element of a value.
virtual void visitNonControlFlowArgumentsImpl(Operation *op, const RegionSuccessor &successor, ValueRange successorInputs, ArrayRef< AbstractSparseLattice * > argLattices, unsigned firstIndex)=0
Given an operation with region control-flow, the lattices of the operands, and a region successor,...
virtual LogicalResult visitOperationImpl(Operation *op, ArrayRef< const AbstractSparseLattice * > operandLattices, ArrayRef< AbstractSparseLattice * > resultLattices)=0
The operation transfer function.
void join(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs)
Join the lattice element and propagate and update if it changed.
This class represents an abstract lattice.
void onUpdate(DataFlowSolver *solver) const override
When the lattice gets updated, propagate an update to users of the value using its use-def chain to s...
virtual ChangeResult join(const AbstractSparseLattice &rhs)
Join the information contained in 'rhs' into this lattice.
virtual ChangeResult meet(const AbstractSparseLattice &rhs)
Meet (intersect) the information in this lattice with 'rhs'.
Value getAnchor() const
Return the value this lattice is located at.
void useDefSubscribe(DataFlowAnalysis *analysis)
Subscribe an analysis to updates of the lattice.
AbstractSparseLattice(Value value)
Lattices can only be created for values.
This class represents a lattice holding a specific value of type ValueT.
ChangeResult join(const ValueT &rhs)
Join the information contained in the 'rhs' value into this lattice.
ValueT & getValue()
Return the value held by this lattice.
Value getAnchor() const
Return the value this lattice is located at.
void print(raw_ostream &os) const override
Print the lattice element.
decltype(&T::meet) has_meet
Trait to check if T provides a meet method.
llvm::is_detected< has_meet, T > lattice_has_meet
const ValueT & getValue() const
ChangeResult join(const AbstractSparseLattice &rhs) override
Join the information contained in the 'rhs' lattice into this lattice.
Lattice< ValueT > LatticeT
ChangeResult meet(const AbstractSparseLattice &rhs) override
Meet (intersect) the information contained in the 'rhs' lattice with this lattice.
AbstractSparseLattice(Value value)
Lattices can only be created for values.
ChangeResult meet(const VT &rhs)
Meet (intersect) the information contained in the 'rhs' value with this lattice.
void setAllToExitStates(ArrayRef< StateT * > lattices)
virtual void visitExternalCall(CallOpInterface call, ArrayRef< StateT * > argumentLattices, ArrayRef< const StateT * > resultLattices)
Visit a call to an external function.
void setToExitState(AbstractSparseLattice *lattice) override
Set the given lattice element(s) at control flow exit point(s) and propagate the update if it chaned.
SparseBackwardDataFlowAnalysis(DataFlowSolver &solver, SymbolTableCollection &symbolTable)
virtual void setToExitState(StateT *lattice)=0
Set the given lattice element(s) at control flow exit point(s).
virtual LogicalResult visitOperation(Operation *op, ArrayRef< StateT * > operands, ArrayRef< const StateT * > results)=0
Visit an operation with the lattices of its results.
StateT * getLatticeElement(Value value) override
Get the lattice element for a value.
virtual void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ValueRange successorInputs, ArrayRef< StateT * > argLattices, unsigned firstIndex)
Given an operation with possible region control-flow, the lattices of the operands,...
virtual LogicalResult visitOperation(Operation *op, ArrayRef< const StateT * > operands, ArrayRef< StateT * > results)=0
Visit an operation with the lattices of its operands.
StateT * getLatticeElement(Value value) override
Get the lattice element for a value.
virtual void visitExternalCall(CallOpInterface call, ArrayRef< const StateT * > argumentLattices, ArrayRef< StateT * > resultLattices)
Visit a call operation to an externally defined function given the lattices of its arguments.
virtual void setToEntryState(StateT *lattice)=0
Set the given lattice element(s) at control flow entry point(s).
void setAllToEntryStates(ArrayRef< StateT * > lattices)
const StateT * getLatticeElementFor(ProgramPoint *point, Value value)
Get the lattice element for a value and create a dependency on the provided program point.
SparseForwardDataFlowAnalysis(DataFlowSolver &solver)
Include the generated interface declarations.
ChangeResult
A result type used to indicate if a change happened.
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:131
Program point represents a specific location in the execution of a program.