diff options
Diffstat (limited to 'flang/lib/Lower/ConvertExpr.cpp')
| -rw-r--r-- | flang/lib/Lower/ConvertExpr.cpp | 127 |
1 files changed, 108 insertions, 19 deletions
diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index 7698fac89c22..d9ae502edbaf 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -194,7 +194,7 @@ enum class ConstituentSemantics { /// Convert parser's INTEGER relational operators to MLIR. TODO: using /// unordered, but we may want to cons ordered in certain situation. static mlir::arith::CmpIPredicate -translateRelational(Fortran::common::RelationalOperator rop) { +translateSignedRelational(Fortran::common::RelationalOperator rop) { switch (rop) { case Fortran::common::RelationalOperator::LT: return mlir::arith::CmpIPredicate::slt; @@ -212,6 +212,25 @@ translateRelational(Fortran::common::RelationalOperator rop) { llvm_unreachable("unhandled INTEGER relational operator"); } +static mlir::arith::CmpIPredicate +translateUnsignedRelational(Fortran::common::RelationalOperator rop) { + switch (rop) { + case Fortran::common::RelationalOperator::LT: + return mlir::arith::CmpIPredicate::ult; + case Fortran::common::RelationalOperator::LE: + return mlir::arith::CmpIPredicate::ule; + case Fortran::common::RelationalOperator::EQ: + return mlir::arith::CmpIPredicate::eq; + case Fortran::common::RelationalOperator::NE: + return mlir::arith::CmpIPredicate::ne; + case Fortran::common::RelationalOperator::GT: + return mlir::arith::CmpIPredicate::ugt; + case Fortran::common::RelationalOperator::GE: + return mlir::arith::CmpIPredicate::uge; + } + llvm_unreachable("unhandled UNSIGNED relational operator"); +} + /// Convert parser's REAL relational operators to MLIR. /// The choice of order (O prefix) vs unorder (U prefix) follows Fortran 2018 /// requirements in the IEEE context (table 17.1 of F2018). This choice is @@ -793,16 +812,28 @@ public: template <typename OpTy> mlir::Value createCompareOp(mlir::arith::CmpIPredicate pred, - const ExtValue &left, const ExtValue &right) { - if (const fir::UnboxedValue *lhs = left.getUnboxed()) - if (const fir::UnboxedValue *rhs = right.getUnboxed()) - return builder.create<OpTy>(getLoc(), pred, *lhs, *rhs); + const ExtValue &left, const ExtValue &right, + std::optional<int> unsignedKind = std::nullopt) { + if (const fir::UnboxedValue *lhs = left.getUnboxed()) { + if (const fir::UnboxedValue *rhs = right.getUnboxed()) { + auto loc = getLoc(); + if (unsignedKind) { + mlir::Type signlessType = converter.genType( + Fortran::common::TypeCategory::Integer, *unsignedKind); + mlir::Value lhsSL = builder.createConvert(loc, signlessType, *lhs); + mlir::Value rhsSL = builder.createConvert(loc, signlessType, *rhs); + return builder.create<OpTy>(loc, pred, lhsSL, rhsSL); + } + return builder.create<OpTy>(loc, pred, *lhs, *rhs); + } + } fir::emitFatalError(getLoc(), "array compare should be handled in genarr"); } template <typename OpTy, typename A> - mlir::Value createCompareOp(const A &ex, mlir::arith::CmpIPredicate pred) { + mlir::Value createCompareOp(const A &ex, mlir::arith::CmpIPredicate pred, + std::optional<int> unsignedKind = std::nullopt) { ExtValue left = genval(ex.left()); - return createCompareOp<OpTy>(pred, left, genval(ex.right())); + return createCompareOp<OpTy>(pred, left, genval(ex.right()), unsignedKind); } template <typename OpTy> @@ -1050,6 +1081,18 @@ public: } template <int KIND> ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type< + Fortran::common::TypeCategory::Unsigned, KIND>> &op) { + auto loc = getLoc(); + mlir::Type signlessType = + converter.genType(Fortran::common::TypeCategory::Integer, KIND); + mlir::Value input = genunbox(op.left()); + mlir::Value signless = builder.createConvert(loc, signlessType, input); + mlir::Value zero = genIntegerConstant<KIND>(builder.getContext(), 0); + mlir::Value neg = builder.create<mlir::arith::SubIOp>(loc, zero, signless); + return builder.createConvert(loc, input.getType(), neg); + } + template <int KIND> + ExtValue genval(const Fortran::evaluate::Negate<Fortran::evaluate::Type< Fortran::common::TypeCategory::Real, KIND>> &op) { return builder.create<mlir::arith::NegFOp>(getLoc(), genunbox(op.left())); } @@ -1065,7 +1108,7 @@ public: mlir::Value lhs = fir::getBase(left); mlir::Value rhs = fir::getBase(right); assert(lhs.getType() == rhs.getType() && "types must be the same"); - return builder.create<OpTy>(getLoc(), lhs, rhs); + return builder.createUnsigned<OpTy>(getLoc(), lhs.getType(), lhs, rhs); } template <typename OpTy, typename A> @@ -1083,15 +1126,19 @@ public: } GENBIN(Add, Integer, mlir::arith::AddIOp) + GENBIN(Add, Unsigned, mlir::arith::AddIOp) GENBIN(Add, Real, mlir::arith::AddFOp) GENBIN(Add, Complex, fir::AddcOp) GENBIN(Subtract, Integer, mlir::arith::SubIOp) + GENBIN(Subtract, Unsigned, mlir::arith::SubIOp) GENBIN(Subtract, Real, mlir::arith::SubFOp) GENBIN(Subtract, Complex, fir::SubcOp) GENBIN(Multiply, Integer, mlir::arith::MulIOp) + GENBIN(Multiply, Unsigned, mlir::arith::MulIOp) GENBIN(Multiply, Real, mlir::arith::MulFOp) GENBIN(Multiply, Complex, fir::MulcOp) GENBIN(Divide, Integer, mlir::arith::DivSIOp) + GENBIN(Divide, Unsigned, mlir::arith::DivUIOp) GENBIN(Divide, Real, mlir::arith::DivFOp) template <int KIND> @@ -1200,8 +1247,14 @@ public: template <int KIND> ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< Fortran::common::TypeCategory::Integer, KIND>> &op) { - return createCompareOp<mlir::arith::CmpIOp>(op, - translateRelational(op.opr)); + return createCompareOp<mlir::arith::CmpIOp>( + op, translateSignedRelational(op.opr)); + } + template <int KIND> + ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< + Fortran::common::TypeCategory::Unsigned, KIND>> &op) { + return createCompareOp<mlir::arith::CmpIOp>( + op, translateUnsignedRelational(op.opr), KIND); } template <int KIND> ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< @@ -1217,7 +1270,7 @@ public: template <int KIND> ExtValue genval(const Fortran::evaluate::Relational<Fortran::evaluate::Type< Fortran::common::TypeCategory::Character, KIND>> &op) { - return createCharCompare(op, translateRelational(op.opr)); + return createCharCompare(op, translateSignedRelational(op.opr)); } ExtValue @@ -5103,21 +5156,37 @@ private: return fir::substBase(val, newBase); }; } - template <int KIND> - CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type< - Fortran::common::TypeCategory::Integer, KIND>> &x) { + template <Fortran::common::TypeCategory CAT, int KIND> + CC genarrIntNeg( + const Fortran::evaluate::Expr<Fortran::evaluate::Type<CAT, KIND>> &left) { mlir::Location loc = getLoc(); - auto f = genarr(x.left()); + auto f = genarr(left); return [=](IterSpace iters) -> ExtValue { mlir::Value val = fir::getBase(f(iters)); mlir::Type ty = converter.genType(Fortran::common::TypeCategory::Integer, KIND); mlir::Value zero = builder.createIntegerConstant(loc, ty, 0); + if constexpr (CAT == Fortran::common::TypeCategory::Unsigned) { + mlir::Value signless = builder.createConvert(loc, ty, val); + mlir::Value neg = + builder.create<mlir::arith::SubIOp>(loc, zero, signless); + return builder.createConvert(loc, val.getType(), neg); + } return builder.create<mlir::arith::SubIOp>(loc, zero, val); }; } template <int KIND> CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type< + Fortran::common::TypeCategory::Integer, KIND>> &x) { + return genarrIntNeg(x.left()); + } + template <int KIND> + CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type< + Fortran::common::TypeCategory::Unsigned, KIND>> &x) { + return genarrIntNeg(x.left()); + } + template <int KIND> + CC genarr(const Fortran::evaluate::Negate<Fortran::evaluate::Type< Fortran::common::TypeCategory::Real, KIND>> &x) { mlir::Location loc = getLoc(); auto f = genarr(x.left()); @@ -5147,7 +5216,8 @@ private: return [=](IterSpace iters) -> ExtValue { mlir::Value left = fir::getBase(lambda(iters)); mlir::Value right = fir::getBase(rf(iters)); - return builder.create<OP>(loc, left, right); + assert(left.getType() == right.getType() && "types must be the same"); + return builder.createUnsigned<OP>(loc, left.getType(), left, right); }; } @@ -5160,15 +5230,19 @@ private: } GENBIN(Add, Integer, mlir::arith::AddIOp) + GENBIN(Add, Unsigned, mlir::arith::AddIOp) GENBIN(Add, Real, mlir::arith::AddFOp) GENBIN(Add, Complex, fir::AddcOp) GENBIN(Subtract, Integer, mlir::arith::SubIOp) + GENBIN(Subtract, Unsigned, mlir::arith::SubIOp) GENBIN(Subtract, Real, mlir::arith::SubFOp) GENBIN(Subtract, Complex, fir::SubcOp) GENBIN(Multiply, Integer, mlir::arith::MulIOp) + GENBIN(Multiply, Unsigned, mlir::arith::MulIOp) GENBIN(Multiply, Real, mlir::arith::MulFOp) GENBIN(Multiply, Complex, fir::MulcOp) GENBIN(Divide, Integer, mlir::arith::DivSIOp) + GENBIN(Divide, Unsigned, mlir::arith::DivUIOp) GENBIN(Divide, Real, mlir::arith::DivFOp) template <int KIND> @@ -6549,13 +6623,21 @@ private: //===--------------------------------------------------------------------===// template <typename OP, typename PRED, typename A> - CC createCompareOp(PRED pred, const A &x) { + CC createCompareOp(PRED pred, const A &x, + std::optional<int> unsignedKind = std::nullopt) { mlir::Location loc = getLoc(); auto lf = genarr(x.left()); auto rf = genarr(x.right()); return [=](IterSpace iters) -> ExtValue { mlir::Value lhs = fir::getBase(lf(iters)); mlir::Value rhs = fir::getBase(rf(iters)); + if (unsignedKind) { + mlir::Type signlessType = converter.genType( + Fortran::common::TypeCategory::Integer, *unsignedKind); + mlir::Value lhsSL = builder.createConvert(loc, signlessType, lhs); + mlir::Value rhsSL = builder.createConvert(loc, signlessType, rhs); + return builder.create<OP>(loc, pred, lhsSL, rhsSL); + } return builder.create<OP>(loc, pred, lhs, rhs); }; } @@ -6573,12 +6655,19 @@ private: template <int KIND> CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type< Fortran::common::TypeCategory::Integer, KIND>> &x) { - return createCompareOp<mlir::arith::CmpIOp>(translateRelational(x.opr), x); + return createCompareOp<mlir::arith::CmpIOp>( + translateSignedRelational(x.opr), x); + } + template <int KIND> + CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type< + Fortran::common::TypeCategory::Unsigned, KIND>> &x) { + return createCompareOp<mlir::arith::CmpIOp>( + translateUnsignedRelational(x.opr), x, KIND); } template <int KIND> CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type< Fortran::common::TypeCategory::Character, KIND>> &x) { - return createCompareCharOp(translateRelational(x.opr), x); + return createCompareCharOp(translateSignedRelational(x.opr), x); } template <int KIND> CC genarr(const Fortran::evaluate::Relational<Fortran::evaluate::Type< |
