[flang-commits] [flang] 7c349c3 - [mlir][Arith] Add arith.is_nan and arith.is_inf predicates

Krzysztof Drewniak via flang-commits flang-commits at lists.llvm.org
Wed Aug 2 07:42:31 PDT 2023


Author: Krzysztof Drewniak
Date: 2023-08-02T14:42:25Z
New Revision: 7c349c369847dc2f1736efb9c90d03521cd44a90

URL: https://github.com/llvm/llvm-project/commit/7c349c369847dc2f1736efb9c90d03521cd44a90
DIFF: https://github.com/llvm/llvm-project/commit/7c349c369847dc2f1736efb9c90d03521cd44a90.diff

LOG: [mlir][Arith] Add arith.is_nan and arith.is_inf predicates

Both LLVM and SPIR-V have some form of "is this float a NaN/Inf"
operation (though LLVM's uses the rather opaque "is.fpclass"
intrinsic), which is not exposed in MLIR.

This has lead to awkward workarounds in -arith-expands-ops where a NaN
test was performed by comparing an operation to itself. This commit
resolves that issue.

Reviewed By: dcaballe, kuhar

Differential Revision: https://reviews.llvm.org/D156169

Added: 
    

Modified: 
    flang/test/Lower/Intrinsics/ieee_class_queries.f90
    flang/test/Lower/Intrinsics/ieee_is_finite.f90
    flang/test/Lower/Intrinsics/ieee_is_normal.f90
    flang/test/Lower/Intrinsics/ieee_unordered.f90
    flang/test/Lower/Intrinsics/isnan.f90
    mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
    mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
    mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
    mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
    mlir/lib/Dialect/Arith/IR/ArithOps.cpp
    mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
    mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
    mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
    mlir/test/Dialect/Arith/canonicalize.mlir
    mlir/test/Dialect/Arith/expand-ops.mlir
    mlir/test/Dialect/Arith/ops.mlir
    mlir/test/Target/LLVMIR/Import/intrinsic.ll
    mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir

Removed: 
    


################################################################################
diff  --git a/flang/test/Lower/Intrinsics/ieee_class_queries.f90 b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
index bb7787ea903e23..137ab23e5de37a 100644
--- a/flang/test/Lower/Intrinsics/ieee_class_queries.f90
+++ b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
@@ -10,38 +10,38 @@
   real(10) :: x10 = -10.0
   real(16) :: x16 = -16.0
 
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 504 : i32}> : (f16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 60 : i32}> : (f16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 60 : i32}> : (f16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f16) -> i1
   print*, ieee_is_finite(x2), ieee_is_negative(x2), ieee_is_normal(x2), &
           ieee_is_nan(x2)
 
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 504 : i32}> : (bf16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 60 : i32}> : (bf16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (bf16) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (bf16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (bf16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 60 : i32}> : (bf16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (bf16) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (bf16) -> i1
   print*, ieee_is_finite(x3), ieee_is_negative(x3), ieee_is_normal(x3), &
           ieee_is_nan(x3)
 
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 504 : i32}> : (f32) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 60 : i32}> : (f32) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f32) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f32) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f32) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 60 : i32}> : (f32) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f32) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f32) -> i1
   print*, ieee_is_finite(x4), ieee_is_negative(x4), ieee_is_normal(x4), &
           ieee_is_nan(x4)
 
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 504 : i32}> : (f64) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 60 : i32}> : (f64) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f64) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f64) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f64) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 60 : i32}> : (f64) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f64) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f64) -> i1
   print*, ieee_is_finite(x8), ieee_is_negative(x8), ieee_is_normal(x8), &
           ieee_is_nan(x8)
 
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 504 : i32}> : (f128) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 60 : i32}> : (f128) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f128) -> i1
-  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f128) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f128) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 60 : i32}> : (f128) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f128) -> i1
+  ! CHECK:     "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
   print*, ieee_is_finite(x16), ieee_is_negative(x16), ieee_is_normal(x16), &
           ieee_is_nan(x16)
 

diff  --git a/flang/test/Lower/Intrinsics/ieee_is_finite.f90 b/flang/test/Lower/Intrinsics/ieee_is_finite.f90
index db226c0d0a5ce7..19b5980c0956d2 100644
--- a/flang/test/Lower/Intrinsics/ieee_is_finite.f90
+++ b/flang/test/Lower/Intrinsics/ieee_is_finite.f90
@@ -7,7 +7,7 @@ subroutine is_finite_test(x, y)
   real(8) y
 
   ! CHECK:     %[[V_3:[0-9]+]] = fir.load %arg0 : !fir.ref<f32>
