[flang-commits] [flang] [flang] Ignore subscript conversions when reassociating sums (PR #222302)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Wed Sep 9 04:21:42 PDT 2026
https://github.com/tblah created https://github.com/llvm/llvm-project/pull/222302
Implicit conversions of INTEGER(4) array indices to SubscriptInteger were treated as conversions in the surrounding floating-point sum, preventing reassociation of ordinary array-element expressions.
Stop only the conversion traversal at subscripts. Keep the independent side-effect and volatile/asynchronous checks and embedded numeric conversion restrictions unchanged.
Assisted-by: Codex
>From 10832a8bfbc78e20968e9a4388d8934bdbbdcb79 Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Wed, 9 Sep 2026 12:05:10 +0100
Subject: [PATCH] [flang] Ignore subscript conversions when reassociating sums
Implicit conversions of INTEGER(4) array indices to SubscriptInteger
were treated as conversions in the surrounding floating-point sum,
preventing reassociation of ordinary array-element expressions.
Stop only the conversion traversal at subscripts. Keep the independent
side-effect and volatile/asynchronous checks and embedded numeric
conversion restrictions unchanged.
Assisted-by: Codex
---
flang/lib/Evaluate/tools.cpp | 4 +
flang/test/Lower/OpenACC/acc-cache.f90 | 2 +-
.../split-sum-expression-tree-subscripts.f90 | 100 ++++++++++++++++++
3 files changed, 105 insertions(+), 1 deletion(-)
create mode 100644 flang/test/Lower/split-sum-expression-tree-subscripts.f90
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 6c8ee3da0046f..def85232cc572 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1416,6 +1416,10 @@ struct HasConversionHelper : public AnyTraverse<HasConversionHelper> {
using Base = AnyTraverse<HasConversionHelper>;
HasConversionHelper() : Base{*this} {}
using Base::operator();
+ // Subscript conversions belong to the array designator and are preserved
+ // when reassociating the surrounding numeric expression. In particular,
+ // implicit conversions to SubscriptInteger must not inhibit reassociation.
+ bool operator()(const Subscript &) const { return false; }
template <typename TO, common::TypeCategory FROM>
bool operator()(const Convert<TO, FROM> &) const {
return true;
diff --git a/flang/test/Lower/OpenACC/acc-cache.f90 b/flang/test/Lower/OpenACC/acc-cache.f90
index 12bdee3833870..9bdacc17cd984 100644
--- a/flang/test/Lower/OpenACC/acc-cache.f90
+++ b/flang/test/Lower/OpenACC/acc-cache.f90
@@ -212,10 +212,10 @@ subroutine test_cache_loop_var()
! CHECK: fir.load
! CHECK: hlfir.designate %[[DECL]]#0
! CHECK: fir.load
-! CHECK: arith.addf
! CHECK: hlfir.designate %[[DECL]]#0
! CHECK: fir.load
! CHECK: arith.addf
+! CHECK: arith.addf
! CHECK: hlfir.assign
! Scope termination
! CHECK: acc.yield
diff --git a/flang/test/Lower/split-sum-expression-tree-subscripts.f90 b/flang/test/Lower/split-sum-expression-tree-subscripts.f90
new file mode 100644
index 0000000000000..aac09e4443465
--- /dev/null
+++ b/flang/test/Lower/split-sum-expression-tree-subscripts.f90
@@ -0,0 +1,100 @@
+! RUN: %flang_fc1 -emit-hlfir -O0 -o - %s | FileCheck %s --check-prefixes=SPLIT,GUARD
+! RUN: %flang_fc1 -emit-hlfir -O3 -o - %s | FileCheck %s --check-prefixes=SPLIT,GUARD
+! RUN: %flang_fc1 -emit-hlfir -ffp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,GUARD
+! RUN: %flang_fc1 -emit-hlfir -fno-fp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=ORDERED,GUARD
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=SPLIT,GUARD
+! RUN: bbc -emit-hlfir -ffp-sum-reassociation=false -o - %s | FileCheck %s --check-prefixes=ORDERED,GUARD
+
+! The implicit INTEGER(4)-to-INTEGER(8) conversions in array subscripts
+! must not prevent reassociation of the REAL(8) sum (as in SNbone).
+subroutine array_elements(i,x,a,b,c,d,e,f)
+ integer(4) :: i
+ real(8) :: x(100),a(100),b(100),c(100),d(100),e(100),f(100)
+ x(i) = x(i) + a(i)*b(i) + c(i)*d(i) + e(i)*f(i)
+end
+
+! SPLIT-LABEL: func.func @_QParray_elements
+! SPLIT: %[[CD:.*]] = arith.mulf
+! SPLIT: %[[EF:.*]] = arith.mulf
+! SPLIT: %[[TAIL:.*]] = arith.addf %[[CD]], %[[EF]]
+! SPLIT: %[[AB:.*]] = arith.mulf
+! SPLIT: %[[HEAD:.*]] = arith.addf %{{.*}}, %[[AB]]
+! SPLIT: %[[SUM:.*]] = arith.addf %[[TAIL]], %[[HEAD]]
+! SPLIT: hlfir.assign %[[SUM]]
+
+! ORDERED-LABEL: func.func @_QParray_elements
+! ORDERED: %[[AB:.*]] = arith.mulf
+! ORDERED: %[[XAB:.*]] = arith.addf %{{.*}}, %[[AB]]
+! ORDERED: %[[CD:.*]] = arith.mulf
+! ORDERED: %[[XABCD:.*]] = arith.addf %[[XAB]], %[[CD]]
+! ORDERED: %[[EF:.*]] = arith.mulf
+! ORDERED: %[[SUM:.*]] = arith.addf %[[XABCD]], %[[EF]]
+! ORDERED: hlfir.assign %[[SUM]]
+
+! Both levels of indexing contain integer conversions.
+subroutine nested_subscript(i,j,x,a,b,c,d,e,f)
+ integer(4) :: i,j(100)
+ real(8) :: x(100),a,b,c,d,e,f
+ x(j(i)) = x(j(i)) + a*b + c*d + e*f
+end
+
+! SPLIT-LABEL: func.func @_QPnested_subscript
+! SPLIT: %[[CD:.*]] = arith.mulf
+! SPLIT: %[[EF:.*]] = arith.mulf
+! SPLIT: %[[TAIL:.*]] = arith.addf %[[CD]], %[[EF]]
+! SPLIT: %[[AB:.*]] = arith.mulf
+! SPLIT: %[[HEAD:.*]] = arith.addf %{{.*}}, %[[AB]]
+! SPLIT: %[[SUM:.*]] = arith.addf %[[TAIL]], %[[HEAD]]
+! SPLIT: hlfir.assign %[[SUM]]
+
+! ORDERED-LABEL: func.func @_QPnested_subscript
+! ORDERED: %[[AB:.*]] = arith.mulf
+! ORDERED: %[[XAB:.*]] = arith.addf %{{.*}}, %[[AB]]
+! ORDERED: %[[CD:.*]] = arith.mulf
+! ORDERED: %[[XABCD:.*]] = arith.addf %[[XAB]], %[[CD]]
+! ORDERED: %[[EF:.*]] = arith.mulf
+! ORDERED: %[[SUM:.*]] = arith.addf %[[XABCD]], %[[EF]]
+! ORDERED: hlfir.assign %[[SUM]]
+
+! A conversion of a real value used only as a subscript is also preserved.
+subroutine real_subscript_conversion(r,x,a,b,c,d,e,f)
+ real(4) :: r
+ real(8) :: x(100),a,b,c,d,e,f
+ x(int(r,8)) = x(int(r,8)) + a*b + c*d + e*f
+end
+
+! SPLIT-LABEL: func.func @_QPreal_subscript_conversion
+! SPLIT: %[[CD:.*]] = arith.mulf
+! SPLIT: %[[EF:.*]] = arith.mulf
+! SPLIT: %[[TAIL:.*]] = arith.addf %[[CD]], %[[EF]]
+! SPLIT: fir.convert %{{.*}} : (f32) -> i64
+! SPLIT: %[[AB:.*]] = arith.mulf
+! SPLIT: %[[HEAD:.*]] = arith.addf %{{.*}}, %[[AB]]
+! SPLIT: %[[SUM:.*]] = arith.addf %[[TAIL]], %[[HEAD]]
+! SPLIT: hlfir.assign %[[SUM]]
+
+! ORDERED-LABEL: func.func @_QPreal_subscript_conversion
+! ORDERED: %[[AB:.*]] = arith.mulf
+! ORDERED: %[[XAB:.*]] = arith.addf %{{.*}}, %[[AB]]
+! ORDERED: %[[CD:.*]] = arith.mulf
+! ORDERED: %[[XABCD:.*]] = arith.addf %[[XAB]], %[[CD]]
+! ORDERED: %[[EF:.*]] = arith.mulf
+! ORDERED: %[[SUM:.*]] = arith.addf %[[XABCD]], %[[EF]]
+! ORDERED: hlfir.assign %[[SUM]]
+
+! Ignoring subscript conversions must not hide a conversion in the real sum.
+subroutine mixed_kind_array_elements(i,x,a,b,c,d,e,f)
+ integer(4) :: i
+ real(8) :: x,a(100),b(100),c(100),d(100)
+ real(4) :: e(100),f(100)
+ x = a(i)*b(i) + c(i)*d(i) + real(e(i)*f(i),8)
+end
+
+! GUARD-LABEL: func.func @_QPmixed_kind_array_elements
+! GUARD: %[[AB:.*]] = arith.mulf
+! GUARD: %[[CD:.*]] = arith.mulf
+! GUARD: %[[HEAD:.*]] = arith.addf %[[AB]], %[[CD]]
+! GUARD: %[[EF:.*]] = arith.mulf %{{.*}}, %{{.*}} {{.*}} : f32
+! GUARD: %[[CONVERT:.*]] = fir.convert %[[EF]] : (f32) -> f64
+! GUARD: %[[SUM:.*]] = arith.addf %[[HEAD]], %[[CONVERT]]
+! GUARD: hlfir.assign %[[SUM]]
More information about the flang-commits
mailing list