diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -29,8 +29,8 @@ /// allocations should always be on the heap. static llvm::cl::opt dynamicArrayStackToHeapAllocation( "fdynamic-heap-array", - llvm::cl::desc("place all array allocations of dynamic size on the heap"), - llvm::cl::init(false), llvm::cl::Hidden); + llvm::cl::desc("place all array allocations of fully dynamic size on the heap"), + llvm::cl::init(true), llvm::cl::Hidden); /// Shared option in tools to set a maximum value for the number of elements in /// a compile-time sized array that can be allocated on the stack. diff --git a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp --- a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp +++ b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp @@ -78,8 +78,15 @@ if (auto seqTy = alloca.getInType().dyn_cast()) { if (fir::hasDynamicSize(seqTy)) { // Move all arrays with runtime determined size to the heap. - if (options.dynamicArrayOnHeap) + if (options.dynamicArrayOnHeap) { + for (const auto d : seqTy.getShape()) { + // Keep array on stack if some of the dimensions are static + if (d != seqTy.getUnknownExtent()) + return true; + } + // move to heap otherwise return false; + } } else { std::int64_t numberOfElements = 1; for (std::int64_t i : seqTy.getShape()) { diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -1,5 +1,4 @@ -// RUN: tco %s | FileCheck %s -// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s +// RUN: %flang_fc1 -mllvm -fdynamic-heap-array=false -emit-llvm %s -o - | FileCheck %s // UNSUPPORTED: system-windows diff --git a/flang/test/Lower/array-stack.f90 b/flang/test/Lower/array-stack.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/array-stack.f90 @@ -0,0 +1,17 @@ +! Tests moving stack allocated dynamic arrays with all dynamic dimensions to heap +! RUN: bbc %s -o - | FileCheck %s + +! CHECK-LABEL: func @_QPss2( +! CHECK: %[[A:.*]] = fir.alloca !fir.array<5xf32> {bindc_name = "a", uniq_name = "{{.*}}Ea"} +! CHECK: %[[B:.*]] = fir.allocmem !fir.array, %4 {bindc_name = "b", uniq_name = "{{.*}}Eb"} +! CHECK: %[[C:.*]] = fir.allocmem !fir.array, %4, %4 {bindc_name = "c", uniq_name = "{{.*}}Ec"} +! CHECK: %[[D:.*]] = fir.alloca !fir.array<5x?x?xi32>, %4, %4 {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK: fir.freemem %[[B]] : !fir.heap> +! CHECK: fir.freemem %[[C]] : !fir.heap> + +subroutine ss2(N) + real :: A(5) + real :: B(N) + integer :: C(N,N) + integer :: D(5,N,N) +end diff --git a/flang/test/Lower/array-temp.f90 b/flang/test/Lower/array-temp.f90 --- a/flang/test/Lower/array-temp.f90 +++ b/flang/test/Lower/array-temp.f90 @@ -1,4 +1,4 @@ -! RUN: bbc %s -o - | FileCheck %s +! RUN: bbc %s -fdynamic-heap-array=false -o - | FileCheck %s ! CHECK-LABEL: func @_QPss1() subroutine ss1 diff --git a/flang/test/Lower/character-local-variables.f90 b/flang/test/Lower/character-local-variables.f90 --- a/flang/test/Lower/character-local-variables.f90 +++ b/flang/test/Lower/character-local-variables.f90 @@ -1,4 +1,4 @@ -! RUN: bbc %s -o - | FileCheck %s +! RUN: bbc %s -fdynamic-heap-array=false -o - | FileCheck %s ! Test lowering of local character variables diff --git a/flang/test/Lower/explicit-interface-results-2.f90 b/flang/test/Lower/explicit-interface-results-2.f90 --- a/flang/test/Lower/explicit-interface-results-2.f90 +++ b/flang/test/Lower/explicit-interface-results-2.f90 @@ -1,7 +1,7 @@ ! Test lowering of internal procedures returning arrays or characters. ! This test allocation on the caller side of the results that may depend on ! host associated symbols. -! RUN: bbc %s -o - | FileCheck %s +! RUN: bbc %s -fdynamic-heap-array=false -o - | FileCheck %s module some_module integer :: n_module