[Mlir-commits] [mlir] [mlir] Handle attempted construction of invalid `AffineExpr` products (PR #103010)

Felix Schneider llvmlistbot at llvm.org
Mon Aug 12 23:30:41 PDT 2024


https://github.com/ubfx created https://github.com/llvm/llvm-project/pull/103010

Binary `AffineExpr`s can be constructed using the overloaded operators as well as respective methods (`AffineExpr::floorDiv()`, `ceilDiv()`). In the case of a `Mul` expression, either LHS or RHS has to be symbolic or constant to constitute a valid `AffineExpr`.

This patch returns nullptr from attempted construction of an `AffineExpr` through the  `*` operator if not at least one operand is symbolic or constant.

Related: https://github.com/llvm/llvm-project/commit/a4b23638d23d603001c19285a7c7535a8ce81317#r144894547

>From 700037df6b6e0a28c96af46b5d675a265aef6a94 Mon Sep 17 00:00:00 2001
From: Felix Schneider <fx.schn at gmail.com>
Date: Tue, 13 Aug 2024 07:50:33 +0200
Subject: [PATCH] [mlir] Handle attempted construction of invalid `AffineExpr`
 products

Binary `AffineExpr`s can be constructed using the overloaded operators
as well as respective methods (`AffineExpr::floorDiv()`, `ceilDiv()`).
In the case of a `Mul` expression, either LHS or RHS has to be symbolic
or constant to constitute a valid `AffineExpr`.

This patch returns nullptr from attempted construction of an `AffineExpr`
through the  `*` operator if not at least one operand is symbolic or
constant.

Related: https://github.com/llvm/llvm-project/commit/a4b23638d23d603001c19285a7c7535a8ce81317#r144894547
---
 mlir/lib/IR/AffineExpr.cpp           | 12 ++++++++---
 mlir/unittests/IR/AffineExprTest.cpp | 30 +++++++++++++++++++++++++++-
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/IR/AffineExpr.cpp b/mlir/lib/IR/AffineExpr.cpp
index fc7ede279643ed..d0fcfb7d7825ea 100644
--- a/mlir/lib/IR/AffineExpr.cpp
+++ b/mlir/lib/IR/AffineExpr.cpp
@@ -781,6 +781,10 @@ AffineExpr AffineExpr::operator+(AffineExpr other) const {
 
 /// Simplify a multiply expression. Return nullptr if it can't be simplified.
 static AffineExpr simplifyMul(AffineExpr lhs, AffineExpr rhs) {
+  // The caller should have checked that this constitutes a valid `AffineExpr`
+  // in principle.
+  assert(lhs.isSymbolicOrConstant() || rhs.isSymbolicOrConstant());
+
   auto lhsConst = dyn_cast<AffineConstantExpr>(lhs);
   auto rhsConst = dyn_cast<AffineConstantExpr>(rhs);
 
@@ -792,9 +796,6 @@ static AffineExpr simplifyMul(AffineExpr lhs, AffineExpr rhs) {
     return getAffineConstantExpr(product, lhs.getContext());
   }
 
-  if (!lhs.isSymbolicOrConstant() && !rhs.isSymbolicOrConstant())
-    return nullptr;
-
   // Canonicalize the mul expression so that the constant/symbolic term is the
   // RHS. If both the lhs and rhs are symbolic, swap them if the lhs is a
   // constant. (Note that a constant is trivially symbolic).
@@ -836,6 +837,11 @@ AffineExpr AffineExpr::operator*(int64_t v) const {
   return *this * getAffineConstantExpr(v, getContext());
 }
 AffineExpr AffineExpr::operator*(AffineExpr other) const {
+  // If neither LHS nor RHS are symbolic or constant, this product will not be a
+  // valid `AffineExpr`.
+  if (!this->isSymbolicOrConstant() && !other.isSymbolicOrConstant())
+    return nullptr;
+
   if (auto simplified = simplifyMul(*this, other))
     return simplified;
 
diff --git a/mlir/unittests/IR/AffineExprTest.cpp b/mlir/unittests/IR/AffineExprTest.cpp
index dc78bbac85f3cf..09f36e42a5c776 100644
--- a/mlir/unittests/IR/AffineExprTest.cpp
+++ b/mlir/unittests/IR/AffineExprTest.cpp
@@ -16,7 +16,7 @@
 using namespace mlir;
 
 // Test creating AffineExprs using the overloaded binary operators.
-TEST(AffineExprTest, constructFromBinaryOperators) {
+TEST(AffineExprTest, constructFromBinaryOperatorsWithDimRHS) {
   MLIRContext ctx;
   OpBuilder b(&ctx);
 
@@ -27,11 +27,39 @@ TEST(AffineExprTest, constructFromBinaryOperators) {
   auto difference = d0 - d1;
   auto product = d0 * d1;
   auto remainder = d0 % d1;
+  auto floorDiv = d0.floorDiv(d1);
+  auto ceilDiv = d0.ceilDiv(d1);
+
+  ASSERT_EQ(sum.getKind(), AffineExprKind::Add);
+  ASSERT_EQ(difference.getKind(), AffineExprKind::Add);
+  ASSERT_EQ(remainder.getKind(), AffineExprKind::Mod);
+  ASSERT_EQ(floorDiv.getKind(), AffineExprKind::FloorDiv);
+  ASSERT_EQ(ceilDiv.getKind(), AffineExprKind::CeilDiv);
+
+  // Invalid (semi-)affine expressions.
+  ASSERT_EQ(product, nullptr);
+}
+
+TEST(AffineExprTest, constructFromBinaryOperatorsWithConstRHS) {
+  MLIRContext ctx;
+  OpBuilder b(&ctx);
+
+  auto d0 = b.getAffineDimExpr(0);
+  auto d1 = b.getAffineConstantExpr(123);
+
+  auto sum = d0 + d1;
+  auto difference = d0 - d1;
+  auto product = d0 * d1;
+  auto remainder = d0 % d1;
+  auto floorDiv = d0.floorDiv(d1);
+  auto ceilDiv = d0.ceilDiv(d1);
 
   ASSERT_EQ(sum.getKind(), AffineExprKind::Add);
   ASSERT_EQ(difference.getKind(), AffineExprKind::Add);
   ASSERT_EQ(product.getKind(), AffineExprKind::Mul);
   ASSERT_EQ(remainder.getKind(), AffineExprKind::Mod);
+  ASSERT_EQ(floorDiv.getKind(), AffineExprKind::FloorDiv);
+  ASSERT_EQ(ceilDiv.getKind(), AffineExprKind::CeilDiv);
 }
 
 TEST(AffineExprTest, constantFolding) {



More information about the Mlir-commits mailing list