Skip to content

Commit d3602a7

Browse files
committed
[flang] Zero initialize uninitialized components in saved default init
Follow up up of llvm#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.
1 parent 06f3b0e commit d3602a7

9 files changed

+21
-18
lines changed

flang/docs/Extensions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ end
101101
* `$` and `@` as legal characters in names
102102
* Initialization in type declaration statements using `/values/`
103103
* Saved variables without explicit or default initializers are zero initialized.
104+
* In a saved entity of a type with a default initializer, components without default
105+
values are zero initialized.
104106
* Kind specification with `*`, e.g. `REAL*4`
105107
* `DOUBLE COMPLEX` as a synonym for `COMPLEX(KIND(0.D0))` --
106108
but not when spelled `TYPE(DOUBLECOMPLEX)`.

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,16 +352,17 @@ static mlir::Value genDefaultInitializerValue(
352352
componentValue = genDefaultInitializerValue(converter, loc, component,
353353
componentTy, stmtCtx);
354354
} else {
355-
// Component has no initial value.
356-
componentValue = builder.create<fir::UndefOp>(loc, componentTy);
355+
// Component has no initial value. Set its bits to zero by extension
356+
// to match what is expected because other compilers are doing it.
357+
componentValue = builder.create<fir::ZeroOp>(loc, componentTy);
357358
}
358359
} else if (const auto *proc{
359360
component
360361
.detailsIf<Fortran::semantics::ProcEntityDetails>()}) {
361362
if (proc->init().has_value())
362363
TODO(loc, "procedure pointer component default initialization");
363364
else
364-
componentValue = builder.create<fir::UndefOp>(loc, componentTy);
365+
componentValue = builder.create<fir::ZeroOp>(loc, componentTy);
365366
}
366367
assert(componentValue && "must have been computed");
367368
componentValue = builder.createConvert(loc, componentTy, componentValue);
@@ -890,7 +891,7 @@ static fir::GlobalOp defineGlobalAggregateStore(
890891
Fortran::lower::createGlobalInitialization(
891892
builder, global, [&](fir::FirOpBuilder &builder) {
892893
Fortran::lower::StatementContext stmtCtx;
893-
mlir::Value initVal = builder.create<fir::UndefOp>(loc, aggTy);
894+
mlir::Value initVal = builder.create<fir::ZeroOp>(loc, aggTy);
894895
builder.create<fir::HasValueOp>(loc, initVal);
895896
});
896897
return global;
@@ -1171,7 +1172,7 @@ static void finalizeCommonBlockDefinition(
11711172
mlir::TupleType commonTy = global.getType().cast<mlir::TupleType>();
11721173
auto initFunc = [&](fir::FirOpBuilder &builder) {
11731174
mlir::IndexType idxTy = builder.getIndexType();
1174-
mlir::Value cb = builder.create<fir::UndefOp>(loc, commonTy);
1175+
mlir::Value cb = builder.create<fir::ZeroOp>(loc, commonTy);
11751176
unsigned tupIdx = 0;
11761177
std::size_t offset = 0;
11771178
LLVM_DEBUG(llvm::dbgs() << "block {\n");

flang/test/Lower/array.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
! CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32
55
! CHECK-DAG: %[[VAL_2:.*]] = arith.constant 2.400000e+00 : f32
66
! CHECK-DAG: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32
7-
! CHECK: %[[VAL_4:.*]] = fir.undefined tuple<!fir.array<5x5xf32>>
7+
! CHECK: %[[VAL_4:.*]] = fir.zero_bits tuple<!fir.array<5x5xf32>>
88
! CHECK: %[[VAL_5:.*]] = fir.undefined !fir.array<5x5xf32>
99
! CHECK: %[[VAL_6:.*]] = fir.insert_on_range %[[VAL_5]], %[[VAL_1]] from (0, 0) to (1, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32>
1010
! CHECK: %[[VAL_7:.*]] = fir.insert_on_range %[[VAL_6]], %[[VAL_3]] from (2, 0) to (4, 0) : (!fir.array<5x5xf32>, f32) -> !fir.array<5x5xf32>

flang/test/Lower/common-block-2.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
! - A common block that is initialized outside of a BLOCK DATA.
77

88
! CHECK-LABEL: fir.global @__BLNK__ : tuple<i32, !fir.array<8xi8>> {
9-
! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
9+
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
1010
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
1111
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>
1212

1313
! CHECK-LABEL: fir.global @a_ : tuple<i32, !fir.array<8xi8>> {
14-
! CHECK: %[[undef:.*]] = fir.undefined tuple<i32, !fir.array<8xi8>>
14+
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<i32, !fir.array<8xi8>>
1515
! CHECK: %[[init:.*]] = fir.insert_value %[[undef]], %c42{{.*}}, [0 : index] : (tuple<i32, !fir.array<8xi8>>, i32) -> tuple<i32, !fir.array<8xi8>>
1616
! CHECK: fir.has_value %[[init]] : tuple<i32, !fir.array<8xi8>>
1717

flang/test/Lower/common-block.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
! CHECK: @with_empty_equiv_ = common global [8 x i8] zeroinitializer
77
! CHECK: @x_ = global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} }
88
! CHECK: @y_ = common global [12 x i8] zeroinitializer
9-
! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] undef, float 3.000000e+00 }
9+
! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] zeroinitializer, float 3.000000e+00 }
1010

1111
! CHECK-LABEL: _QPs0
1212
subroutine s0

