[flang-commits] [flang] 1253071 - [flang] Lower relational to HLFIR
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Fri Dec 2 05:18:46 PST 2022
Author: Jean Perier
Date: 2022-12-02T14:18:10+01:00
New Revision: 12530711fc2b57806ebd6a046196fb718ed3479e
URL: https://github.com/llvm/llvm-project/commit/12530711fc2b57806ebd6a046196fb718ed3479e
DIFF: https://github.com/llvm/llvm-project/commit/12530711fc2b57806ebd6a046196fb718ed3479e.diff
LOG: [flang] Lower relational to HLFIR
Differential Revision: https://reviews.llvm.org/D139176
Added:
Modified:
flang/lib/Lower/ConvertExprToHLFIR.cpp
flang/test/Lower/HLFIR/binary-ops.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 284b1cc7ea674..c278072ac75d9 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -20,6 +20,7 @@
#include "flang/Lower/IntrinsicCall.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Lower/SymbolMap.h"
+#include "flang/Optimizer/Builder/Runtime/Character.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
@@ -341,6 +342,121 @@ struct BinaryOp<
}
};
+/// Convert parser's INTEGER relational operators to MLIR.
+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");
+}
+
+/// 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
+/// also applied in other contexts because it is easier and in line with
+/// other Fortran compilers.
+/// FIXME: The signaling/quiet aspect of the table 17.1 requirement is not
+/// fully enforced. FIR and LLVM `fcmp` instructions do not give any guarantee
+/// whether the comparison will signal or not in case of quiet NaN argument.
+static mlir::arith::CmpFPredicate
+translateFloatRelational(Fortran::common::RelationalOperator rop) {
+ switch (rop) {
+ case Fortran::common::RelationalOperator::LT:
+ return mlir::arith::CmpFPredicate::OLT;
+ case Fortran::common::RelationalOperator::LE:
+ return mlir::arith::CmpFPredicate::OLE;
+ case Fortran::common::RelationalOperator::EQ:
+ return mlir::arith::CmpFPredicate::OEQ;
+ case Fortran::common::RelationalOperator::NE:
+ return mlir::arith::CmpFPredicate::UNE;
+ case Fortran::common::RelationalOperator::GT:
+ return mlir::arith::CmpFPredicate::OGT;
+ case Fortran::common::RelationalOperator::GE:
+ return mlir::arith::CmpFPredicate::OGE;
+ }
+ llvm_unreachable("unhandled REAL relational operator");
+}
+
+template <int KIND>
+struct BinaryOp<Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>> {
+ using Op = Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>;
+ static hlfir::EntityWithAttributes gen(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ const Op &op, hlfir::Entity lhs,
+ hlfir::Entity rhs) {
+ auto cmp = builder.create<mlir::arith::CmpIOp>(
+ loc, translateRelational(op.opr), lhs, rhs);
+ return hlfir::EntityWithAttributes{cmp};
+ }
+};
+
+template <int KIND>
+struct BinaryOp<Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>> {
+ using Op = Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>;
+ static hlfir::EntityWithAttributes gen(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ const Op &op, hlfir::Entity lhs,
+ hlfir::Entity rhs) {
+ auto cmp = builder.create<mlir::arith::CmpFOp>(
+ loc, translateFloatRelational(op.opr), lhs, rhs);
+ return hlfir::EntityWithAttributes{cmp};
+ }
+};
+
+template <int KIND>
+struct BinaryOp<Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>> {
+ using Op = Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>;
+ static hlfir::EntityWithAttributes gen(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ const Op &op, hlfir::Entity lhs,
+ hlfir::Entity rhs) {
+ auto cmp = builder.create<fir::CmpcOp>(
+ loc, translateFloatRelational(op.opr), lhs, rhs);
+ return hlfir::EntityWithAttributes{cmp};
+ }
+};
+
+template <int KIND>
+struct BinaryOp<Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>> {
+ using Op = Fortran::evaluate::Relational<
+ Fortran::evaluate::Type<Fortran::common::TypeCategory::Character, KIND>>;
+ static hlfir::EntityWithAttributes gen(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ const Op &op, hlfir::Entity lhs,
+ hlfir::Entity rhs) {
+ auto [lhsExv, lhsCleanUp] =
+ hlfir::translateToExtendedValue(loc, builder, lhs);
+ auto [rhsExv, rhsCleanUp] =
+ hlfir::translateToExtendedValue(loc, builder, rhs);
+ auto cmp = fir::runtime::genCharCompare(
+ builder, loc, translateRelational(op.opr), lhsExv, rhsExv);
+ if (lhsCleanUp)
+ lhsCleanUp.value()();
+ if (rhsCleanUp)
+ rhsCleanUp.value()();
+ return hlfir::EntityWithAttributes{cmp};
+ }
+};
+
/// Lower Expr to HLFIR.
class HlfirBuilder {
public:
diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index 678cd23bf5615..8f504c49a1cb1 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -207,3 +207,85 @@ subroutine extremum(c, n, l)
! CHECK: %[[VAL_12:.*]] = fir.load %{{.*}} : !fir.ref<i64>
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64
+
+subroutine cmp_int(l, x, y)
+ logical :: l
+ integer :: x, y
+ l = x .eq. y
+end subroutine
+! CHECK-LABEL: func.func @_QPcmp_int(
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare {{.*}}x"
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}y"
+! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK: %[[VAL_8:.*]] = arith.cmpi eq, %[[VAL_6]], %[[VAL_7]] : i32
+
+subroutine cmp_int_2(l, x, y)
+ logical :: l
+ integer :: x, y
+ l = x .ne. y
+! CHECK: arith.cmpi ne
+ l = x .gt. y
+! CHECK: arith.cmpi sgt
+ l = x .ge. y
+! CHECK: arith.cmpi sge
+ l = x .lt. y
+! CHECK: arith.cmpi slt
+ l = x .le. y
+! CHECK: arith.cmpi sle
+end subroutine
+
+subroutine cmp_real(l, x, y)
+ logical :: l
+ real :: x, y
+ l = x .eq. y
+end subroutine
+! CHECK-LABEL: func.func @_QPcmp_real(
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare {{.*}}x"
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}y"
+! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
+! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<f32>
+! CHECK: %[[VAL_8:.*]] = arith.cmpf oeq, %[[VAL_6]], %[[VAL_7]] : f32
+
+subroutine cmp_real_2(l, x, y)
+ logical :: l
+ real :: x, y
+ l = x .ne. y
+! CHECK: arith.cmpf une
+ l = x .gt. y
+! CHECK: arith.cmpf ogt
+ l = x .ge. y
+! CHECK: arith.cmpf oge
+ l = x .lt. y
+! CHECK: arith.cmpf olt
+ l = x .le. y
+! CHECK: arith.cmpf ole
+end subroutine
+
+subroutine cmp_cmplx(l, x, y)
+ logical :: l
+ complex :: x, y
+ l = x .eq. y
+end subroutine
+! CHECK-LABEL: func.func @_QPcmp_cmplx(
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare {{.*}}x"
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare {{.*}}y"
+! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK: %[[VAL_8:.*]] = fir.cmpc "oeq", %[[VAL_6]], %[[VAL_7]] : !fir.complex<4>
+
+subroutine cmp_char(l, x, y)
+ logical :: l
+ character(*) :: x, y
+ l = x .eq. y
+end subroutine
+! CHECK-LABEL: func.func @_QPcmp_char(
+! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_4:.*]]#1 {uniq_name = "_QFcmp_charEx"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %{{.*}} typeparams %[[VAL_6:.*]]#1 {uniq_name = "_QFcmp_charEy"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_5]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
+! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_7]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
+! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_4]]#1 : (index) -> i64
+! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_6]]#1 : (index) -> i64
+! CHECK: %[[VAL_12:.*]] = fir.call @_FortranACharacterCompareScalar1(%[[VAL_8]], %[[VAL_9]], %[[VAL_10]], %[[VAL_11]]) fastmath<contract> : (!fir.ref<i8>, !fir.ref<i8>, i64, i64) -> i32
+! CHECK: %[[VAL_13:.*]] = arith.constant 0 : i32
+! CHECK: %[[VAL_14:.*]] = arith.cmpi eq, %[[VAL_12]], %[[VAL_13]] : i32
More information about the flang-commits
mailing list