@@ -1033,109 +1033,78 @@ class ScalarExprLowering {
1033
1033
ExtValue genArrayLit (
1034
1034
const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>>
1035
1035
&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
+ }
1036
1055
llvm::SmallVector<mlir::Value> lbounds;
1037
1056
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));
1042
1060
}
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
+ };
1043
1069
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 ();
1050
1070
do {
1051
- auto charVal =
1071
+ auto elementVal =
1052
1072
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 ());
1059
1075
} while (con.IncrementSubscripts (subscripts));
1060
- auto len = builder.createIntegerConstant (getLoc () , idxTy, con.LEN ());
1076
+ auto len = builder.createIntegerConstant (loc , idxTy, con.LEN ());
1061
1077
return fir::CharArrayBoxValue{array, len, extents, lbounds};
1062
1078
} 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;
1071
1079
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 ;
1076
1081
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))));
1087
1086
};
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]);
1129
1104
}
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 ;
1139
1108
}
1140
1109
} while (con.IncrementSubscripts (subscripts));
1141
1110
return fir::ArrayBoxValue{array, extents, lbounds};
0 commit comments