Commit Graph

1009 Commits

Author SHA1 Message Date
Alexander Pivovarov
a24c468782 [MLIR] Fix assert expressions (#112474)
I noticed that several assertions in MLIR codebase have issues with
operator precedence

The issue with operator precedence in these assertions is due to the way
logical operators are evaluated. The `&&` operator has higher precedence
than the `||` operator, which means the assertion is currently
evaluating incorrectly, like this:
```
assert((resType.getNumDynamicDims() == dynOutDims.size()) ||
       (dynOutDims.empty() && "Either none or all output dynamic dims must be specified!"));
```

We should add parentheses around the entire expression involving
`dynOutDims.empty()` to ensure that the logical conditions are grouped
correctly. Here’s the corrected version:
```
assert(((resType.getNumDynamicDims() == dynOutDims.size()) || dynOutDims.empty()) &&
       "Either none or all output dynamic dims must be specified!");

```
2024-10-16 15:22:29 -07:00
donald chen
4b3f251bad [mlir] [dataflow] unify semantics of program point (#110344)
The concept of a 'program point' in the original data flow framework is
ambiguous. It can refer to either an operation or a block itself. This
representation has different interpretations in forward and backward
data-flow analysis. In forward data-flow analysis, the program point of
an operation represents the state after the operation, while in backward
data flow analysis, it represents the state before the operation. When
using forward or backward data-flow analysis, it is crucial to carefully
handle this distinction to ensure correctness.

This patch refactors the definition of program point, unifying the
interpretation of program points in both forward and backward data-flow
analysis.

How to integrate this patch?

For dense forward data-flow analysis and other analysis (except dense
backward data-flow analysis), the program point corresponding to the
original operation can be obtained by `getProgramPointAfter(op)`, and
the program point corresponding to the original block can be obtained by
`getProgramPointBefore(block)`.

For dense backward data-flow analysis, the program point corresponding
to the original operation can be obtained by
`getProgramPointBefore(op)`, and the program point corresponding to the
original block can be obtained by `getProgramPointAfter(block)`.

NOTE: If you need to get the lattice of other data-flow analyses in
dense backward data-flow analysis, you should still use the dense
forward data-flow approach. For example, to get the Executable state of
a block in dense backward data-flow analysis and add the dependency of
the current operation, you should write:

``getOrCreateFor<Executable>(getProgramPointBefore(op),
getProgramPointBefore(block))``

In case above, we use getProgramPointBefore(op) because the analysis we
rely on is dense backward data-flow, and we use
getProgramPointBefore(block) because the lattice we query is the result
of a non-dense backward data flow computation.

related dsscussion:
https://discourse.llvm.org/t/rfc-unify-the-semantics-of-program-points/80671/8
corresponding PSA:
https://discourse.llvm.org/t/psa-program-point-semantics-change/81479
2024-10-11 21:59:05 +08:00
Mehdi Amini
6c7a3f80e7 Fix LLVM_ENABLE_ABI_BREAKING_CHECKS macro check: use #if instead of #ifdef (#110938)
This macros is always defined: either 0 or 1. The correct pattern is to
use #if.

Re-apply #110185 with more fixes for debug build with the ABI breaking
checks disabled.
2024-10-03 01:24:14 +02:00
Amy Wang
2740273505 [MLIR][Presburger] Make printing aligned to assist in debugging (#107648)
Hello Arjun! Please allow me to contribute this patch as it helps me
debugging significantly! When the 1's and 0's don't line up when
debugging farkas lemma of numerous polyhedrons using simplex lexmin
solver, it is truly straining on the eyes. Hopefully this patch can help
others!

The unfortunate part is the lack of testcase as I'm not sure how to add
testcase for debug dumps. :) However, you can add this testcase to the
SimplexTest.cpp to witness the nice printing!

```c++
TEST(SimplexTest, DumpTest) {
  int COLUMNS = 2;
  int ROWS = 2;
  LexSimplex simplex(COLUMNS * 2);
  IntMatrix m1(ROWS, COLUMNS * 2 + 1);
  // Adding LHS columns.
  for (int i = 0; i < ROWS; i++) {
    // an arbitrary formula to test all kinds of integers
    for (int j = 0; j < COLUMNS; j++) 
      m1(i, j) = i + (2 << (i % 3)) * (-1 * ((i + j) % 2));
  }
  // Adding RHS columns.
  for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLUMNS; j++)
      m1(i, j + COLUMNS) = j - (3 << (j % 4)) * (-1 * ((i + j * 2) % 2));
  }
  for (int i = 0; i < m1.getNumRows(); i++) {
    ArrayRef<DynamicAPInt> curRow = m1.getRow(i);
    simplex.addInequality(curRow);
  }
  IntegerRelation rel =
      parseRelationFromSet("(x, y, z)[] : (z - x - 17 * y == 0, x - 11 * z >= 1)",2);
  simplex.dump();
  m1.dump();
  rel.dump();
}
```

```
rows = 2, columns = 7
var: c3, c4, c5, c6
con: r0 [>=0], r1 [>=0]
r0: -1, r1: -2
c0: denom, c1: const, c2: 2147483647, c3: 0, c4: 1, c5: 2, c6: 3
  1  0  1  0 -2  0  1
  1  0 -8 -3  1  3  7

  0 -2  0  1  0
 -3  1  3  7  0
Domain: 2, Range: 1, Symbols: 0, Locals: 0
2 constraints
 -1  -17  1   0   = 0
  1   0  -11 -1  >= 0

```
2024-09-11 23:22:54 -04:00
Henrich Lauko
d1cad2290c Reland [MLIR] Make resolveCallable customizable in CallOpInterface (#107989)
Relands #100361 with fixed dependencies.
2024-09-10 15:33:13 +02:00
Matthias Springer
7574042e2a Revert "[MLIR] Make resolveCallable customizable in CallOpInterface" (#107984)
Reverts llvm/llvm-project#100361

This commit caused some linker errors. (Missing `MLIRCallInterfaces`
dependency.)
2024-09-10 10:24:05 +02:00
Henrich Lauko
958f59d90f [MLIR] Make resolveCallable customizable in CallOpInterface (#100361)
Allow customization of the `resolveCallable` method in the
`CallOpInterface`. This change allows for operations implementing this
interface to provide their own logic for resolving callables.

- Introduce the `resolveCallable` method, which does not include the
optional symbol table parameter. This method replaces the previously
existing extra class declaration `resolveCallable`.

- Introduce the `resolveCallableInTable` method, which incorporates the
symbol table parameter. This method replaces the previous extra class
declaration `resolveCallable` that used the optional symbol table
parameter.
2024-09-10 10:08:41 +02:00
Kazu Hirata
b2dbcf4dc1 [Presburger] Avoid repeated hash lookups (NFC) (#107426) 2024-09-05 11:43:19 -07:00
donald chen
b6603e1bf1 [mlir] [dataflow] Refactoring the definition of program points in data flow analysis (#105656)
This patch distinguishes between program points and lattice anchors in
data flow analysis, where lattice anchors represent locations where a
lattice can be attached, while program points denote points in program
execution.

Related discussions:
https://discourse.llvm.org/t/rfc-unify-the-semantics-of-program-points/80671/8
2024-08-25 19:21:47 +08:00
Ivan Butygin
15e915a44f [mlir][dataflow] Propagate errors from visitOperation (#105448)
Base `DataFlowAnalysis::visit` returns `LogicalResult`, but wrappers's
Sparse/Dense/Forward/Backward `visitOperation` doesn't.

Sometimes it's needed to abort solver early if some unrecoverable
condition detected inside analysis.

Update `visitOperation` to return `LogicalResult` and propagate it to
`solver.initializeAndRun()`. Only `visitOperation` is updated for now,
it's possible to update other hooks like `visitNonControlFlowArguments`,
bit it's not needed immediately and let's keep this PR small.

Hijacked `UnderlyingValueAnalysis` test analysis to test it.
2024-08-22 12:16:03 +03:00
Christian Ulmann
bf68e9047f [MLIR] Introduce a SelectLikeOpInterface (#104751)
This commit introduces a `SelectLikeOpInterface` that can be used to
handle select-like operations generically. Select operations are similar
to control flow operations, as they forward operands depending on
conditions. This is the reason why it was placed to the already existing
control flow interfaces.
2024-08-20 07:32:12 +02:00
Christian Ulmann
141536544f [MLIR][LLVM]: Add an IR utility to perform slice walking (#103053)
This commit introduces a slicing utility that can be used to walk
arbitrary IR slices. It additionally ships logic to determine control
flow predecessors, which allows users to walk backward slices without
dealing with both `RegionBranchOpInterface` and `BranchOpInterface`.

This utility is used to improve the `noalias` propagation in the LLVM
dialect's inliner interface. Before this change, it broke down as soon
as pointer were passed through region control flow operations.
2024-08-15 10:30:44 +02:00
Kazu Hirata
165f45354a [mlir] Use llvm::is_contained (NFC) (#102714) 2024-08-09 21:42:19 -07:00
Kazu Hirata
5262865aac [mlir] Construct SmallVector with ArrayRef (NFC) (#101896) 2024-08-04 11:43:05 -07:00
Ramkumar Ramachandra
266a5a9cb9 mlir/Presburger: optimize to avoid creating copies (#97897)
Optimize the Presburger library to avoid unnecessarily creating copies.
While at it, fix some other minor issues in the codebase.
2024-07-15 19:42:27 +01:00
Ramkumar Ramachandra
64740edac8 mlir/Presburger: optimize normalizeDiv when gcd=1 (#97893) 2024-07-08 08:28:53 +01:00
Ramkumar Ramachandra
f819302a09 mlir/Presburger: reinstate use of LogicalResult (#97415)
Follow up on a desire post-landing d0fee98 (mlir/Presburger: strip
dependency on MLIRSupport) to reinstate the use of LogicalResult in
Presburger. Since db791b2 (mlir/LogicalResult: move into llvm),
LogicalResult is in LLVM, and fulfilling this desire is possible while
still maintaining the goal of stripping the Presburger library of mlir
dependencies.
2024-07-03 10:51:25 +01:00
Ramkumar Ramachandra
db791b278a mlir/LogicalResult: move into llvm (#97309)
This patch is part of a project to move the Presburger library into
LLVM.
2024-07-02 10:42:33 +01:00
Ramkumar Ramachandra
d0fee98e0c mlir/Presburger: strip dependency on MLIRSupport (#96517)
Strip the Presburger library's dependency on the MLIR Support library,
as well as the headers, in the interest of making it leaner.

This patch is part of a project to move the Presburger library into
LLVM.
2024-06-29 12:23:20 +01:00
Felix Schneider
b78883fc6d [mlir][intrange] Fix inference of zero-trip loop bound (#96429)
When lower bound and exclusive upper bound of a loop are the same, and
the zero-trip loop is not canonicalized away before the analysis, this
leads to a meaningless range for the induction variable being inferred.
This patch adds a check to make sure that the inferred range for the IV
is meaningful before updating the analysis state.

Fix https://github.com/llvm/llvm-project/issues/94423
2024-06-24 08:05:04 +02:00
Jay Foad
d4a0154902 [llvm-project] Fix typo "seperate" (#95373) 2024-06-13 20:20:27 +01:00
Ramkumar Ramachandra
1a0e67d730 Reland "mlir/Presburger/MPInt: move into llvm/ADT" (#95254)
Change: remove guards on debug-printing, to allow Release builds without
LLVM_ENABLE_DUMP to pass.

MPInt is an arbitrary-precision integer library that builds on top of
APInt, and has a fast-path when the number fits within 64 bits. It was
originally written for the Presburger library in MLIR, but seems useful
to the LLVM project in general, independently of the Presburger library
or MLIR. Hence, move it into LLVM/ADT under the name DynamicAPInt.

This patch is part of a project to move the Presburger library into
LLVM.
2024-06-12 18:09:16 +01:00
Maksim Levental
cb5d1b52ad Revert #95218 and #94953 (#95244) 2024-06-12 08:55:48 -05:00
Ramkumar Ramachandra
76030dc157 mlir/Presburger/MPInt: move into llvm/ADT (#94953)
MPInt is an arbitrary-precision integer library that builds on top of
APInt, and has a fast-path when the number fits within 64 bits. It was
originally written for the Presburger library in MLIR, but seems useful
to the LLVM project in general, independently of the Presburger library
or MLIR. Hence, move it into LLVM/ADT under the name DynamicAPInt.

This patch is part of a project to move the Presburger library into
LLVM.
2024-06-12 09:19:21 +01:00
Ramkumar Ramachandra
0fb216fb2f mlir/MathExtras: consolidate with llvm/MathExtras (#95087)
This patch is part of a project to move the Presburger library into
LLVM.
2024-06-11 23:00:02 +01:00
Benjamin Maxwell
29a925abb6 [mlir][affine][Analysis] Add conservative bounds for semi-affine mods (#93576)
This patch adds support for computing bounds for semi-affine mod
expression to FlatLinearConstraints. This is then enabled within the
ScalableValueBoundsConstraintSet to allow computing the bounds of
scalable remainder loops.

E.g. computing the bound of something like:
```
// `1000 mod s0` is a semi-affine.
#remainder_start_index = affine_map<()[s0] -> (-(1000 mod s0) + 1000)>
#remaining_iterations = affine_map<(d0) -> (-d0 + 1000)>

%0 = affine.apply #remainder_start_index()[%c8_vscale]
scf.for %i = %0 to %c1000 step %c8_vscale {
  %remaining_iterations = affine.apply #remaining_iterations(%i)
  // The upper bound for the remainder loop iterations should be:
  // %c8_vscale - 1  (expressed as an affine map,
  // affine_map<()[s0] -> (s0 * 8 - 1)>, where s0 is vscale)
  %bound = "test.reify_bound"(%remaining_iterations) <{scalable, ...}>
}
```

There are caveats to this implementation. To be able to add a bound for
a `mod` we need to assume the rhs is positive (> 0). This may not be
known when adding the bounds for the `mod` expression. So to handle this
a constraint is added for `rhs > 0`, this may later be found not to hold
(in which case the constraints set becomes empty/invalid).

This is not a problem for computing scalable bounds where it's safe to
assume `s0` is vscale (or some positive multiple of it). But this may
need to be considered when enabling this feature elsewhere (to ensure
correctness).
2024-06-05 11:35:13 +01:00
Spenser Bauman
6aeea700df [mlir][dataflow] Fix for integer range analysis propagation bug (#93199)
Integer range analysis will not update the range of an operation when
any of the inferred input lattices are uninitialized. In the current
behavior, all lattice values for non integer types are uninitialized.

For operations like arith.cmpf

```mlir
%3 = arith.cmpf ugt, %arg0, %arg1 : f32
```

that will result in the range of the output also being uninitialized,
and so on for any consumer of the arith.cmpf result. When control-flow
ops are involved, the lack of propagation results in incorrect ranges,
as the back edges for loop carried values are not properly joined with
the definitions from the body region.

For example, an scf.while loop whose body region produces a value that
is in a dataflow relationship with some floating-point values through an
arith.cmpf operation:

```mlir
func.func @test_bad_range(%arg0: f32, %arg1: f32) -> (index, index) {
  %c4 = arith.constant 4 : index
  %c1 = arith.constant 1 : index
  %c0 = arith.constant 0 : index

  %3 = arith.cmpf ugt, %arg0, %arg1 : f32

  %1:2 = scf.while (%arg2 = %c0, %arg3 = %c0) : (index, index) -> (index, index) {
    %2 = arith.cmpi ult, %arg2, %c4 : index
    scf.condition(%2) %arg2, %arg3 : index, index
  } do {
  ^bb0(%arg2: index, %arg3: index):
    %4 = arith.select %3, %arg3, %arg3 : index
    %5 = arith.addi %arg2, %c1 : index
    scf.yield %5, %4 : index, index
  }

  return %1#0, %1#1 : index, index
}
```

The existing behavior results in the control condition %2 being
optimized to true, turning the while loop into an infinite loop. The
update to %arg2 through the body region is never factored into the range
calculation, as the ranges for the body ops all test as uninitialized.

This change causes all values initialized with setToEntryState to be set
to some initialized range, even if the values are not integers.

---------

Co-authored-by: Spenser Bauman <sabauma@fastmail>
2024-05-28 18:29:17 -04:00
Ivan Kulagin
63e8c0a0e4 [mlir] Fix liveness analysis for block arguments (#88848)
The current implementation does not take into account definitions
created by arguments of nested blocks. This leads to an incorrect
construction of the live-in set of an outer block. Arguments of nested
blocks are added to the live-in set of an outer block.

---------

Signed-off-by: ikulagin <i.kulagin@ispras.ru>
Co-authored-by: ikulagin <i.kulagin@ispras.ru>
2024-05-23 15:09:45 -07:00
Christian Ulmann
b00e0c1671 [MLIR][Analysis] Consolidate topological sort utilities (#92563)
This PR attempts to consolidate the different topological sort utilities
into one place. It adds them to the analysis folder because the
`SliceAnalysis` uses some of these.

There are now two different sorting strategies: 
1. Sort only according to SSA use-def chains
2. Sort while taking regions into account. This requires a much more
elaborate traversal and cannot be applied on graph regions that easily.

This additionally reimplements the region aware topological sorting
because the previous implementation had an exponential space complexity.

I'm open to suggestions on how to combine this further or how to fuse
the test passes.
2024-05-22 08:48:10 +02:00
Krzysztof Parzyszek
33550b43f4 [mlir] Add operator<< for printing Block (#92550)
Turns out it was already in Analysis/CFGLoopInfo, so just move it
to IR/AsmPrinter.
2024-05-18 08:03:19 -05:00
Bharathi Ramana Joshi
24da7fa029 [MLIR][Presburger] Use Identifiers outside Presburger library (#77316)
The pull request includes the following changes.
1. Refactors the interface to `PresburgerSpace::identifiers` to `setId` and a
const `getId`, instead of previous `getId` which returned a mutable
reference. `resetIds` does not need to be called to use identifiers, `setId`
calls `resetIds` if identifiers are not enabled.
2. Deprecates `FlatAffineRelation` by refactoring all usages of
`FlatAffineRelation` to `IntegerRelation`. To achieve this,
`FlatAffineRelation::compose` is refactored into
`IntegerRelation::mergeAndCompose`.
3. Deletes unneeded overrides of virtual functions `hasConsistentState`,
`clearAndCopyFrom` and `fourierMotzkinEliminate` from
`FlatLinearValueConstraints` as these were only used through
`FlatAffineRelation` and we now use `IntegerRelation`'s member functions
instead.
4. Fixes an existing bug in FlatLinearValueConstraints' constructor
which caused
identifiers set by superclass FlatLinearConstraints' constructor to be
erased.
5. Fixes `IntegerRelation::convertVarKind` not preserving identifiers.
2024-04-18 21:56:53 +05:30
Mehdi Amini
1837579bbc Apply clang-tidy fixes for readability-simplify-boolean-expr in IntegerRelation.cpp (NFC) 2024-03-04 23:15:10 -08:00
Mehdi Amini
1934fc6a0c Apply clang-tidy fixes for readability-container-size-empty in Barvinok.cpp (NFC) 2024-03-04 23:15:10 -08:00
Mehdi Amini
2db8b94138 Apply clang-tidy fixes for performance-unnecessary-value-param in Barvinok.cpp (NFC) 2024-03-04 23:15:10 -08:00
Mehdi Amini
9915418144 Apply clang-tidy fixes for modernize-use-emplace in Barvinok.cpp (NFC) 2024-03-04 23:15:10 -08:00
Mehdi Amini
a36b73e5a7 Apply clang-tidy fixes for modernize-loop-convert in Barvinok.cpp (NFC) 2024-03-04 23:15:10 -08:00
Adrian Kuegel
654e65d3b2 [mlir] Apply ClangTidy performance fix.
Use const reference for loop variable.
2024-02-21 13:17:43 +00:00
Abhinav271828
562790f371 [MLIR][Presburger] Implement vertex enumeration and chamber decomposition for polytope generating function computation. (#78987)
We implement a function to compute the generating function corresponding
to a full-dimensional parametric polytope whose tangent cones are all
unimodular.
We fix a bug in unimodGenFunc to check the absolute value of the index.
We also implement Matrix<T>::negateMatrix() and Matrix<T>::scaleRow for
convenience.
2024-02-15 11:03:32 +05:30
Jie Fu
3c94154c86 [mlir] Fix -Wunused-variable in Barvinok.cpp (NFC)
llvm-project/mlir/lib/Analysis/Presburger/Barvinok.cpp:262:21:
 error: unused variable 'd' [-Werror,-Wunused-variable]
  for (const Point &d : ds)
                    ^
1 error generated.
2024-01-22 20:12:39 +08:00
Abhinav271828
68a5261d26 [MLIR][Presburger] Implement function to evaluate the number of terms in a generating function. (#78078)
We implement `computeNumTerms()`, which counts the number of terms in a
generating function by substituting the unit vector in it.
This is the main function in Barvinok's algorithm – the number of points
in a polytope is given by the number of terms in the generating function
corresponding to it.
We also modify the GeneratingFunction class to have `const` getters and
improve the simplification of QuasiPolynomials.
2024-01-22 14:22:01 +05:30
Bharathi Ramana Joshi
d70bfeb4e1 [MLIR][Presburger] Implement IntegerRelation::setId (#77872) 2024-01-20 15:19:10 +05:30
Benjamin Kramer
9c33a2e9a3 [MLIR][Presburger] Fold loop into assert
This way it doesn't trigger -Wunused-variable when assertions are disabled.
2024-01-13 17:52:58 +01:00
Abhinav271828
850f713e80 [MLIR][Presburger] Helper functions to compute the constant term of a generating function (#77819)
We implement two functions that are needed to compute the constant term
of a GF.
One finds a vector not orthogonal to all the non-null vectors in a given
set.
One computes the coefficient of any term in an arbitrary rational
function (quotient of two polynomials).
2024-01-13 21:30:06 +05:30
Bharathi Ramana Joshi
66786a79d6 [MLIR][Presburger] Implement Matrix::moveColumns (#68362) 2024-01-13 18:51:26 +05:30
Bharathi Ramana Joshi
c39926e679 [MLIR][Presburger] Fix style violations in ff80414 (NFC) (#76720)
Use preincrement not postincrement; use `Identifier::getIds` not
`getVarKindOffset`
2024-01-12 10:36:28 +05:30
Abhinav271828
2dde029df8 [MLIR][Presburger] Implement computation of generating function for unimodular cones (#77235)
We implement a function that computes the generating function
corresponding to a unimodular cone.
The generating function for a polytope is obtained by summing these
generating functions over all tangent cones.
2024-01-11 01:28:36 +05:30
Bharathi Ramana Joshi
3eb9fd8ac8 [MLIR][Presburger] Implement IntegerRelation::mergeAndAlignSymbols (#76736) 2024-01-07 17:06:52 +05:30
Abhinav271828
4c8dbb6813 [MLIR][Presburger] Definitions for basic functions related to cones (#76650)
We add some basic type aliases and function definitions relating to
cones for Barvinok's algorithm.
These include functions to get the dual of a cone and find its index.
2024-01-07 10:30:22 +00:00
Abhinav271828
bd0dc357af [MLIR][Presburger] Shift GeneratingFunction.h to includes (#77114)
We shift the GeneratingFunction.h header file to the include/ directory
and wrap it in a `detail` namespace.
2024-01-06 17:08:25 +05:30
drblallo
2bd6642533 [mlir][dataflow]Fix dense backward dataflow intraprocedural hook (#76865)
The dataflow analysis framework within MLIR allows to customize the
transfer function when a `call-like` operation is encuntered.

The check to see if the analysis was executed in intraprocedural mode
was executed after the check to see if the callee had the
CallableOpInterface, and thus intraprocedural analyses would behave as
interpocedural ones when performing indirect calls.

This commit fixes the issue by performing the check for
intraprocedurality first.

Dense forward analyses were already behaving correctly.
https://github.com/llvm/llvm-project/blob/main/mlir/lib/Analysis/DataFlow/DenseAnalysis.cpp#L63

Co-authored-by: massimo <mo.fioravanti@gmail.com>
2024-01-04 10:28:12 +01:00