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 the non-forwarded arguments of a region, such as the
435 // induction variables of a loop.
436 virtual void
438 ArrayRef<BlockArgument> arguments) = 0;
439
440 // Visit operands on call instructions that are not forwarded.
441 virtual void visitCallOperand(OpOperand &operand) = 0;
442
443 /// Set the given lattice element(s) at control flow exit point(s) and
444 /// propagate the update if it chaned.
445 virtual void setToExitState(AbstractSparseLattice *lattice) = 0;
446
447 /// Set the given lattice element(s) at control flow exit point(s) and
448 /// propagate the update if it chaned.
450
451 /// Get the lattice element for a value.
453
454 /// Get the lattice elements for a range of values.
456
457 /// Join the lattice element and propagate and update if it changed.
459
460 /// Visits a callable operation. If all the call sites are known computes the
461 /// operand lattices of `op` from the result lattices of all the call sites;
462 /// otherwise, conservatively marks them as having reached their pessimistic
463 /// fixpoints.
464 /// This method can be overridden to, for example, be less conservative and
465 /// propagate the information even if some call sites are unknown.
466 virtual LogicalResult
467 visitCallableOperation(Operation *op, CallableOpInterface callable,
468 ArrayRef<AbstractSparseLattice *> operandLattices);
469
470private:
471 /// Recursively initialize the analysis on nested operations and blocks.
472 LogicalResult initializeRecursively(Operation *op);
473
474 /// Visit an operation. If this is a call operation or an operation with
475 /// region control-flow, then its operand lattices are set accordingly.
476 /// Otherwise, the operation transfer function is invoked.
477 LogicalResult visitOperation(Operation *op);
478
479 /// Visit a block.
480 void visitBlock(Block *block);
481
482 /// Visit an op with regions (like e.g. `scf.while`)
483 void visitRegionSuccessors(RegionBranchOpInterface branch,
485
486 /// Visit a `RegionBranchTerminatorOpInterface` to compute the lattice values
487 /// of its operands, given its parent op `branch`. The lattice value of an
488 /// operand is determined based on the corresponding arguments in
489 /// `terminator`'s region successor(s).
490 void visitRegionSuccessorsFromTerminator(
491 RegionBranchTerminatorOpInterface terminator,
492 RegionBranchOpInterface branch);
493
494 /// Get the lattice element for a value, and also set up
495 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
496 /// if the value changes.
497 const AbstractSparseLattice *getLatticeElementFor(ProgramPoint *point,
498 Value value);
499
500 /// Get the lattice elements for a range of values, and also set up
501 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
502 /// if any of the values change.
504 getLatticeElementsFor(ProgramPoint *point, ValueRange values);
505
506 SymbolTableCollection &symbolTable;
507};
508
509//===----------------------------------------------------------------------===//
510// SparseBackwardDataFlowAnalysis
511//===----------------------------------------------------------------------===//
512
513/// A sparse (backward) data-flow analysis for propagating SSA value lattices
514/// backwards across the IR by implementing transfer functions for operations.
515///
516/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
517///
518/// Visit a program point in sparse backward data-flow analysis will invoke the
519/// transfer function of the operation preceding the program point iterator.
520/// Visit a program point at the begining of block will visit the block itself.
521template <typename StateT>
524 static_assert(
525 std::is_base_of<AbstractSparseLattice, StateT>::value,
526 "analysis state class expected to subclass AbstractSparseLattice");
527
528public:
532
533 /// Visit an operation with the lattices of its results. This function is
534 /// expected to set the lattices of the operation's operands.
535 virtual LogicalResult visitOperation(Operation *op,
536 ArrayRef<StateT *> operands,
537 ArrayRef<const StateT *> results) = 0;
538
539 /// Visit a call to an external function. This function is expected to set
540 /// lattice values of the call operands. By default, calls `visitCallOperand`
541 /// for all operands.
542 virtual void visitExternalCall(CallOpInterface call,
543 ArrayRef<StateT *> argumentLattices,
544 ArrayRef<const StateT *> resultLattices) {
545 (void)argumentLattices;
546 (void)resultLattices;
547 for (OpOperand &operand : call->getOpOperands()) {
548 visitCallOperand(operand);
549 }
550 };
551
552protected:
553 /// Get the lattice element for a value.
554 StateT *getLatticeElement(Value value) override {
555 return getOrCreate<StateT>(value);
556 }
557
558 /// Set the given lattice element(s) at control flow exit point(s).
559 virtual void setToExitState(StateT *lattice) = 0;
560 void setToExitState(AbstractSparseLattice *lattice) override {
561 return setToExitState(reinterpret_cast<StateT *>(lattice));
562 }
565 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
566 lattices.size()});
567 }
568
569private:
570 /// Type-erased wrappers that convert the abstract lattice operands to derived
571 /// lattices and invoke the virtual hooks operating on the derived lattices.
572 LogicalResult visitOperationImpl(
573 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
574 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
575 return visitOperation(
576 op,
577 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
578 operandLattices.size()},
579 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
580 resultLattices.size()});
581 }
582
583 void visitExternalCallImpl(
584 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
585 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
587 call,
588 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
589 operandLattices.size()},
590 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
591 resultLattices.size()});
592 }
593};
594
595} // end namespace dataflow
596} // end namespace mlir
597
598#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
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 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.