From d3602a7628923ab118a40b7ceb45523b0f53e83a Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Fri, 29 Sep 2023 01:36:06 -0700 Subject: [PATCH] [flang] Zero initialize uninitialized components in saved default init Follow up up of https://github.com/llvm/llvm-project/pull/67693 - Zero initialize uninitialized components of saved derived type entity with a default initial value. - Zero initialize uninitialized storage of common blocks with a member with an initial value. - Zero initialized uninitialized saved equivalence This removes all the cases where fir.global are created with an initial value that results in an undef in LLVM for part of the global, leading in surprising LLVM optimizations at -O2 for Fortran folks that expects there saved variables to be zero initialized if there is no explicit or default initial value. --- flang/docs/Extensions.md | 2 ++ flang/lib/Lower/ConvertVariable.cpp | 11 ++++++----- flang/test/Lower/array.f90 | 2 +- flang/test/Lower/common-block-2.f90 | 4 ++-- flang/test/Lower/common-block.f90 | 2 +- flang/test/Lower/default-initialization-globals.f90 | 8 ++++---- flang/test/Lower/equivalence-static-init.f90 | 2 +- flang/test/Lower/pointer-default-init.f90 | 4 ++-- flang/test/Lower/pointer-initial-target-2.f90 | 4 ++-- 9 files changed, 21 insertions(+), 18 deletions(-) diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index c1591eb49732b..480039911719c 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -101,6 +101,8 @@ end * `$` and `@` as legal characters in names * Initialization in type declaration statements using `/values/` * Saved variables without explicit or default initializers are zero initialized. +* In a saved entity of a type with a default initializer, components without default + values are zero initialized. * Kind specification with `*`, e.g. `REAL*4` * `DOUBLE COMPLEX` as a synonym for `COMPLEX(KIND(0.D0))` -- but not when spelled `TYPE(DOUBLECOMPLEX)`. diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index 87b570d1ac4b7..74e07ec77c0cb 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -352,8 +352,9 @@ static mlir::Value genDefaultInitializerValue( componentValue = genDefaultInitializerValue(converter, loc, component, componentTy, stmtCtx); } else { - // Component has no initial value. - componentValue = builder.create(loc, componentTy); + // Component has no initial value. Set its bits to zero by extension + // to match what is expected because other compilers are doing it. + componentValue = builder.create(loc, componentTy); } } else if (const auto *proc{ component @@ -361,7 +362,7 @@ static mlir::Value genDefaultInitializerValue( if (proc->init().has_value()) TODO(loc, "procedure pointer component default initialization"); else - componentValue = builder.create(loc, componentTy); + componentValue = builder.create(loc, componentTy); } assert(componentValue && "must have been computed"); componentValue = builder.createConvert(loc, componentTy, componentValue); @@ -890,7 +891,7 @@ static fir::GlobalOp defineGlobalAggregateStore( Fortran::lower::createGlobalInitialization( builder, global, [&](fir::FirOpBuilder &builder) { Fortran::lower::StatementContext stmtCtx; - mlir::Value initVal = builder.create(loc, aggTy); + mlir::Value initVal = builder.create(loc, aggTy); builder.create(loc, initVal); }); return global; @@ -1171,7 +1172,7 @@ static void finalizeCommonBlockDefinition( mlir::TupleType commonTy = global.getType().cast(); auto initFunc = [&](fir::FirOpBuilder &builder) { mlir::IndexType idxTy = builder.getIndexType(); - mlir::Value cb = builder.create(loc, commonTy); + mlir::Value cb = builder.create(loc, commonTy); unsigned tupIdx = 0; std::size_t offset = 0; LLVM_DEBUG(llvm::dbgs() << "block {\n"); diff --git a/flang/test/Lower/array.f90 b/flang/test/Lower/array.f90 index e6e1286285838..3371887d04127 100644 --- a/flang/test/Lower/array.f90 +++ b/flang/test/Lower/array.f90 @@ -4,7 +4,7 @@ ! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32 ! CHECK-DAG: %[[VAL_2:.*]] = arith.constant 2.400000e+00 : f32 ! CHECK-DAG: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32 -! CHECK: %[[VAL_4:.*]] = fir.undefined tuple> +! CHECK: %[[VAL_4:.*]] = fir.zero_bits tuple> ! CHECK: %[[VAL_5:.*]] = fir.undefined !fir.array<5x5xf32> ! CHECK: %[[VAL_6:.*]] = fir.insert_on_range %[[VAL_5]], %[[VAL_1]] from (0, 0) to (1, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32> ! CHECK: %[[VAL_7:.*]] = fir.insert_on_range %[[VAL_6]], %[[VAL_3]] from (2, 0) to (4, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32> diff --git a/flang/test/Lower/common-block-2.f90 b/flang/test/Lower/common-block-2.f90 index 31916f4be9fcb..4b12860a48ffa 100644 --- a/flang/test/Lower/common-block-2.f90 +++ b/flang/test/Lower/common-block-2.f90 @@ -6,12 +6,12 @@ ! - A common block that is initialized outside of a BLOCK DATA. ! CHECK-LABEL: fir.global @__BLNK__ : tuple> { -! CHECK: %[[undef:.*]] = fir.undefined tuple> +! CHECK: %[[undef:.*]] = fir.zero_bits tuple> ! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple>, i32) -> tuple> ! CHECK: fir.has_value %[[init]] : tuple> ! CHECK-LABEL: fir.global @a_ : tuple> { -! CHECK: %[[undef:.*]] = fir.undefined tuple> +! CHECK: %[[undef:.*]] = fir.zero_bits tuple> ! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple>, i32) -> tuple> ! CHECK: fir.has_value %[[init]] : tuple> diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90 index bd3fab507c0ef..3934b71b75694 100644 --- a/flang/test/Lower/common-block.f90 +++ b/flang/test/Lower/common-block.f90 @@ -6,7 +6,7 @@ ! CHECK: @with_empty_equiv_ = common global [8 x i8] zeroinitializer ! CHECK: @x_ = global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} } ! CHECK: @y_ = common global [12 x i8] zeroinitializer -! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] undef, float 3.000000e+00 } +! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] zeroinitializer, float 3.000000e+00 } ! CHECK-LABEL: _QPs0 subroutine s0 diff --git a/flang/test/Lower/default-initialization-globals.f90 b/flang/test/Lower/default-initialization-globals.f90 index bbcea75a5b1f9..2b5e3c36367e2 100644 --- a/flang/test/Lower/default-initialization-globals.f90 +++ b/flang/test/Lower/default-initialization-globals.f90 @@ -97,7 +97,7 @@ module tinit ! CHECK-DAG: %[[VAL_15:.*]] = arith.constant 66 : i32 ! CHECK: %[[VAL_16:.*]] = fir.undefined !fir.type<_QMtinitTt1{{.*}}> ! CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_11]], ["i", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}> - ! CHECK: %[[VAL_18:.*]] = fir.undefined i32 + ! CHECK: %[[VAL_18:.*]] = fir.zero_bits i32 ! CHECK: %[[VAL_19:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_18]], ["j", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}> ! CHECK: %[[VAL_20:.*]] = fir.address_of(@_QMtinitEziel) : !fir.ref> ! CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1> @@ -111,12 +111,12 @@ module tinit ! CHECK: %[[VAL_28:.*]] = fir.insert_value %[[VAL_27]], %[[VAL_26]], ["z", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.box>>) -> !fir.type<_QMtinitTt1{{.*}}> ! CHECK: %[[VAL_29:.*]] = fir.string_lit "hello "(10) : !fir.char<1,10> ! CHECK: %[[VAL_30:.*]] = fir.insert_value %[[VAL_28]], %[[VAL_29]], ["c1", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}> - ! CHECK: %[[VAL_31:.*]] = fir.undefined !fir.char<1,10> + ! CHECK: %[[VAL_31:.*]] = fir.zero_bits !fir.char<1,10> ! CHECK: %[[VAL_32:.*]] = fir.insert_value %[[VAL_30]], %[[VAL_31]], ["c2", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}> ! CHECK: %[[VAL_33:.*]] = fir.undefined !fir.type<_QMtinitTt0{k:i32}> ! CHECK: %[[VAL_34:.*]] = fir.insert_value %[[VAL_33]], %[[VAL_15]], ["k", !fir.type<_QMtinitTt0{k:i32}>] : (!fir.type<_QMtinitTt0{k:i32}>, i32) -> !fir.type<_QMtinitTt0{k:i32}> ! CHECK: %[[VAL_35:.*]] = fir.insert_value %[[VAL_32]], %[[VAL_34]], ["somet0", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTt0{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}> - ! CHECK: %[[VAL_36:.*]] = fir.undefined !fir.type<_QMtinitTtno_init{k:i32}> + ! CHECK: %[[VAL_36:.*]] = fir.zero_bits !fir.type<_QMtinitTtno_init{k:i32}> ! CHECK: %[[VAL_37:.*]] = fir.insert_value %[[VAL_35]], %[[VAL_36]], ["sometno_init", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTtno_init{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}> ! CHECK: %[[VAL_38:.*]] = fir.insert_value %[[VAL_33]], %[[VAL_14]], ["k", !fir.type<_QMtinitTt0{k:i32}>] : (!fir.type<_QMtinitTt0{k:i32}>, i32) -> !fir.type<_QMtinitTt0{k:i32}> ! CHECK: %[[VAL_39:.*]] = fir.insert_value %[[VAL_37]], %[[VAL_38]], ["somet0_2", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.type<_QMtinitTt0{k:i32}>) -> !fir.type<_QMtinitTt1{{.*}}> @@ -129,7 +129,7 @@ module tinit ! CHECK: %[[VAL_42:.*]] = arith.constant 66 : i32 ! CHECK: %[[VAL_43:.*]] = fir.undefined !fir.type<_QMtinitTtextendst0{k:i32,l:i32}> ! CHECK: %[[VAL_44:.*]] = fir.insert_value %[[VAL_43]], %[[VAL_42]], ["k", !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>] : (!fir.type<_QMtinitTtextendst0{k:i32,l:i32}>, i32) -> !fir.type<_QMtinitTtextendst0{k:i32,l:i32}> - ! CHECK: %[[VAL_45:.*]] = fir.undefined i32 + ! CHECK: %[[VAL_45:.*]] = fir.zero_bits i32 ! CHECK: %[[VAL_46:.*]] = fir.insert_value %[[VAL_44]], %[[VAL_45]], ["l", !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>] : (!fir.type<_QMtinitTtextendst0{k:i32,l:i32}>, i32) -> !fir.type<_QMtinitTtextendst0{k:i32,l:i32}> ! CHECK: fir.has_value %[[VAL_46]] : !fir.type<_QMtinitTtextendst0{k:i32,l:i32}> diff --git a/flang/test/Lower/equivalence-static-init.f90 b/flang/test/Lower/equivalence-static-init.f90 index 6b4b0ccff4c5e..4c52a4a7d8448 100644 --- a/flang/test/Lower/equivalence-static-init.f90 +++ b/flang/test/Lower/equivalence-static-init.f90 @@ -8,7 +8,7 @@ module module_without_init equivalence(i(1), x) end module ! CHECK-LABEL: fir.global @_QMmodule_without_initEi : !fir.array<8xi8> { - ! CHECK: %0 = fir.undefined !fir.array<8xi8> + ! CHECK: %0 = fir.zero_bits !fir.array<8xi8> ! CHECK: fir.has_value %0 : !fir.array<8xi8> ! CHECK} diff --git a/flang/test/Lower/pointer-default-init.f90 b/flang/test/Lower/pointer-default-init.f90 index 4697d601347e7..6dde5d56aaa82 100644 --- a/flang/test/Lower/pointer-default-init.f90 +++ b/flang/test/Lower/pointer-default-init.f90 @@ -21,7 +21,7 @@ module test type(t) :: test_module_var ! CHECK-LABEL: fir.global @_QMtestEtest_module_var : !fir.type<_QMtestTt{i:i32,x:!fir.box>>}> { ! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box>>}> -! CHECK: %[[VAL_1:.*]] = fir.undefined i32 +! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32 ! CHECK: %[[VAL_2:.*]] = fir.field_index i ! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]] ! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr> @@ -97,7 +97,7 @@ subroutine test_saved_pointer() ! CHECK-LABEL: fir.global internal @_QFtest_savedEx : !fir.type<_QMtestTt{i:i32,x:!fir.box>>}> { ! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box>>}> -! CHECK: %[[VAL_1:.*]] = fir.undefined i32 +! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32 ! CHECK: %[[VAL_2:.*]] = fir.field_index i ! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]] ! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr> diff --git a/flang/test/Lower/pointer-initial-target-2.f90 b/flang/test/Lower/pointer-initial-target-2.f90 index 69e9f23126708..a3f2292e7fb76 100644 --- a/flang/test/Lower/pointer-initial-target-2.f90 +++ b/flang/test/Lower/pointer-initial-target-2.f90 @@ -12,7 +12,7 @@ common /a/ p data p /b/ ! CHECK-LABEL: fir.global @a_ : tuple>> - ! CHECK: %[[undef:.*]] = fir.undefined tuple>> + ! CHECK: %[[undef:.*]] = fir.zero_bits tuple>> ! CHECK: %[[b:.*]] = fir.address_of(@_QEb) : !fir.ref ! CHECK: %[[box:.*]] = fir.embox %[[b]] : (!fir.ref) -> !fir.box ! CHECK: %[[rebox:.*]] = fir.rebox %[[box]] : (!fir.box) -> !fir.box> @@ -41,7 +41,7 @@ block data bdsnake integer, pointer :: p => b common /snake/ p, b ! CHECK-LABEL: fir.global @snake_ : tuple>, i32> - ! CHECK: %[[tuple0:.*]] = fir.undefined tuple>, i32> + ! CHECK: %[[tuple0:.*]] = fir.zero_bits tuple>, i32> ! CHECK: %[[snakeAddr:.*]] = fir.address_of(@snake_) : !fir.ref>, i32>> ! CHECK: %[[byteView:.*]] = fir.convert %[[snakeAddr:.*]] : (!fir.ref>, i32>>) -> !fir.ref> ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[byteView]], %c24{{.*}} : (!fir.ref>, index) -> !fir.ref