-  ! CHECK:     %[[V_4:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_3]]) <{bit = 504 : i32}> : (f32) -> i1
+  ! CHECK:     %[[V_4:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_3]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f32) -> i1
   ! CHECK:     %[[V_5:[0-9]+]] = fir.convert %[[V_4]] : (i1) -> !fir.logical<4>
   ! CHECK:     %[[V_6:[0-9]+]] = fir.convert %[[V_5]] : (!fir.logical<4>) -> i1
   ! CHECK:     %[[V_7:[0-9]+]] = fir.call @_FortranAioOutputLogical(%{{.*}}, %[[V_6]]) {{.*}} : (!fir.ref<i8>, i1) -> i1
@@ -16,14 +16,14 @@ subroutine is_finite_test(x, y)
   ! CHECK:     %[[V_12:[0-9]+]] = fir.load %arg0 : !fir.ref<f32>
   ! CHECK:     %[[V_13:[0-9]+]] = fir.load %arg0 : !fir.ref<f32>
   ! CHECK:     %[[V_14:[0-9]+]] = arith.addf %[[V_12]], %[[V_13]] {{.*}} : f32
-  ! CHECK:     %[[V_15:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_14]]) <{bit = 504 : i32}> : (f32) -> i1
+  ! CHECK:     %[[V_15:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_14]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f32) -> i1
   ! CHECK:     %[[V_16:[0-9]+]] = fir.convert %[[V_15]] : (i1) -> !fir.logical<4>
   ! CHECK:     %[[V_17:[0-9]+]] = fir.convert %[[V_16]] : (!fir.logical<4>) -> i1
   ! CHECK:     %[[V_18:[0-9]+]] = fir.call @_FortranAioOutputLogical(%{{.*}}, %[[V_17]]) {{.*}} : (!fir.ref<i8>, i1) -> i1
   print*, ieee_is_finite(x+x)
 
   ! CHECK:     %[[V_23:[0-9]+]] = fir.load %arg1 : !fir.ref<f64>
-  ! CHECK:     %[[V_24:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_23]]) <{bit = 504 : i32}> : (f64) -> i1
+  ! CHECK:     %[[V_24:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_23]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f64) -> i1
   ! CHECK:     %[[V_25:[0-9]+]] = fir.convert %[[V_24]] : (i1) -> !fir.logical<4>
   ! CHECK:     %[[V_26:[0-9]+]] = fir.convert %[[V_25]] : (!fir.logical<4>) -> i1
   ! CHECK:     %[[V_27:[0-9]+]] = fir.call @_FortranAioOutputLogical(%{{.*}}, %[[V_26]]) {{.*}} : (!fir.ref<i8>, i1) -> i1
@@ -32,7 +32,7 @@ subroutine is_finite_test(x, y)
   ! CHECK:     %[[V_32:[0-9]+]] = fir.load %arg1 : !fir.ref<f64>
   ! CHECK:     %[[V_33:[0-9]+]] = fir.load %arg1 : !fir.ref<f64>
   ! CHECK:     %[[V_34:[0-9]+]] = arith.addf %[[V_32]], %[[V_33]] {{.*}} : f64
-  ! CHECK:     %[[V_35:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_34]]) <{bit = 504 : i32}> : (f64) -> i1
+  ! CHECK:     %[[V_35:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_34]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 504 : i32}> : (f64) -> i1
   ! CHECK:     %[[V_36:[0-9]+]] = fir.convert %[[V_35]] : (i1) -> !fir.logical<4>
   ! CHECK:     %[[V_37:[0-9]+]] = fir.convert %[[V_36]] : (!fir.logical<4>) -> i1
   ! CHECK:     %[[V_38:[0-9]+]] = fir.call @_FortranAioOutputLogical(%{{.*}}, %[[V_37]]) {{.*}} : (!fir.ref<i8>, i1) -> i1

diff  --git a/flang/test/Lower/Intrinsics/ieee_is_normal.f90 b/flang/test/Lower/Intrinsics/ieee_is_normal.f90
index f9ab01881d250d..fef5b361448577 100644
--- a/flang/test/Lower/Intrinsics/ieee_is_normal.f90
+++ b/flang/test/Lower/Intrinsics/ieee_is_normal.f90
@@ -6,7 +6,7 @@ subroutine ieee_is_normal_f16(r)
   use ieee_arithmetic
   real(KIND=2) :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f16) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f16) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_f16
 
@@ -15,7 +15,7 @@ subroutine ieee_is_normal_bf16(r)
   use ieee_arithmetic
   real(KIND=3) :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (bf16) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (bf16) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_bf16
 
@@ -26,7 +26,7 @@ subroutine ieee_is_normal_f32(r)
   use ieee_arithmetic
   real :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f32) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f32) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_f32
 
@@ -35,7 +35,7 @@ subroutine ieee_is_normal_f64(r)
   use ieee_arithmetic
   real(KIND=8) :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f64) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f64) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_f64
 
