MLIR 24.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.
46 }
47
48 /// Meet (intersect) the information in this lattice with 'rhs'. Returns
49 /// if the value of the lattice changed.
52 }
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 /// Compute lattice values for successor values not supplied by control-flow
213 /// forwarding at `point`. Lattice reads must register dependencies on
214 /// `point`.
216 ProgramPoint *point, Operation *op, const RegionSuccessor &successor,
217 ValueRange nonSuccessorInputs,
218 ArrayRef<AbstractSparseLattice *> nonSuccessorInputLattices) = 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.
233 void join(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs);
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:
306 /// Read a value's lattice and register a dependency on the current visit.
307 using GetLatticeFn = function_ref<const StateT *(Value)>;
308
311
312 /// Visit an operation with the lattices of its operands. This function is
313 /// expected to set the lattices of the operation's results.
314 virtual LogicalResult visitOperation(Operation *op,
316 ArrayRef<StateT *> results) = 0;
317
318 /// Visit a call operation to an externally defined function given the
319 /// lattices of its arguments.
320 virtual void visitExternalCall(CallOpInterface call,
321 ArrayRef<const StateT *> argumentLattices,
322 ArrayRef<StateT *> resultLattices) {
323 setAllToEntryStates(resultLattices);
324 }
325
326 /// Given an operation with possible region control-flow, the lattices of the
327 /// operands, and a region successor, compute the lattice values for
328 /// non-successor-inputs (ex. loop induction variables) of a given region
329 /// successor. Use `getLattice` to read lattices, including those of captured
330 /// values. Changes to the lattices read through this callback revisit this
331 /// hook. The callback is valid only for the duration of this call.
332 ///
333 /// For example, for an `scf.for` body, the region successor is the loop body
334 /// and the non-successor input is the induction variable. Its lattice is in
335 /// `nonSuccessorInputLattices` and must be computed or updated by this hook.
336 /// Use `getLattice` to read the lattices of the lower bound, upper bound, and
337 /// step when they are needed to infer the induction variable's lattice.
338 ///
339 /// By default, this method marks all lattice elements as having reached a
340 /// pessimistic fixpoint.
341 virtual void
343 ValueRange nonSuccessorInputs,
344 ArrayRef<StateT *> nonSuccessorInputLattices,
345 GetLatticeFn getLattice) {
346 assert(nonSuccessorInputs.size() == nonSuccessorInputLattices.size() &&
347 "size mismatch");
348 setAllToEntryStates(nonSuccessorInputLattices);
349 }
350
351protected:
352 /// Get the lattice element for a value.
353 StateT *getLatticeElement(Value value) override {
354 return getOrCreate<StateT>(value);
355 }
356
357 /// Get the lattice element for a value and create a dependency on the
358 /// provided program point.
359 const StateT *getLatticeElementFor(ProgramPoint *point, Value value) {
360 return static_cast<const StateT *>(
362 value));
363 }
364
365 /// Set the given lattice element(s) at control flow entry point(s).
366 virtual void setToEntryState(StateT *lattice) = 0;
369 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
370 lattices.size()});
371 }
372
373private:
374 /// Type-erased wrappers that convert the abstract lattice operands to derived
375 /// lattices and invoke the virtual hooks operating on the derived lattices.
376 LogicalResult visitOperationImpl(
378 ArrayRef<AbstractSparseLattice *> resultLattices) override {
379 return visitOperation(
380 op,
381 {reinterpret_cast<const StateT *const *>(operandLattices.begin()),
382 operandLattices.size()},
383 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
384 resultLattices.size()});
385 }
386 void visitExternalCallImpl(
387 CallOpInterface call,
388 ArrayRef<const AbstractSparseLattice *> argumentLattices,
389 ArrayRef<AbstractSparseLattice *> resultLattices) override {
391 call,
392 {reinterpret_cast<const StateT *const *>(argumentLattices.begin()),
393 argumentLattices.size()},
394 {reinterpret_cast<StateT *const *>(resultLattices.begin()),
395 resultLattices.size()});
396 }
397 void visitNonControlFlowArgumentsImpl(
398 ProgramPoint *point, Operation *op, const RegionSuccessor &successor,
399 ValueRange nonSuccessorInputs,
400 ArrayRef<AbstractSparseLattice *> nonSuccessorInputLattices) override {
402 op, successor, nonSuccessorInputs,
403 {reinterpret_cast<StateT *const *>(nonSuccessorInputLattices.begin()),
404 nonSuccessorInputLattices.size()},
405 [&](Value value) { return getLatticeElementFor(point, value); });
406 }
407
408 void setToEntryState(AbstractSparseLattice *lattice) override {
409 return setToEntryState(reinterpret_cast<StateT *>(lattice));
410 }
411};
412
413//===----------------------------------------------------------------------===//
414// AbstractSparseBackwardDataFlowAnalysis
415//===----------------------------------------------------------------------===//
416
417/// Base class for sparse backward data-flow analyses. Similar to
418/// AbstractSparseForwardDataFlowAnalysis, but walks bottom to top.
420public:
421 /// Initialize the analysis by visiting the operation and everything nested
422 /// under it.
423 LogicalResult initialize(Operation *top) override;
424
425 /// Visit a program point. If it is after call operation or an operation with
426 /// block or region control-flow, then operand lattices are set accordingly.
427 /// Otherwise, invokes the operation transfer function (`visitOperationImpl`).
428 LogicalResult visit(ProgramPoint *point) override;
429
430protected:
432 DataFlowSolver &solver, SymbolTableCollection &symbolTable);
433
434 /// The operation transfer function. Given the result lattices, this
435 /// function is expected to set the operand lattices.
436 virtual LogicalResult visitOperationImpl(
437 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
438 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
439
440 /// The transfer function for calls to external functions.
442 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
443 ArrayRef<const AbstractSparseLattice *> resultLattices) = 0;
444
445 // Visit operands on branch instructions that are not forwarded.
446 virtual void visitBranchOperand(OpOperand &operand) = 0;
447
448 // Visit the non-forwarded arguments of a region, such as the
449 // induction variables of a loop.
450 virtual void
452 ArrayRef<BlockArgument> arguments) = 0;
453
454 // Visit operands on call instructions that are not forwarded.
455 virtual void visitCallOperand(OpOperand &operand) = 0;
456
457 /// Set the given lattice element(s) at control flow exit point(s) and
458 /// propagate the update if it chaned.
459 virtual void setToExitState(AbstractSparseLattice *lattice) = 0;
460
461 /// Set the given lattice element(s) at control flow exit point(s) and
462 /// propagate the update if it chaned.
464
465 /// Get the lattice element for a value.
467
468 /// Get the lattice elements for a range of values.
470
471 /// Join the lattice element and propagate and update if it changed.
472 void meet(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs);
473
474 /// Visits a callable operation. If all the call sites are known computes the
475 /// operand lattices of `op` from the result lattices of all the call sites;
476 /// otherwise, conservatively marks them as having reached their pessimistic
477 /// fixpoints.
478 /// This method can be overridden to, for example, be less conservative and
479 /// propagate the information even if some call sites are unknown.
480 virtual LogicalResult
481 visitCallableOperation(Operation *op, CallableOpInterface callable,
482 ArrayRef<AbstractSparseLattice *> operandLattices);
483
484private:
485 /// Recursively initialize the analysis on nested operations and blocks.
486 LogicalResult initializeRecursively(Operation *op);
487
488 /// Visit an operation. If this is a call operation or an operation with
489 /// region control-flow, then its operand lattices are set accordingly.
490 /// Otherwise, the operation transfer function is invoked.
491 LogicalResult visitOperation(Operation *op);
492
493 /// Visit a block.
494 void visitBlock(Block *block);
495
496 /// Visit an op with regions (like e.g. `scf.while`)
497 void visitRegionSuccessors(RegionBranchOpInterface branch,
499
500 /// Visit a `RegionBranchTerminatorOpInterface` to compute the lattice values
501 /// of its operands, given its parent op `branch`. The lattice value of an
502 /// operand is determined based on the corresponding arguments in
503 /// `terminator`'s region successor(s).
504 void visitRegionSuccessorsFromTerminator(
505 RegionBranchTerminatorOpInterface terminator,
506 RegionBranchOpInterface branch);
507
508 /// Get the lattice element for a value, and also set up
509 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
510 /// if the value changes.
511 const AbstractSparseLattice *getLatticeElementFor(ProgramPoint *point,
512 Value value);
513
514 /// Get the lattice elements for a range of values, and also set up
515 /// dependencies so that the analysis on the given ProgramPoint is re-invoked
516 /// if any of the values change.
518 getLatticeElementsFor(ProgramPoint *point, ValueRange values);
519
520 SymbolTableCollection &symbolTable;
521};
522
523//===----------------------------------------------------------------------===//
524// SparseBackwardDataFlowAnalysis
525//===----------------------------------------------------------------------===//
526
527/// A sparse (backward) data-flow analysis for propagating SSA value lattices
528/// backwards across the IR by implementing transfer functions for operations.
529///
530/// `StateT` is expected to be a subclass of `AbstractSparseLattice`.
531///
532/// Visit a program point in sparse backward data-flow analysis will invoke the
533/// transfer function of the operation preceding the program point iterator.
534/// Visit a program point at the begining of block will visit the block itself.
535template <typename StateT>
538 static_assert(
539 std::is_base_of<AbstractSparseLattice, StateT>::value,
540 "analysis state class expected to subclass AbstractSparseLattice");
541
542public:
546
547 /// Visit an operation with the lattices of its results. This function is
548 /// expected to set the lattices of the operation's operands.
549 virtual LogicalResult visitOperation(Operation *op,
550 ArrayRef<StateT *> operands,
551 ArrayRef<const StateT *> results) = 0;
552
553 /// Visit a call to an external function. This function is expected to set
554 /// lattice values of the call operands. By default, calls `visitCallOperand`
555 /// for all operands.
556 virtual void visitExternalCall(CallOpInterface call,
557 ArrayRef<StateT *> argumentLattices,
558 ArrayRef<const StateT *> resultLattices) {
559 (void)argumentLattices;
560 (void)resultLattices;
561 for (OpOperand &operand : call->getOpOperands()) {
562 visitCallOperand(operand);
563 }
564 };
565
566protected:
567 /// Get the lattice element for a value.
568 StateT *getLatticeElement(Value value) override {
569 return getOrCreate<StateT>(value);
570 }
571
572 /// Set the given lattice element(s) at control flow exit point(s).
573 virtual void setToExitState(StateT *lattice) = 0;
574 void setToExitState(AbstractSparseLattice *lattice) override {
575 return setToExitState(reinterpret_cast<StateT *>(lattice));
576 }
579 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()),
580 lattices.size()});
581 }
582
583private:
584 /// Type-erased wrappers that convert the abstract lattice operands to derived
585 /// lattices and invoke the virtual hooks operating on the derived lattices.
586 LogicalResult visitOperationImpl(
587 Operation *op, ArrayRef<AbstractSparseLattice *> operandLattices,
588 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
589 return visitOperation(
590 op,
591 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
592 operandLattices.size()},
593 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
594 resultLattices.size()});
595 }
596
597 void visitExternalCallImpl(
598 CallOpInterface call, ArrayRef<AbstractSparseLattice *> operandLattices,
599 ArrayRef<const AbstractSparseLattice *> resultLattices) override {
601 call,
602 {reinterpret_cast<StateT *const *>(operandLattices.begin()),
603 operandLattices.size()},
604 {reinterpret_cast<const StateT *const *>(resultLattices.begin()),
605 resultLattices.size()});
606 }
607};
608
609} // end namespace dataflow
610} // end namespace mlir
611
612#endif // MLIR_ANALYSIS_DATAFLOW_SPARSEANALYSIS_H
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:34
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:256
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
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:392
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 void visitNonControlFlowArgumentsImpl(ProgramPoint *point, Operation *op, const RegionSuccessor &successor, ValueRange nonSuccessorInputs, ArrayRef< AbstractSparseLattice * > nonSuccessorInputLattices)=0
Compute lattice values for successor values not supplied by control-flow forwarding at point.
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).
function_ref< const StateT *(Value)> GetLatticeFn
Read a value's lattice and register a dependency on the current visit.
virtual void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ValueRange nonSuccessorInputs, ArrayRef< StateT * > nonSuccessorInputLattices, GetLatticeFn getLattice)
Given an operation with possible region control-flow, the lattices of the operands,...
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:128
llvm::function_ref< Fn > function_ref
Definition LLVM.h:155
Program point represents a specific location in the execution of a program.