Skip to content

Commit

Permalink
[flang] Implement ieee_is_normal
Browse files Browse the repository at this point in the history
This patch adds an implementation of ieee_is_normal using a call
to llvm.is.fpclass.

Depends on D144649

Differential Revision: https://reviews.llvm.org/D144966
  • Loading branch information
DavidTruby committed Mar 6, 2023
1 parent 66ec326 commit 75ddabd
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 11 deletions.
11 changes: 7 additions & 4 deletions flang/lib/Evaluate/fold-logical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,13 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
} else if (name == "__builtin_ieee_is_normal") {
auto restorer{context.messages().DiscardMessages()};
using DefaultReal = Type<TypeCategory::Real, 4>;
return FoldElementalIntrinsic<T, DefaultReal>(context, std::move(funcRef),
ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
return Scalar<T>{x.IsNormal()};
}));
if (args[0] && args[0]->UnwrapExpr() &&
IsActuallyConstant(*args[0]->UnwrapExpr())) {
return FoldElementalIntrinsic<T, DefaultReal>(context, std::move(funcRef),
ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
return Scalar<T>{x.IsNormal()};
}));
}
} else if (name == "is_contiguous") {
if (args.at(0)) {
if (auto *expr{args[0]->UnwrapExpr()}) {
Expand Down
31 changes: 24 additions & 7 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ struct IntrinsicLibrary {
fir::ExtendedValue genIchar(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genFindloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIeeeIsNormal(mlir::Type, llvm::ArrayRef<mlir::Value>);
template <mlir::arith::CmpIPredicate pred>
fir::ExtendedValue genIeeeTypeCompare(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
Expand All @@ -251,6 +252,8 @@ struct IntrinsicLibrary {
fir::ExtendedValue genIsContiguous(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIsFPClass(mlir::Type, llvm::ArrayRef<mlir::Value>,
int fpclass);
mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
Expand Down Expand Up @@ -623,6 +626,7 @@ static constexpr IntrinsicHandler handlers[]{
{"ieee_class_ne", &I::genIeeeTypeCompare<mlir::arith::CmpIPredicate::ne>},
{"ieee_is_finite", &I::genIeeeIsFinite},
{"ieee_is_nan", &I::genIsNan},
{"ieee_is_normal", &I::genIeeeIsNormal},
{"ieee_round_eq", &I::genIeeeTypeCompare<mlir::arith::CmpIPredicate::eq>},
{"ieee_round_ne", &I::genIeeeTypeCompare<mlir::arith::CmpIPredicate::ne>},
{"ieor", &I::genIeor},
Expand Down Expand Up @@ -3603,6 +3607,13 @@ IntrinsicLibrary::genIeeeIsFinite(mlir::Type resultType,
exponent, maxExponent));
}

mlir::Value
IntrinsicLibrary::genIeeeIsNormal(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
// Check if is positive or negative normal
return genIsFPClass(resultType, args, 0b101101000);
}

// IEOR
mlir::Value IntrinsicLibrary::genIeor(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
Expand Down Expand Up @@ -3693,18 +3704,24 @@ IntrinsicLibrary::genIsContiguous(mlir::Type resultType,
fir::runtime::genIsContiguous(builder, loc, fir::getBase(args[0])));
}

mlir::Value IntrinsicLibrary::genIsNan(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
mlir::Value IntrinsicLibrary::genIsFPClass(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args,
int fpclass) {
assert(args.size() == 1);
mlir::MLIRContext *context = builder.getContext();
mlir::IntegerType i1ty = mlir::IntegerType::get(context, 1);
mlir::IntegerType i32ty = mlir::IntegerType::get(context, 32);
// The last two bits indicate we are checking for signalling or quiet nan.
mlir::Value nan = builder.createIntegerConstant(loc, i32ty, 0b11);

mlir::Value isnan =
builder.create<mlir::LLVM::IsFPClass>(loc, i1ty, args[0], nan);
return builder.createConvert(loc, resultType, isnan);
mlir::Value test = builder.createIntegerConstant(loc, i32ty, fpclass);
mlir::Value isfpclass =
builder.create<mlir::LLVM::IsFPClass>(loc, i1ty, args[0], test);
return builder.createConvert(loc, resultType, isfpclass);
}

mlir::Value IntrinsicLibrary::genIsNan(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
// Check is signaling or quiet nan
return genIsFPClass(resultType, args, 0b11);
}

// ISHFT
Expand Down
64 changes: 64 additions & 0 deletions flang/test/Lower/Intrinsics/ieee_is_normal.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: flang-new -fc1 -emit-fir %s -o - | FileCheck %s

! CHECK-LABEL: ieee_is_normal_f16
subroutine ieee_is_normal_f16(r)
use ieee_arithmetic
real(KIND=2) :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (f16, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_f16

! CHECK-LABEL: ieee_is_normal_bf16
subroutine ieee_is_normal_bf16(r)
use ieee_arithmetic
real(KIND=3) :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (bf16, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_bf16



! CHECK-LABEL: ieee_is_normal_f32
subroutine ieee_is_normal_f32(r)
use ieee_arithmetic
real :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (f32, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_f32

! CHECK-LABEL: ieee_is_normal_f64
subroutine ieee_is_normal_f64(r)
use ieee_arithmetic
real(KIND=8) :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (f64, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_f64

! CHECK-LABEL: ieee_is_normal_f80
subroutine ieee_is_normal_f80(r)
use ieee_arithmetic
real(KIND=10) :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (f80, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_f80

! CHECK-LABEL: ieee_is_normal_f128
subroutine ieee_is_normal_f128(r)
use ieee_arithmetic
real(KIND=16) :: r
i = ieee_is_normal(r)
! CHECK: %[[test:.*]] = arith.constant 360 : i32
! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}, %[[test]]) : (f128, i32) -> i1
! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
end subroutine ieee_is_normal_f128

0 comments on commit 75ddabd

Please sign in to comment.