[clang] bf81ba3 - [flang] add -fstack-arrays flag

Tom Eccles via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 7 02:28:30 PST 2023


Author: Tom Eccles
Date: 2023-02-07T10:27:52Z
New Revision: bf81ba37262880a8391f63c1747d61e4851344c4

URL: https://github.com/llvm/llvm-project/commit/bf81ba37262880a8391f63c1747d61e4851344c4
DIFF: https://github.com/llvm/llvm-project/commit/bf81ba37262880a8391f63c1747d61e4851344c4.diff

LOG: [flang] add -fstack-arrays flag

The implementation of -fstack-arrays was added in
https://reviews.llvm.org/D140415

The new macro BoolOptionWithoutMarshalling in Options.td avoids
generating code to store the flags in clang data structures. For
example, writing something like

  defm stack_arrays : BoolOption<"f", "stack-arrays",
                                 CodeGenOpts<"StackArrays">, [...]

Would generate code referring to `clang::CodeGenOpts::StackArrays`, which
does not exist.

Differential Revision: https://reviews.llvm.org/D140972

Added: 
    

Modified: 
    clang/include/clang/Driver/Options.td
    clang/lib/Driver/ToolChains/Flang.cpp
    flang/docs/FlangDriver.md
    flang/include/flang/Frontend/CodeGenOptions.def
    flang/include/flang/Tools/CLOptions.inc
    flang/lib/Frontend/CompilerInvocation.cpp
    flang/lib/Frontend/FrontendActions.cpp
    flang/test/Driver/driver-help-hidden.f90
    flang/test/Driver/driver-help.f90
    flang/test/Driver/fast_math.f90
    flang/test/Transforms/stack-arrays.f90

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 03e6e7c52d63a..6392597153e34 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -482,6 +482,40 @@ multiclass BoolGOption<string flag_base, KeyPathAndMacro kpm,
               Group<g_Group>;
 }
 
+// Works like BoolOption except without marshalling
+multiclass BoolOptionWithoutMarshalling<string prefix = "", string spelling_base,
+                                        FlagDef flag1_base, FlagDef flag2_base,
+                                        BothFlags suffix = BothFlags<[], "">> {
+  defvar flag1 = FlagDefExpanded<ApplySuffix<flag1_base, suffix>.Result, prefix,
+                                 NAME, spelling_base>;
+
+  defvar flag2 = FlagDefExpanded<ApplySuffix<flag2_base, suffix>.Result, prefix,
+                                 NAME, spelling_base>;
+
+  // The flags must have 
diff erent polarity, 
diff erent values, and only
+  // one can be implied.
+  assert !xor(flag1.Polarity, flag2.Polarity),
+         "the flags must have 
diff erent polarity: flag1: " #
+             flag1.Polarity # ", flag2: " # flag2.Polarity;
+  assert !ne(flag1.Value, flag2.Value),
+         "the flags must have 
diff erent values: flag1: " #
+             flag1.Value # ", flag2: " # flag2.Value;
+  assert !not(!and(flag1.CanBeImplied, flag2.CanBeImplied)),
+         "only one of the flags can be implied: flag1: " #
+             flag1.CanBeImplied # ", flag2: " # flag2.CanBeImplied;
+
+  defvar implied = !if(flag1.CanBeImplied, flag1, flag2);
+
+  def flag1.RecordName : Flag<["-"], flag1.Spelling>, Flags<flag1.OptionFlags>,
+                         HelpText<flag1.Help>,
+                         ImpliedByAnyOf<implied.ImpliedBy, implied.ValueAsCode>
+                         {}
+  def flag2.RecordName : Flag<["-"], flag2.Spelling>, Flags<flag2.OptionFlags>,
+                         HelpText<flag2.Help>,
+                         ImpliedByAnyOf<implied.ImpliedBy, implied.ValueAsCode>
+                         {}
+}
+
 // FIXME: Diagnose if target does not support protected visibility.
 class MarshallingInfoVisibility<KeyPathAndMacro kpm, code default>
   : MarshallingInfoEnum<kpm, default>,
@@ -4986,7 +5020,6 @@ defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
 defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
 defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;
 defm sign_zero : BooleanFFlag<"sign-zero">, Group<gfortran_Group>;
-defm stack_arrays : BooleanFFlag<"stack-arrays">, Group<gfortran_Group>;
 defm underscoring : BooleanFFlag<"underscoring">, Group<gfortran_Group>;
 defm whole_file : BooleanFFlag<"whole-file">, Group<gfortran_Group>;
 
