[clang] [flang] [flang] Enable FP sum reassociation by default (PR #218746)

Tom Eccles via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 6 11:24:17 PDT 2026


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

>From 7aecd7d9509f98f68ce64390dcd6ee78bc24a4bf Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Tue, 25 Aug 2026 17:12:17 +0100
Subject: [PATCH 1/2] [flang] Enable FP sum reassociation by default

Enable Fortran-standard-compliant reassociation within individual
REAL and COMPLEX sum expressions by default at -O1 and above. Keep
left-to-right lowering at -O0 and preserve the explicit positive and
negative Flang override flags.

bbc uses -O2 by default, so enable the same lowering by default in bbc
with a boolean option.

Assisted-by: Codex
---
 clang/include/clang/Options/FlangOptions.td             | 6 ++++--
 flang/docs/ReleaseNotes.md                              | 5 +++++
 flang/lib/Frontend/CompilerInvocation.cpp               | 3 ++-
 flang/test/Driver/driver-help.f90                       | 2 ++
 flang/test/Lower/math-lowering/exponentiation.f90       | 6 +++---
 flang/test/Lower/split-sum-expression-tree-lowering.f90 | 9 ++++++---
 flang/tools/bbc/bbc.cpp                                 | 7 +++++++
 7 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 9dfe50593f33d..3e6cd0b8d9ea1 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -321,7 +321,8 @@ defm fp_sum_reassociation
           PosFlag<SetTrue, [], [],
                   "Enable Fortran-standard compliant reassociation within "
                   "individual REAL and COMPLEX sum expressions. This may "
-                  "change exact floating-point results">,
+                  "change exact floating-point results. Enabled by default "
+                  "with -O1 and higher">,
           NegFlag<SetFalse, [], [],
                   "Disable reassociation within individual REAL and COMPLEX "
                   "sum expressions">>,
@@ -329,7 +330,8 @@ defm fp_sum_reassociation
         Enable Fortran-standard compliant reassociation within individual
         ``REAL`` and ``COMPLEX`` sum expressions. This can improve optimization
         opportunities and may change exact floating-point results while
-        preserving standard-conforming Fortran semantics.
+        preserving standard-conforming Fortran semantics. It is enabled by
+        default with ``-O1`` and higher.
       }]>;
 
 def freal_sum_reassociation : Flag<["-"], "freal-sum-reassociation">,
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 0f5c1548f943d..bab1cfc722278 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -43,6 +43,11 @@ page](https://llvm.org/releases/).
   as specified on the command line (except that ./foo.f90 removes the ./
   prefix).
 
+- Fortran-standard-compliant reassociation within individual `REAL` and
+  `COMPLEX` sum expressions is now enabled by default at `-O1` and above.
+  This may change exact floating-point results. Flang users can restore
+  left-to-right evaluation with `-fno-fp-sum-reassociation`.
+
 - The legacy array-value operations (`fir.array_load`, `fir.array_fetch`,
   `fir.array_update`, `fir.array_modify`, `fir.array_access`,
   `fir.array_amend`, `fir.array_merge_store`) have been removed from FIR,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 7cfd89e120b7d..89d417a572c54 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -318,7 +318,8 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
     opts.EnableSafeTrampoline = 1;
 
   if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
-                   clang::options::OPT_fno_fp_sum_reassociation, false))
+                   clang::options::OPT_fno_fp_sum_reassociation,
+                   opts.OptimizationLevel > 0))
     opts.SplitSumExpressionTree = 1;
 
   // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 1ca446d159305..56843777aa2d0 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -10,6 +10,7 @@
 ! HELP: -ffp-sum-reassociation
 ! HELP: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP: may change exact floating-point results
+! HELP: Enabled by default with -O1 and higher
 ! HELP-NOT: -freal-sum-reassociation
 
 ! HELP-FC1:USAGE: flang
@@ -18,6 +19,7 @@
 ! HELP-FC1: -ffp-sum-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: Enabled by default with -O1 and higher
 ! HELP-FC1-NOT: -freal-sum-reassociation
 
 ! ERROR: error: unknown argument '-helps'; did you mean '-help'
diff --git a/flang/test/Lower/math-lowering/exponentiation.f90 b/flang/test/Lower/math-lowering/exponentiation.f90
index 6a007d08671d6..4d3ebd10ef5e8 100644
--- a/flang/test/Lower/math-lowering/exponentiation.f90
+++ b/flang/test/Lower/math-lowering/exponentiation.f90
@@ -1,8 +1,8 @@
-! RUN: bbc -emit-fir %s -o - --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %s
+! RUN: bbc -emit-fir %s -o - --math-runtime=fast -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,FAST %s
 ! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=fast %s -o - | FileCheck --check-prefixes=ALL,FAST %s
-! RUN: bbc -emit-fir %s -o - --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %s
+! RUN: bbc -emit-fir %s -o - --math-runtime=relaxed -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,RELAXED %s
 ! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=relaxed %s -o - | FileCheck --check-prefixes=ALL,RELAXED %s
