MLIR  19.0.0git
IntegerRangeAnalysis.h
Go to the documentation of this file.
1 //===-IntegerRangeAnalysis.h - Integer range analysis -----------*- C++ -*-===//
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 declares the dataflow analysis class for integer range inference
10 // so that it can be used in transformations over the `arith` dialect such as
11 // branch elimination or signed->unsigned rewriting.
12 //
13 // One can also implement InferIntRangeInterface on ops in custom dialects,
14 // and then use this analysis to propagate ranges with custom semantics.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
19 #define MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
20 
23 
24 namespace mlir {
25 namespace dataflow {
26 
27 /// This lattice value represents the integer range of an SSA value.
29 public:
30  /// Create a maximal range ([0, uint_max(t)] / [int_min(t), int_max(t)])
31  /// range that is used to mark the value as unable to be analyzed further,
32  /// where `t` is the type of `value`.
33  static IntegerValueRange getMaxRange(Value value);
34 
35  /// Create an integer value range lattice value.
36  IntegerValueRange(std::optional<ConstantIntRanges> value = std::nullopt)
37  : value(std::move(value)) {}
38 
39  /// Whether the range is uninitialized. This happens when the state hasn't
40  /// been set during the analysis.
41  bool isUninitialized() const { return !value.has_value(); }
42 
43  /// Get the known integer value range.
44  const ConstantIntRanges &getValue() const {
45  assert(!isUninitialized());
46  return *value;
47  }
48 
49  /// Compare two ranges.
50  bool operator==(const IntegerValueRange &rhs) const {
51  return value == rhs.value;
52  }
53 
54  /// Take the union of two ranges.
56  const IntegerValueRange &rhs) {
57  if (lhs.isUninitialized())
58  return rhs;
59  if (rhs.isUninitialized())
60  return lhs;
61  return IntegerValueRange{lhs.getValue().rangeUnion(rhs.getValue())};
62  }
63 
64  /// Print the integer value range.
65  void print(raw_ostream &os) const { os << value; }
66 
67 private:
68  /// The known integer value range.
69  std::optional<ConstantIntRanges> value;
70 };
71 
72 /// This lattice element represents the integer value range of an SSA value.
73 /// When this lattice is updated, it automatically updates the constant value
74 /// of the SSA value (if the range can be narrowed to one).
75 class IntegerValueRangeLattice : public Lattice<IntegerValueRange> {
76 public:
77  using Lattice::Lattice;
78 
79  /// If the range can be narrowed to an integer constant, update the constant
80  /// value of the SSA value.
81  void onUpdate(DataFlowSolver *solver) const override;
82 };
83 
84 /// Integer range analysis determines the integer value range of SSA values
85 /// using operations that define `InferIntRangeInterface` and also sets the
86 /// range of iteration indices of loops with known bounds.
87 ///
88 /// This analysis depends on DeadCodeAnalysis, and will be a silent no-op
89 /// if DeadCodeAnalysis is not loaded in the same solver context.
91  : public SparseForwardDataFlowAnalysis<IntegerValueRangeLattice> {
92 public:
94 
95  /// At an entry point, we cannot reason about interger value ranges.
96  void setToEntryState(IntegerValueRangeLattice *lattice) override {
98  lattice->getPoint())));
99  }
100 
101  /// Visit an operation. Invoke the transfer function on each operation that
102  /// implements `InferIntRangeInterface`.
103  void visitOperation(Operation *op,
105  ArrayRef<IntegerValueRangeLattice *> results) override;
106 
107  /// Visit block arguments or operation results of an operation with region
108  /// control-flow for which values are not defined by region control-flow. This
109  /// function calls `InferIntRangeInterface` to provide values for block
110  /// arguments or tries to reduce the range on loop induction variables with
111  /// known bounds.
112  void
115  unsigned firstIndex) override;
116 };
117 
118 } // end namespace dataflow
119 } // end namespace mlir
120 
121 #endif // MLIR_ANALYSIS_DATAFLOW_INTEGERANGEANALYSIS_H
A set of arbitrary-precision integers representing bounds on a given integer value.
ConstantIntRanges rangeUnion(const ConstantIntRanges &other) const
Returns the union (computed separately for signed and unsigned bounds) of this range and other.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
The general data-flow analysis solver.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
This class represents a successor of a region.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
Integer range analysis determines the integer value range of SSA values using operations that define ...
void visitOperation(Operation *op, ArrayRef< const IntegerValueRangeLattice * > operands, ArrayRef< IntegerValueRangeLattice * > results) override
Visit an operation.
void setToEntryState(IntegerValueRangeLattice *lattice) override
At an entry point, we cannot reason about interger value ranges.
void visitNonControlFlowArguments(Operation *op, const RegionSuccessor &successor, ArrayRef< IntegerValueRangeLattice * > argLattices, unsigned firstIndex) override
Visit block arguments or operation results of an operation with region control-flow for which values ...
This lattice element represents the integer value range of an SSA value.
void onUpdate(DataFlowSolver *solver) const override
If the range can be narrowed to an integer constant, update the constant value of the SSA value.
This lattice value represents the integer range of an SSA value.
const ConstantIntRanges & getValue() const
Get the known integer value range.
void print(raw_ostream &os) const
Print the integer value range.
IntegerValueRange(std::optional< ConstantIntRanges > value=std::nullopt)
Create an integer value range lattice value.
bool isUninitialized() const
Whether the range is uninitialized.
bool operator==(const IntegerValueRange &rhs) const
Compare two ranges.
static IntegerValueRange getMaxRange(Value value)
Create a maximal range ([0, uint_max(t)] / [int_min(t), int_max(t)]) range that is used to mark the v...
static IntegerValueRange join(const IntegerValueRange &lhs, const IntegerValueRange &rhs)
Take the union of two ranges.
This class represents a lattice holding a specific value of type ValueT.
ChangeResult join(const AbstractSparseLattice &rhs) override
Join the information contained in the 'rhs' lattice into this lattice.
Value getPoint() const
Return the program point this lattice is located at.
A sparse forward data-flow analysis for propagating SSA value lattices across the IR by implementing ...
SparseForwardDataFlowAnalysis(DataFlowSolver &solver)
Include the generated interface declarations.