diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -459,12 +459,6 @@ // The number of dimensions of the sequence unsigned getDimension() const { return getShape().size(); } - // Is the interior of the sequence constant? Check if the array is - // one of constant shape (`array`), unknown shape - // (`array<*xT>`), or rows with shape and ending with column(s) of - // unknown extent (`array`). - bool hasConstantInterior() const; - // Is the shape of the sequence constant? bool hasConstantShape() const { return getConstantRows() == getDimension(); diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -334,18 +334,31 @@ mlir::Type dataTy = op.getInType(); mlir::Type scalarType = fir::unwrapSequenceType(dataTy); auto seqTy = dataTy.dyn_cast(); - if ((op.hasShapeOperands() && seqTy && !seqTy.hasConstantInterior()) || - (seqTy && fir::characterWithDynamicLen(scalarType))) { - fir::SequenceType::Extent constSize = 1; - for (auto extent : seqTy.getShape()) + fir::SequenceType::Extent constSize = 1; + if (op.hasShapeOperands() && seqTy && + seqTy.getConstantRows() != seqTy.getShape().size()) { + int constRows = seqTy.getConstantRows(); + for (auto extent : seqTy.getShape()) { + if (constRows-- > 0) + continue; + if (extent != fir::SequenceType::getUnknownExtent()) + constSize *= extent; + } + } + if (seqTy && fir::characterWithDynamicLen(scalarType)) { + for (auto extent : seqTy.getShape()) { if (extent != fir::SequenceType::getUnknownExtent()) constSize *= extent; - if (constSize != 1) { - mlir::Value constVal{ - genConstantIndex(loc, ity, rewriter, constSize).getResult()}; - return constVal; + else + break; } } + + if (constSize != 1) { + mlir::Value constVal{ + genConstantIndex(loc, ity, rewriter, constSize).getResult()}; + return constVal; + } return nullptr; } diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h --- a/flang/lib/Optimizer/CodeGen/TypeConverter.h +++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h @@ -318,7 +318,7 @@ if (auto seqTy = eleTy.dyn_cast()) { if (!seqTy.hasConstantShape() || characterWithDynamicLen(seqTy.getEleTy())) { - if (seqTy.hasConstantInterior()) + if (seqTy.getConstantRows() > 0) return convertType(seqTy); eleTy = seqTy.getEleTy(); } diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -793,23 +793,6 @@ return count; } -// This test helps us determine if we can degenerate an array to a -// pointer to some interior section (possibly a single element) of the -// sequence. This is used to determine if we can lower to the LLVM IR. -bool fir::SequenceType::hasConstantInterior() const { - if (hasUnknownShape()) - return true; - auto rows = getConstantRows(); - auto dim = getDimension(); - if (rows == dim) - return true; - auto shape = getShape(); - for (unsigned i = rows, size = dim; i < size; ++i) - if (shape[i] != getUnknownExtent()) - return false; - return true; -} - mlir::LogicalResult fir::SequenceType::verify( llvm::function_ref emitError, llvm::ArrayRef shape, mlir::Type eleTy, diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -277,9 +277,9 @@ // CHECK-LABEL: define ptr @alloca_array_with_holes_nonchar( // CHECK-SAME: i64 %[[a:.*]], i64 %[[b:.*]]) -// CHECK: %[[prod1:.*]] = mul i64 60, %[[a]] +// CHECK: %[[prod1:.*]] = mul i64 15, %[[a]] // CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[b]] -// CHECK: alloca i32, i64 %[[prod2]] +// CHECK: alloca [4 x i32], i64 %[[prod2]] func.func @alloca_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.ref> { %a = fir.alloca !fir.array<4x?x3x?x5xi32>, %0, %1 return %a : !fir.ref> @@ -287,8 +287,8 @@ // CHECK-LABEL: define ptr @alloca_array_with_holes_char( // CHECK-SAME: i64 %[[e:.*]]) -// CHECK: %[[mul:.*]] = mul i64 12, %[[e]] -// CHECK: alloca [10 x i16], i64 %[[mul]] +// CHECK: %[[mul:.*]] = mul i64 4, %[[e]] +// CHECK: alloca [3 x [10 x i16]], i64 %[[mul]] func.func @alloca_array_with_holes_char(%e: index) -> !fir.ref>> { %1 = fir.alloca !fir.array<3x?x4x!fir.char<2,10>>, %e return %1 : !fir.ref>> @@ -306,7 +306,7 @@ // CHECK-LABEL: define ptr @allocmem_array_with_holes_nonchar( // CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]]) -// CHECK: %[[a:.*]] = mul i64 240, %[[e1]] +// CHECK: %[[a:.*]] = mul i64 mul (i64 ptrtoint{{.*}} 15), %[[e1]] // CHECK: %[[b:.*]] = mul i64 %3, %[[e2]] // CHECK: call ptr @malloc(i64 %[[b]]) func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.heap> { @@ -316,7 +316,7 @@ // CHECK-LABEL: define ptr @allocmem_array_with_holes_char( // CHECK-SAME: i64 %[[e:.*]]) -// CHECK: %[[mul:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr ([10 x i16], ptr null, i64 1) to i64), i64 12), %[[e]] +// CHECK: %[[mul:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr ([3 x [10 x i16]], ptr null, i64 1) to i64), i64 4), %[[e]] // CHECK: call ptr @malloc(i64 %[[mul]]) func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,10>>, %e diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -1164,14 +1164,14 @@ } // CHECK-LABEL: llvm.func @alloca_array_with_holes -// CHECK-SAME: ([[A:%.*]]: i64, [[B:%.*]]: i64) -> !llvm.ptr +// CHECK-SAME: ([[A:%.*]]: i64, [[B:%.*]]: i64) -> !llvm.ptr> // CHECK-DAG: [[ONE:%.*]] = llvm.mlir.constant(1 : i64) : i64 -// CHECK-DAG: [[FIXED:%.*]] = llvm.mlir.constant(60 : i64) : i64 +// CHECK-DAG: [[FIXED:%.*]] = llvm.mlir.constant(15 : i64) : i64 // CHECK: [[PROD1:%.*]] = llvm.mul [[ONE]], [[FIXED]] : i64 // CHECK: [[PROD2:%.*]] = llvm.mul [[PROD1]], [[A]] : i64 // CHECK: [[PROD3:%.*]] = llvm.mul [[PROD2]], [[B]] : i64 -// CHECK: [[RES:%.*]] = llvm.alloca [[PROD3]] x i32 {in_type = !fir.array<4x?x3x?x5xi32> -// CHECK: llvm.return [[RES]] : !llvm.ptr +// CHECK: [[RES:%.*]] = llvm.alloca [[PROD3]] x !llvm.array<4 x i32> {in_type = !fir.array<4x?x3x?x5xi32> +// CHECK: llvm.return [[RES]] : !llvm.ptr> // ----- diff --git a/flang/test/Fir/types-to-llvm.fir b/flang/test/Fir/types-to-llvm.fir --- a/flang/test/Fir/types-to-llvm.fir +++ b/flang/test/Fir/types-to-llvm.fir @@ -49,7 +49,7 @@ // CHECK-SAME: !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, ptr, array<1 x i{{.*}}>)>> func.func private @foo3(%arg0: !fir.ref>) // CHECK-LABEL: foo3 -// CHECK-SAME: !llvm.ptr +// CHECK-SAME: !llvm.ptr> func.func private @foo4(%arg0: !fir.ref>) // CHECK-LABEL: foo4 // CHECK-SAME: !llvm.ptr>>