[flang-commits] [clang] [flang] [flang][Lower] Add complex sum reassociation (PR #214775)

Tom Eccles via flang-commits flang-commits at lists.llvm.org
Mon Aug 10 04:24:37 PDT 2026


https://github.com/tblah updated https://github.com/llvm/llvm-project/pull/214775

>From 7dd15ee0cd04457d95cd9b03bba10a6c9c96ca6b Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Tue, 4 Aug 2026 14:18:23 +0100
Subject: [PATCH 1/2] [Flang][Lower] Add complex sum reassociation

Third part of generalisations requested in #207377.

Extend the experimental split-sum transformation to complex addition
and subtraction chains. Share the signed-term builder across explicitly
supported real and complex categories while keeping integer expressions
excluded.

There are no known effect on benchmarks as a result of this patch.

Assisted-by: Codex
---
 clang/include/clang/Options/FlangOptions.td   | 14 +--
 flang/include/flang/Evaluate/tools.h          |  6 +-
 flang/lib/Evaluate/tools.cpp                  | 98 ++++++++++---------
 flang/test/Driver/driver-help.f90             |  4 +-
 .../split-sum-expression-tree-lowering.f90    | 88 +++++++++++++++++
 5 files changed, 152 insertions(+), 58 deletions(-)

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index bafc063663fe2..3950847251828 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -315,16 +315,16 @@ defm real_sum_reassociation
           "f", "real-sum-reassociation",
           PosFlag<SetTrue, [], [],
                   "Enable Fortran-standard compliant reassociation within "
-                  "individual REAL sum expressions. This may change exact "
-                  "floating-point results">,
+                  "individual REAL and COMPLEX sum expressions. This may "
+                  "change exact floating-point results">,
           NegFlag<SetFalse, [], [],
-                  "Disable reassociation within individual REAL sum "
-                  "expressions">>,
+                  "Disable reassociation within individual REAL and COMPLEX "
+                  "sum expressions">>,
       DocBrief<[{
         Enable Fortran-standard compliant reassociation within individual
-        ``REAL`` sum expressions. This can improve optimization opportunities
-        and may change exact floating-point results while preserving
-        standard-conforming Fortran semantics.
+        ``REAL`` and ``COMPLEX`` sum expressions. This can improve optimization
+        opportunities and may change exact floating-point results while
+        preserving standard-conforming Fortran semantics.
       }]>;
 
 defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero",
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index cce2325b33da7..c877ec5f5705b 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1126,12 +1126,12 @@ bool HasProcedureRef(const Expr<SomeType> &expr);
 // Predicate: does an expression contain a VOLATILE or ASYNCHRONOUS symbol?
 bool HasVolatileOrAsynchronousSymbol(const Expr<SomeType> &expr);
 
-// Can a scalar real RHS expression in an assignment be rewritten as a split
-// sum expression tree?
+// Can a scalar real or complex RHS expression in an assignment be rewritten
+// as a split sum expression tree?
 bool CanBuildSplitSumExpressionTree(
     const Expr<SomeType> &lhs, const Expr<SomeType> &rhs);
 
-// Try to rewrite a scalar real sum as a split sum expression tree.
+// Try to rewrite a scalar real or complex sum as a split sum expression tree.
 std::optional<Expr<SomeType>> TryBuildSplitSumExpressionTree(
     const Expr<SomeType> &expr);
 
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 34deaaea289c1..589aab5132a65 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1382,76 +1382,79 @@ bool HasVolatileOrAsynchronousSymbol(const Expr<SomeType> &expr) {
 
 namespace {
 
-template <int KIND> using Real = Type<common::TypeCategory::Real, KIND>;
+template <common::TypeCategory CAT, int KIND> using Numeric = Type<CAT, KIND>;
 
-template <int KIND> using RealExpr = Expr<Real<KIND>>;
+template <common::TypeCategory CAT, int KIND>
+using NumericExpr = Expr<Numeric<CAT, KIND>>;
 
-template <int KIND> struct SignedRealTerm {
-  RealExpr<KIND> expr;
+template <common::TypeCategory CAT, int KIND> struct SignedNumericTerm {
+  NumericExpr<CAT, KIND> expr;
   bool isPositive;
 };
 
-template <int KIND> struct SignedRealExpr {
-  RealExpr<KIND> expr;
+template <common::TypeCategory CAT, int KIND> struct SignedNumericExpr {
+  NumericExpr<CAT, KIND> expr;
   bool isPositive;
 };
 
-template <int KIND>
-static void flattenTopLevelAddSubtract(const RealExpr<KIND> &expr,
-    llvm::SmallVectorImpl<SignedRealTerm<KIND>> &terms,
+template <common::TypeCategory CAT, int KIND>
+static void flattenTopLevelAddSubtract(const NumericExpr<CAT, KIND> &expr,
+    llvm::SmallVectorImpl<SignedNumericTerm<CAT, KIND>> &terms,
     bool isPositive = true) {
-  // Only flatten real Add and Subtract nodes. Every other node, including
+  // Only flatten Add and Subtract nodes. Every other node, including
   // Parentheses, is one opaque signed term whose tree is preserved.
-  if (const auto *add = std::get_if<Add<Real<KIND>>>(&expr.u)) {
+  if (const auto *add = std::get_if<Add<Numeric<CAT, KIND>>>(&expr.u)) {
     flattenTopLevelAddSubtract(add->left(), terms, isPositive);
     flattenTopLevelAddSubtract(add->right(), terms, isPositive);
     return;
   }
-  if (const auto *subtract = std::get_if<Subtract<Real<KIND>>>(&expr.u)) {
+  if (const auto *subtract =
+          std::get_if<Subtract<Numeric<CAT, KIND>>>(&expr.u)) {
     flattenTopLevelAddSubtract(subtract->left(), terms, isPositive);
     flattenTopLevelAddSubtract(subtract->right(), terms, !isPositive);
     return;
   }
-  terms.push_back(SignedRealTerm<KIND>{expr, isPositive});
+  terms.push_back(SignedNumericTerm<CAT, KIND>{expr, isPositive});
 }
 
-template <int KIND>
-static SignedRealExpr<KIND> buildRightAssociatedSignedFold(
-    llvm::MutableArrayRef<SignedRealTerm<KIND>> terms) {
+template <common::TypeCategory CAT, int KIND>
+static SignedNumericExpr<CAT, KIND> buildRightAssociatedSignedFold(
+    llvm::MutableArrayRef<SignedNumericTerm<CAT, KIND>> terms) {
   assert(!terms.empty() && "cannot build empty signed fold");
   const bool isPositive{terms.front().isPositive};
-  RealExpr<KIND> result{std::move(terms.back().expr)};
+  NumericExpr<CAT, KIND> result{std::move(terms.back().expr)};
   for (std::size_t i{terms.size() - 1}; i > 0; --i) {
-    SignedRealTerm<KIND> &term{terms[i - 1]};
+    SignedNumericTerm<CAT, KIND> &term{terms[i - 1]};
     const bool useAdd{term.isPositive == terms[i].isPositive};
     if (useAdd)
-      result = RealExpr<KIND>{
-          Add<Real<KIND>>{std::move(term.expr), std::move(result)}};
+      result = NumericExpr<CAT, KIND>{
+          Add<Numeric<CAT, KIND>>{std::move(term.expr), std::move(result)}};
     else
-      result = RealExpr<KIND>{
-          Subtract<Real<KIND>>{std::move(term.expr), std::move(result)}};
+      result = NumericExpr<CAT, KIND>{Subtract<Numeric<CAT, KIND>>{
+          std::move(term.expr), std::move(result)}};
   }
-  return SignedRealExpr<KIND>{std::move(result), isPositive};
+  return SignedNumericExpr<CAT, KIND>{std::move(result), isPositive};
 }
 
-template <int KIND>
-static SignedRealExpr<KIND> buildSignedAdd(
-    SignedRealExpr<KIND> left, SignedRealExpr<KIND> right) {
+template <common::TypeCategory CAT, int KIND>
+static SignedNumericExpr<CAT, KIND> buildSignedAdd(
+    SignedNumericExpr<CAT, KIND> left, SignedNumericExpr<CAT, KIND> right) {
   if (left.isPositive == right.isPositive) {
-    return SignedRealExpr<KIND>{
-        RealExpr<KIND>{
-            Add<Real<KIND>>{std::move(left.expr), std::move(right.expr)}},
+    return SignedNumericExpr<CAT, KIND>{
+        NumericExpr<CAT, KIND>{Add<Numeric<CAT, KIND>>{
+            std::move(left.expr), std::move(right.expr)}},
         left.isPositive};
   }
   if (left.isPositive) {
-    return SignedRealExpr<KIND>{
-        RealExpr<KIND>{
-            Subtract<Real<KIND>>{std::move(left.expr), std::move(right.expr)}},
+    return SignedNumericExpr<CAT, KIND>{
+        NumericExpr<CAT, KIND>{Subtract<Numeric<CAT, KIND>>{
+            std::move(left.expr), std::move(right.expr)}},
         true};
   }
   // Prefer Y-X to introducing a unary negation for -X+Y.
-  return SignedRealExpr<KIND>{RealExpr<KIND>{Subtract<Real<KIND>>{
-                                  std::move(right.expr), std::move(left.expr)}},
+  return SignedNumericExpr<CAT, KIND>{
+      NumericExpr<CAT, KIND>{Subtract<Numeric<CAT, KIND>>{
+          std::move(right.expr), std::move(left.expr)}},
       true};
 }
 
@@ -1460,25 +1463,25 @@ static std::optional<Expr<SomeType>> tryBuildSplitSumExpressionTree(const T &) {
   return std::nullopt;
 }
 
-template <int KIND>
+template <common::TypeCategory CAT, int KIND>
 static std::optional<Expr<SomeType>> tryBuildSplitSumExpressionTree(
-    const RealExpr<KIND> &expr) {
-  if (!std::get_if<Add<Real<KIND>>>(&expr.u) &&
-      !std::get_if<Subtract<Real<KIND>>>(&expr.u))
+    const NumericExpr<CAT, KIND> &expr) {
+  if (!std::get_if<Add<Numeric<CAT, KIND>>>(&expr.u) &&
+      !std::get_if<Subtract<Numeric<CAT, KIND>>>(&expr.u))
     return std::nullopt;
 
-  llvm::SmallVector<SignedRealTerm<KIND>, 8> terms;
+  llvm::SmallVector<SignedNumericTerm<CAT, KIND>, 8> terms;
   flattenTopLevelAddSubtract(expr, terms);
   if (terms.size() <= 2)
     return std::nullopt;
 
-  llvm::MutableArrayRef<SignedRealTerm<KIND>> head{terms.data(), 2};
-  llvm::MutableArrayRef<SignedRealTerm<KIND>> tail{
+  llvm::MutableArrayRef<SignedNumericTerm<CAT, KIND>> head{terms.data(), 2};
+  llvm::MutableArrayRef<SignedNumericTerm<CAT, KIND>> tail{
       terms.data() + 2, terms.size() - 2};
-  SignedRealExpr<KIND> headExpr = buildRightAssociatedSignedFold<KIND>(head);
-  SignedRealExpr<KIND> tailExpr = buildRightAssociatedSignedFold<KIND>(tail);
-  SignedRealExpr<KIND> result =
-      buildSignedAdd<KIND>(std::move(tailExpr), std::move(headExpr));
+  SignedNumericExpr<CAT, KIND> headExpr = buildRightAssociatedSignedFold(head);
+  SignedNumericExpr<CAT, KIND> tailExpr = buildRightAssociatedSignedFold(tail);
+  SignedNumericExpr<CAT, KIND> result =
+      buildSignedAdd(std::move(tailExpr), std::move(headExpr));
   assert(result.isPositive &&
       "the first flattened term and therefore the split sum are positive");
   return Expr<SomeType>{std::move(result.expr)};
@@ -1487,7 +1490,10 @@ static std::optional<Expr<SomeType>> tryBuildSplitSumExpressionTree(
 template <common::TypeCategory CAT>
 static std::optional<Expr<SomeType>> tryBuildSplitSumExpressionTree(
     const Expr<SomeKind<CAT>> &expr) {
-  if constexpr (CAT == common::TypeCategory::Real) {
+  // Keep the supported categories explicit: integer reassociation requires a
+  // separate intermediate-range policy.
+  if constexpr (CAT == common::TypeCategory::Real ||
+      CAT == common::TypeCategory::Complex) {
     return common::visit(
         [&](const auto &typedExpr) -> std::optional<Expr<SomeType>> {
           return tryBuildSplitSumExpressionTree(typedExpr);
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index e77fc460850b2..c7c9ef887c594 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -8,14 +8,14 @@
 ! HELP-EMPTY:
 ! HELP-NEXT:OPTIONS:
 ! HELP: -freal-sum-reassociation
-! HELP: Enable Fortran-standard compliant reassociation within individual REAL sum expressions
+! HELP: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP: may change exact floating-point results
 
 ! HELP-FC1:USAGE: flang
 ! HELP-FC1-EMPTY:
 ! HELP-FC1-NEXT:OPTIONS:
 ! HELP-FC1: -freal-sum-reassociation
-! HELP-FC1: Enable Fortran-standard compliant reassociation within individual REAL sum expressions
+! HELP-FC1: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP-FC1: may change exact floating-point results
 
 ! ERROR: error: unknown argument '-helps'; did you mean '-help'
diff --git a/flang/test/Lower/split-sum-expression-tree-lowering.f90 b/flang/test/Lower/split-sum-expression-tree-lowering.f90
index 1b1400f756177..93bb4396348c7 100644
--- a/flang/test/Lower/split-sum-expression-tree-lowering.f90
+++ b/flang/test/Lower/split-sum-expression-tree-lowering.f90
@@ -587,6 +587,94 @@ subroutine eligible_nested_unparenthesized_subtraction(x,a,b,c,d)
 ! DEFAULT: %[[RES:.*]] = arith.addf %[[XABC]], %[[DV]]
 ! DEFAULT: hlfir.assign %[[RES]] to %[[X]]#0
 
+! Complex addition and subtraction use the same signed-term split. The
+! parenthesized c-d remains one opaque no_reassoc value.
+! Default:   (((x - a) + b) - (c-d))
+! Rewritten: (b - (c-d)) + (x - a)
+subroutine eligible_complex_signed_parenthesized(x,a,b,c,d)
+  complex(4) :: x,a,b,c,d
+  x = x - a + b - (c-d)
+end
+
+! SPLIT-LABEL: func.func @_QPeligible_complex_signed_parenthesized
+! SPLIT-DAG: %[[A:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEa"}
+! SPLIT-DAG: %[[B:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEb"}
+! SPLIT-DAG: %[[C:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEc"}
+! SPLIT-DAG: %[[D:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEd"}
+! SPLIT-DAG: %[[X:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEx"}
+! SPLIT: %[[BV:.*]] = fir.load %[[B]]#0
+! SPLIT: %[[CV:.*]] = fir.load %[[C]]#0
+! SPLIT: %[[DV:.*]] = fir.load %[[D]]#0
+! SPLIT: %[[CD_SUB:.*]] = fir.subc %[[CV]], %[[DV]] {{.*}} : complex<f32>
+! SPLIT: %[[CD:.*]] = hlfir.no_reassoc %[[CD_SUB]] : complex<f32>
+! SPLIT: %[[TAIL:.*]] = fir.subc %[[BV]], %[[CD]] {{.*}} : complex<f32>
+! SPLIT: %[[XV:.*]] = fir.load %[[X]]#0
+! SPLIT: %[[AV:.*]] = fir.load %[[A]]#0
+! SPLIT: %[[HEAD:.*]] = fir.subc %[[XV]], %[[AV]] {{.*}} : complex<f32>
+! SPLIT: %[[RES:.*]] = fir.addc %[[TAIL]], %[[HEAD]] {{.*}} : complex<f32>
+! SPLIT: hlfir.assign %[[RES]] to %[[X]]#0
+
+! DEFAULT-LABEL: func.func @_QPeligible_complex_signed_parenthesized
+! DEFAULT-DAG: %[[A:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEa"}
+! DEFAULT-DAG: %[[B:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEb"}
+! DEFAULT-DAG: %[[C:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEc"}
+! DEFAULT-DAG: %[[D:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEd"}
+! DEFAULT-DAG: %[[X:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_signed_parenthesizedEx"}
+! DEFAULT: %[[XV:.*]] = fir.load %[[X]]#0
+! DEFAULT: %[[AV:.*]] = fir.load %[[A]]#0
+! DEFAULT: %[[XA:.*]] = fir.subc %[[XV]], %[[AV]] {{.*}} : complex<f32>
+! DEFAULT: %[[BV:.*]] = fir.load %[[B]]#0
+! DEFAULT: %[[XAB:.*]] = fir.addc %[[XA]], %[[BV]] {{.*}} : complex<f32>
+! DEFAULT: %[[CV:.*]] = fir.load %[[C]]#0
+! DEFAULT: %[[DV:.*]] = fir.load %[[D]]#0
+! DEFAULT: %[[CD_SUB:.*]] = fir.subc %[[CV]], %[[DV]] {{.*}} : complex<f32>
+! DEFAULT: %[[CD:.*]] = hlfir.no_reassoc %[[CD_SUB]] : complex<f32>
+! DEFAULT: %[[RES:.*]] = fir.subc %[[XAB]], %[[CD]] {{.*}} : complex<f32>
+! DEFAULT: hlfir.assign %[[RES]] to %[[X]]#0
+
+! A second complex kind exercises category dispatch independently of kind.
+! Default:   (((x + a) + b) + c)
+! Rewritten: (b + c) + (x + a)
+subroutine eligible_complex_kind8(x,a,b,c)
+  complex(8) :: x,a,b,c
+  x = x + a + b + c
+end
+
+! SPLIT-LABEL: func.func @_QPeligible_complex_kind8
+! SPLIT-DAG: %[[A:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_kind8Ea"}
+! SPLIT-DAG: %[[B:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_kind8Eb"}
+! SPLIT-DAG: %[[C:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_kind8Ec"}
+! SPLIT-DAG: %[[X:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFeligible_complex_kind8Ex"}
+! SPLIT: %[[BV:.*]] = fir.load %[[B]]#0
+! SPLIT: %[[CV:.*]] = fir.load %[[C]]#0
+! SPLIT: %[[TAIL:.*]] = fir.addc %[[BV]], %[[CV]] {{.*}} : complex<f64>
+! SPLIT: %[[XV:.*]] = fir.load %[[X]]#0
+! SPLIT: %[[AV:.*]] = fir.load %[[A]]#0
+! SPLIT: %[[HEAD:.*]] = fir.addc %[[XV]], %[[AV]] {{.*}} : complex<f64>
+! SPLIT: %[[RES:.*]] = fir.addc %[[TAIL]], %[[HEAD]] {{.*}} : complex<f64>
+! SPLIT: hlfir.assign %[[RES]] to %[[X]]#0
+
+! It isn't as useful to re-write integer expressions because the middle-end can
+! already re-associate them somewhat (within the bounds of avoiding overflow).
+subroutine guard_integer(x,a,b,c)
+  integer :: x,a,b,c
+  x = x + a - b + c
+end
+
+! NO-REWRITE-LABEL: func.func @_QPguard_integer
+! NO-REWRITE-DAG: %[[A:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFguard_integerEa"}
+! NO-REWRITE-DAG: %[[B:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFguard_integerEb"}
+! NO-REWRITE-DAG: %[[C:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFguard_integerEc"}
+! NO-REWRITE-DAG: %[[X:.*]]:2 = hlfir.declare {{.*}} {uniq_name = "_QFguard_integerEx"}
+! NO-REWRITE: %[[XV:.*]] = fir.load %[[X]]#0
+! NO-REWRITE: %[[AV:.*]] = fir.load %[[A]]#0
+! NO-REWRITE: %[[XA:.*]] = arith.addi %[[XV]], %[[AV]]
+! NO-REWRITE: %[[BV:.*]] = fir.load %[[B]]#0
+! NO-REWRITE: %[[XAB:.*]] = arith.subi %[[XA]], %[[BV]]
+! NO-REWRITE: %[[CV:.*]] = fir.load %[[C]]#0
+! NO-REWRITE: %[[RES:.*]] = arith.addi %[[XAB]], %[[CV]]
+! NO-REWRITE: hlfir.assign %[[RES]] to %[[X]]#0
+
 ! Subtraction immediately outside a parenthesized term changes the term's
 ! outer sign, but the parenthesized b-c remains one opaque no_reassoc value.
 ! Default:   (((x + a) - (b-c)) + d)

>From 487989ccccbf531d3f0f1e41e76109a1b53aee83 Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Mon, 10 Aug 2026 12:21:02 +0100
Subject: [PATCH 2/2] Rename flag to -fsum-association

Aliases with the old names are retained.
---
 clang/include/clang/Options/FlangOptions.td   |  9 +++-
 clang/lib/Driver/ToolChains/Flang.cpp         |  4 +-
 flang/lib/Frontend/CompilerInvocation.cpp     |  4 +-
 flang/test/Driver/driver-help.f90             |  6 ++-
 flang/test/Driver/real-sum-reassociation.f90  | 27 ------------
 flang/test/Driver/sum-reassociation.f90       | 43 +++++++++++++++++++
 .../split-sum-expression-tree-lowering.f90    |  4 +-
 7 files changed, 60 insertions(+), 37 deletions(-)
 delete mode 100644 flang/test/Driver/real-sum-reassociation.f90
 create mode 100644 flang/test/Driver/sum-reassociation.f90

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 3950847251828..0d06043586736 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -310,9 +310,9 @@ def ffast_real_mod : Flag<["-"], "ffast-real-mod">, Group<f_Group>,
 def fno_fast_real_mod : Flag<["-"], "fno-fast-real-mod">, Group<f_Group>,
   HelpText<"Disable optimization of MOD for REAL types in presence of -ffast-math">;
 
-defm real_sum_reassociation
+defm sum_reassociation
     : BoolOptionWithoutMarshalling<
-          "f", "real-sum-reassociation",
+          "f", "sum-reassociation",
           PosFlag<SetTrue, [], [],
                   "Enable Fortran-standard compliant reassociation within "
                   "individual REAL and COMPLEX sum expressions. This may "
@@ -327,6 +327,11 @@ defm real_sum_reassociation
         preserving standard-conforming Fortran semantics.
       }]>;
 
+def freal_sum_reassociation : Flag<["-"], "freal-sum-reassociation">,
+  Flags<[HelpHidden]>, Alias<fsum_reassociation>;
+def fno_real_sum_reassociation : Flag<["-"], "fno-real-sum-reassociation">,
+  Flags<[HelpHidden]>, Alias<fno_sum_reassociation>;
+
 defm init_global_zero : BoolOptionWithoutMarshalling<"f", "init-global-zero",
   PosFlag<SetTrue, [], [], "Zero initialize globals without default initialization (default)">,
   NegFlag<SetFalse, [], [], "Do not zero initialize globals without default initialization">>;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 7ea657ad49474..e8e411755cf00 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -337,8 +337,8 @@ void Flang::addCodegenOptions(const ArgList &Args,
 
   Args.addOptInFlag(CmdArgs, options::OPT_fexperimental_loop_fusion,
                     options::OPT_fno_experimental_loop_fusion);
-  Args.addOptInFlag(CmdArgs, options::OPT_freal_sum_reassociation,
-                    options::OPT_fno_real_sum_reassociation);
+  Args.addOptInFlag(CmdArgs, options::OPT_fsum_reassociation,
+                    options::OPT_fno_sum_reassociation);
 
   handleInterchangeLoopsArgs(Args, CmdArgs);
   handleVectorizeLoopsArgs(Args, CmdArgs);
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index da9877cf2e417..01e47f3d8d4ce 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -316,8 +316,8 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                    clang::options::OPT_fno_safe_trampoline, false))
     opts.EnableSafeTrampoline = 1;
 
-  if (args.hasFlag(clang::options::OPT_freal_sum_reassociation,
-                   clang::options::OPT_fno_real_sum_reassociation, false))
+  if (args.hasFlag(clang::options::OPT_fsum_reassociation,
+                   clang::options::OPT_fno_sum_reassociation, false))
     opts.SplitSumExpressionTree = 1;
 
   if (args.getLastArg(clang::options::OPT_floop_interchange))
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index c7c9ef887c594..1d618812419fd 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -7,15 +7,17 @@
 ! HELP:USAGE: flang
 ! HELP-EMPTY:
 ! HELP-NEXT:OPTIONS:
-! HELP: -freal-sum-reassociation
+! HELP: -fsum-reassociation
 ! HELP: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP: may change exact floating-point results
+! HELP-NOT: -freal-sum-reassociation
 
 ! HELP-FC1:USAGE: flang
 ! HELP-FC1-EMPTY:
 ! HELP-FC1-NEXT:OPTIONS:
-! HELP-FC1: -freal-sum-reassociation
+! HELP-FC1: -fsum-reassociation
 ! HELP-FC1: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP-FC1: may change exact floating-point results
+! HELP-FC1-NOT: -freal-sum-reassociation
 
 ! ERROR: error: unknown argument '-helps'; did you mean '-help'
diff --git a/flang/test/Driver/real-sum-reassociation.f90 b/flang/test/Driver/real-sum-reassociation.f90
deleted file mode 100644
index 7d98da0aabb39..0000000000000
--- a/flang/test/Driver/real-sum-reassociation.f90
+++ /dev/null
@@ -1,27 +0,0 @@
-! Test driver handling of -freal-sum-reassociation and
-! -fno-real-sum-reassociation.
-
-! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
-! RUN:   | FileCheck %s --check-prefix=DISABLED
-
-! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
-! RUN:     -freal-sum-reassociation \
-! RUN:   | FileCheck %s --check-prefix=ENABLED
-
-! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
-! RUN:     -fno-real-sum-reassociation \
-! RUN:   | FileCheck %s --check-prefix=DISABLED
-
-! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
-! RUN:     -fno-real-sum-reassociation -freal-sum-reassociation \
-! RUN:   | FileCheck %s --check-prefix=ENABLED
-
-! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
-! RUN:     -freal-sum-reassociation -fno-real-sum-reassociation \
-! RUN:   | FileCheck %s --check-prefix=DISABLED
-
-! DISABLED: "-fc1"
-! DISABLED-NOT: "-freal-sum-reassociation"
-
-! ENABLED: "-fc1"
-! ENABLED-SAME: "-freal-sum-reassociation"
diff --git a/flang/test/Driver/sum-reassociation.f90 b/flang/test/Driver/sum-reassociation.f90
new file mode 100644
index 0000000000000..c65bba75cfa73
--- /dev/null
+++ b/flang/test/Driver/sum-reassociation.f90
@@ -0,0 +1,43 @@
+! Test driver handling of -fsum-reassociation and
+! -fno-sum-reassociation, including the old hidden aliases.
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:   | FileCheck %s --check-prefix=DISABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fsum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=ENABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fno-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=DISABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fno-sum-reassociation -fsum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=ENABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fsum-reassociation -fno-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=DISABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -freal-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=ENABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fno-real-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=DISABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fsum-reassociation -fno-real-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=DISABLED
+
+! RUN: %flang -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     -fno-sum-reassociation -freal-sum-reassociation \
+! RUN:   | FileCheck %s --check-prefix=ENABLED
+
+! DISABLED: "-fc1"
+! DISABLED-NOT: "-fsum-reassociation"
+
+! ENABLED: "-fc1"
+! ENABLED-SAME: "-fsum-reassociation"
diff --git a/flang/test/Lower/split-sum-expression-tree-lowering.f90 b/flang/test/Lower/split-sum-expression-tree-lowering.f90
index 93bb4396348c7..66081a343b6b2 100644
--- a/flang/test/Lower/split-sum-expression-tree-lowering.f90
+++ b/flang/test/Lower/split-sum-expression-tree-lowering.f90
@@ -1,5 +1,5 @@
-! RUN: %flang_fc1 -emit-hlfir -freal-sum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
-! RUN: %flang_fc1 -emit-hlfir -fno-real-sum-reassociation -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
+! RUN: %flang_fc1 -emit-hlfir -fsum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
+! RUN: %flang_fc1 -emit-hlfir -fno-sum-reassociation -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
 ! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
 
 ! Default:   (((x + a*b) + c*d) + e*f)



More information about the flang-commits mailing list