[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