[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:46:45 PDT 2026
https://github.com/tblah updated https://github.com/llvm/llvm-project/pull/214775
>From 268e70d624dc7988e5879e651ad8197418ce387e 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 6b375c3b2b7dc..696bb2331345b 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -314,16 +314,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.
}]>;
def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<f_Group>,
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 d5181f6fcd4272b9ab45f0f8fb4ae54d264ba82c 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 696bb2331345b..2581e9cc387b1 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -309,9 +309,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 "
@@ -326,6 +326,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>;
+
def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<f_Group>,
HelpText<"Set the initial floating-point exception halting mode for the main program">,
DocBrief<[{The ``-ffpe-trap=[list]`` option sets the initial floating-point
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 25bb9832432cc..168fd348aa3ff 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 33ce6cb6869f1..bc0239112b8a2 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