diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -32,7 +32,8 @@ OldLabelDoEndStatements, LogicalIntegerAssignment, EmptySourceFile, ProgramReturn, ImplicitNoneTypeNever, ImplicitNoneTypeAlways, ForwardRefDummyImplicitNone, OpenAccessAppend, BOZAsDefaultInteger, - DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat) + DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat, + SaveMainProgram, SaveBigMainProgramVariables) using LanguageFeatures = EnumSet; @@ -46,6 +47,7 @@ disable_.set(LanguageFeature::ImplicitNoneTypeNever); disable_.set(LanguageFeature::ImplicitNoneTypeAlways); disable_.set(LanguageFeature::DefaultSave); + disable_.set(LanguageFeature::SaveMainProgram); // These features, if enabled, conflict with valid standard usage, // so there are disabled here by default. disable_.set(LanguageFeature::BackslashEscapes); diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1403,6 +1403,8 @@ bool IsSaved(const Symbol &original) { const Symbol &symbol{GetAssociationRoot(original)}; const Scope &scope{symbol.owner()}; + const common::LanguageFeatureControl &features{ + scope.context().languageFeatures()}; auto scopeKind{scope.kind()}; if (symbol.has()) { return false; // ASSOCIATE(non-variable) @@ -1422,8 +1424,18 @@ // BLOCK DATA entities must all be in COMMON, // which was checked above. return true; - } else if (scope.context().languageFeatures().IsEnabled( - common::LanguageFeature::DefaultSave) && + } else if (scopeKind == Scope::Kind::MainProgram && + (features.IsEnabled(common::LanguageFeature::SaveMainProgram) || + (features.IsEnabled( + common::LanguageFeature::SaveBigMainProgramVariables) && + symbol.size() > 32))) { + // With SaveBigMainProgramVariables, keeping all unsaved main program + // variables of 32 bytes or less on the stack allows keeping numerical and + // logical scalars, small scalar characters or derived, small arrays, and + // scalar descriptors on the stack. This leaves more room for lower level + // optimizers to do register promotion or get easy aliasing information. + return true; + } else if (features.IsEnabled(common::LanguageFeature::DefaultSave) && (scopeKind == Scope::Kind::MainProgram || (scope.kind() == Scope::Kind::Subprogram && !(scope.symbol() && diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp --- a/flang/lib/Lower/PFTBuilder.cpp +++ b/flang/lib/Lower/PFTBuilder.cpp @@ -24,19 +24,6 @@ "no-structured-fir", llvm::cl::desc("disable generation of structured FIR"), llvm::cl::init(false), llvm::cl::Hidden); -static llvm::cl::opt nonRecursiveProcedures( - "non-recursive-procedures", - llvm::cl::desc("Make procedures non-recursive by default. This was the " - "default for all Fortran standards prior to 2018."), - llvm::cl::init(/*2018 standard=*/false)); - -static llvm::cl::opt mainProgramGlobals( - "main-program-globals", - llvm::cl::desc( - "Allocate all variables in the main program as global variables and " - "not on the stack regardless of type, kind, and rank."), - llvm::cl::init(/*2018 standard=*/false), llvm::cl::Hidden); - using namespace Fortran; namespace { @@ -1268,40 +1255,8 @@ return semantics::FindCommonBlockContaining(sym); } -static bool isReentrant(const Fortran::semantics::Scope &scope) { - if (scope.kind() == Fortran::semantics::Scope::Kind::MainProgram) - return false; - if (scope.kind() == Fortran::semantics::Scope::Kind::Subprogram) { - const Fortran::semantics::Symbol *sym = scope.symbol(); - assert(sym && "Subprogram scope must have a symbol"); - return sym->attrs().test(semantics::Attr::RECURSIVE) || - (!sym->attrs().test(semantics::Attr::NON_RECURSIVE) && - Fortran::lower::defaultRecursiveFunctionSetting()); - } - if (scope.kind() == Fortran::semantics::Scope::Kind::Module) - return false; - return true; -} - /// Is the symbol `sym` a global? bool Fortran::lower::symbolIsGlobal(const semantics::Symbol &sym) { - if (const auto *details = sym.detailsIf()) { - if (details->init()) - return true; - if (!isReentrant(sym.owner())) { - // Turn array and character of non re-entrant programs (like the main - // program) into global memory. - if (const Fortran::semantics::DeclTypeSpec *symTy = sym.GetType()) - if (symTy->category() == semantics::DeclTypeSpec::Character) - if (auto e = symTy->characterTypeSpec().length().GetExplicit()) - return true; - if (!details->shape().empty() || !details->coshape().empty()) - return true; - } - if (mainProgramGlobals && - sym.owner().kind() == Fortran::semantics::Scope::Kind::MainProgram) - return true; - } return semantics::IsSaved(sym) || lower::definedInCommonBlock(sym) || semantics::IsNamedConstant(sym); } @@ -1695,14 +1650,6 @@ return walker.result(); } -// FIXME: FlangDriver -// This option should be integrated with the real driver as the default of -// RECURSIVE vs. NON_RECURSIVE may be changed by other command line options, -// etc., etc. -bool Fortran::lower::defaultRecursiveFunctionSetting() { - return !nonRecursiveProcedures; -} - void Fortran::lower::dumpPFT(llvm::raw_ostream &outputStream, const lower::pft::Program &pft) { PFTDumper{}.dumpPFT(outputStream, pft); diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90 --- a/flang/test/Lower/OpenMP/atomic-read.f90 +++ b/flang/test/Lower/OpenMP/atomic-read.f90 @@ -3,12 +3,12 @@ ! This test checks the lowering of atomic read !CHECK: func @_QQmain() { -!CHECK: %[[VAR_A:.*]] = fir.address_of(@_QFEa) : !fir.ref> -!CHECK: %[[VAR_B:.*]] = fir.address_of(@_QFEb) : !fir.ref> +!CHECK: %[[VAR_A:.*]] = fir.alloca !fir.char<1> {bindc_name = "a", uniq_name = "_QFEa"} +!CHECK: %[[VAR_B:.*]] = fir.alloca !fir.char<1> {bindc_name = "b", uniq_name = "_QFEb"} !CHECK: %[[VAR_C:.*]] = fir.alloca !fir.logical<4> {bindc_name = "c", uniq_name = "_QFEc"} !CHECK: %[[VAR_D:.*]] = fir.alloca !fir.logical<4> {bindc_name = "d", uniq_name = "_QFEd"} -!CHECK: %[[VAR_E:.*]] = fir.address_of(@_QFEe) : !fir.ref> -!CHECK: %[[VAR_F:.*]] = fir.address_of(@_QFEf) : !fir.ref> +!CHECK: %[[VAR_E:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "e", uniq_name = "_QFEe"} +!CHECK: %[[VAR_F:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "f", uniq_name = "_QFEf"} !CHECK: %[[VAR_G:.*]] = fir.alloca f32 {bindc_name = "g", uniq_name = "_QFEg"} !CHECK: %[[VAR_H:.*]] = fir.alloca f32 {bindc_name = "h", uniq_name = "_QFEh"} !CHECK: %[[VAR_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} diff --git a/flang/test/Lower/array-character.f90 b/flang/test/Lower/array-character.f90 --- a/flang/test/Lower/array-character.f90 +++ b/flang/test/Lower/array-character.f90 @@ -58,7 +58,7 @@ ! CHECK-DAG: %[[VAL_0:.*]] = arith.constant 4 : index ! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[VAL_2:.*]] = arith.constant -1 : i32 - ! CHECK: %[[VAL_5:.*]] = fir.address_of(@_QFEc1) : !fir.ref>> + ! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.array<3x!fir.char<1,4>> {bindc_name = "c1", uniq_name = "_QFEc1"} ! CHECK: %[[VAL_6:.*]] = fir.address_of(@_QFEc2) : !fir.ref>> ! CHECK: %[[VAL_7:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref>) -> !fir.ref diff --git a/flang/test/Lower/array-expression-slice-1.f90 b/flang/test/Lower/array-expression-slice-1.f90 --- a/flang/test/Lower/array-expression-slice-1.f90 +++ b/flang/test/Lower/array-expression-slice-1.f90 @@ -18,10 +18,10 @@ ! CHECK-DAG: %[[VAL_23:.*]] = arith.constant 1 : i32 ! CHECK-DAG: %[[VAL_24:.*]] = arith.constant 0 : i32 ! CHECK-DAG: %[[VAL_25:.*]] = fir.address_of(@_QFEa1) : !fir.ref> -! CHECK-DAG: %[[VAL_26:.*]] = fir.address_of(@_QFEa2) : !fir.ref> +! CHECK-DAG: %[[VAL_26:.*]] = fir.alloca !fir.array<3xf32> {bindc_name = "a2", uniq_name = "_QFEa2"} ! CHECK-DAG: %[[VAL_27:.*]] = fir.address_of(@_QFEa3) : !fir.ref> ! CHECK-DAG: %[[VAL_28:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} -! CHECK-DAG: %[[VAL_29:.*]] = fir.address_of(@_QFEiv) : !fir.ref> +! CHECK-DAG: %[[VAL_29:.*]] = fir.alloca !fir.array<3xi32> {bindc_name = "iv", uniq_name = "_QFEiv"} ! CHECK-DAG: %[[VAL_30:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFEj"} ! CHECK-DAG: %[[VAL_31:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFEk"} ! CHECK: fir.store %[[VAL_24]] to %[[VAL_31]] : !fir.ref diff --git a/flang/test/Lower/associate-construct.f90 b/flang/test/Lower/associate-construct.f90 --- a/flang/test/Lower/associate-construct.f90 +++ b/flang/test/Lower/associate-construct.f90 @@ -4,7 +4,7 @@ program p ! CHECK-DAG: [[I:%[0-9]+]] = fir.alloca i32 {{{.*}}uniq_name = "_QFEi"} ! CHECK-DAG: [[N:%[0-9]+]] = fir.alloca i32 {{{.*}}uniq_name = "_QFEn"} - ! CHECK: [[T:%[0-9]+]] = fir.address_of(@_QFEt) : !fir.ref> + ! CHECK: [[T:%[0-9]+]] = fir.alloca !fir.array<3xi32> {bindc_name = "t", uniq_name = "_QFEt"} integer :: n, foo, t(3) ! CHECK: [[N]] ! CHECK-COUNT-3: fir.coordinate_of [[T]] diff --git a/flang/test/Lower/io-write.f90 b/flang/test/Lower/io-write.f90 --- a/flang/test/Lower/io-write.f90 +++ b/flang/test/Lower/io-write.f90 @@ -6,8 +6,8 @@ character(3) string write(string,getstring(6)) ! CHECK: %[[Val_0:.*]] = fir.alloca i32 {adapt.valuebyref} -! CHECK: %[[Val_1:.*]] = fir.address_of(@_QFEstring) : !fir.ref> ! CHECK: %[[Const_3:.*]] = arith.constant 3 : index +! CHECK: %[[Val_1:.*]] = fir.alloca !fir.char<1,3> {bindc_name = "string", uniq_name = "_QFEstring"} ! CHECK: %[[Val_2:.*]] = fir.convert %[[Val_1]] : (!fir.ref>) -> !fir.ref ! CHECK: %[[Val_3:.*]] = fir.convert %[[Const_3]] : (index) -> i64 ! CHECK: %[[Const_6:.*]] = arith.constant 6 : i32 diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90 --- a/flang/test/Lower/namelist.f90 +++ b/flang/test/Lower/namelist.f90 @@ -2,7 +2,7 @@ ! CHECK-LABEL: func @_QQmain program p - ! CHECK-DAG: [[ccc:%[0-9]+]] = fir.address_of(@_QFEccc) : !fir.ref>> + ! CHECK-DAG: [[ccc:%[0-9]+]] = fir.alloca !fir.array<4x!fir.char<1,3>> {bindc_name = "ccc", uniq_name = "_QFEccc"} ! CHECK-DAG: [[jjj:%[0-9]+]] = fir.alloca i32 {bindc_name = "jjj", uniq_name = "_QFEjjj"} character*3 ccc(4) namelist /nnn/ jjj, ccc @@ -17,7 +17,7 @@ ! CHECK: fir.insert_value ! CHECK: fir.address_of ! CHECK: fir.insert_value - ! CHECK: fir.address_of(@_QFEccc.desc) : !fir.ref>>>> + ! CHECK: fir.embox [[ccc]] ! CHECK: fir.insert_value ! CHECK: fir.alloca tuple, i64, !fir.ref, !fir.ref>>>>> ! CHECK: fir.address_of @@ -37,7 +37,7 @@ ! CHECK: fir.insert_value ! CHECK: fir.address_of ! CHECK: fir.insert_value - ! CHECK: fir.address_of(@_QFEccc.desc) : !fir.ref>>>> + ! CHECK: fir.embox [[ccc]] ! CHECK: fir.insert_value ! CHECK: fir.alloca tuple, i64, !fir.ref, !fir.ref>>>>> ! CHECK: fir.address_of @@ -86,4 +86,3 @@ ! CHECK-DAG: fir.global linkonce @_QQcl.6A6A6A00 constant : !fir.char<1,4> ! CHECK-DAG: fir.global linkonce @_QQcl.63636300 constant : !fir.char<1,4> ! CHECK-DAG: fir.global linkonce @_QQcl.6E6E6E00 constant : !fir.char<1,4> - ! CHECK-DAG: fir.global linkonce @_QFEccc.desc constant : !fir.box>>>