[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