[flang-commits] [flang] [Flang] Check if two ArrayConstructor's are Equal (PR #121181)

Thirumalai Shaktivel via flang-commits flang-commits at lists.llvm.org
Mon Jan 27 00:50:37 PST 2025


https://github.com/Thirumalai-Shaktivel updated https://github.com/llvm/llvm-project/pull/121181

>From 63e1034d4e996849e4a297bce8b409cec18c31aa Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 27 Dec 2024 05:21:24 +0000
Subject: [PATCH 1/7] [Flang] Check if two ArrayConstructor's are Equal This
 also includes comparing the two ImpliedDo

Details:
- For ArrayConstructor, check if x and y have the same
  elements and type
- For ImpliedDo, check if x and y have the same lower,
  upper, stride and values
---
 flang/include/flang/Lower/Support/Utils.h | 44 ++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 1cc74521e22d88..5eb39a08898f16 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -545,9 +545,51 @@ class IsEqualEvaluateExpr {
     return isEqual(x.proc(), y.proc()) && isEqual(x.arguments(), y.arguments());
   }
   template <typename A>
+  static bool isEqual(const Fortran::evaluate::ImpliedDo<A> &x,
+                      const Fortran::evaluate::ImpliedDo<A> &y) {
+    using Expr = Fortran::evaluate::Expr<A>;
+    for (const auto &[xValue, yValue] : llvm::zip(x.values(), y.values())) {
+      bool checkValue = Fortran::common::visit(
+          common::visitors{
+              [&](const Expr &v, const Expr &w) { return isEqual(v, w); },
+              [&](const auto &, const auto &) {
+                llvm::report_fatal_error("isEqual is not handled yet for "
+                                         "the element type in ImpliedDo");
+                return false;
+              },
+          },
+          xValue.u, yValue.u);
+      if (!checkValue) {
+        return false;
+      }
+    }
+    return isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper()) &&
+           isEqual(x.stride(), y.stride());
+  }
+  template <typename A>
   static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
                       const Fortran::evaluate::ArrayConstructor<A> &y) {
-    llvm::report_fatal_error("not implemented");
+    for (const auto &[xValue, yValue] : llvm::zip(x, y)) {
+      using Expr = Fortran::evaluate::Expr<A>;
+      using ImpliedDo = Fortran::evaluate::ImpliedDo<A>;
+      bool checkElement = Fortran::common::visit(
+          common::visitors{
+              [&](const Expr &v, const Expr &w) { return isEqual(v, w); },
+              [&](const ImpliedDo &v, const ImpliedDo &w) {
+                return isEqual(v, w);
+              },
+              [&](const auto &, const auto &) {
+                llvm::report_fatal_error("isEqual is not handled yet for "
+                                         "the element type in ImpliedDo");
+                return false;
+              },
+          },
+          xValue.u, yValue.u);
+      if (!checkElement) {
+        return false;
+      }
+    }
+    return x.GetType() == y.GetType();
   }
   static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
                       const Fortran::evaluate::ImpliedDoIndex &y) {

>From 06b6e83462c2db0a0b89f0effd13297372cd8e50 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Fri, 27 Dec 2024 05:58:14 +0000
Subject: [PATCH 2/7] [Test] Add a test

---
 flang/test/Lower/OpenMP/atomic-update.f90 | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90
index 16dae9d5f301c1..7d04745015faab 100644
--- a/flang/test/Lower/OpenMP/atomic-update.f90
+++ b/flang/test/Lower/OpenMP/atomic-update.f90
@@ -185,4 +185,19 @@ program OmpAtomicUpdate
   !$omp atomic update
     w = max(w,x,y,z)
 
+!CHECK:  %[[IMP_DO:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
+!CHECK:  ^bb0(%{{.*}}: index):
+!          [...]
+!CHECK:    %[[ADD_I1:.*]] = arith.addi {{.*}} : i32
+!CHECK:    hlfir.yield_element %[[ADD_I1]] : i32
+!CHECK:  }
+!        [...]
+!CHECK:  %[[SUM:.*]] = hlfir.sum %[[IMP_DO]]
+!CHECK:  omp.atomic.update %[[VAL_X_DECLARE]]#1 : !fir.ref<i32> {
+!CHECK:  ^bb0(%[[ARG0:.*]]: i32):
+!CHECK:    %[[ADD_I2:.*]] = arith.addi %[[ARG0]], %[[SUM]] : i32
+!CHECK:    omp.yield(%[[ADD_I2]] : i32)
+!CHECK:  }
+  !$omp atomic update
+    x = x + sum([ (y+2, y=1, z) ])
 end program OmpAtomicUpdate

>From 0b5e7a876eb74a562c99f8dbea882606a8eeba4c Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 16 Jan 2025 10:10:23 +0000
Subject: [PATCH 3/7] [Flang] Add isEqual visitor  for ArrayConstructorValue

---
 flang/include/flang/Lower/Support/Utils.h | 42 ++++++++---------------
 1 file changed, 14 insertions(+), 28 deletions(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 5eb39a08898f16..742db701dacfbd 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -547,49 +547,35 @@ class IsEqualEvaluateExpr {
   template <typename A>
   static bool isEqual(const Fortran::evaluate::ImpliedDo<A> &x,
                       const Fortran::evaluate::ImpliedDo<A> &y) {
-    using Expr = Fortran::evaluate::Expr<A>;
-    for (const auto &[xValue, yValue] : llvm::zip(x.values(), y.values())) {
-      bool checkValue = Fortran::common::visit(
-          common::visitors{
-              [&](const Expr &v, const Expr &w) { return isEqual(v, w); },
-              [&](const auto &, const auto &) {
-                llvm::report_fatal_error("isEqual is not handled yet for "
-                                         "the element type in ImpliedDo");
-                return false;
-              },
-          },
-          xValue.u, yValue.u);
-      if (!checkValue) {
-        return false;
-      }
-    }
-    return isEqual(x.lower(), y.lower()) && isEqual(x.upper(), y.upper()) &&
-           isEqual(x.stride(), y.stride());
+    return isEqual(x.values(), y.values()) && isEqual(x.lower(), y.lower()) &&
+           isEqual(x.upper(), y.upper()) && isEqual(x.stride(), y.stride());
   }
   template <typename A>
-  static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
-                      const Fortran::evaluate::ArrayConstructor<A> &y) {
+  static bool isEqual(const Fortran::evaluate::ArrayConstructorValue<A> &x,
+                      const Fortran::evaluate::ArrayConstructorValue<A> &y) {
+    using Expr = Fortran::evaluate::Expr<A>;
+    using ImpliedDo = Fortran::evaluate::ImpliedDo<A>;
     for (const auto &[xValue, yValue] : llvm::zip(x, y)) {
-      using Expr = Fortran::evaluate::Expr<A>;
-      using ImpliedDo = Fortran::evaluate::ImpliedDo<A>;
       bool checkElement = Fortran::common::visit(
           common::visitors{
               [&](const Expr &v, const Expr &w) { return isEqual(v, w); },
               [&](const ImpliedDo &v, const ImpliedDo &w) {
                 return isEqual(v, w);
               },
-              [&](const auto &, const auto &) {
-                llvm::report_fatal_error("isEqual is not handled yet for "
-                                         "the element type in ImpliedDo");
-                return false;
-              },
+              [&](const Expr &, const ImpliedDo &) { return false; },
+              [&](const ImpliedDo &, const Expr &) { return false; },
           },
           xValue.u, yValue.u);
       if (!checkElement) {
         return false;
       }
     }
-    return x.GetType() == y.GetType();
+    return true;
+  }
+  template <typename A>
+  static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
+                      const Fortran::evaluate::ArrayConstructor<A> &y) {
+    return isEqual(x, y) && x.GetType() == y.GetType();
   }
   static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
                       const Fortran::evaluate::ImpliedDoIndex &y) {

>From 47acfec912ec16ae588241ae88cd179eeff740ae Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Thu, 16 Jan 2025 10:14:34 +0000
Subject: [PATCH 4/7] [Flang] Add check for CharacterType for ArrayConstructor

---
 flang/include/flang/Lower/Support/Utils.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 742db701dacfbd..b3dfe74fc6573a 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -575,7 +575,11 @@ class IsEqualEvaluateExpr {
   template <typename A>
   static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
                       const Fortran::evaluate::ArrayConstructor<A> &y) {
-    return isEqual(x, y) && x.GetType() == y.GetType();
+    bool checkCharacterType = true;
+    if constexpr (A::category == Fortran::common::TypeCategory::Character) {
+      checkCharacterType = x.LEN() == y.LEN();
+    }
+    return isEqual(x, y) && x.GetType() == y.GetType() && checkCharacterType;
   }
   static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
                       const Fortran::evaluate::ImpliedDoIndex &y) {

>From 8d7305b3b73d36131d4434030c97e9a0b27f3233 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Tue, 21 Jan 2025 07:33:08 +0000
Subject: [PATCH 5/7] Fix type conflicts

---
 flang/include/flang/Lower/Support/Utils.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index b3dfe74fc6573a..7159f049a08a26 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -551,8 +551,8 @@ class IsEqualEvaluateExpr {
            isEqual(x.upper(), y.upper()) && isEqual(x.stride(), y.stride());
   }
   template <typename A>
-  static bool isEqual(const Fortran::evaluate::ArrayConstructorValue<A> &x,
-                      const Fortran::evaluate::ArrayConstructorValue<A> &y) {
+  static bool isEqual(const Fortran::evaluate::ArrayConstructorValues<A> &x,
+                      const Fortran::evaluate::ArrayConstructorValues<A> &y) {
     using Expr = Fortran::evaluate::Expr<A>;
     using ImpliedDo = Fortran::evaluate::ImpliedDo<A>;
     for (const auto &[xValue, yValue] : llvm::zip(x, y)) {
@@ -579,7 +579,9 @@ class IsEqualEvaluateExpr {
     if constexpr (A::category == Fortran::common::TypeCategory::Character) {
       checkCharacterType = x.LEN() == y.LEN();
     }
-    return isEqual(x, y) && x.GetType() == y.GetType() && checkCharacterType;
+    using Base = Fortran::evaluate::ArrayConstructorValues<A>;
+    return isEqual((Base) x, (Base) y) &&
+           (x.GetType() == y.GetType() && checkCharacterType);
   }
   static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
                       const Fortran::evaluate::ImpliedDoIndex &y) {

>From 595c4f64512df0555ebb0360ddd6ba40323487f2 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Tue, 21 Jan 2025 08:09:30 +0000
Subject: [PATCH 6/7] Fix clang format

---
 flang/include/flang/Lower/Support/Utils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 7159f049a08a26..7dc380c40c012e 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -580,7 +580,7 @@ class IsEqualEvaluateExpr {
       checkCharacterType = x.LEN() == y.LEN();
     }
     using Base = Fortran::evaluate::ArrayConstructorValues<A>;
-    return isEqual((Base) x, (Base) y) &&
+    return isEqual((Base)x, (Base)y) &&
            (x.GetType() == y.GetType() && checkCharacterType);
   }
   static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,

>From 6442b335c2a5d2560b3a67aed6d87e36eeea88e5 Mon Sep 17 00:00:00 2001
From: Thirumalai-Shaktivel <thirumalaishaktivel at gmail.com>
Date: Mon, 27 Jan 2025 08:42:15 +0000
Subject: [PATCH 7/7] [Flang] Move the check inside `isEqual`

---
 flang/include/flang/Lower/Support/Utils.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index 7dc380c40c012e..f50288ff4d7cfa 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -572,12 +572,16 @@ class IsEqualEvaluateExpr {
     }
     return true;
   }
+  static bool isEqual(const Fortran::evaluate::SubscriptInteger &x,
+                      const Fortran::evaluate::SubscriptInteger &y) {
+  return x == y;
+  }
   template <typename A>
   static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
                       const Fortran::evaluate::ArrayConstructor<A> &y) {
     bool checkCharacterType = true;
     if constexpr (A::category == Fortran::common::TypeCategory::Character) {
-      checkCharacterType = x.LEN() == y.LEN();
+      checkCharacterType = isEqual(*x.LEN(), *y.LEN());
     }
     using Base = Fortran::evaluate::ArrayConstructorValues<A>;
     return isEqual((Base)x, (Base)y) &&



More information about the flang-commits mailing list