Skip to content

Commit bf166d3

Browse files
authored
Zero size array initializers (#1011)
Zero size array initializers Special case zero size arrays in genArrayLit. Reduce code duplication and dead FIR generation.
1 parent d195a85 commit bf166d3

File tree

2 files changed

+74
-90
lines changed

2 files changed

+74
-90
lines changed

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 59 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,109 +1033,78 @@ class ScalarExprLowering {
10331033
ExtValue genArrayLit(
10341034
const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>>
10351035
&con) {
1036+
auto loc = getLoc();
1037+
auto idxTy = builder.getIndexType();
1038+
auto size = Fortran::evaluate::GetSize(con.shape());
1039+
fir::SequenceType::Shape shape(con.shape().begin(), con.shape().end());
1040+
mlir::Type eleTy;
1041+
if constexpr (TC == Fortran::common::TypeCategory::Character)
1042+
eleTy = converter.genType(TC, KIND, {con.LEN()});
1043+
else
1044+
eleTy = converter.genType(TC, KIND);
1045+
auto arrayTy = fir::SequenceType::get(shape, eleTy);
1046+
mlir::Value array = builder.create<fir::UndefOp>(loc, arrayTy);
1047+
if (size == 0) {
1048+
if constexpr (TC == Fortran::common::TypeCategory::Character) {
1049+
auto len = builder.createIntegerConstant(loc, idxTy, con.LEN());
1050+
return fir::CharArrayBoxValue{array, len, {}, {}};
1051+
} else {
1052+
return fir::ArrayBoxValue{array, {}, {}};
1053+
}
1054+
}
10361055
llvm::SmallVector<mlir::Value> lbounds;
10371056
llvm::SmallVector<mlir::Value> extents;
1038-
auto idxTy = builder.getIndexType();
1039-
for (auto [lb, extent] : llvm::zip(con.lbounds(), con.shape())) {
1040-
lbounds.push_back(builder.createIntegerConstant(getLoc(), idxTy, lb - 1));
1041-
extents.push_back(builder.createIntegerConstant(getLoc(), idxTy, extent));
1057+
for (auto [lb, extent] : llvm::zip(con.lbounds(), shape)) {
1058+
lbounds.push_back(builder.createIntegerConstant(loc, idxTy, lb - 1));
1059+
extents.push_back(builder.createIntegerConstant(loc, idxTy, extent));
10421060
}
1061+
Fortran::evaluate::ConstantSubscripts subscripts = con.lbounds();
1062+
auto createIdx = [&]() {
1063+
llvm::SmallVector<mlir::Value> idx;
1064+
for (size_t i = 0; i < subscripts.size(); ++i)
1065+
idx.push_back(builder.createIntegerConstant(
1066+
getLoc(), idxTy, subscripts[i] - con.lbounds()[i]));
1067+
return idx;
1068+
};
10431069
if constexpr (TC == Fortran::common::TypeCategory::Character) {
1044-
fir::SequenceType::Shape shape;
1045-
shape.append(con.shape().begin(), con.shape().end());
1046-
auto chTy = converter.genType(TC, KIND, {con.LEN()});
1047-
auto arrayTy = fir::SequenceType::get(shape, chTy);
1048-
mlir::Value array = builder.create<fir::UndefOp>(getLoc(), arrayTy);
1049-
Fortran::evaluate::ConstantSubscripts subscripts = con.lbounds();
10501070
do {
1051-
auto charVal =
1071+
auto elementVal =
10521072
fir::getBase(genScalarLit<KIND>(con.At(subscripts), con.LEN()));
1053-
llvm::SmallVector<mlir::Value> idx;
1054-
for (auto [dim, lb] : llvm::zip(subscripts, con.lbounds()))
1055-
idx.push_back(
1056-
builder.createIntegerConstant(getLoc(), idxTy, dim - lb));
1057-
array = builder.create<fir::InsertValueOp>(getLoc(), arrayTy, array,
1058-
charVal, idx);
1073+
array = builder.create<fir::InsertValueOp>(loc, arrayTy, array,
1074+
elementVal, createIdx());
10591075
} while (con.IncrementSubscripts(subscripts));
1060-
auto len = builder.createIntegerConstant(getLoc(), idxTy, con.LEN());
1076+
auto len = builder.createIntegerConstant(loc, idxTy, con.LEN());
10611077
return fir::CharArrayBoxValue{array, len, extents, lbounds};
10621078
} else {
1063-
// Convert Ev::ConstantSubs to SequenceType::Shape
1064-
fir::SequenceType::Shape shape(con.shape().begin(), con.shape().end());
1065-
auto eleTy = converter.genType(TC, KIND);
1066-
auto arrayTy = fir::SequenceType::get(shape, eleTy);
1067-
mlir::Value array = builder.create<fir::UndefOp>(getLoc(), arrayTy);
1068-
Fortran::evaluate::ConstantSubscripts subscripts = con.lbounds();
1069-
bool foundRange = false;
1070-
mlir::Value rangeValue;
10711079
llvm::SmallVector<mlir::Value> rangeStartIdx;
1072-
Fortran::evaluate::ConstantSubscripts rangeStartSubscripts;
1073-
uint64_t elemsInRange = 0;
1074-
const uint64_t minRangeSize = 2;
1075-
1080+
uint64_t rangeSize = 0;
10761081
do {
1077-
auto constant =
1078-
fir::getBase(genScalarLit<TC, KIND>(con.At(subscripts)));
1079-
auto createIndexes = [&](Fortran::evaluate::ConstantSubscripts subs) {
1080-
llvm::SmallVector<mlir::Value> idx;
1081-
for (auto [dim, lb] : llvm::zip(subs, con.lbounds()))
1082-
// Add normalized upper bound index to idx.
1083-
idx.push_back(
1084-
builder.createIntegerConstant(getLoc(), idxTy, dim - lb));
1085-
1086-
return idx;
1082+
auto getElementVal = [&]() {
1083+
return builder.createConvert(
1084+
loc, eleTy,
1085+
fir::getBase(genScalarLit<TC, KIND>(con.At(subscripts))));
10871086
};
1088-
1089-
auto idx = createIndexes(subscripts);
1090-
auto insVal = builder.createConvert(getLoc(), eleTy, constant);
1091-
auto nextSubs = subscripts;
1092-
1093-
// Check to see if the next value is the same as the current value
1094-
bool nextIsSame = con.IncrementSubscripts(nextSubs) &&
1095-
con.At(subscripts) == con.At(nextSubs);
1096-
bool newRange = (nextIsSame != foundRange) && !foundRange;
1097-
bool endOfRange = (nextIsSame != foundRange) && foundRange;
1098-
bool continueRange = nextIsSame && foundRange;
1099-
1100-
if (newRange) {
1101-
// Mark the start of the range
1102-
rangeStartIdx = idx;
1103-
rangeStartSubscripts = subscripts;
1104-
rangeValue = insVal;
1105-
foundRange = true;
1106-
elemsInRange = 1;
1107-
} else if (endOfRange) {
1108-
++elemsInRange;
1109-
if (elemsInRange >= minRangeSize) {
1110-
// Zip together the upper and lower bounds of the range for each
1111-
// index in the form [lb0, up0, lb1, up1, ... , lbn, upn] to pass
1112-
// to the InserOnEangeOp.
1113-
llvm::SmallVector<mlir::Value> zippedRange;
1114-
for (size_t i = 0; i < idx.size(); ++i) {
1115-
zippedRange.push_back(rangeStartIdx[i]);
1116-
zippedRange.push_back(idx[i]);
1117-
}
1118-
array = builder.create<fir::InsertOnRangeOp>(
1119-
getLoc(), arrayTy, array, rangeValue, zippedRange);
1120-
} else {
1121-
while (true) {
1122-
idx = createIndexes(rangeStartSubscripts);
1123-
array = builder.create<fir::InsertValueOp>(
1124-
getLoc(), arrayTy, array, rangeValue, idx);
1125-
if (rangeStartSubscripts == subscripts)
1126-
break;
1127-
con.IncrementSubscripts(rangeStartSubscripts);
1128-
}
1087+
auto nextSubscripts = subscripts;
1088+
bool nextIsSame = con.IncrementSubscripts(nextSubscripts) &&
1089+
con.At(subscripts) == con.At(nextSubscripts);
1090+
if (!rangeSize && !nextIsSame) { // single (non-range) value
1091+
array = builder.create<fir::InsertValueOp>(
1092+
loc, arrayTy, array, getElementVal(), createIdx());
1093+
} else if (!rangeSize) { // start a range
1094+
rangeStartIdx = createIdx();
1095+
rangeSize = 1;
1096+
} else if (nextIsSame) { // expand a range
1097+
++rangeSize;
1098+
} else { // end a range
1099+
llvm::SmallVector<mlir::Value> rangeBounds;
1100+
auto idx = createIdx();
1101+
for (size_t i = 0; i < idx.size(); ++i) {
1102+
rangeBounds.push_back(rangeStartIdx[i]);
1103+
rangeBounds.push_back(idx[i]);
11291104
}
1130-
foundRange = false;
1131-
} else if (continueRange) {
1132-
// Loop until the end of the range is found.
1133-
++elemsInRange;
1134-
continue;
1135-
} else /* no range */ {
1136-
// If a range has not been found then insert the current value.
1137-
array = builder.create<fir::InsertValueOp>(getLoc(), arrayTy, array,
1138-
insVal, idx);
1105+
array = builder.create<fir::InsertOnRangeOp>(
1106+
loc, arrayTy, array, getElementVal(), rangeBounds);
1107+
rangeSize = 0;
11391108
}
11401109
} while (con.IncrementSubscripts(subscripts));
11411110
return fir::ArrayBoxValue{array, extents, lbounds};

flang/test/Lower/array-constructor-1.f90

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,24 @@ subroutine check_units
2626
enddo
2727
end
2828

29+
! CHECK-LABEL: _QPzero
30+
subroutine zero
31+
complex, parameter :: a(0) = [(((k,k=1,10),j=-2,2,-1),i=2,-2,-2)]
32+
complex, parameter :: b(0) = [(7,i=3,-3)]
33+
! CHECK: fir.address_of(@_QQro.0xz4.null) : !fir.ref<!fir.array<0x!fir.complex<4>>>
34+
! CHECK-NOT: _QQro
35+
print*, '>', a, '<'
36+
print*, '>', b, '<'
37+
end
38+
2939
! CHECK-LABEL: _QQmain
3040
program prog
3141
call check_units
42+
call zero
3243
end
3344

3445
! CHECK: fir.global linkonce [[units_value]] constant : !fir.array<3xi32>
46+
47+
! CHECK: fir.global internal @_QFzeroECa constant : !fir.array<0x!fir.complex<4>>
48+
! CHECK: %0 = fir.undefined !fir.array<0x!fir.complex<4>>
49+
! CHECK: fir.has_value %0 : !fir.array<0x!fir.complex<4>>

0 commit comments

Comments
 (0)