@@ -44,7 +44,7 @@ subroutine ieee_is_normal_f80(r)
   use ieee_arithmetic
   real(KIND=10) :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f80) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f80) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_f80
 
@@ -53,6 +53,6 @@ subroutine ieee_is_normal_f128(r)
   use ieee_arithmetic
   real(KIND=16) :: r
   i = ieee_is_normal(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 360 : i32}> : (f128) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 360 : i32}> : (f128) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_normal_f128

diff  --git a/flang/test/Lower/Intrinsics/ieee_unordered.f90 b/flang/test/Lower/Intrinsics/ieee_unordered.f90
index 58b827348bfe03..e84738e2356099 100644
--- a/flang/test/Lower/Intrinsics/ieee_unordered.f90
+++ b/flang/test/Lower/Intrinsics/ieee_unordered.f90
@@ -44,8 +44,8 @@
 
 ! CHECK:     %[[V_40:[0-9]+]] = fir.load %[[V_2]] : !fir.ref<f128>
 ! CHECK:     %[[V_41:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f128>
-! CHECK:     %[[V_42:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_40]]) <{bit = 3 : i32}> : (f128) -> i1
-! CHECK:     %[[V_43:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_41]]) <{bit = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_42:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_40]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_43:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_41]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
 ! CHECK:     %[[V_44:[0-9]+]] = arith.ori %[[V_42]], %[[V_43]] : i1
 ! CHECK:     %[[V_45:[0-9]+]] = fir.convert %[[V_44]] : (i1) -> !fir.logical<4>
 ! CHECK:     %[[V_46:[0-9]+]] = fir.convert %[[V_45]] : (!fir.logical<4>) -> i1
@@ -53,8 +53,8 @@
 
 ! CHECK:     %[[V_48:[0-9]+]] = fir.load %[[V_2]] : !fir.ref<f128>
 ! CHECK:     %[[V_49:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f128>
-! CHECK:     %[[V_50:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_48]]) <{bit = 3 : i32}> : (f128) -> i1
-! CHECK:     %[[V_51:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_49]]) <{bit = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_50:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_48]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_51:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_49]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
 ! CHECK:     %[[V_52:[0-9]+]] = arith.ori %[[V_50]], %[[V_51]] : i1
 ! CHECK:     %[[V_53:[0-9]+]] = fir.convert %[[V_52]] : (i1) -> !fir.logical<4>
 ! CHECK:     %[[V_54:[0-9]+]] = fir.convert %[[V_53]] : (!fir.logical<4>) -> i1
@@ -62,8 +62,8 @@
 
 ! CHECK:     %[[V_56:[0-9]+]] = fir.load %[[V_3]] : !fir.ref<f128>
 ! CHECK:     %[[V_57:[0-9]+]] = fir.load %[[V_4]] : !fir.ref<f128>
-! CHECK:     %[[V_58:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_56]]) <{bit = 3 : i32}> : (f128) -> i1
-! CHECK:     %[[V_59:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_57]]) <{bit = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_58:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_56]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
+! CHECK:     %[[V_59:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_57]]) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
 ! CHECK:     %[[V_60:[0-9]+]] = arith.ori %[[V_58]], %[[V_59]] : i1
 ! CHECK:     %[[V_61:[0-9]+]] = fir.convert %[[V_60]] : (i1) -> !fir.logical<4>
 ! CHECK:     %[[V_62:[0-9]+]] = fir.convert %[[V_61]] : (!fir.logical<4>) -> i1

diff  --git a/flang/test/Lower/Intrinsics/isnan.f90 b/flang/test/Lower/Intrinsics/isnan.f90
index 700b2d1a67c656..10af98e7aa9186 100644
--- a/flang/test/Lower/Intrinsics/isnan.f90
+++ b/flang/test/Lower/Intrinsics/isnan.f90
@@ -5,7 +5,7 @@
 subroutine isnan_f32(r)
   real :: r
   i = isnan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f32) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f32) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine isnan_f32
 
@@ -14,7 +14,7 @@ subroutine ieee_is_nan_f32(r)
   use ieee_arithmetic
   real :: r
   i = ieee_is_nan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f32) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f32) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_nan_f32
 
@@ -22,7 +22,7 @@ end subroutine ieee_is_nan_f32
 subroutine isnan_f64(r)
   real(KIND=8) :: r
   i = isnan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f64) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f64) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine isnan_f64
 
@@ -31,7 +31,7 @@ subroutine ieee_is_nan_f64(r)
   use ieee_arithmetic
   real(KIND=8) :: r
   i = ieee_is_nan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f64) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f64) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_nan_f64
 
