@@ -170,6 +170,17 @@ class HlfirCShiftLowering : public HlfirTransformationalIntrinsic {
170
170
mlir::Type stmtResultType) override ;
171
171
};
172
172
173
+ class HlfirEOShiftLowering : public HlfirTransformationalIntrinsic {
174
+ public:
175
+ using HlfirTransformationalIntrinsic::HlfirTransformationalIntrinsic;
176
+
177
+ protected:
178
+ mlir::Value
179
+ lowerImpl (const Fortran::lower::PreparedActualArguments &loweredActuals,
180
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
181
+ mlir::Type stmtResultType) override ;
182
+ };
183
+
173
184
class HlfirReshapeLowering : public HlfirTransformationalIntrinsic {
174
185
public:
175
186
using HlfirTransformationalIntrinsic::HlfirTransformationalIntrinsic;
@@ -430,6 +441,46 @@ mlir::Value HlfirCShiftLowering::lowerImpl(
430
441
return createOp<hlfir::CShiftOp>(resultType, operands);
431
442
}
432
443
444
+ mlir::Value HlfirEOShiftLowering::lowerImpl (
445
+ const Fortran::lower::PreparedActualArguments &loweredActuals,
446
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
447
+ mlir::Type stmtResultType) {
448
+ auto operands = getOperandVector (loweredActuals, argLowering);
449
+ assert (operands.size () == 4 );
450
+ mlir::Value array = operands[0 ];
451
+ mlir::Value shift = operands[1 ];
452
+ mlir::Value boundary = operands[2 ];
453
+ mlir::Value dim = operands[3 ];
454
+ // If DIM is present, then dereference it if it is a ref.
455
+ if (dim)
456
+ dim = hlfir::loadTrivialScalar (loc, builder, hlfir::Entity{dim});
457
+
458
+ mlir::Type resultType = computeResultType (array, stmtResultType);
459
+
460
+ if (boundary && fir::isa_trivial (boundary.getType ())) {
461
+ mlir::Type elementType = hlfir::getFortranElementType (resultType);
462
+ if (auto logicalTy = mlir::dyn_cast<fir::LogicalType>(elementType)) {
463
+ // Scalar logical constant boundary might be represented using i1, i2, ...
464
+ // type. We need to cast it to fir.logical type of the ARRAY/result.
465
+ if (boundary.getType () != logicalTy)
466
+ boundary = builder.createConvert (loc, logicalTy, boundary);
467
+ } else {
468
+ // When the boundary is a constant like '1u', the lowering converts
469
+ // it into a signless arith.constant value (which is a requirement
470
+ // of the Arith dialect). If the ARRAY/RESULT is also UNSIGNED,
471
+ // we have to cast the boundary to the same unsigned type.
472
+ auto resultIntTy = mlir::dyn_cast<mlir::IntegerType>(elementType);
473
+ auto boundaryIntTy =
474
+ mlir::dyn_cast<mlir::IntegerType>(boundary.getType ());
475
+ if (resultIntTy && boundaryIntTy &&
476
+ resultIntTy.getSignedness () != boundaryIntTy.getSignedness ())
477
+ boundary = builder.createConvert (loc, resultIntTy, boundary);
478
+ }
479
+ }
480
+
481
+ return createOp<hlfir::EOShiftOp>(resultType, array, shift, boundary, dim);
482
+ }
483
+
433
484
mlir::Value HlfirReshapeLowering::lowerImpl (
434
485
const Fortran::lower::PreparedActualArguments &loweredActuals,
435
486
const fir::IntrinsicArgumentLoweringRules *argLowering,
@@ -489,6 +540,9 @@ std::optional<hlfir::EntityWithAttributes> Fortran::lower::lowerHlfirIntrinsic(
489
540
if (name == " cshift" )
490
541
return HlfirCShiftLowering{builder, loc}.lower (loweredActuals, argLowering,
491
542
stmtResultType);
543
+ if (name == " eoshift" )
544
+ return HlfirEOShiftLowering{builder, loc}.lower (loweredActuals, argLowering,
545
+ stmtResultType);
492
546
if (name == " reshape" )
493
547
return HlfirReshapeLowering{builder, loc}.lower (loweredActuals, argLowering,
494
548
stmtResultType);
0 commit comments