-! RUN: bbc -emit-fir %s -o - --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %s
+! RUN: bbc -emit-fir %s -o - --math-runtime=precise -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,PRECISE %s
 ! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=precise %s -o - | FileCheck --check-prefixes=ALL,PRECISE %s
 
 function test_real4(x, y, s, i, k)
diff --git a/flang/test/Lower/split-sum-expression-tree-lowering.f90 b/flang/test/Lower/split-sum-expression-tree-lowering.f90
index 4b9b49219d8b8..2da6c48e7326d 100644
--- a/flang/test/Lower/split-sum-expression-tree-lowering.f90
+++ b/flang/test/Lower/split-sum-expression-tree-lowering.f90
@@ -1,6 +1,9 @@
-! RUN: %flang_fc1 -emit-hlfir -ffp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
-! RUN: %flang_fc1 -emit-hlfir -fno-fp-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
+! RUN: %flang_fc1 -emit-hlfir -O0 -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
+! RUN: %flang_fc1 -emit-hlfir -O1 -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
+! RUN: %flang_fc1 -emit-hlfir -O0 -ffp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
+! RUN: %flang_fc1 -emit-hlfir -O1 -fno-fp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
+! RUN: bbc -emit-hlfir -ffp-sum-reassociation=false -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
 
 ! Default:   (((x + a*b) + c*d) + e*f)
 ! Rewritten: ((c*d + e*f) + (x + a*b))
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 50742eb106421..d6e0643c813c2 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -282,6 +282,12 @@ static llvm::cl::opt<bool>
                                  "the LHS of the intrinsic assignment"),
                   llvm::cl::init(true));
 
+static llvm::cl::opt<bool> fpSumReassociation(
+    "ffp-sum-reassociation",
+    llvm::cl::desc("Enable Fortran-standard compliant reassociation within "
+                   "individual REAL and COMPLEX sum expressions"),
+    llvm::cl::init(true));
+
 static llvm::cl::opt<bool> stackRepackArrays(
     "fstack-repack-arrays",
     llvm::cl::desc("Allocate temporary arrays for -frepack-arrays "
@@ -507,6 +513,7 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
   loweringOptions.setIntegerWrapAround(integerWrapAround);
   loweringOptions.setInitGlobalZero(initGlobalZero);
   loweringOptions.setReallocateLHS(reallocateLHS);
+  loweringOptions.setSplitSumExpressionTree(fpSumReassociation);
   loweringOptions.setStackRepackArrays(stackRepackArrays);
   loweringOptions.setRepackArrays(repackArrays);
   loweringOptions.setRepackArraysWhole(repackArraysWhole);

>From 8ac7f8d53e8d9babcc2420b2cdb130d26418744d Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Sun, 6 Sep 2026 18:45:57 +0100
Subject: [PATCH 2/2] Enable FP sum reassociation at all optimization levels

I decided to do it at O0 after Jean's feedback on the RFC/Discourse.
Thinking more about it, in badly written programs this could
theoretically change program flow and so it would be very confusing if a
slightly different numerical result was given at -O0 (e.g. a debug
build) than -O3.

Assisted-by: Codex
---
 clang/include/clang/Options/FlangOptions.td             | 5 ++---
 flang/docs/ReleaseNotes.md                              | 6 +++---
 flang/lib/Frontend/CompilerInvocation.cpp               | 3 +--
 flang/test/Driver/driver-help.f90                       | 4 ++--
 flang/test/Lower/math-lowering/exponentiation.f90       | 6 +++---
 flang/test/Lower/split-sum-expression-tree-lowering.f90 | 4 ++--
 6 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 3e6cd0b8d9ea1..dad57464799c3 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -321,8 +321,7 @@ defm fp_sum_reassociation
           PosFlag<SetTrue, [], [],
                   "Enable Fortran-standard compliant reassociation within "
                   "individual REAL and COMPLEX sum expressions. This may "
-                  "change exact floating-point results. Enabled by default "
-                  "with -O1 and higher">,
+                  "change exact floating-point results. Enabled by default">,
           NegFlag<SetFalse, [], [],
                   "Disable reassociation within individual REAL and COMPLEX "
                   "sum expressions">>,
@@ -331,7 +330,7 @@ defm fp_sum_reassociation
         ``REAL`` and ``COMPLEX`` sum expressions. This can improve optimization
         opportunities and may change exact floating-point results while
         preserving standard-conforming Fortran semantics. It is enabled by
-        default with ``-O1`` and higher.
+        default at all optimization levels.
       }]>;
 
 def freal_sum_reassociation : Flag<["-"], "freal-sum-reassociation">,
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index bab1cfc722278..76a6b95dd3ecc 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -44,9 +44,9 @@ page](https://llvm.org/releases/).
   prefix).
 
 - Fortran-standard-compliant reassociation within individual `REAL` and