@@ -39,7 +39,7 @@ end subroutine ieee_is_nan_f64
 subroutine isnan_f80(r)
   real(KIND=10) :: r
   i = isnan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f80) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f80) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine isnan_f80
 
@@ -48,7 +48,7 @@ subroutine ieee_is_nan_f80(r)
   use ieee_arithmetic
   real(KIND=10) :: r
   i = ieee_is_nan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f80) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f80) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_nan_f80
 
@@ -56,7 +56,7 @@ end subroutine ieee_is_nan_f80
 subroutine isnan_f128(r)
   real(KIND=16) :: r
   i = isnan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f128) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine isnan_f128
 
@@ -65,6 +65,6 @@ subroutine ieee_is_nan_f128(r)
   use ieee_arithmetic
   real(KIND=16) :: r
   i = ieee_is_nan(r)
-  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 3 : i32}> : (f128) -> i1
+  ! CHECK: %[[l:.*]] = "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f128) -> i1
   ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4>
 end subroutine ieee_is_nan_f128

diff  --git a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
index eea16b4da6a690..b924f05e39f7ed 100644
--- a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
+++ b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h
@@ -49,9 +49,29 @@ class AttrConvertFastMathToLLVM {
 
   ArrayRef<NamedAttribute> getAttrs() const { return convertedAttr.getAttrs(); }
 
-private:
+protected:
   NamedAttrList convertedAttr;
 };
+
+/// Wrapper around AttrConvertFastMathToLLVM that also sets the "kinds"
+/// attribute to the bitmask specified in `Kinds`, which is used for converting
+/// operations that lower to llvm.is.fpclass.
+template <unsigned Kinds, typename SourceOp, typename TargetOp>
+class AttrConvertAddFpclassKinds
+    : public AttrConvertFastMathToLLVM<SourceOp, TargetOp> {
+public:
+  AttrConvertAddFpclassKinds(SourceOp op)
+      : AttrConvertFastMathToLLVM<SourceOp, TargetOp>(op) {
+    convertedAttr.set(
+        "kinds",
+        IntegerAttr::get(IntegerType::get(op.getContext(), 32), Kinds));
+  }
+
+  ArrayRef<NamedAttribute> getAttrs() const { return convertedAttr.getAttrs(); }
+
+protected:
+  using AttrConvertFastMathToLLVM<SourceOp, TargetOp>::convertedAttr;
+};
 } // namespace arith
 } // namespace mlir
 

diff  --git a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
index 2ffd49c5034e69..d7d297ce81c185 100644
--- a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
+++ b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
@@ -83,6 +83,20 @@ class Arith_FloatBinaryOp<string mnemonic, list<Trait> traits = []> :
                           attr-dict `:` type($result) }];
 }
 
+// Base class for floating point unary predicate operations.
+class Arith_FloatPredicateOp<string mnemonic, list<Trait> traits = []> :
+    Arith_Op<mnemonic,
+      !listconcat([DeclareOpInterfaceMethods<ArithFastMathInterface>, Pure,
+        TypesMatchWith<"result type has i1 element type and same shape as operands",
+        "operand", "result", "::getI1SameShape($_self)">], traits)>,
+    Arguments<(ins FloatLike:$operand,
+      DefaultValuedAttr<
+        Arith_FastMathAttr, "::mlir::arith::FastMathFlags::none">:$fastmath)>,
+    Results<(outs BoolLike:$result)> {
+  let assemblyFormat = [{ $operand (`fastmath` `` $fastmath^)?
+                          attr-dict `:` type($operand) }];
+}
+
 // Base class for arithmetic cast operations. Requires a single operand and
 // result. If either is a shaped type, then the other must be of the same shape.
 class Arith_CastOp<string mnemonic, TypeConstraint From, TypeConstraint To,
@@ -971,6 +985,22 @@ def Arith_RemFOp : Arith_FloatBinaryOp<"remf"> {
   let hasFolder = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// IsNanOp
+//===----------------------------------------------------------------------===//
+def Arith_IsNanOp : Arith_FloatPredicateOp<"is_nan"> {
+  let summary = "Returns true for IEEE NaN inputs";
+  let hasFolder = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// IsInfOp
+//===----------------------------------------------------------------------===//
+def Arith_IsInfOp : Arith_FloatPredicateOp<"is_inf"> {
+  let summary = "Returns true for infinite float inputs";
+  let hasFolder = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // ExtUIOp
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index 990af1d3d61fe0..88316bedcce8fc 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -120,17 +120,21 @@ def LLVM_AbsOp : LLVM_OneResultIntrOp<"abs", [], [0], [Pure]> {
   }];
 }
 
-def LLVM_IsFPClass : LLVM_OneResultIntrOp<"is.fpclass", [], [0], [Pure]> {
-  let arguments = (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$in, I32Attr:$bit);
+def LLVM_IsFPClass : LLVM_OneResultIntrOp<"is.fpclass", [], [0], [Pure],
+                                          /*requiresFastmath=*/1> {
+  let arguments = (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$in,
+                       I32Attr:$kinds,
+                       DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags);
   string mlirBuilder = [{
     auto op = $_builder.create<$_qualCppClassName>($_location,
-      $_resultType, $in, $_int_attr($bit));
-      $res = op;
+      $_resultType, $in, $_int_attr($kinds), nullptr);
+    moduleImport.setFastmathFlagsAttr(inst, op);
+    $res = op;
   }];
   string llvmBuilder = [{
     auto *inst = createIntrinsicCall(
       builder, llvm::Intrinsic::}] # llvmEnumName # [{,
-      {$in, builder.getInt32(op.getBit())},
+      {$in, builder.getInt32(op.getKinds())},
       }] # declTypes # [{);
     $res = inst;
   }];

