Skip to content

Commit bf8ebcd

Browse files
authored
Zero size arrays of derived type (#1050)
Fix two problems with zero size arrays with derived type elements. The first problem occurs when the derived type element of a zero size array has default initialization. -- fix in ConvertVariable.cpp type dt integer :: j = 17 end type type(dt) :: z(0) The second problem occurs when the derived type element of a zero size array has an explicit, conformable, scalar initialization. That appears to be standard conforming, if not too useful, although it has the side affect of forcing the SAVE attribute on z. -- fix in ConvertExpr.cpp type dt integer :: j end type type(dt) :: z(0) = dt(99) Also add a verifier for fir.insert_on_range ops, which triggers for the first test case without the corresponding fix.
1 parent fbb3d2e commit bf8ebcd

File tree

5 files changed

+88
-29
lines changed

5 files changed

+88
-29
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,9 +2222,20 @@ def fir_InsertOnRangeOp : fir_OneResultOp<"insert_on_range", [NoSideEffect]> {
22222222
let summary = "insert sub-value into a range on an existing sequence";
22232223

22242224
let description = [{
2225-
Insert a constant value into an entity with an array type. Returns a
2226-
new ssa value where the range of offsets from the original array have been
2227-
replaced with the constant. The result is an array type entity.
2225+
Insert copies of a value into an entity with an array type.
2226+
Returns a new ssa value with the same type as the original entity.
2227+
The values are inserted at a contiguous range of indices in Fortran
2228+
row-to-column element order as specified by lower and upper bound
2229+
coordinates.
2230+
2231+
```mlir
2232+
%a = fir.undefined !fir.array<10x10xf32>
2233+
%c = constant 3.0 : f32
2234+
%1 = fir.insert_on_range %a, %c, [0 : index, 7 : index, 0 : index, 2 : index] : (!fir.array<10x10xf32>, f32) -> !fir.array<10x10xf32>
2235+
```
2236+
2237+
The first 28 elements of %1, with coordinates from (0,0) to (7,2), have
2238+
the value 3.0.
22282239
}];
22292240

22302241
let arguments = (ins fir_SequenceType:$seq, AnyType:$val, ArrayAttr:$coor);
@@ -2238,6 +2249,8 @@ def fir_InsertOnRangeOp : fir_OneResultOp<"insert_on_range", [NoSideEffect]> {
22382249
OpBuilder<(ins "mlir::Type":$rty, "mlir::Value":$adt, "mlir::Value":$val,
22392250
"llvm::ArrayRef<mlir::Value>":$vcoor)>
22402251
];
2252+
2253+
let verifier = [{ return ::verify(*this); }];
22412254
}
22422255

22432256
def fir_LenParamIndexOp : fir_OneResultOp<"len_param_index", [NoSideEffect]> {

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,20 +1100,20 @@ class ScalarExprLowering {
11001100
eleTy = converter.genType(TC, KIND);
11011101
auto arrayTy = fir::SequenceType::get(shape, eleTy);
11021102
mlir::Value array = builder.create<fir::UndefOp>(loc, arrayTy);
1103-
if (size == 0) {
1104-
if constexpr (TC == Fortran::common::TypeCategory::Character) {
1105-
auto len = builder.createIntegerConstant(loc, idxTy, con.LEN());
1106-
return fir::CharArrayBoxValue{array, len, {}, {}};
1107-
} else {
1108-
return fir::ArrayBoxValue{array, {}, {}};
1109-
}
1110-
}
11111103
llvm::SmallVector<mlir::Value> lbounds;
11121104
llvm::SmallVector<mlir::Value> extents;
11131105
for (auto [lb, extent] : llvm::zip(con.lbounds(), shape)) {
11141106
lbounds.push_back(builder.createIntegerConstant(loc, idxTy, lb - 1));
11151107
extents.push_back(builder.createIntegerConstant(loc, idxTy, extent));
11161108
}
1109+
if (size == 0) {
1110+
if constexpr (TC == Fortran::common::TypeCategory::Character) {
1111+
auto len = builder.createIntegerConstant(loc, idxTy, con.LEN());
1112+
return fir::CharArrayBoxValue{array, len, extents, lbounds};
1113+
} else {
1114+
return fir::ArrayBoxValue{array, extents, lbounds};
1115+
}
1116+
}
11171117
Fortran::evaluate::ConstantSubscripts subscripts = con.lbounds();
11181118
auto createIdx = [&]() {
11191119
llvm::SmallVector<mlir::Value> idx;
@@ -1169,25 +1169,28 @@ class ScalarExprLowering {
11691169

11701170
fir::ExtendedValue genArrayLit(
11711171
const Fortran::evaluate::Constant<Fortran::evaluate::SomeDerived> &con) {
1172+
auto loc = getLoc();
1173+
auto idxTy = builder.getIndexType();
1174+
auto size = Fortran::evaluate::GetSize(con.shape());
1175+
fir::SequenceType::Shape shape(con.shape().begin(), con.shape().end());
1176+
auto eleTy = converter.genType(con.GetType().GetDerivedTypeSpec());
1177+
auto arrayTy = fir::SequenceType::get(shape, eleTy);
1178+
mlir::Value array = builder.create<fir::UndefOp>(loc, arrayTy);
11721179
llvm::SmallVector<mlir::Value> lbounds;
11731180
llvm::SmallVector<mlir::Value> extents;
1174-
auto idxTy = builder.getIndexType();
11751181
for (auto [lb, extent] : llvm::zip(con.lbounds(), con.shape())) {
1176-
lbounds.push_back(builder.createIntegerConstant(getLoc(), idxTy, lb - 1));
1177-
extents.push_back(builder.createIntegerConstant(getLoc(), idxTy, extent));
1182+
lbounds.push_back(builder.createIntegerConstant(loc, idxTy, lb - 1));
1183+
extents.push_back(builder.createIntegerConstant(loc, idxTy, extent));
11781184
}
1179-
fir::SequenceType::Shape shape;
1180-
shape.append(con.shape().begin(), con.shape().end());
1181-
auto recTy = converter.genType(con.GetType().GetDerivedTypeSpec());
1182-
auto arrayTy = fir::SequenceType::get(shape, recTy);
1183-
mlir::Value array = builder.create<fir::UndefOp>(getLoc(), arrayTy);
1185+
if (size == 0)
1186+
return fir::ArrayBoxValue{array, extents, lbounds};
11841187
Fortran::evaluate::ConstantSubscripts subscripts = con.lbounds();
11851188
do {
11861189
auto derivedVal = fir::getBase(genval(con.At(subscripts)));
11871190
llvm::SmallVector<mlir::Value> idx;
11881191
for (auto [dim, lb] : llvm::zip(subscripts, con.lbounds()))
1189-
idx.push_back(builder.createIntegerConstant(getLoc(), idxTy, dim - lb));
1190-
array = builder.create<fir::InsertValueOp>(getLoc(), arrayTy, array,
1192+
idx.push_back(builder.createIntegerConstant(loc, idxTy, dim - lb));
1193+
array = builder.create<fir::InsertValueOp>(loc, arrayTy, array,
11911194
derivedVal, idx);
11921195
} while (con.IncrementSubscripts(subscripts));
11931196
return fir::ArrayBoxValue{array, extents, lbounds};

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ static mlir::Value genScalarValue(Fortran::lower::AbstractConverter &converter,
8787
loc, converter, expr, symMap, context));
8888
}
8989

90-
/// Does this variable has a default initialization ?
90+
/// Does this variable have a default initialization?
9191
static bool hasDefaultInitialization(const Fortran::semantics::Symbol &sym) {
92-
if (sym.has<Fortran::semantics::ObjectEntityDetails>())
92+
if (sym.has<Fortran::semantics::ObjectEntityDetails>() && sym.size())
9393
if (!Fortran::semantics::IsAllocatableOrPointer(sym))
9494
if (const auto *declTypeSpec = sym.GetType())
9595
if (const auto *derivedTypeSpec = declTypeSpec->AsDerived())

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,23 @@ void fir::InsertOnRangeOp::build(mlir::OpBuilder &builder,
991991
build(builder, result, resTy, aggVal, eleVal, aa);
992992
}
993993

994+
/// Range bounds must be nonnegative, and the range must not be empty.
995+
static mlir::LogicalResult verify(fir::InsertOnRangeOp op) {
996+
bool rangeIsKnownToBeNonempty = false;
997+
for (auto i = op.coor().end(), b = op.coor().begin(); i != b;) {
998+
int64_t ub = (*--i).cast<IntegerAttr>().getInt();
999+
int64_t lb = (*--i).cast<IntegerAttr>().getInt();
1000+
if (lb < 0 || ub < 0)
1001+
return op.emitOpError("negative range bound");
1002+
if (rangeIsKnownToBeNonempty)
1003+
continue;
1004+
if (lb > ub)
1005+
return op.emitOpError("empty range");
1006+
rangeIsKnownToBeNonempty = lb < ub;
1007+
}
1008+
return mlir::success();
1009+
}
1010+
9941011
//===----------------------------------------------------------------------===//
9951012
// InsertValueOp
9961013
//===----------------------------------------------------------------------===//

flang/test/Lower/zero-size.f90

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
11
! RUN: bbc -o - %s | FileCheck %s
22

3-
! CHECK-LABEL: _QPzero
4-
subroutine zero(aa)
5-
real, dimension(:) :: aa
6-
print*, size(aa)
3+
! CHECK-LABEL: _QPzero1
4+
subroutine zero1(z)
5+
real, dimension(:) :: z
6+
print*, size(z), z, ':'
7+
end
8+
9+
! CHECK-LABEL: _QPzero2
10+
subroutine zero2
11+
type dt
12+
integer :: j = 17
13+
end type
14+
! CHECK: %[[z:[0-9]*]] = fir.alloca !fir.array<0x!fir.type<_QFzero2Tdt{j:i32}>> {bindc_name = "z", uniq_name = "_QFzero2Ez"}
15+
! CHECK: %[[shape:[0-9]*]] = fir.shape %c0 : (index) -> !fir.shape<1>
16+
! CHECK: fir.embox %[[z]](%[[shape]]) : (!fir.ref<!fir.array<0x!fir.type<_QFzero2Tdt{j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<0x!fir.type<_QFzero2Tdt{j:i32}>>>
17+
type(dt) :: z(0)
18+
print*, size(z), z, ':'
19+
end
20+
21+
! CHECK-LABEL: _QPzero3
22+
subroutine zero3
23+
type dt
24+
integer :: j
25+
end type
26+
! CHECK: %[[z:[0-9]*]] = fir.address_of(@_QFzero3Ez) : !fir.ref<!fir.array<0x!fir.type<_QFzero3Tdt{j:i32}>>>
27+
! CHECK: %[[shape:[0-9]*]] = fir.shape %c0 : (index) -> !fir.shape<1>
28+
! CHECK: fir.embox %[[z]](%[[shape]]) : (!fir.ref<!fir.array<0x!fir.type<_QFzero3Tdt{j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<0x!fir.type<_QFzero3Tdt{j:i32}>>>
29+
type(dt) :: z(0) = dt(99)
30+
print*, size(z), z, ':'
731
end
832

933
! CHECK-LABEL: _QQmain
1034
program prog
1135
real nada(2:-1)
1236
interface
13-
subroutine zero(aa)
37+
subroutine zero1(aa)
1438
real, dimension(:) :: aa
1539
end
1640
end interface
1741
! CHECK: %[[shape:[0-9]*]] = fir.shape_shift %c2, %c0 : (index, index) -> !fir.shapeshift<1>
1842
! CHECK: %2 = fir.embox %0(%[[shape]]) : (!fir.ref<!fir.array<0xf32>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<0xf32>>
19-
call zero(nada)
43+
call zero1(nada)
44+
call zero2
45+
call zero3
2046
end

0 commit comments

Comments
 (0)