https://github.com/madhur13490 updated 
https://github.com/llvm/llvm-project/pull/216920

>From 2c9a2cfe3e40ab9ab8c3cf90af8895e37414c086 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Fri, 14 Aug 2026 09:32:57 -0700
Subject: [PATCH 1/3] [Clang][Flang] Enable loop interchange by default at -O3

PR #124911 enabled the LoopInterchange pass by default in the LLVM
optimization pipeline (the PipelineTuningOptions default used by opt),
but the clang and flang frontends override that default and keep it
off. As a result, driving the compiler through clang or flang never
runs loop interchange unless -floop-interchange is passed explicitly.

Default the -floop-interchange flag on at -O3 for both frontends so
they match the pipeline default. The decision is made in the frontend
(-cc1) for both clang and flang, mirroring -funroll-loops; the flang
driver only forwards an explicit -f[no-]loop-interchange. Lower opt
levels and an explicit -fno-loop-interchange keep it off.
---
 clang/lib/Driver/ToolChains/CommonArgs.cpp |  7 ++++---
 clang/lib/Frontend/CompilerInvocation.cpp  |  4 +++-
 clang/test/Driver/clang_f_opts.c           |  7 +++++++
 flang/lib/Frontend/CompilerInvocation.cpp  |  6 ++++--
 flang/test/Driver/loop-interchange.f90     | 14 +++++++-------
 5 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index a76f4aa6ae853..ad6280ae45277 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3564,9 +3564,10 @@ void tools::handleVectorizeSLPArgs(const ArgList &Args,
 
 void tools::handleInterchangeLoopsArgs(const ArgList &Args,
                                        ArgStringList &CmdArgs) {
-  if (Args.hasFlag(options::OPT_floop_interchange,
-                   options::OPT_fno_loop_interchange, false))
-    CmdArgs.push_back("-floop-interchange");
+  // Forward the user's explicit choice; the frontend applies the -O3
+  // default when neither flag is present.
+  Args.AddLastArg(CmdArgs, options::OPT_floop_interchange,
+                  options::OPT_fno_loop_interchange);
 }
 
 std::string tools::complexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 70fc346d85920..f023df260d55e 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1945,8 +1945,10 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions 
&Opts, ArgList &Args,
   Opts.UnrollLoops =
       Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
                    (Opts.OptimizationLevel > 1));
+  // Loop interchange is only enabled by default at -O3.
   Opts.InterchangeLoops =
-      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, false);
+      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange,
+                   (Opts.OptimizationLevel == 3));
   Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,
                                 OPT_fno_experimental_loop_fusion, false);
   Opts.BinutilsVersion =
diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index 5871f1580d6b7..c14885b04ad6f 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -51,6 +51,13 @@
 // RUN: %clang -### -S -floop-interchange -fno-loop-interchange %s 2>&1 | 
FileCheck -check-prefix=CHECK-NO-INTERCHANGE-LOOPS %s
 // CHECK-INTERCHANGE-LOOPS: "-floop-interchange"
 // CHECK-NO-INTERCHANGE-LOOPS: "-fno-loop-interchange"
+//
+// Loop interchange is enabled by default only at -O3.
+// RUN: %clang -c -mllvm -print-pipeline-passes -O3 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-ON %s
+// RUN: %clang -c -mllvm -print-pipeline-passes -O2 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-OFF %s
+// RUN: %clang -c -fno-loop-interchange -mllvm -print-pipeline-passes -O3 %s 
-o /dev/null 2>&1 | FileCheck --check-prefixes=INTERCHANGE-OFF %s
+// INTERCHANGE-ON: loop-interchange
+// INTERCHANGE-OFF-NOT: loop-interchange
 
 // RUN: %clang -### -S -fexperimental-loop-fusion %s -o /dev/null 2>&1 | 
FileCheck -check-prefix=CHECK-FUSE-LOOPS %s
 // CHECK-FUSE-LOOPS: "-fexperimental-loop-fusion"
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index b57bc4583be38..d50dc4878e60d 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -320,8 +320,10 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                    clang::options::OPT_fno_fp_sum_reassociation, false))
     opts.SplitSumExpressionTree = 1;
 