@@ -5066,6 +5099,10 @@ defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing allowed
 def fno_automatic : Flag<["-"], "fno-automatic">, Group<f_Group>,
   HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">;
 
+defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays",
+  PosFlag<SetTrue, [], "Attempt to allocate array temporaries on the stack, no matter their size">,
+  NegFlag<SetFalse, [], "Allocate array temporaries on the heap (default)">>;
+
 } // let Flags = [FC1Option, FlangOption, FlangOnlyOption]
 
 def J : JoinedOrSeparate<["-"], "J">,

diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 4ee046be9ea97..8d9fae58ce50e 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -57,6 +57,13 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
                    options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
                    options::OPT_std_EQ, options::OPT_W_Joined,
                    options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ});
+
+  Arg *stackArrays =
+      Args.getLastArg(options::OPT_Ofast, options::OPT_fstack_arrays,
+                      options::OPT_fno_stack_arrays);
+  if (stackArrays &&
+      !stackArrays->getOption().matches(options::OPT_fno_stack_arrays))
+    CmdArgs.push_back("-fstack-arrays");
 }
 
 void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {

diff  --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index d3db110565f42..f4b41b90c3b12 100644
--- a/flang/docs/FlangDriver.md
+++ b/flang/docs/FlangDriver.md
@@ -546,8 +546,7 @@ See the
 documentation for more details.
 
 ## Ofast and Fast Math
-`-Ofast` in Flang means `-O3 -ffast-math`. `-fstack-arrays` will be added to
-`-Ofast` in the future (https://github.com/llvm/llvm-project/issues/59231).
+`-Ofast` in Flang means `-O3 -ffast-math -fstack-arrays`.
 
 `-ffast-math` means the following:
  - `-fno-honor-infinities`
@@ -570,9 +569,8 @@ to zero.
 
 ### Comparison with GCC/GFortran
 GCC/GFortran translate `-Ofast` to
-`-O3 -ffast-math -fstack-arrays -fno-semantic-interposition`. `-fstack-arrays`
-is TODO for Flang.
-`-fno-semantic-interposition` is not used because clang does not enable this as
+`-O3 -ffast-math -fstack-arrays -fno-semantic-interposition`.
+`-fno-semantic-interposition` is not used because Clang does not enable this as
 part of `-Ofast` as the default behaviour is similar.
 
 GCC/GFortran has a wider definition of `-ffast-math`: also including

diff  --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def
index 966f9f864f7d1..0de2360fd95be 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.def
+++ b/flang/include/flang/Frontend/CodeGenOptions.def
@@ -26,6 +26,7 @@ CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
 
 CODEGENOPT(PICLevel, 2, 0) ///< PIC level of the LLVM module.
 CODEGENOPT(IsPIE, 1, 0) ///< PIE level is the same as PIC Level.
+CODEGENOPT(StackArrays, 1, 0) ///< -fstack-arrays (enable the stack-arrays pass)
 
 ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///< Name of the relocation model to use.
 

diff  --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
index f499c11f54777..c61ff61fa5cfc 100644
--- a/flang/include/flang/Tools/CLOptions.inc
+++ b/flang/include/flang/Tools/CLOptions.inc
@@ -166,8 +166,9 @@ inline void addExternalNameConversionPass(mlir::PassManager &pm) {
 /// incremental conversion of FIR.
 ///
 /// \param pm - MLIR pass manager that will hold the pipeline definition
-inline void createDefaultFIROptimizerPassPipeline(
-    mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) {
+inline void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
+    llvm::OptimizationLevel optLevel = defaultOptLevel,
+    bool stackArrays = false) {
   // simplify the IR
   mlir::GreedyRewriteConfig config;
   config.enableRegionSimplification = false;
@@ -182,7 +183,11 @@ inline void createDefaultFIROptimizerPassPipeline(
     pm.addPass(fir::createAlgebraicSimplificationPass(config));
   }
   pm.addPass(mlir::createCSEPass());
-  fir::addMemoryAllocationOpt(pm);
+
+  if (stackArrays)
+    pm.addPass(fir::createStackArraysPass());
+  else
+    fir::addMemoryAllocationOpt(pm);
 
   // The default inliner pass adds the canonicalizer pass with the default
   // configuration. Create the inliner pass with tco config.
@@ -220,10 +225,11 @@ inline void createDefaultFIRCodeGenPassPipeline(
 /// \param pm - MLIR pass manager that will hold the pipeline definition
 /// \param optLevel - optimization level used for creating FIR optimization
 ///   passes pipeline
-inline void createMLIRToLLVMPassPipeline(
-    mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) {
+inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
+    llvm::OptimizationLevel optLevel = defaultOptLevel,
+    bool stackArrays = false) {
   // Add default optimizer pass pipeline.
-  fir::createDefaultFIROptimizerPassPipeline(pm, optLevel);
+  fir::createDefaultFIROptimizerPassPipeline(pm, optLevel, stackArrays);
 
   // Add codegen pass pipeline.
   fir::createDefaultFIRCodeGenPassPipeline(pm, optLevel);

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 9ab7030da940d..8bcc3f6d17406 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -126,6 +126,11 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                    clang::driver::options::OPT_fno_debug_pass_manager, false))
     opts.DebugPassManager = 1;
 
+  if (args.hasFlag(clang::driver::options::OPT_fstack_arrays,
+                   clang::driver::options::OPT_fno_stack_arrays, false)) {
+    opts.StackArrays = 1;
+  }
+
   for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
     opts.LLVMPassPlugins.push_back(a->getValue());
 

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 7cb352a85e0c1..79183c6e8f14a 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -545,7 +545,7 @@ void CodeGenAction::generateLLVMIR() {
   pm.enableVerifier(/*verifyPasses=*/true);
 
   // Create the pass pipeline
-  fir::createMLIRToLLVMPassPipeline(pm, level);
+  fir::createMLIRToLLVMPassPipeline(pm, level, opts.StackArrays);
   mlir::applyPassManagerCLOptions(pm);
 
   // run the pass manager

diff  --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 188f344fd9a7a..a19919758b62f 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -47,10 +47,12 @@
 ! CHECK-NEXT: -fno-color-diagnostics  Disable colors in diagnostics
 ! CHECK-NEXT: -fno-integrated-as     Disable the integrated assembler
 ! CHECK-NEXT: -fno-signed-zeros      Allow optimizations that ignore the sign of floating point zeros
+! CHECK-NEXT: -fno-stack-arrays      Allocate array temporaries on the heap (default)
 ! CHECK-NEXT: -fopenacc              Enable OpenACC
 ! CHECK-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
 ! CHECK-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! CHECK-NEXT: -freciprocal-math      Allow division operations to be reassociated
+! CHECK-NEXT: -fstack-arrays         Attempt to allocate array temporaries on the stack, no matter their size
 ! CHECK-NEXT: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! CHECK-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! CHECK-NEXT: -help     Display available options

diff  --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 1714d75431dc7..42c7d4d8cdb28 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -45,10 +45,12 @@
 ! HELP-NEXT: -fno-color-diagnostics  Disable colors in diagnostics
 ! HELP-NEXT: -fno-integrated-as      Disable the integrated assembler
 ! HELP-NEXT: -fno-signed-zeros      Allow optimizations that ignore the sign of floating point zeros
+! HELP-NEXT: -fno-stack-arrays      Allocate array temporaries on the heap (default)
 ! HELP-NEXT: -fopenacc              Enable OpenACC
 ! HELP-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
 ! HELP-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! HELP-NEXT: -freciprocal-math      Allow division operations to be reassociated
+! HELP-NEXT: -fstack-arrays         Attempt to allocate array temporaries on the stack, no matter their size
 ! HELP-NEXT: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! HELP-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! HELP-NEXT: -help                  Display available options
@@ -133,10 +135,12 @@
 ! HELP-FC1-NEXT: -fno-debug-pass-manager Disables debug printing for the new pass manager
 ! HELP-FC1-NEXT: -fno-reformat          Dump the cooked character stream in -E mode
 ! HELP-FC1-NEXT: -fno-signed-zeros      Allow optimizations that ignore the sign of floating point zeros
+! HELP-FC1-NEXT: -fno-stack-arrays      Allocate array temporaries on the heap (default)
 ! HELP-FC1-NEXT: -fopenacc              Enable OpenACC
 ! HELP-FC1-NEXT: -fopenmp               Parse OpenMP pragmas and generate parallel code.
 ! HELP-FC1-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! HELP-FC1-NEXT: -freciprocal-math      Allow division operations to be reassociated
+! HELP-FC1-NEXT: -fstack-arrays         Attempt to allocate array temporaries on the stack, no matter their size
 ! HELP-FC1-NEXT: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! HELP-FC1-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! HELP-FC1-NEXT: -help                  Display available options

diff  --git a/flang/test/Driver/fast_math.f90 b/flang/test/Driver/fast_math.f90
index 07c8ec6ea0710..996fdf0fcc107 100644
--- a/flang/test/Driver/fast_math.f90
+++ b/flang/test/Driver/fast_math.f90
@@ -1,25 +1,35 @@
 ! Test for correct forwarding of fast-math flags from the compiler driver to the
 ! frontend driver
 
-! -Ofast => -ffast-math -O3
+! -Ofast => -ffast-math -O3 -fstack-arrays
 ! RUN: %flang -Ofast -fsyntax-only -### %s -o %t 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-OFAST %s
 ! CHECK-OFAST: -fc1
 ! CHECK-OFAST-SAME: -ffast-math
+! CHECK-OFAST-SAME: -fstack-arrays
 ! CHECK-OFAST-SAME: -O3
 
-! TODO: update once -fstack-arays is added
-! RUN: %flang -fstack-arrays -fsyntax-only %s -o %t 2>&1 \
+! RUN: %flang -fstack-arrays -fsyntax-only -### %s -o %t 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-STACK-ARRAYS %s
-! CHECK-STACK-ARRAYS: warning: argument unused during compilation: '-fstack-arrays'
+! CHECK-STACK-ARRAYS: -fc1
+! CHECK-STACK-ARRAYS-SAME: -fstack-arrays
 
-! -Ofast -fno-fast-math => -O3
+! -Ofast -fno-fast-math => -O3 -fstack-arrays
 ! RUN: %flang -Ofast -fno-fast-math -fsyntax-only -### %s -o %t 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-OFAST-NO-FAST %s
 ! CHECK-OFAST-NO-FAST: -fc1
 ! CHECK-OFAST-NO-FAST-NOT: -ffast-math
+! CHECK-OFAST-NO-FAST-SAME: -fstack-arrays
 ! CHECK-OFAST-NO-FAST-SAME: -O3
 
+! -Ofast -fno-stack-arrays -> -O3 -ffast-math
+! RUN: %flang -Ofast -fno-stack-arrays -fsyntax-only -### %s -o %t 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-OFAST-NO-SA %s
+! CHECK-OFAST-NO-SA: -fc1
+! CHECK-OFAST-NO-SA-SAME: -ffast-math
+! CHECK-OFAST-NO-SA-NOT: -fstack-arrays
+! CHECK-OFAST-NO-SA-SAME: -O3
+
 ! -ffast-math => -ffast-math
 ! RUN: %flang -ffast-math -fsyntax-only -### %s -o %t 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-FFAST %s

diff  --git a/flang/test/Transforms/stack-arrays.f90 b/flang/test/Transforms/stack-arrays.f90
index 7622e679f9196..16ccd2a2a4250 100644
--- a/flang/test/Transforms/stack-arrays.f90
+++ b/flang/test/Transforms/stack-arrays.f90
@@ -1,5 +1,10 @@
 ! RUN: %flang_fc1 -emit-fir %s -o - | fir-opt --array-value-copy | fir-opt --stack-arrays | FileCheck %s
 
+! In order to verify the whole MLIR pipeline, make the driver generate LLVM IR.
+! This is only to check that -fstack-arrays enables the stack-arrays pass so
+! only check the first example
+! RUN: %flang_fc1 -emit-llvm -o - -fstack-arrays %s | FileCheck --check-prefix=LLVM-IR %s
+
 ! check simple array value copy case
 subroutine array_value_copy_simple(arr)
   integer, intent(inout) :: arr(4)
@@ -14,6 +19,15 @@ subroutine array_value_copy_simple(arr)
 ! CHECK: return
 ! CHECK-NEXT: }
 
+! LLVM-IR: array_value_copy_simple
+! LLVM-IR-NOT: malloc
+! LLVM-IR-NOT: free
+! LLVM-IR: alloca [4 x i32]
+! LLVM-IR-NOT: malloc
+! LLVM-IR-NOT: free
+! LLVM-IR: ret void
+! LLVM-IR-NEXT: }
+
 ! check complex array value copy case
 module stuff
   type DerivedWithAllocatable


        


More information about the cfe-commits mailing list