diff  --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
index 3b4b6452a8ec31..d12fee3552dcf2 100644
--- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
+++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp
@@ -53,6 +53,18 @@ using FPToSIOpLowering =
     VectorConvertToLLVMPattern<arith::FPToSIOp, LLVM::FPToSIOp>;
 using FPToUIOpLowering =
     VectorConvertToLLVMPattern<arith::FPToUIOp, LLVM::FPToUIOp>;
+template <typename SourceOp, typename TargetOp>
+// FPClass bitmask for -inf (bit 2) and +inf (bit 9).
+using InfKinds =
+    arith::AttrConvertAddFpclassKinds<(1 << 2) | (1 << 9), SourceOp, TargetOp>;
+using IsInfLowering =
+    VectorConvertToLLVMPattern<arith::IsInfOp, LLVM::IsFPClass, InfKinds>;
+// FPClass bitmask for signalling NaN (bit 0) or quiet NaN (bit 1).
+template <typename SourceOp, typename TargetOp>
+using NanKinds =
+    arith::AttrConvertAddFpclassKinds<(1 << 0) | (1 << 1), SourceOp, TargetOp>;
+using IsNanLowering =
+    VectorConvertToLLVMPattern<arith::IsNanOp, LLVM::IsFPClass, NanKinds>;
 using MaxFOpLowering =
     VectorConvertToLLVMPattern<arith::MaxFOp, LLVM::MaxNumOp,
                                arith::AttrConvertFastMathToLLVM>;
@@ -465,6 +477,8 @@ void mlir::arith::populateArithToLLVMConversionPatterns(
     FPToUIOpLowering,
     IndexCastOpSILowering,
     IndexCastOpUILowering,
+    IsInfLowering,
+    IsNanLowering,
     MaxFOpLowering,
     MaxSIOpLowering,
     MaxUIOpLowering,

diff  --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
index f74c7e3490cd80..fe6e9de75c248c 100644
--- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
@@ -1094,6 +1094,8 @@ void mlir::arith::populateArithToSPIRVPatterns(
     spirv::ElementwiseOpPattern<arith::MulFOp, spirv::FMulOp>,
     spirv::ElementwiseOpPattern<arith::DivFOp, spirv::FDivOp>,
     spirv::ElementwiseOpPattern<arith::RemFOp, spirv::FRemOp>,
+    spirv::ElementwiseOpPattern<arith::IsNanOp, spirv::IsNanOp>,
+    spirv::ElementwiseOpPattern<arith::IsInfOp, spirv::IsInfOp>,
     TypeCastingOpPattern<arith::ExtUIOp, spirv::UConvertOp>, ExtUII1Pattern,
     TypeCastingOpPattern<arith::ExtSIOp, spirv::SConvertOp>, ExtSII1Pattern,
     TypeCastingOpPattern<arith::ExtFOp, spirv::FConvertOp>,

diff  --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index eb73787b354778..482198771c3f6a 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -1109,6 +1109,42 @@ OpFoldResult arith::RemFOp::fold(FoldAdaptor adaptor) {
                                       });
 }
 