-  if (args.getLastArg(clang::options::OPT_floop_interchange))
-    opts.InterchangeLoops = 1;
+  // Loop interchange is only enabled by default at -O3.
+  opts.InterchangeLoops = args.hasFlag(clang::options::OPT_floop_interchange,
+                                       
clang::options::OPT_fno_loop_interchange,
+                                       opts.OptimizationLevel == 3);
 
   if (args.getLastArg(clang::options::OPT_fexperimental_loop_fusion))
     opts.FuseLoops = 1;
diff --git a/flang/test/Driver/loop-interchange.f90 
b/flang/test/Driver/loop-interchange.f90
index 1e5a11902709c..c9d88cd63cf5b 100644
--- a/flang/test/Driver/loop-interchange.f90
+++ b/flang/test/Driver/loop-interchange.f90
@@ -1,15 +1,15 @@
+! The driver only forwards an explicit -f[no-]loop-interchange; the -O3
+! default is applied in the frontend, so it is not visible in -###.
 ! RUN: %flang -### -S -floop-interchange %s 2>&1 | FileCheck 
-check-prefix=CHECK-LOOP-INTERCHANGE %s
 ! RUN: %flang -### -S -fno-loop-interchange %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
-! RUN: %flang -### -S -O0 %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
-! RUN: %flang -### -S -O1 %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
-! RUN: %flang -### -S -O2 %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
 ! RUN: %flang -### -S -O3 %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
-! RUN: %flang -### -S -Os %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
-! RUN: %flang -### -S -Oz %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE %s
 ! CHECK-LOOP-INTERCHANGE: "-floop-interchange"
 ! CHECK-NO-LOOP-INTERCHANGE-NOT: "-floop-interchange"
-! RUN: %flang_fc1 -emit-llvm -O2 -floop-interchange -mllvm 
-print-pipeline-passes -o /dev/null %s 2>&1 | FileCheck 
-check-prefix=CHECK-LOOP-INTERCHANGE-PASS %s
-! RUN: %flang_fc1 -emit-llvm -O2 -fno-loop-interchange -mllvm 
-print-pipeline-passes -o /dev/null %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE-PASS %s
+!
+! Loop interchange is enabled by default only at -O3.
+! RUN: %flang_fc1 -emit-llvm -O3 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE-PASS %s
+! RUN: %flang_fc1 -emit-llvm -O2 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE-PASS %s
+! RUN: %flang_fc1 -emit-llvm -O3 -fno-loop-interchange -mllvm 
-print-pipeline-passes -o /dev/null %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE-PASS %s
 ! CHECK-LOOP-INTERCHANGE-PASS: loop-interchange
 ! CHECK-NO-LOOP-INTERCHANGE-PASS-NOT: loop-interchange
 

>From 1b0a914d4e0c13920bff6ff67243ebadc28b1ec4 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Mon, 17 Aug 2026 23:47:02 -0700
Subject: [PATCH 2/3] fixup! [Clang][Flang] Enable loop interchange by default
 at -O3

---
 clang/lib/Frontend/CompilerInvocation.cpp | 1 -
 flang/lib/Frontend/CompilerInvocation.cpp | 1 -
 2 files changed, 2 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index f023df260d55e..a92f2ba7092f5 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1945,7 +1945,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions 
&Opts, ArgList &Args,
   Opts.UnrollLoops =
       Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
                    (Opts.OptimizationLevel > 1));
-  // Loop interchange is only enabled by default at -O3.
   Opts.InterchangeLoops =
       Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange,
                    (Opts.OptimizationLevel == 3));
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index d50dc4878e60d..58a4470e342a8 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -320,7 +320,6 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                    clang::options::OPT_fno_fp_sum_reassociation, false))
     opts.SplitSumExpressionTree = 1;
 
-  // Loop interchange is only enabled by default at -O3.
   opts.InterchangeLoops = args.hasFlag(clang::options::OPT_floop_interchange,
                                        
clang::options::OPT_fno_loop_interchange,
                                        opts.OptimizationLevel == 3);

>From 0407d8a4ba85513af9fe05687d54239dc6a32c23 Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <[email protected]>
Date: Tue, 18 Aug 2026 03:43:14 -0700
Subject: [PATCH 3/3] fixup! enable for all opt levels

---
 clang/lib/Frontend/CompilerInvocation.cpp | 5 +++--
 clang/test/Driver/clang_f_opts.c          | 7 +++++--
 flang/lib/Frontend/CompilerInvocation.cpp | 8 +++++---
 flang/test/Driver/loop-interchange.f90    | 7 +++++--
 4 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index a92f2ba7092f5..021201f09457c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1945,9 +1945,10 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions 
