diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -59,8 +59,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include +#include #include - #define DEBUG_TYPE "flang-lower-expr" using namespace Fortran::runtime; @@ -2994,10 +2994,51 @@ // Initialization expressions can never allocate memory. return genval(a); } - mlir::Type storageType = converter.genType(toEvExpr(a)); - return placeScalarValueInMemory(builder, getLoc(), genval(a), storageType); + Fortran::lower::SomeExpr expr = toEvExpr(a); + + // Process as usual if non-constant + if (!Fortran::evaluate::IsActuallyConstant(expr)) { + mlir::Type storageType = converter.genType(expr); + return placeScalarValueInMemory(builder, getLoc(), genval(a), + storageType); + } + + // Extract internal constant + fir::ExtendedValue exv = genval(a); + mlir::Value valBase = fir::getBase(exv); + if (fir::conformsWithPassByRef(valBase.getType())) + return exv; + mlir::Type storageType = converter.genType(expr); + assert(!fir::hasDynamicSize(storageType) && + "only expect statically sized scalars to be by value"); + + llvm::StringRef globalPrefix = converter.getUniqueLitName( + getLoc(), std::make_unique(expr), + storageType); + + std::string globalName; + while (!globalName.length() || builder.getNamedGlobal(globalName)) + globalName = globalPrefix.str() + "." + std::to_string(uniqueLitId++); + + assert(!builder.getNamedGlobal(globalName) && "global name exists!"); + + auto global = builder.createGlobalConstant( + getLoc(), storageType, globalName, + [&](fir::FirOpBuilder &builder) { + fir::ExtendedValue exv = genval(a); + mlir::Value valBase = fir::getBase(exv); + mlir::Value val = + builder.createConvert(getLoc(), storageType, valBase); + builder.create(getLoc(), val); + }, + builder.createInternalLinkage()); + + return {builder.create(getLoc(), global.resultType(), + global.getSymbol())}; } + std::atomic uniqueLitId = 1; + template typename T, typename B = std::decay_t>, std::enable_if_t< diff --git a/flang/test/Lower/Intrinsics/ieee_class.f90 b/flang/test/Lower/Intrinsics/ieee_class.f90 --- a/flang/test/Lower/Intrinsics/ieee_class.f90 +++ b/flang/test/Lower/Intrinsics/ieee_class.f90 @@ -40,7 +40,6 @@ subroutine classify(x) use m; use ieee_arithmetic real(k) :: x - ! CHECK-DAG: %[[V_0:[0-9]+]] = fir.alloca i32 {adapt.valuebyref} ! CHECK-DAG: %[[V_1:[0-9]+]] = fir.alloca !fir.type<_QMieee_arithmeticTieee_class_type{which:i8}> ! CHECK-DAG: %[[V_2:[0-9]+]] = fir.alloca !fir.type<_QMieee_arithmeticTieee_class_type{which:i8}> {bindc_name = "r", uniq_name = "_QFclassifyEr"} type(ieee_class_type) :: r @@ -86,7 +85,7 @@ ! CHECK: %[[V_45:[0-9]+]] = fir.load %[[V_43]] : !fir.ref ! CHECK: %[[V_46:[0-9]+]] = arith.cmpi eq, %[[V_44]], %[[V_45]] : i8 ! CHECK: fir.if %[[V_46]] { - ! CHECK: fir.store %c3{{.*}} to %[[V_0]] : !fir.ref + ! CHECK: %[[V_0:[0-9]+]] = fir.address_of(@_QQro.i4.0.1) : !fir.ref ! CHECK: fir.call @_QMmPout(%arg0, %[[V_0]]) {{.*}} : (!fir.ref, !fir.ref) -> () ! CHECK: } if (r==ieee_negative_inf) call out(x, 3) diff --git a/flang/test/Lower/basic-call.f90 b/flang/test/Lower/basic-call.f90 --- a/flang/test/Lower/basic-call.f90 +++ b/flang/test/Lower/basic-call.f90 @@ -25,12 +25,8 @@ end ! CHECK-LABEL: func @_QPsub4() { -! CHECK-DAG: %[[REAL_VALUE:.*]] = fir.alloca f32 {adapt.valuebyref} -! CHECK-DAG: %[[INT_VALUE:.*]] = fir.alloca i32 {adapt.valuebyref} -! CHECK: %[[C2:.*]] = arith.constant 2 : i32 -! CHECK: fir.store %[[C2]] to %[[INT_VALUE]] : !fir.ref -! CHECK: %[[C3:.*]] = arith.constant 3.000000e+00 : f32 -! CHECK: fir.store %[[C3]] to %[[REAL_VALUE]] : !fir.ref +! CHECK-DAG: %[[INT_VALUE:.*]] = fir.address_of(@_QQro.i4.0.1) : !fir.ref +! CHECK-DAG: %[[REAL_VALUE:.*]] = fir.address_of(@_QQro.r4.1.2) : !fir.ref ! CHECK: fir.call @_QPsub3(%[[INT_VALUE]], %[[REAL_VALUE]]) {{.*}}: (!fir.ref, !fir.ref) -> () subroutine call_fct1() @@ -46,4 +42,7 @@ ! CHECK: fir.store %[[RES]] to %[[C]] : !fir.ref ! CHECK: return +! CHECK: fir.global internal @_QQro.i4.0.1 constant : i32 { +! CHECK: fir.global internal @_QQro.r4.1.2 constant : f32 { + ! CHECK: func private @_QPfct1(!fir.ref, !fir.ref) -> f32 diff --git a/flang/test/Lower/block.f90 b/flang/test/Lower/block.f90 --- a/flang/test/Lower/block.f90 +++ b/flang/test/Lower/block.f90 @@ -2,7 +2,6 @@ ! CHECK-LABEL: func @_QQmain program bb ! block stack management and exits - ! CHECK: %[[V_0:[0-9]+]] = fir.alloca i32 {adapt.valuebyref} ! CHECK: %[[V_1:[0-9]+]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} integer :: i, j ! CHECK: fir.store %c0{{.*}} to %[[V_1]] : !fir.ref @@ -80,7 +79,7 @@ 100 print*, i ! expect 21 ! CHECK: %[[V_51:[0-9]+]] = fir.call @llvm.stacksave() fastmath : () -> !fir.ref - ! CHECK: fir.store %c5{{.*}} to %[[V_0]] : !fir.ref + ! CHECK: %[[V_0:[0-9]+]] = fir.address_of(@_QQro.i4.0.1) : !fir.ref ! CHECK: fir.call @ss(%[[V_0]]) fastmath : (!fir.ref) -> () ! CHECK: fir.call @llvm.stackrestore(%[[V_51]]) fastmath : (!fir.ref) -> () block @@ -96,3 +95,4 @@ subroutine ss(n) bind(c) print*, n end subroutine +! CHECK: fir.global internal @_QQro.i4.0.1 constant : i32 { diff --git a/flang/test/Lower/dummy-arguments.f90 b/flang/test/Lower/dummy-arguments.f90 --- a/flang/test/Lower/dummy-arguments.f90 +++ b/flang/test/Lower/dummy-arguments.f90 @@ -2,9 +2,7 @@ ! CHECK-LABEL: _QQmain program test1 - ! CHECK-DAG: %[[TMP:.*]] = fir.alloca - ! CHECK-DAG: %[[TEN:.*]] = arith.constant - ! CHECK: fir.store %[[TEN]] to %[[TMP]] + ! CHECK-DAG: %[[TMP:.*]] = fir.address_of(@_QQro.i4.0.1) : !fir.ref ! CHECK-NEXT: fir.call @_QFPfoo call foo(10) contains @@ -39,3 +37,4 @@ real, target :: x(:) print *, xs, xa end subroutine +! CHECK: fir.global internal @_QQro.i4.0.1 constant : i32 { diff --git a/flang/test/Lower/host-associated.f90 b/flang/test/Lower/host-associated.f90 --- a/flang/test/Lower/host-associated.f90 +++ b/flang/test/Lower/host-associated.f90 @@ -448,9 +448,7 @@ ! CHECK-LABEL: func @_QPtest_proc_dummy_other( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxproc<() -> ()>) { -! CHECK: %[[VAL_1:.*]] = arith.constant 4 : i32 -! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {adapt.valuebyref} -! CHECK: fir.store %[[VAL_1]] to %[[VAL_2]] : !fir.ref +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QQro.i4.2.1) : !fir.ref ! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_0]] : (!fir.boxproc<() -> ()>) -> ((!fir.ref) -> ()) ! CHECK: fir.call %[[VAL_3]](%[[VAL_2]]) {{.*}}: (!fir.ref) -> () ! CHECK: return @@ -657,6 +655,8 @@ ! CHECK: fir.call @_QPtest_11c(%[[b]], %{{.*}}) {{.*}}: (!fir.boxproc<() -> ()>, !fir.ref) -> () ! CHECK: func private @_QPtest_11c(!fir.boxproc<() -> ()>, !fir.ref) +! CHECK: fir.global internal @_QQro.i4.3.1 constant : i32 { + subroutine test_11a external test_11b call test_11c(test_11b, 3) @@ -683,3 +683,4 @@ print *, i end subroutine end subroutine +