-  `COMPLEX` sum expressions is now enabled by default at `-O1` and above.
-  This may change exact floating-point results. Flang users can restore
-  left-to-right evaluation with `-fno-fp-sum-reassociation`.
+  `COMPLEX` sum expressions is now enabled by default at all optimization
+  levels. This may change exact floating-point results. Flang users can
+  restore left-to-right evaluation with `-fno-fp-sum-reassociation`.
 
 - The legacy array-value operations (`fir.array_load`, `fir.array_fetch`,
   `fir.array_update`, `fir.array_modify`, `fir.array_access`,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 89d417a572c54..b76b38ff6497f 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -318,8 +318,7 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
     opts.EnableSafeTrampoline = 1;
 
   if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
-                   clang::options::OPT_fno_fp_sum_reassociation,
-                   opts.OptimizationLevel > 0))
+                   clang::options::OPT_fno_fp_sum_reassociation, true))
     opts.SplitSumExpressionTree = 1;
 
   // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 56843777aa2d0..ddffedac5d9f6 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -10,7 +10,7 @@
 ! HELP: -ffp-sum-reassociation
 ! HELP: Enable Fortran-standard compliant reassociation within individual REAL and COMPLEX sum expressions
 ! HELP: may change exact floating-point results
-! HELP: Enabled by default with -O1 and higher
+! HELP: Enabled by default
 ! HELP-NOT: -freal-sum-reassociation
 
 ! HELP-FC1:USAGE: flang
@@ -19,7 +19,7 @@
 ! HELP-FC1: -ffp-sum-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: Enabled by default with -O1 and higher
+! HELP-FC1: Enabled by default
 ! HELP-FC1-NOT: -freal-sum-reassociation
 
 ! ERROR: error: unknown argument '-helps'; did you mean '-help'
diff --git a/flang/test/Lower/math-lowering/exponentiation.f90 b/flang/test/Lower/math-lowering/exponentiation.f90
index 4d3ebd10ef5e8..95cbfad7a83a8 100644
--- a/flang/test/Lower/math-lowering/exponentiation.f90
+++ b/flang/test/Lower/math-lowering/exponentiation.f90
@@ -1,9 +1,9 @@
 ! RUN: bbc -emit-fir %s -o - --math-runtime=fast -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,FAST %s
-! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=fast %s -o - | FileCheck --check-prefixes=ALL,FAST %s
+! RUN: %flang_fc1 -emit-fir -fno-fp-sum-reassociation -mllvm -math-runtime=fast %s -o - | FileCheck --check-prefixes=ALL,FAST %s
 ! RUN: bbc -emit-fir %s -o - --math-runtime=relaxed -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,RELAXED %s
-! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=relaxed %s -o - | FileCheck --check-prefixes=ALL,RELAXED %s
+! RUN: %flang_fc1 -emit-fir -fno-fp-sum-reassociation -mllvm -math-runtime=relaxed %s -o - | FileCheck --check-prefixes=ALL,RELAXED %s
 ! RUN: bbc -emit-fir %s -o - --math-runtime=precise -ffp-sum-reassociation=false | FileCheck --check-prefixes=ALL,PRECISE %s
-! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=precise %s -o - | FileCheck --check-prefixes=ALL,PRECISE %s
+! RUN: %flang_fc1 -emit-fir -fno-fp-sum-reassociation -mllvm -math-runtime=precise %s -o - | FileCheck --check-prefixes=ALL,PRECISE %s
 
 function test_real4(x, y, s, i, k)
   real :: x, y, test_real4
diff --git a/flang/test/Lower/split-sum-expression-tree-lowering.f90 b/flang/test/Lower/split-sum-expression-tree-lowering.f90
index 2da6c48e7326d..7d418d09cc319 100644
--- a/flang/test/Lower/split-sum-expression-tree-lowering.f90
+++ b/flang/test/Lower/split-sum-expression-tree-lowering.f90
@@ -1,6 +1,6 @@
-! RUN: %flang_fc1 -emit-hlfir -O0 -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
+! RUN: %flang_fc1 -emit-hlfir -O0 -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
 ! RUN: %flang_fc1 -emit-hlfir -O1 -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
-! RUN: %flang_fc1 -emit-hlfir -O0 -ffp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
+! RUN: %flang_fc1 -emit-hlfir -O0 -fno-fp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
 ! RUN: %flang_fc1 -emit-hlfir -O1 -fno-fp-sum-reassociation -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE
 ! RUN: bbc -emit-hlfir -o - %s | FileCheck %s --check-prefixes=SPLIT,NO-REWRITE --implicit-check-not=arith.negf
 ! RUN: bbc -emit-hlfir -ffp-sum-reassociation=false -o - %s | FileCheck %s --check-prefixes=DEFAULT,NO-REWRITE



More information about the cfe-commits mailing list