flang/test/Lower/default-initialization-globals.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ module tinit
9797
! CHECK-DAG: %[[VAL_15:.*]] = arith.constant 66 : i32
9898
! CHECK: %[[VAL_16:.*]] = fir.undefined !fir.type<_QMtinitTt1{{.*}}>
9999
! CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_11]], ["i", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}>
100-
! CHECK: %[[VAL_18:.*]] = fir.undefined i32
100+
! CHECK: %[[VAL_18:.*]] = fir.zero_bits i32
101101
! CHECK: %[[VAL_19:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_18]], ["j", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, i32) -> !fir.type<_QMtinitTt1{{.*}}>
102102
! CHECK: %[[VAL_20:.*]] = fir.address_of(@_QMtinitEziel) : !fir.ref<!fir.array<100xf32>>
103103
! CHECK: %[[VAL_21:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
@@ -111,12 +111,12 @@ module tinit
111111
! 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{{.*}}>
112112
! CHECK: %[[VAL_29:.*]] = fir.string_lit "hello "(10) : !fir.char<1,10>
113113
! CHECK: %[[VAL_30:.*]] = fir.insert_value %[[VAL_28]], %[[VAL_29]], ["c1", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}>
114-
! CHECK: %[[VAL_31:.*]] = fir.undefined !fir.char<1,10>
114+
! CHECK: %[[VAL_31:.*]] = fir.zero_bits !fir.char<1,10>
115115
! CHECK: %[[VAL_32:.*]] = fir.insert_value %[[VAL_30]], %[[VAL_31]], ["c2", !fir.type<_QMtinitTt1{{.*}}>] : (!fir.type<_QMtinitTt1{{.*}}>, !fir.char<1,10>) -> !fir.type<_QMtinitTt1{{.*}}>
116116
! CHECK: %[[VAL_33:.*]] = fir.undefined !fir.type<_QMtinitTt0{k:i32}>
117117
! 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}>
118118
! 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{{.*}}>
119-
! CHECK: %[[VAL_36:.*]] = fir.undefined !fir.type<_QMtinitTtno_init{k:i32}>
119+
! CHECK: %[[VAL_36:.*]] = fir.zero_bits !fir.type<_QMtinitTtno_init{k:i32}>
120120
! 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{{.*}}>
121121
! 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}>
122122
! 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
129129
! CHECK: %[[VAL_42:.*]] = arith.constant 66 : i32
130130
! CHECK: %[[VAL_43:.*]] = fir.undefined !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
131131
! 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}>
132-
! CHECK: %[[VAL_45:.*]] = fir.undefined i32
132+
! CHECK: %[[VAL_45:.*]] = fir.zero_bits i32
133133
! 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}>
134134
! CHECK: fir.has_value %[[VAL_46]] : !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
135135

flang/test/Lower/equivalence-static-init.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module module_without_init
88
equivalence(i(1), x)
99
end module
1010
! CHECK-LABEL: fir.global @_QMmodule_without_initEi : !fir.array<8xi8> {
11-
! CHECK: %0 = fir.undefined !fir.array<8xi8>
11+
! CHECK: %0 = fir.zero_bits !fir.array<8xi8>
1212
! CHECK: fir.has_value %0 : !fir.array<8xi8>
1313
! CHECK}
1414

flang/test/Lower/pointer-default-init.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module test
2121
type(t) :: test_module_var
2222
! CHECK-LABEL: fir.global @_QMtestEtest_module_var : !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {
2323
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
24-
! CHECK: %[[VAL_1:.*]] = fir.undefined i32
24+
! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32
2525
! CHECK: %[[VAL_2:.*]] = fir.field_index i
2626
! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]]
2727
! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
@@ -97,7 +97,7 @@ subroutine test_saved_pointer()
9797

9898
! CHECK-LABEL: fir.global internal @_QFtest_savedEx : !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}> {
9999
! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMtestTt{i:i32,x:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
100-
! CHECK: %[[VAL_1:.*]] = fir.undefined i32
100+
! CHECK: %[[VAL_1:.*]] = fir.zero_bits i32
101101
! CHECK: %[[VAL_2:.*]] = fir.field_index i
102102
! CHECK: %[[VAL_3:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]]
103103
! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>

flang/test/Lower/pointer-initial-target-2.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
common /a/ p
1313
data p /b/
1414
! CHECK-LABEL: fir.global @a_ : tuple<!fir.box<!fir.ptr<f32>>>
15-
! CHECK: %[[undef:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<f32>>>
15+
! CHECK: %[[undef:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<f32>>>
1616
! CHECK: %[[b:.*]] = fir.address_of(@_QEb) : !fir.ref<f32>
1717
! CHECK: %[[box:.*]] = fir.embox %[[b]] : (!fir.ref<f32>) -> !fir.box<f32>
1818
! CHECK: %[[rebox:.*]] = fir.rebox %[[box]] : (!fir.box<f32>) -> !fir.box<!fir.ptr<f32>>
@@ -41,7 +41,7 @@ block data bdsnake
4141
integer, pointer :: p => b
4242
common /snake/ p, b
4343
! CHECK-LABEL: fir.global @snake_ : tuple<!fir.box<!fir.ptr<i32>>, i32>
44-
! CHECK: %[[tuple0:.*]] = fir.undefined tuple<!fir.box<!fir.ptr<i32>>, i32>
44+
! CHECK: %[[tuple0:.*]] = fir.zero_bits tuple<!fir.box<!fir.ptr<i32>>, i32>
4545
! CHECK: %[[snakeAddr:.*]] = fir.address_of(@snake_) : !fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>
4646
! CHECK: %[[byteView:.*]] = fir.convert %[[snakeAddr:.*]] : (!fir.ref<tuple<!fir.box<!fir.ptr<i32>>, i32>>) -> !fir.ref<!fir.array<?xi8>>
4747
! CHECK: %[[coor:.*]] = fir.coordinate_of %[[byteView]], %c24{{.*}} : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>

0 commit comments

Comments
 (0)