[flang-commits] [flang] 75ddabd - [flang] Implement ieee_is_normal
David Truby via flang-commits
flang-commits at lists.llvm.org
Mon Mar 6 06:46:59 PST 2023
Author: David Truby
Date: 2023-03-06T14:46:48Z
New Revision: 75ddabd520db0f924b819516428cc7b618aaf5e7
URL: https://github.com/llvm/llvm-project/commit/75ddabd520db0f924b819516428cc7b618aaf5e7
DIFF: https://github.com/llvm/llvm-project/commit/75ddabd520db0f924b819516428cc7b618aaf5e7.diff
LOG: [flang] Implement ieee_is_normal
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
Added:
flang/test/Lower/Intrinsics/ieee_is_normal.f90
Modified:
flang/lib/Evaluate/fold-logical.cpp
flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Removed:
################################################################################
diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index 4c3476a53c1a2..43406497a9e66 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -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()}) {
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 14081b7e9a6c3..84d534febdba5 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -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>);
@@ -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>);
@@ -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},
@@ -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) {
@@ -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
diff --git a/flang/test/Lower/Intrinsics/ieee_is_normal.f90 b/flang/test/Lower/Intrinsics/ieee_is_normal.f90
new file mode 100644
index 0000000000000..84b3d2bf0a6d3
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/ieee_is_normal.f90
@@ -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
More information about the flang-commits
mailing list