From f1dcf3ae92d0e12a89fef77f0cfb1e974c98f7c5 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Fri, 25 Feb 2022 21:00:07 +0100 Subject: [PATCH] [flang] Lower integer comparison operation This patch handles the lowering of comprison operator between integers. The comparison is lowered to a `arith.cmpi` operation. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: PeteSteinfeld, schweitz, rovka Differential Revision: https://reviews.llvm.org/D120559 Co-authored-by: Eric Schweitz Co-authored-by: Jean Perier --- flang/lib/Lower/ConvertExpr.cpp | 40 +++++++++++- flang/test/Lower/integer-operations.f90 | 109 ++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 flang/test/Lower/integer-operations.f90 diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index 93deace..ff5ae13 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -109,6 +109,27 @@ enum class ConstituentSemantics { RefOpaque }; +/// 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) { + switch (rop) { + case Fortran::common::RelationalOperator::LT: + return mlir::arith::CmpIPredicate::slt; + case Fortran::common::RelationalOperator::LE: + return mlir::arith::CmpIPredicate::sle; + 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::sgt; + case Fortran::common::RelationalOperator::GE: + return mlir::arith::CmpIPredicate::sge; + } + llvm_unreachable("unhandled INTEGER relational operator"); +} + /// Place \p exv in memory if it is not already a memory reference. If /// \p forceValueType is provided, the value is first casted to the provided /// type before being stored (this is mainly intended for logicals whose value @@ -338,6 +359,20 @@ public: return builder.createRealConstant(getLoc(), fltTy, value); } + template + 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(getLoc(), pred, *lhs, *rhs); + fir::emitFatalError(getLoc(), "array compare should be handled in genarr"); + } + template + mlir::Value createCompareOp(const A &ex, mlir::arith::CmpIPredicate pred) { + ExtValue left = genval(ex.left()); + return createCompareOp(pred, left, genval(ex.right())); + } + /// Returns a reference to a symbol or its box/boxChar descriptor if it has /// one. ExtValue gen(Fortran::semantics::SymbolRef sym) { @@ -494,7 +529,8 @@ public: template ExtValue genval(const Fortran::evaluate::Relational> &op) { - TODO(getLoc(), "genval integer comparison"); + return createCompareOp(op, + translateRelational(op.opr)); } template ExtValue genval(const Fortran::evaluate::Relational &op) { - TODO(getLoc(), "genval comparison"); + return std::visit([&](const auto &x) { return genval(x); }, op.u); } template !fir.logical<4> +eq0_test = x0 .EQ. x1 +END FUNCTION + +! CHECK-LABEL:ne1_test +LOGICAL FUNCTION ne1_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:[[reg3:%[0-9]+]] = arith.cmpi ne, [[reg1]], [[reg2]] : i32 +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<4> +ne1_test = x0 .NE. x1 +END FUNCTION + +! CHECK-LABEL:lt2_test +LOGICAL FUNCTION lt2_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:[[reg3:%[0-9]+]] = arith.cmpi slt, [[reg1]], [[reg2]] : i32 +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<4> +lt2_test = x0 .LT. x1 +END FUNCTION + +! CHECK-LABEL:le3_test +LOGICAL FUNCTION le3_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:[[reg3:%[0-9]+]] = arith.cmpi sle, [[reg1]], [[reg2]] : i32 +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<4> +le3_test = x0 .LE. x1 +END FUNCTION + +! CHECK-LABEL:gt4_test +LOGICAL FUNCTION gt4_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:[[reg3:%[0-9]+]] = arith.cmpi sgt, [[reg1]], [[reg2]] : i32 +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<4> +gt4_test = x0 .GT. x1 +END FUNCTION + +! CHECK-LABEL:ge5_test +LOGICAL FUNCTION ge5_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:[[reg3:%[0-9]+]] = arith.cmpi sge, [[reg1]], [[reg2]] : i32 +! CHECK:fir.convert [[reg3]] {{.*}} -> !fir.logical<4> +ge5_test = x0 .GE. x1 +END FUNCTION + +! CHECK-LABEL:add6_test +INTEGER(4) FUNCTION add6_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:addi [[reg1]], [[reg2]] : i32 +add6_test = x0 + x1 +END FUNCTION + +! CHECK-LABEL:sub7_test +INTEGER(4) FUNCTION sub7_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:subi [[reg1]], [[reg2]] : i32 +sub7_test = x0 - x1 +END FUNCTION + +! CHECK-LABEL:mult8_test +INTEGER(4) FUNCTION mult8_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:muli [[reg1]], [[reg2]] : i32 +mult8_test = x0 * x1 +END FUNCTION + +! CHECK-LABEL:div9_test +INTEGER(4) FUNCTION div9_test(x0, x1) +INTEGER(4) :: x0 +INTEGER(4) :: x1 +! CHECK-DAG:[[reg1:%[0-9]+]] = fir.load %arg0 +! CHECK-DAG:[[reg2:%[0-9]+]] = fir.load %arg1 +! CHECK:arith.divsi [[reg1]], [[reg2]] : i32 +div9_test = x0 / x1 +END FUNCTION -- 2.7.4