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/IntrinsicCall.h"
|
||||||
#include "flang/Lower/StatementContext.h"
|
#include "flang/Lower/StatementContext.h"
|
||||||
#include "flang/Lower/SymbolMap.h"
|
#include "flang/Lower/SymbolMap.h"
|
||||||
|
#include "flang/Optimizer/Builder/Runtime/Character.h"
|
||||||
#include "flang/Optimizer/Builder/Todo.h"
|
#include "flang/Optimizer/Builder/Todo.h"
|
||||||
#include "flang/Optimizer/HLFIR/HLFIROps.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.
|
/// Lower Expr to HLFIR.
|
||||||
class HlfirBuilder {
|
class HlfirBuilder {
|
||||||
public:
|
public:
|
||||||
|
@ -207,3 +207,85 @@ end subroutine
|
|||||||
! CHECK: %[[VAL_12:.*]] = fir.load %{{.*}} : !fir.ref<i64>
|
! CHECK: %[[VAL_12:.*]] = fir.load %{{.*}} : !fir.ref<i64>
|
||||||
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
|
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
|
||||||
! CHECK: arith.select %[[VAL_13]], %[[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