+static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value) {
+  auto boolAttr = BoolAttr::get(ctx, value);
+  ShapedType shapedType = llvm::dyn_cast_or_null<ShapedType>(type);
+  if (!shapedType)
+    return boolAttr;
+  return DenseElementsAttr::get(shapedType, boolAttr);
+}
+
+//===----------------------------------------------------------------------===//
+// IsNanOp
+//===----------------------------------------------------------------------===//
+OpFoldResult IsNanOp::fold(FoldAdaptor adaptor) {
+  if (bitEnumContainsAll(getFastmath(), FastMathFlags::nnan))
+    return getBoolAttribute(getType(), getContext(), false);
+  return constFoldCastOp<FloatAttr, IntegerAttr>(
+      adaptor.getOperands(), getType(),
+      [](const APFloat &x, bool &success) -> APInt {
+        success = true;
+        return APInt(1, x.isNaN());
+      });
+}
+
+//===----------------------------------------------------------------------===//
+// IsInfOp
+//===----------------------------------------------------------------------===//
+OpFoldResult IsInfOp::fold(FoldAdaptor adaptor) {
+  if (bitEnumContainsAll(getFastmath(), FastMathFlags::ninf))
+    return getBoolAttribute(getType(), getContext(), false);
+  return constFoldCastOp<FloatAttr, IntegerAttr>(
+      adaptor.getOperands(), getType(),
+      [](const APFloat &x, bool &success) -> APInt {
+        success = true;
+        return APInt(1, x.isInfinity());
+      });
+}
+
 //===----------------------------------------------------------------------===//
 // Utility functions for verifying cast ops
 //===----------------------------------------------------------------------===//
@@ -1659,14 +1695,6 @@ static bool applyCmpPredicateToEqualOperands(arith::CmpIPredicate predicate) {
   llvm_unreachable("unknown cmpi predicate kind");
 }
 
