mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 16:11:29 +00:00
[flang] Lower relational to HLFIR
Differential Revision: https://reviews.llvm.org/D139176
This commit is contained in:
parent
63150f4639
commit
12530711fc
@ -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:
|
||||
|
@ -207,3 +207,85 @@ end subroutine
|
||||
! 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
|
||||
|
Loading…
Reference in New Issue
Block a user