MLIR 22.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 ArrayRef<AbstractSparseLattice *> argLattices, unsigned firstIndex) = 0;
219
220 /// Get the lattice element of a value.
222
223 /// Get a read-only lattice element for a value and add it as a dependency to
224 /// a program point.
226 Value value);
227
228 /// Set the given lattice element(s) at control flow entry point(s).
229 virtual void setToEntryState(AbstractSparseLattice *lattice) = 0;
231
232 /// Join the lattice element and propagate and update if it changed.
234
235 /// Visits a call operation. Given the operand lattices, sets the result
236 /// lattices. Performs interprocedural data flow as follows: if the call
237 /// operation targets an external function, or if the solver is not
238 /// interprocedural, attempts to infer the results from the call arguments
239 /// using the user-provided `visitExternalCallImpl`. Otherwise, computes the
240 /// result lattices from the return sites if all return sites are known;
241 /// otherwise, conservatively marks the result lattices as having reached
242 /// their pessimistic fixpoints.
243 /// This method can be overridden to, for example, be less conservative and
244 /// propagate the information even if some return sites are unknown.
245 virtual LogicalResult
246 visitCallOperation(CallOpInterface call,
248 ArrayRef<AbstractSparseLattice *> resultLattices);
249
250 /// Visits a callable operation. Computes the argument lattices from call
251 /// sites if all call sites are known; otherwise, conservatively marks them
252 /// as having reached their pessimistic fixpoints.
253 /// This method can be overridden to, for example, be less conservative and
254 /// propagate the information even if some call sites are unknown.
255 virtual void
256 visitCallableOperation(CallableOpInterface callable,
258
259private:
260 /// Recursively initialize the analysis on nested operations and blocks.
261 LogicalResult initializeRecursively(Operation *op);
262
263 /// Visit an operation. If this is a call operation or an operation with
264 /// region control-flow, then its result lattices are set accordingly.
265 /// Otherwise, the operation transfer function is invoked.
266 LogicalResult visitOperation(Operation *op);
267
268 /// Visit a block to compute the lattice values of its arguments. If this is
269 /// an entry block, then the argument values are determined from the block's
270 /// "predecessors" as set by `PredecessorState`. The predecessors can be
271 /// region terminators or callable callsites. Otherwise, the values are
272 /// determined from block predecessors.
273 void visitBlock(Block *block);
274
275 /// Visit a program point `point` with predecessors within a region branch
276 /// operation `branch`, which can either be the entry block of one of the
277 /// regions or the parent operation itself, and set either the argument or
278 /// parent result lattices.
279 /// This method can be overridden to control precisely how the region
280 /// successors of `branch` are visited. For example in order to precisely
281 /// control the order in which predecessor operand lattices are propagated
282 /// from. An override is responsible for visiting all the known predecessors
283 /// and propagating therefrom.
284 virtual void
285 visitRegionSuccessors(ProgramPoint *point, RegionBranchOpInterface branch,
286 RegionSuccessor successor,
288};
289
290//===----------------------------------------------------------------------===//
291// SparseForwardDataFlowAnalysis
292//===----------------------------------------------------------------------===//
293
294/// A sparse forward data-flow analysis for propagating SSA value lattices
295/// across the IR by implementing transfer functions for operations.
296///
297/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
298template <typename StateT>
301 static_assert(
302 std::is_base_of<AbstractSparseLattice, StateT>::value,
303 "analysis state class expected to subclass AbstractSparseLattice");
304
305public:
308
309 /// Visit an operation with the lattices of its operands. This function is
310 /// expected to set the lattices of the operation's results.
311 virtual LogicalResult visitOperation(Operation *op,
313 ArrayRef<StateT *> results) = 0;
314
315 /// Visit a call operation to an externally defined function given the
316 /// lattices of its arguments.
317 virtual void visitExternalCall(CallOpInterface call,
318 ArrayRef<const StateT *> argumentLattices,
319 ArrayRef<StateT *> resultLattices) {
320 setAllToEntryStates(resultLattices);
321 }
322
323 /// Given an operation with possible region control-flow, the lattices of the
324 /// operands, and a region successor, compute the lattice values for block
325 /// arguments that are not accounted for by the branching control flow (ex.
326 /// the bounds of loops). By default, this method marks all such lattice
327 /// elements as having reached a pessimistic fixpoint. `firstIndex` is the
328 /// index of the first element of `argLattices` that is set by control-flow.
330 const RegionSuccessor &successor,
331 ArrayRef<StateT *> argLattices,
332 unsigned firstIndex) {
333 setAllToEntryStates(argLattices.take_front(firstIndex));
334 setAllToEntryStates(argLattices.drop_front(
335 firstIndex + successor.getSuccessorInputs().size()));
336 }
337
338protected:
339 /// Get the lattice element for a value.
340 StateT *getLatticeElement(Value value) override {
341 return getOrCreate<StateT>(value);
342 }
343
344 /// Get the lattice element for a value and create a dependency on the
345 /// provided program point.
346 const StateT *getLatticeElementFor(ProgramPoint *point, Value value) {
347 return static_cast<const StateT *>(
349 value));
350 }
351
352 /// Set the given lattice element(s) at control flow entry point(s).
353 virtual void setToEntryState(StateT *lattice) = 0;
356 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
357 lattices.size()});
358 }
359
360private:
361 /// Type-erased wrappers that convert the abstract lattice operands to derived
362 /// lattices and invoke the virtual hooks operating on the derived lattices.
363 LogicalResult visitOperationImpl(
365 ArrayRef<AbstractSparseLattice *> resultLattices) override {
366 return visitOperation(
367 op,
368 {reinterpret_cast<const StateT *const *>(operandLattices.begin()),
369 operandLattices.size()},
370 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
371 resultLattices.size()});
372 }
373 void visitExternalCallImpl(
374 CallOpInterface call,
375 ArrayRef<const AbstractSparseLattice *> argumentLattices,
376 ArrayRef<AbstractSparseLattice *> resultLattices) override {
378 call,
379 {reinterpret_cast<const StateT *const *>(argumentLattices.begin()),
380 argumentLattices.size()},
381 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
382 resultLattices.size()});
383 }
384 void visitNonControlFlowArgumentsImpl(
385 Operation *op, const RegionSuccessor &successor,
386 ArrayRef<AbstractSparseLattice *> argLattices,
387 unsigned firstIndex) override {
389 op, successor,
390 {reinterpret_cast<StateT *const *>(argLattices.begin()),
391 argLattices.size()},
392 firstIndex);
393 }
394 void setToEntryState(AbstractSparseLattice *lattice) override {
395 return setToEntryState(reinterpret_cast<StateT *>(lattice));
396 }
397};
398
399//===----------------------------------------------------------------------===//
400// AbstractSparseBackwardDataFlowAnalysis
401//===----------------------------------------------------------------------===//
402
403/// Base class for sparse backward data-flow analyses. Similar to
404/// AbstractSparseForwardDataFlowAnalysis, but walks bottom to top.
406public:
407 /// Initialize the analysis by visiting the operation and everything nested
408 /// under it.
409 LogicalResult initialize(Operation *top) override;
410
411 /// Visit a program point. If it is after call operation or an operation with
412 /// block or region control-flow, then operand lattices are set accordingly.
413 /// Otherwise, invokes the operation transfer function (`visitOperationImpl`).
414 LogicalResult visit(ProgramPoint *point) override;
415
416protected:
418 DataFlowSolver &solver, SymbolTableCollection &symbolTable);
419
420 /// The operation transfer function. Given the result lattices, this
421 /// function is expected to set the operand lattices.
422 virtual LogicalResult visitOperationImpl(
423 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
424 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
425
426 /// The transfer function for calls to external functions.
428 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
429 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
430
431 // Visit operands on branch instructions that are not forwarded.
432 virtual void visitBranchOperand(OpOperand &operand) = 0;
433
434 // Visit operands on call instructions that are not forwarded.
435 virtual void visitCallOperand(OpOperand &operand) = 0;
436
437 /// Set the given lattice element(s) at control flow exit point(s) and
438 /// propagate the update if it chaned.
439 virtual void setToExitState(AbstractSparseLattice *lattice) = 0;
440
441 /// Set the given lattice element(s) at control flow exit point(s) and
442 /// propagate the update if it chaned.
444
445 /// Get the lattice element for a value.
447
448 /// Get the lattice elements for a range of values.
450
451 /// Join the lattice element and propagate and update if it changed.
453
454 /// Visits a callable operation. If all the call sites are known computes the
455 /// operand lattices of `op` from the result lattices of all the call sites;
456 /// otherwise, conservatively marks them as having reached their pessimistic
457 /// fixpoints.
458 /// This method can be overridden to, for example, be less conservative and
459 /// propagate the information even if some call sites are unknown.
460 virtual LogicalResult
461 visitCallableOperation(Operation *op, CallableOpInterface callable,
462 ArrayRef<AbstractSparseLattice *> operandLattices);
463
464private:
465 /// Recursively initialize the analysis on nested operations and blocks.
466 LogicalResult initializeRecursively(Operation *op);
467
468 /// Visit an operation. If this is a call operation or an operation with
469 /// region control-flow, then its operand lattices are set accordingly.
470 /// Otherwise, the operation transfer function is invoked.
471 LogicalResult visitOperation(Operation *op);
472
473 /// Visit a block.
474 void visitBlock(Block *block);
475
476 /// Visit an op with regions (like e.g. `scf.while`)
477 void visitRegionSuccessors(RegionBranchOpInterface branch,
479
480 /// Visit a `RegionBranchTerminatorOpInterface` to compute the lattice values
481 /// of its operands, given its parent op `branch`. The lattice value of an
482 /// operand is determined based on the corresponding arguments in
483 /// `terminator`'s region successor(s).
484 void visitRegionSuccessorsFromTerminator(
485 RegionBranchTerminatorOpInterface terminator,
486 RegionBranchOpInterface branch);
487
488 /// Get the lattice element for a value, and also set up
489 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
490 /// if the value changes.
491 const AbstractSparseLattice *getLatticeElementFor(ProgramPoint *point,
492 Value value);
493
494 /// Get the lattice elements for a range of values, and also set up
495 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
496 /// if any of the values change.
498 getLatticeElementsFor(ProgramPoint *point, ValueRange values);
499
500 SymbolTableCollection &symbolTable;
501};
502
503//===----------------------------------------------------------------------===//
504// SparseBackwardDataFlowAnalysis
505//===----------------------------------------------------------------------===//
506
507/// A sparse (backward) data-flow analysis for propagating SSA value lattices
508/// backwards across the IR by implementing transfer functions for operations.
509///
510/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
511///
512/// Visit a program point in sparse backward data-flow analysis will invoke the
513/// transfer function of the operation preceding the program point iterator.
514/// Visit a program point at the begining of block will visit the block itself.
515template <typename StateT>
518 static_assert(
519 std::is_base_of<AbstractSparseLattice, StateT>::value,
520 "analysis state class expected to subclass AbstractSparseLattice");
521
522public:
526
527 /// Visit an operation with the lattices of its results. This function is
528 /// expected to set the lattices of the operation's operands.
529 virtual LogicalResult visitOperation(Operation *op,
530 ArrayRef<StateT *> operands,
531 ArrayRef<const StateT *> results) = 0;
532
533 /// Visit a call to an external function. This function is expected to set
534 /// lattice values of the call operands. By default, calls `visitCallOperand`
535 /// for all operands.
536 virtual void visitExternalCall(CallOpInterface call,
537 ArrayRef<StateT *> argumentLattices,
538 ArrayRef<const StateT *> resultLattices) {
539 (void)argumentLattices;
540 (void)resultLattices;
541 for (OpOperand &operand : call->getOpOperands()) {
542 visitCallOperand(operand);
543 }
544 };
545
546protected:
547 /// Get the lattice element for a value.
548 StateT *getLatticeElement(Value value) override {
549 return getOrCreate<StateT>(value);
550 }
551
552 /// Set the given lattice element(s) at control flow exit point(s).
553 virtual void setToExitState(StateT *lattice) = 0;
554 void setToExitState(AbstractSparseLattice *lattice) override {
555 return setToExitState(reinterpret_cast<StateT *>(lattice));
556 }
559 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
560 lattices.size()});
561 }
562
563private:
564 /// Type-erased wrappers that convert the abstract lattice operands to derived
565 /// lattices and invoke the virtual hooks operating on the derived lattices.
566 LogicalResult visitOperationImpl(
567 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
568 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
569 return visitOperation(
570 op,
571 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
572 operandLattices.size()},
573 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
574 resultLattices.size()});
575 }
576
577 void visitExternalCallImpl(
578 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
579 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
581 call,
582 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
583 operandLattices.size()},
584 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
585 resultLattices.size()});
586 }
587};
588
589} // end namespace dataflow
590} // end namespace mlir
591
592#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.
ValueRange getSuccessorInputs() const
Return the inputs to the successor that are remapped by the exit values of the current 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
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 void visitNonControlFlowArgumentsImpl(Operation *op, const RegionSuccessor &successor, ArrayRef< AbstractSparseLattice * > argLattices, unsigned firstIndex)=0
Given an operation with region control-flow, the lattices of the operands, and a region successor,...
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 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 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.
virtual void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ArrayRef< StateT * > argLattices, unsigned firstIndex)
Given an operation with possible region control-flow, the lattices of the operands,...
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.