-static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value) {
-  auto boolAttr = BoolAttr::get(ctx, value);
-  ShapedType shapedType = llvm::dyn_cast_or_null<ShapedType>(type);
-  if (!shapedType)
-    return boolAttr;
-  return DenseElementsAttr::get(shapedType, boolAttr);
-}
-
 static std::optional<int64_t> getIntegerWidth(Type t) {
   if (auto intType = llvm::dyn_cast<IntegerType>(t)) {
     return intType.getWidth();

diff  --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
index 9810d2923da40a..092ff52319a98e 100644
--- a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp
@@ -179,8 +179,7 @@ struct MaxMinFOpConverter : public OpRewritePattern<OpTy> {
     Value select = rewriter.create<arith::SelectOp>(loc, cmp, lhs, rhs);
 
     // Handle the case where rhs is NaN: 'isNaN(rhs) ? rhs : select'.
-    Value isNaN = rewriter.create<arith::CmpFOp>(loc, arith::CmpFPredicate::UNO,
-                                                 rhs, rhs);
+    Value isNaN = rewriter.create<arith::IsNanOp>(loc, rhs, op.getFastmath());
     rewriter.replaceOpWithNewOp<arith::SelectOp>(op, isNaN, rhs, select);
     return success();
   }

diff  --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
index 1788232aee40c8..db9df579820d69 100644
--- a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
+++ b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir
@@ -71,6 +71,28 @@ func.func @ops(f32, f32, i32, i32, f64) -> (f32, i32) {
   return %0, %4 : f32, i32
 }
 
+// CHECK-LABEL: @float_pred_ops
+func.func @float_pred_ops(%arg0: f32) {
+  // CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 516 : i32}> : (f32) -> i1
+  arith.is_inf %arg0 : f32
+  // CHECK-NEXT: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<nnan>, kinds = 516 : i32}> : (f32) -> i1
+  arith.is_inf %arg0 fastmath <nnan> : f32
+  // CHECK-NEXT: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (f32) -> i1
+  arith.is_nan %arg0 : f32
+  // CHECK-NEXT: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<ninf>, kinds = 3 : i32}> : (f32) -> i1
+  arith.is_nan %arg0 fastmath <ninf> : f32
+  return
+}
+
+// CHECK-LABEL: @vector_float_pred_ops
+func.func @vector_float_pred_ops(%arg0: vector<4xf32>) {
+  // CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 516 : i32}> : (vector<4xf32>) -> vector<4xi1>
+  arith.is_inf %arg0 : vector<4xf32>
+  // CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 3 : i32}> : (vector<4xf32>) -> vector<4xi1>
+  arith.is_nan %arg0 : vector<4xf32>
+  return
+}
+
 // Checking conversion of index types to integers using i1, assuming no target
 // system would have a 1-bit address space.  Otherwise, we would have had to
 // make this test dependent on the pointer size on the target system.

diff  --git a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
index d70df982c366ad..06b5cccd5f41e1 100644
--- a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
+++ b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
@@ -169,6 +169,16 @@ func.func @float32_binary_scalar(%lhs: f32, %rhs: f32) {
   return
 }
 
+// Check float predicate operation conversions
+// CHECK-LABEL: @float32_predicate_scalar
+func.func @float32_predicate_scalar(%arg0 : f32) {
+  // CHECK: spirv.IsNan %{{.*}}: f32
+  %0 = arith.is_nan %arg0 : f32
+  // CHECK: spirv.IsInf %{{.*}}: f32
+  %1 = arith.is_inf %arg0 : f32
+  return
+}
+
 // Check int vector types.
 // CHECK-LABEL: @int_vector234
 func.func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) {

diff  --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir
index 5b392fe9cf58a0..b65f8d3b0e01e4 100644
--- a/mlir/test/Dialect/Arith/canonicalize.mlir
+++ b/mlir/test/Dialect/Arith/canonicalize.mlir
@@ -2567,3 +2567,78 @@ func.func @foldOrXor6(%arg0: index) -> index {
   %2 = arith.ori %arg0, %1 : index
   return %2 : index
 }
+
+// -----
+
+// CHECK-LABEL: @foldIsNanFastmath
+//  CHECK-SAME: (%[[ARG:.+]]: f32)
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldIsNanFastmath(%arg0: f32) -> i1 {
+  %0 = arith.is_nan %arg0 fastmath <nnan> : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: @foldIsNan
+//      CHECK:   %[[TRUE:.+]] = arith.constant true
+//      CHECK:   return %[[TRUE]]
+func.func @foldIsNan() -> i1 {
+  %cNan = arith.constant 0x7FFFFFFF : f32
+  %0 = arith.is_nan %cNan : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: @foldNanIsNotNanWithFastmath
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldNanIsNotNanWithFastmath() -> i1 {
+  %cNan = arith.constant 0x7FFFFFFF : f32
+  %0 = arith.is_nan %cNan fastmath<nnan> : f32
+  func.return %0 : i1
+}
+
+
+// CHECK-LABEL: @foldIsNotNan
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldIsNotNan() -> i1 {
+  %cNan = arith.constant 1.0 : f32
+  %0 = arith.is_nan %cNan : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: @foldIsInfFastmath
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldIsInfFastmath(%arg0: f32) -> i1 {
+  %0 = arith.is_inf %arg0 fastmath <ninf> : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: @foldIsInf
+//      CHECK:   %[[TRUE:.+]] = arith.constant true
+//      CHECK:   return %[[TRUE]]
+func.func @foldIsInf() -> i1 {
+  %cInf = arith.constant 0x7F800000 : f32
+  %0 = arith.is_inf %cInf : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: @foldInfIsNotInfWithFastmath
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldInfIsNotInfWithFastmath() -> i1 {
+  %cInf = arith.constant 0x7F800000 : f32
+  %0 = arith.is_inf %cInf fastmath<ninf> : f32
+  func.return %0 : i1
+}
+
+
+// CHECK-LABEL: @foldIsNotInf
+//      CHECK:   %[[FALSE:.+]] = arith.constant false
+//      CHECK:   return %[[FALSE]]
+func.func @foldIsNotInf() -> i1 {
+  %cInf = arith.constant 1.0 : f32
+  %0 = arith.is_inf %cInf : f32
+  func.return %0 : i1
+}

diff  --git a/mlir/test/Dialect/Arith/expand-ops.mlir b/mlir/test/Dialect/Arith/expand-ops.mlir
index 9f63c941353631..e8d98a0736e8ed 100644
--- a/mlir/test/Dialect/Arith/expand-ops.mlir
+++ b/mlir/test/Dialect/Arith/expand-ops.mlir
@@ -184,7 +184,7 @@ func.func @maxf(%a: f32, %b: f32) -> f32 {
 // CHECK-SAME: %[[LHS:.*]]: f32, %[[RHS:.*]]: f32)
 // CHECK-NEXT: %[[CMP:.*]] = arith.cmpf ugt, %[[LHS]], %[[RHS]] : f32
 // CHECK-NEXT: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LHS]], %[[RHS]] : f32
-// CHECK-NEXT: %[[IS_NAN:.*]] = arith.cmpf uno, %[[RHS]], %[[RHS]] : f32
+// CHECK-NEXT: %[[IS_NAN:.*]] = arith.is_nan %[[RHS]] : f32
 // CHECK-NEXT: %[[RESULT:.*]] = arith.select %[[IS_NAN]], %[[RHS]], %[[SELECT]] : f32
 // CHECK-NEXT: return %[[RESULT]] : f32
 
@@ -198,7 +198,7 @@ func.func @maxf_vector(%a: vector<4xf16>, %b: vector<4xf16>) -> vector<4xf16> {
 // CHECK-SAME: %[[LHS:.*]]: vector<4xf16>, %[[RHS:.*]]: vector<4xf16>)
 // CHECK-NEXT: %[[CMP:.*]] = arith.cmpf ugt, %[[LHS]], %[[RHS]] : vector<4xf16>
 // CHECK-NEXT: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LHS]], %[[RHS]]
-// CHECK-NEXT: %[[IS_NAN:.*]] = arith.cmpf uno, %[[RHS]], %[[RHS]] : vector<4xf16>
+// CHECK-NEXT: %[[IS_NAN:.*]] = arith.is_nan  %[[RHS]] : vector<4xf16>
 // CHECK-NEXT: %[[RESULT:.*]] = arith.select %[[IS_NAN]], %[[RHS]], %[[SELECT]]
 // CHECK-NEXT: return %[[RESULT]] : vector<4xf16>
 
@@ -213,7 +213,7 @@ func.func @minf(%a: f32, %b: f32) -> f32 {
 // CHECK-SAME: %[[LHS:.*]]: f32, %[[RHS:.*]]: f32)
 // CHECK-NEXT: %[[CMP:.*]] = arith.cmpf ult, %[[LHS]], %[[RHS]] : f32
 // CHECK-NEXT: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LHS]], %[[RHS]] : f32
-// CHECK-NEXT: %[[IS_NAN:.*]] = arith.cmpf uno, %[[RHS]], %[[RHS]] : f32
+// CHECK-NEXT: %[[IS_NAN:.*]] = arith.is_nan %[[RHS]] : f32
 // CHECK-NEXT: %[[RESULT:.*]] = arith.select %[[IS_NAN]], %[[RHS]], %[[SELECT]] : f32
 // CHECK-NEXT: return %[[RESULT]] : f32
 

diff  --git a/mlir/test/Dialect/Arith/ops.mlir b/mlir/test/Dialect/Arith/ops.mlir
index faa138a170ddfa..2e3af34169b85e 100644
--- a/mlir/test/Dialect/Arith/ops.mlir
+++ b/mlir/test/Dialect/Arith/ops.mlir
@@ -577,6 +577,30 @@ func.func @test_remf_scalable_vector(%arg0 : vector<[8]xf64>, %arg1 : vector<[8]
   return %0 : vector<[8]xf64>
 }
 
+// CHECK-LABEL: test_is_nan
+func.func @test_is_nan(%arg0 : f32) -> i1 {
+  %0 = arith.is_nan %arg0 : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: test_is_nan_vector
+func.func @test_is_nan_vector(%arg0 : vector<2x2xf32>) -> vector<2x2xi1> {
+  %0 = arith.is_nan %arg0 : vector<2x2xf32>
+  func.return %0 : vector<2x2xi1>
+}
+
+// CHECK-LABEL: test_is_inf
+func.func @test_is_inf(%arg0 : f32) -> i1 {
+  %0 = arith.is_inf %arg0 : f32
+  func.return %0 : i1
+}
+
+// CHECK-LABEL: test_is_inf_vector
+func.func @test_is_inf_vector(%arg0 : vector<2x2xf32>) -> vector<2x2xi1> {
+  %0 = arith.is_inf %arg0 : vector<2x2xf32>
+  func.return %0 : vector<2x2xi1>
+}
+
 // CHECK-LABEL: test_extui
 func.func @test_extui(%arg0 : i32) -> i64 {
   %0 = arith.extui %arg0 : i32 to i64

diff  --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll
index 543de93f2f44c0..5ebe98991687a8 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll
@@ -17,9 +17,9 @@ define void @fmuladd_test(float %0, float %1, <8 x float> %2, ptr %3) {
 
 ; CHECK-LABEL:  llvm.func @fpclass_test
 define void @fpclass_test(float %0, <8 x float> %1) {
-  ; CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 0 : i32}> : (f32) -> i1
+  ; CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 0 : i32}> : (f32) -> i1
   %3 = call i1 @llvm.is.fpclass.f32(float %0, i32 0)
-  ; CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{bit = 1 : i32}> : (vector<8xf32>) -> vector<8xi1>
+  ; CHECK: "llvm.intr.is.fpclass"(%{{.*}}) <{fastmathFlags = #llvm.fastmath<none>, kinds = 1 : i32}> : (vector<8xf32>) -> vector<8xi1>
   %4 = call <8 x i1> @llvm.is.fpclass.v8f32(<8 x float> %1, i32 1)
   ret void
 }

diff  --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
index d666017f6aa248..9dfcacd7dedd38 100644
--- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir
@@ -18,7 +18,7 @@ llvm.func @intrinsics(%arg0: f32, %arg1: f32, %arg2: vector<8xf32>, %arg3: !llvm
 // CHECK-LABEL: @fpclass_test
 llvm.func @fpclass_test(%arg0: f32) -> i1 {
   // CHECK: call i1 @llvm.is.fpclass
-  %0 = "llvm.intr.is.fpclass"(%arg0) <{bit = 0 : i32 }>: (f32) -> i1
+  %0 = "llvm.intr.is.fpclass"(%arg0) <{fastmathFlags = #llvm.fastmath<nnan>, kinds = 3 : i32 }>: (f32) -> i1
   llvm.return %0 : i1
 }
 


        


More information about the flang-commits mailing list