[flang-commits] [flang] [flang] Zero initialize uninitialized components in saved default init (PR #67777)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 29 02:11:38 PDT 2023
https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/67777
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.
>From d3602a7628923ab118a40b7ceb45523b0f53e83a Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
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 c1591eb49732b7f..480039911719c6d 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 87b570d1ac4b7e2..74e07ec77c0cb55 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<fir::UndefOp>(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<fir::ZeroOp>(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<fir::UndefOp>(loc, componentTy);
+ componentValue = builder.create<fir::ZeroOp>(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<fir::UndefOp>(loc, aggTy);
+ mlir::Value initVal = builder.create<fir::ZeroOp>(loc, aggTy);
builder.create<fir::HasValueOp>(loc, initVal);
});
return global;
@@ -1171,7 +1172,7 @@ static void finalizeCommonBlockDefinition(
mlir::TupleType commonTy = global.getType().cast<mlir::TupleType>();
auto initFunc = [&](fir::FirOpBuilder &builder) {
mlir::IndexType idxTy = builder.getIndexType();
- mlir::Value cb = builder.create<fir::UndefOp>(loc, commonTy);
+ mlir::Value cb = builder.create<fir::ZeroOp>(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 e6e12862858385d..3371887d041279a 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<!fir.array<5x5xf32>>
+! CHECK: %[[VAL_4:.*]] = fir.zero_bits tuple<!fir.array<5x5xf32>>
! 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 31916f4be9fcb2e..4b12860a48ffaed 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<i32, !fir.array<8xi8>> {
-! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
+! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>
! CHECK-LABEL: fir.global @a_ : tuple<i32, !fir.array<8xi8>> {
-! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
+! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>
diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90
index bd3fab507c0ef41..3934b71b75694ed 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 bbcea75a5b1f979..2b5e3c36367e2e5 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<!fir.array<100xf32>>
! 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.ptr<!fir.array<?xf32>>>) -> !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 6b4b0ccff4c5e66..4c52a4a7d8448ae 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 4697d601347e749..6dde5d56aaa8222 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<!fir.ptr<!fir.array<?xf32>>>}> {
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
-! 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<!fir.array<?xf32>>
@@ -97,7 +97,7 @@ subroutine test_saved_pointer()
! CHECK-LABEL: fir.global internal @_QFtest_savedEx : !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
-! 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<!fir.array<?xf32>>
diff --git a/flang/test/Lower/pointer-initial-target-2.f90 b/flang/test/Lower/pointer-initial-target-2.f90
index 69e9f23126708fb..a3f2292e7fb7676 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<!fir.box<!fir.ptr<f32>>>
- ! CHECK: %[[undef:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<f32>>>
+ ! CHECK: %[[undef:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<f32>>>
! CHECK: %[[b:.*]] = fir.address_of(@_QEb) : !fir.ref<f32>
! CHECK: %[[box:.*]] = fir.embox %[[b]] : (!fir.ref<f32>) -> !fir.box<f32>
! CHECK: %[[rebox:.*]] = fir.rebox %[[box]] : (!fir.box<f32>) -> !fir.box<!fir.ptr<f32>>
@@ -41,7 +41,7 @@ block data bdsnake
integer, pointer :: p => b
common /snake/ p, b
! CHECK-LABEL: fir.global @snake_ : tuple<!fir.box<!fir.ptr<i32>>, i32>
- ! CHECK: %[[tuple0:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<i32>>, i32>
+ ! CHECK: %[[tuple0:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<i32>>, i32>
! CHECK: %[[snakeAddr:.*]] = fir.address_of(@snake_) : !fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>
! CHECK: %[[byteView:.*]] = fir.convert %[[snakeAddr:.*]] : (!fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>) -> !fir.ref<!fir.array<?xi8>>
! CHECK: %[[coor:.*]] = fir.coordinate_of %[[byteView]], %c24{{.*}} : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
More information about the flang-commits
mailing list