&Opts, ArgList &Args,
   Opts.UnrollLoops =
       Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
                    (Opts.OptimizationLevel > 1));
+  // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
+  // which enables the pass whenever the optimization pipeline runs.
   Opts.InterchangeLoops =
-      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange,
-                   (Opts.OptimizationLevel == 3));
+      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, true);
   Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,
                                 OPT_fno_experimental_loop_fusion, false);
   Opts.BinutilsVersion =
diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index c14885b04ad6f..0ec2cb5133b21 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -52,9 +52,12 @@
 // CHECK-INTERCHANGE-LOOPS: "-floop-interchange"
 // CHECK-NO-INTERCHANGE-LOOPS: "-fno-loop-interchange"
 //
-// Loop interchange is enabled by default only at -O3.
+// Loop interchange matches the LLVM pipeline default: on whenever the
+// optimization pipeline runs (-O1 and above), off with an explicit
+// -fno-loop-interchange.
+// RUN: %clang -c -mllvm -print-pipeline-passes -O1 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-ON %s
+// RUN: %clang -c -mllvm -print-pipeline-passes -O2 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-ON %s
 // RUN: %clang -c -mllvm -print-pipeline-passes -O3 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-ON %s
-// RUN: %clang -c -mllvm -print-pipeline-passes -O2 %s -o /dev/null 2>&1 | 
FileCheck --check-prefixes=INTERCHANGE-OFF %s
 // RUN: %clang -c -fno-loop-interchange -mllvm -print-pipeline-passes -O3 %s 
-o /dev/null 2>&1 | FileCheck --check-prefixes=INTERCHANGE-OFF %s
 // INTERCHANGE-ON: loop-interchange
 // INTERCHANGE-OFF-NOT: loop-interchange
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 58a4470e342a8..0278a608368c2 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -320,9 +320,11 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                    clang::options::OPT_fno_fp_sum_reassociation, false))
     opts.SplitSumExpressionTree = 1;
 
-  opts.InterchangeLoops = args.hasFlag(clang::options::OPT_floop_interchange,
-                                       
clang::options::OPT_fno_loop_interchange,
-                                       opts.OptimizationLevel == 3);
+  // Match the LLVM pipeline default (PipelineTuningOptions::LoopInterchange),
+  // which enables the pass whenever the optimization pipeline runs.
+  opts.InterchangeLoops =
+      args.hasFlag(clang::options::OPT_floop_interchange,
+                   clang::options::OPT_fno_loop_interchange, true);
 
   if (args.getLastArg(clang::options::OPT_fexperimental_loop_fusion))
     opts.FuseLoops = 1;
diff --git a/flang/test/Driver/loop-interchange.f90 
b/flang/test/Driver/loop-interchange.f90
index c9d88cd63cf5b..0370f7c54866d 100644
--- a/flang/test/Driver/loop-interchange.f90
+++ b/flang/test/Driver/loop-interchange.f90
@@ -6,9 +6,12 @@
 ! CHECK-LOOP-INTERCHANGE: "-floop-interchange"
 ! CHECK-NO-LOOP-INTERCHANGE-NOT: "-floop-interchange"
 !
-! Loop interchange is enabled by default only at -O3.
+! Loop interchange matches the LLVM pipeline default: on whenever the
+! optimization pipeline runs (-O1 and above), off with an explicit
+! -fno-loop-interchange.
+! RUN: %flang_fc1 -emit-llvm -O1 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE-PASS %s
+! RUN: %flang_fc1 -emit-llvm -O2 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE-PASS %s
 ! RUN: %flang_fc1 -emit-llvm -O3 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE-PASS %s
-! RUN: %flang_fc1 -emit-llvm -O2 -mllvm -print-pipeline-passes -o /dev/null %s 
2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE-PASS %s
 ! RUN: %flang_fc1 -emit-llvm -O3 -fno-loop-interchange -mllvm 
-print-pipeline-passes -o /dev/null %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-LOOP-INTERCHANGE-PASS %s
 ! CHECK-LOOP-INTERCHANGE-PASS: loop-interchange
 ! CHECK-NO-LOOP-INTERCHANGE-PASS-NOT: loop-interchange

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to