diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -149,7 +149,7 @@ CArg<"mlir::ValueRange", "{}">:$typeparams, CArg<"mlir::ValueRange", "{}">:$shape, CArg<"llvm::ArrayRef", "{}">:$attributes)>, - OpBuilder<(ins "mlir::Type":$inType, "llvm::StringRef":$uniqName, + OpBuilder<(ins "mlir::Type":$inType, "llvm::StringRef":$uniqName, CArg<"mlir::ValueRange", "{}">:$typeparams, CArg<"mlir::ValueRange", "{}">:$shape, CArg<"llvm::ArrayRef", "{}">:$attributes)>, 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 @@ -419,7 +419,9 @@ bool hasConstantInterior() const; // Is the shape of the sequence constant? - bool hasConstantShape() const { return getConstantRows() == getDimension(); } + bool hasConstantShape() const { + return getConstantRows() == getDimension(); + } // Does the sequence have unknown shape? (`array<* x T>`) bool hasUnknownShape() const { return getShape().empty(); } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -348,10 +348,14 @@ return op.emitOpError("number of indices do not match dim rank"); } - if (auto sliceOp = op.slice()) + if (auto sliceOp = op.slice()) { + if (auto sl = mlir::dyn_cast_or_null(sliceOp.getDefiningOp())) + if (!sl.substr().empty()) + return op.emitOpError("array_coor cannot take a slice with substring"); if (auto sliceTy = sliceOp.getType().dyn_cast()) if (sliceTy.getRank() != arrDim) return op.emitOpError("rank of dimension in slice mismatched"); + } return mlir::success(); } @@ -407,10 +411,14 @@ return op.emitOpError("rank of dimension mismatched"); } - if (auto sliceOp = op.slice()) + if (auto sliceOp = op.slice()) { + if (auto sl = mlir::dyn_cast_or_null(sliceOp.getDefiningOp())) + if (!sl.substr().empty()) + return op.emitOpError("array_load cannot take a slice with substring"); if (auto sliceTy = sliceOp.getType().dyn_cast()) if (sliceTy.getRank() != arrDim) return op.emitOpError("rank of dimension in slice mismatched"); + } return mlir::success(); } @@ -423,8 +431,11 @@ if (!isa(op.original().getDefiningOp())) return op.emitOpError("operand #0 must be result of a fir.array_load op"); if (auto sl = op.slice()) { - if (auto *slOp = sl.getDefiningOp()) { - auto sliceOp = mlir::cast(slOp); + if (auto sliceOp = + mlir::dyn_cast_or_null(sl.getDefiningOp())) { + if (!sliceOp.substr().empty()) + return op.emitOpError( + "array_merge_store cannot take a slice with substring"); if (!sliceOp.fields().empty()) { // This is an intra-object merge, where the slice is projecting the // subfields that are to be overwritten by the merge operation. diff --git a/flang/test/Fir/invalid.fir b/flang/test/Fir/invalid.fir --- a/flang/test/Fir/invalid.fir +++ b/flang/test/Fir/invalid.fir @@ -616,3 +616,42 @@ %2 = fir.slice %1, %1, %1 : (!fir.field, !fir.field, !fir.field) -> !fir.slice<1> return } + +// ----- + +func @array_coor_no_slice_substr(%a : !fir.ref>) { + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %slice = fir.slice %c1, %c10, %c1 substr %c1, %c10 : (index, index, index, index, index) -> !fir.slice<1> + // expected-error@+1 {{'fir.array_coor' op array_coor cannot take a slice with substring}} + %p = fir.array_coor %a[%slice] %c1, %c1 : (!fir.ref>, !fir.slice<1>, index, index) -> !fir.ref + return +} + +// ----- + +func @array_coor_no_slice_substr(%a : !fir.ref>) { + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %slice = fir.slice %c1, %c10, %c1 substr %c1, %c10 : (index, index, index, index, index) -> !fir.slice<1> + // expected-error@+1 {{'fir.array_load' op array_load cannot take a slice with substring}} + %v = fir.array_load %a[%slice] : (!fir.ref>, !fir.slice<1>) -> !fir.array + return +} + +// ----- + +func @array_merge_store_no_slice_substr(%arr1 : !fir.ref>, %m : index, %n : index, %o : index, %p : index, %f : f32) { + %i10 = arith.constant 10 : index + %j20 = arith.constant 20 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %s = fir.shape_shift %m, %n, %o, %p : (index, index, index, index) -> !fir.shapeshift<2> + %slice = fir.slice %c1, %c10, %c1 substr %c1, %c10 : (index, index, index, index, index) -> !fir.slice<1> + %av1 = fir.array_load %arr1(%s) : (!fir.ref>, !fir.shapeshift<2>) -> !fir.array + %addr, %av2 = fir.array_modify %av1, %i10, %i10 : (!fir.array, index, index) -> (!fir.ref, !fir.array) + fir.store %f to %addr : !fir.ref + // expected-error@+1 {{'fir.array_merge_store' op array_merge_store cannot take a slice with substring}} + fir.array_merge_store %av1, %av2 to %arr1[%slice] : !fir.array, !fir.array, !fir.ref>, !fir.slice<1> + return +}