@@ -1440,96 +1440,148 @@ void hlfir::MatmulTransposeOp::getEffects(
14401440}
14411441
14421442// ===----------------------------------------------------------------------===//
1443- // CShiftOp
1443+ // Array shifts: CShiftOp/EOShiftOp
14441444// ===----------------------------------------------------------------------===//
14451445
1446- llvm::LogicalResult hlfir::CShiftOp::verify () {
1447- mlir::Value array = getArray ();
1446+ template <typename Op>
1447+ static llvm::LogicalResult verifyArrayShift (Op op) {
1448+ mlir::Value array = op.getArray ();
14481449 fir::SequenceType arrayTy = mlir::cast<fir::SequenceType>(
14491450 hlfir::getFortranElementOrSequenceType (array.getType ()));
14501451 llvm::ArrayRef<int64_t > inShape = arrayTy.getShape ();
14511452 std::size_t arrayRank = inShape.size ();
14521453 mlir::Type eleTy = arrayTy.getEleTy ();
1453- hlfir::ExprType resultTy = mlir::cast<hlfir::ExprType>(getResult ().getType ());
1454+ hlfir::ExprType resultTy =
1455+ mlir::cast<hlfir::ExprType>(op.getResult ().getType ());
14541456 llvm::ArrayRef<int64_t > resultShape = resultTy.getShape ();
14551457 std::size_t resultRank = resultShape.size ();
14561458 mlir::Type resultEleTy = resultTy.getEleTy ();
1457- mlir::Value shift = getShift ();
1459+ mlir::Value shift = op. getShift ();
14581460 mlir::Type shiftTy = hlfir::getFortranElementOrSequenceType (shift.getType ());
14591461
1460- // TODO: turn allowCharacterLenMismatch into true.
1461- if ( auto match = areMatchingTypes (* this , eleTy, resultEleTy,
1462- /* allowCharacterLenMismatch=*/ false );
1462+ if ( auto match = areMatchingTypes (
1463+ op , eleTy, resultEleTy,
1464+ /* allowCharacterLenMismatch=*/ !useStrictIntrinsicVerifier );
14631465 match.failed ())
1464- return emitOpError (
1466+ return op. emitOpError (
14651467 " input and output arrays should have the same element type" );
14661468
14671469 if (arrayRank != resultRank)
1468- return emitOpError (" input and output arrays should have the same rank" );
1470+ return op. emitOpError (" input and output arrays should have the same rank" );
14691471
14701472 constexpr int64_t unknownExtent = fir::SequenceType::getUnknownExtent ();
14711473 for (auto [inDim, resultDim] : llvm::zip (inShape, resultShape))
14721474 if (inDim != unknownExtent && resultDim != unknownExtent &&
14731475 inDim != resultDim)
1474- return emitOpError (
1476+ return op. emitOpError (
14751477 " output array's shape conflicts with the input array's shape" );
14761478
14771479 int64_t dimVal = -1 ;
1478- if (!getDim ())
1480+ if (!op. getDim ())
14791481 dimVal = 1 ;
1480- else if (auto dim = fir::getIntIfConstant (getDim ()))
1482+ else if (auto dim = fir::getIntIfConstant (op. getDim ()))
14811483 dimVal = *dim;
14821484
14831485 // The DIM argument may be statically invalid (e.g. exceed the
14841486 // input array rank) in dead code after constant propagation,
14851487 // so avoid some checks unless useStrictIntrinsicVerifier is true.
14861488 if (useStrictIntrinsicVerifier && dimVal != -1 ) {
14871489 if (dimVal < 1 )
1488- return emitOpError (" DIM must be >= 1" );
1490+ return op. emitOpError (" DIM must be >= 1" );
14891491 if (dimVal > static_cast <int64_t >(arrayRank))
1490- return emitOpError (" DIM must be <= input array's rank" );
1492+ return op. emitOpError (" DIM must be <= input array's rank" );
14911493 }
14921494
1493- if (auto shiftSeqTy = mlir::dyn_cast<fir::SequenceType>(shiftTy)) {
1494- // SHIFT is an array. Verify the rank and the shape (if DIM is constant).
1495- llvm::ArrayRef<int64_t > shiftShape = shiftSeqTy.getShape ();
1496- std::size_t shiftRank = shiftShape.size ();
1497- if (shiftRank != arrayRank - 1 )
1498- return emitOpError (
1499- " SHIFT's rank must be 1 less than the input array's rank" );
1500-
1501- if (useStrictIntrinsicVerifier && dimVal != -1 ) {
1502- // SHIFT's shape must be [d(1), d(2), ..., d(DIM-1), d(DIM+1), ..., d(n)],
1503- // where [d(1), d(2), ..., d(n)] is the shape of the ARRAY.
1504- int64_t arrayDimIdx = 0 ;
1505- int64_t shiftDimIdx = 0 ;
1506- for (auto shiftDim : shiftShape) {
1507- if (arrayDimIdx == dimVal - 1 )
1495+ // A helper lambda to verify the shape of the array types of
1496+ // certain operands of the array shift (e.g. the SHIFT and BOUNDARY operands).
1497+ auto verifyOperandTypeShape = [&](mlir::Type type,
1498+ llvm::Twine name) -> llvm::LogicalResult {
1499+ if (auto opndSeqTy = mlir::dyn_cast<fir::SequenceType>(type)) {
1500+ // The operand is an array. Verify the rank and the shape (if DIM is
1501+ // constant).
1502+ llvm::ArrayRef<int64_t > opndShape = opndSeqTy.getShape ();
1503+ std::size_t opndRank = opndShape.size ();
1504+ if (opndRank != arrayRank - 1 )
1505+ return op.emitOpError (
1506+ name + " 's rank must be 1 less than the input array's rank" );
1507+
1508+ if (useStrictIntrinsicVerifier && dimVal != -1 ) {
1509+ // The operand's shape must be
1510+ // [d(1), d(2), ..., d(DIM-1), d(DIM+1), ..., d(n)],
1511+ // where [d(1), d(2), ..., d(n)] is the shape of the ARRAY.
1512+ int64_t arrayDimIdx = 0 ;
1513+ int64_t opndDimIdx = 0 ;
1514+ for (auto opndDim : opndShape) {
1515+ if (arrayDimIdx == dimVal - 1 )
1516+ ++arrayDimIdx;
1517+
1518+ if (inShape[arrayDimIdx] != unknownExtent &&
1519+ opndDim != unknownExtent && inShape[arrayDimIdx] != opndDim)
1520+ return op.emitOpError (" SHAPE(ARRAY)(" +
1521+ llvm::Twine (arrayDimIdx + 1 ) +
1522+ " ) must be equal to SHAPE(" + name + " )(" +
1523+ llvm::Twine (opndDimIdx + 1 ) +
1524+ " ): " + llvm::Twine (inShape[arrayDimIdx]) +
1525+ " != " + llvm::Twine (opndDim));
15081526 ++arrayDimIdx;
1509-
1510- if (inShape[arrayDimIdx] != unknownExtent &&
1511- shiftDim != unknownExtent && inShape[arrayDimIdx] != shiftDim)
1512- return emitOpError (" SHAPE(ARRAY)(" + llvm::Twine (arrayDimIdx + 1 ) +
1513- " ) must be equal to SHAPE(SHIFT)(" +
1514- llvm::Twine (shiftDimIdx + 1 ) +
1515- " ): " + llvm::Twine (inShape[arrayDimIdx]) +
1516- " != " + llvm::Twine (shiftDim));
1517- ++arrayDimIdx;
1518- ++shiftDimIdx;
1527+ ++opndDimIdx;
1528+ }
15191529 }
15201530 }
1531+ return mlir::success ();
1532+ };
1533+
1534+ if (failed (verifyOperandTypeShape (shiftTy, " SHIFT" )))
1535+ return mlir::failure ();
1536+
1537+ if constexpr (std::is_same_v<Op, hlfir::EOShiftOp>) {
1538+ if (mlir::Value boundary = op.getBoundary ()) {
1539+ mlir::Type boundaryTy =
1540+ hlfir::getFortranElementOrSequenceType (boundary.getType ());
1541+ if (auto match = areMatchingTypes (
1542+ op, eleTy, hlfir::getFortranElementType (boundaryTy),
1543+ /* allowCharacterLenMismatch=*/ !useStrictIntrinsicVerifier);
1544+ match.failed ())
1545+ return op.emitOpError (
1546+ " ARRAY and BOUNDARY operands must have the same element type" );
1547+ if (failed (verifyOperandTypeShape (boundaryTy, " BOUNDARY" )))
1548+ return mlir::failure ();
1549+ }
15211550 }
15221551
15231552 return mlir::success ();
15241553}
15251554
1555+ // ===----------------------------------------------------------------------===//
1556+ // CShiftOp
1557+ // ===----------------------------------------------------------------------===//
1558+
1559+ llvm::LogicalResult hlfir::CShiftOp::verify () {
1560+ return verifyArrayShift (*this );
1561+ }
1562+
15261563void hlfir::CShiftOp::getEffects (
15271564 llvm::SmallVectorImpl<
15281565 mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
15291566 &effects) {
15301567 getIntrinsicEffects (getOperation (), effects);
15311568}
15321569
1570+ // ===----------------------------------------------------------------------===//
1571+ // EOShiftOp
1572+ // ===----------------------------------------------------------------------===//
1573+
1574+ llvm::LogicalResult hlfir::EOShiftOp::verify () {
1575+ return verifyArrayShift (*this );
1576+ }
1577+
1578+ void hlfir::EOShiftOp::getEffects (
1579+ llvm::SmallVectorImpl<
1580+ mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
1581+ &effects) {
1582+ getIntrinsicEffects (getOperation (), effects);
1583+ }
1584+
15331585// ===----------------------------------------------------------------------===//
15341586// ReshapeOp
15351587// ===----------------------------------------------------------------------===//
@@ -1543,7 +1595,8 @@ llvm::LogicalResult hlfir::ReshapeOp::verify() {
15431595 hlfir::getFortranElementOrSequenceType (array.getType ()));
15441596 if (auto match = areMatchingTypes (
15451597 *this , hlfir::getFortranElementType (resultType),
1546- arrayType.getElementType (), /* allowCharacterLenMismatch=*/ true );
1598+ arrayType.getElementType (),
1599+ /* allowCharacterLenMismatch=*/ !useStrictIntrinsicVerifier);
15471600 match.failed ())
15481601 return emitOpError (" ARRAY and the result must have the same element type" );
15491602 if (hlfir::isPolymorphicType (resultType) !=
@@ -1565,9 +1618,9 @@ llvm::LogicalResult hlfir::ReshapeOp::verify() {
15651618 if (mlir::Value pad = getPad ()) {
15661619 auto padArrayType = mlir::cast<fir::SequenceType>(
15671620 hlfir::getFortranElementOrSequenceType (pad.getType ()));
1568- if (auto match = areMatchingTypes (* this , arrayType. getElementType (),
1569- padArrayType.getElementType (),
1570- /* allowCharacterLenMismatch=*/ true );
1621+ if (auto match = areMatchingTypes (
1622+ * this , arrayType. getElementType (), padArrayType.getElementType (),
1623+ /* allowCharacterLenMismatch=*/ !useStrictIntrinsicVerifier );
15711624 match.failed ())
15721625 return emitOpError (" ARRAY and PAD must be of the same type" );
15731626 }
0 commit comments