; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool igc_opt
;=========================== begin_copyright_notice ============================
;
; Copyright (C) 2026 Intel Corporation
;
; SPDX-License-Identifier: MIT
;
;============================ end_copyright_notice =============================

; REQUIRES: llvm-15-plus
; RUN: igc_opt -igc-replace-unsupported-intrinsics -verify -S < %s | FileCheck %s --check-prefixes=CHECK,%if llvm-22-plus %{CHECK-LLVM22%} %else %{CHECK-PRE22%}

; uncomment for correctness checks using alive-tv
; UN: igc_opt -igc-replace-unsupported-intrinsics -verify -S < %s -o %t
; UN: cat %t | sed 's/@test/@tgt_test/' > %t.alive
; UN: cat %s | sed 's/@test/@src_test/' | sed 's/declare.*//' >> %t.alive
; UN: alive-tv %t.alive | grep ' 0 incorrect transformations'

; The test is ported from LLVM-SPIRV-Translator, which in turn was ported from the LLVM testsuite.

; check for no mask
define i1 @test_class_no_mask_f32(float %x) {
; CHECK-LABEL: @test_class_no_mask_f32(
; CHECK-NEXT:    ret i1 false
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 0)
  ret i1 %val
}

; check for full mask
define i1 @test_class_full_mask_f32(float %x) {
; CHECK-LABEL: @test_class_full_mask_f32(
; CHECK-NEXT:    ret i1 true
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 1023)
  ret i1 %val
}

; check for nan
define i1 @test_class_isnan_f32(float %x) {
; CHECK-LABEL: @test_class_isnan_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], 2139095040
; CHECK-NEXT:    ret i1 [[TMP3]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 3)
  ret i1 %val
}

define <2 x i1> @test_class_isnan_v2f32(<2 x float> %x) {
; CHECK-LABEL: @test_class_isnan_v2f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32>
; CHECK-PRE22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 2147483647, i32 2147483647>
; CHECK-LLVM22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 2147483647)
; CHECK-PRE22-NEXT:    [[TMP3:%.*]] = icmp ugt <2 x i32> [[TMP2]], <i32 2139095040, i32 2139095040>
; CHECK-LLVM22-NEXT:    [[TMP3:%.*]] = icmp ugt <2 x i32> [[TMP2]], splat (i32 2139095040)
; CHECK-NEXT:    ret <2 x i1> [[TMP3]]
;
  %val = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %x, i32 3)
  ret <2 x i1> %val
}

; check for snan
define i1 @test_class_issnan_f32(float %x) {
; CHECK-LABEL: @test_class_issnan_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], 2139095040
; CHECK-NEXT:    [[TMP4:%.*]] = icmp uge i32 [[TMP2]], 2143289344
; CHECK-NEXT:    [[TMP5:%.*]] = xor i1 [[TMP4]], true
; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP5]]
; CHECK-NEXT:    ret i1 [[TMP6]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 1)
  ret i1 %val
}

; check for qnan
define i1 @test_class_isqnan_f32(float %x) {
; CHECK-LABEL: @test_class_isqnan_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], 2139095040
; CHECK-NEXT:    [[TMP4:%.*]] = icmp uge i32 [[TMP2]], 2143289344
; CHECK-NEXT:    ret i1 [[TMP4]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 2)
  ret i1 %val
}

; check for inf
define i1 @test_class_is_inf_f32(float %x) {
; CHECK-LABEL: @test_class_is_inf_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT:    [[TMP4:%.*]] = fcmp oeq float [[TMP3]], 0x7FF0000000000000
; CHECK-NEXT:    ret i1 [[TMP4]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 516)
  ret i1 %val
}

define <2 x i1> @test_class_is_inf_v2f32(<2 x float> %x) {
; CHECK-LABEL: @test_class_is_inf_v2f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32>
; CHECK-PRE22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 2147483647, i32 2147483647>
; CHECK-LLVM22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 2147483647)
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float>
; CHECK-PRE22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], <float 0x7FF0000000000000, float 0x7FF0000000000000>
; CHECK-LLVM22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], splat (float 0x7FF0000000000000)
; CHECK-NEXT:    ret <2 x i1> [[TMP4]]
;
  %val = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %x, i32 516)
  ret <2 x i1> %val
}

; check for pos inf
define i1 @test_class_is_pinf_f32(float %x) {
; CHECK-LABEL: @test_class_is_pinf_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT:    [[TMP4:%.*]] = fcmp oeq float [[TMP3]], 0x7FF0000000000000
; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TMP6]], true
; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP4]]
; CHECK-NEXT:    ret i1 [[TMP8]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 512)
  ret i1 %val
}

define <2 x i1> @test_class_is_pinf_v2f32(<2 x float> %x) {
; CHECK-LABEL: @test_class_is_pinf_v2f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32>
; CHECK-PRE22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 2147483647, i32 2147483647>
; CHECK-LLVM22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 2147483647)
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float>
; CHECK-PRE22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], <float 0x7FF0000000000000, float 0x7FF0000000000000>
; CHECK-LLVM22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], splat (float 0x7FF0000000000000)
; CHECK-PRE22-NEXT:    [[TMP5:%.*]] = and <2 x i32> [[TMP1]], <i32 -2147483648, i32 -2147483648>
; CHECK-LLVM22-NEXT:    [[TMP5:%.*]] = and <2 x i32> [[TMP1]], splat (i32 -2147483648)
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne <2 x i32> [[TMP5]], zeroinitializer
; CHECK-PRE22-NEXT:    [[TMP7:%.*]] = xor <2 x i1> [[TMP6]], <i1 true, i1 true>
; CHECK-LLVM22-NEXT:    [[TMP7:%.*]] = xor <2 x i1> [[TMP6]], splat (i1 true)
; CHECK-NEXT:    [[TMP8:%.*]] = and <2 x i1> [[TMP7]], [[TMP4]]
; CHECK-NEXT:    ret <2 x i1> [[TMP8]]
;
  %val = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %x, i32 512)
  ret <2 x i1> %val
}

; check for neg inf
define i1 @test_class_is_ninf_f32(float %x) {
; CHECK-LABEL: @test_class_is_ninf_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT:    [[TMP4:%.*]] = fcmp oeq float [[TMP3]], 0x7FF0000000000000
; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
; CHECK-NEXT:    [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP4]]
; CHECK-NEXT:    ret i1 [[TMP7]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 4)
  ret i1 %val
}

define <2 x i1> @test_class_is_ninf_v2f32(<2 x float> %x) {
; CHECK-LABEL: @test_class_is_ninf_v2f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x float> [[X:%.*]] to <2 x i32>
; CHECK-PRE22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 2147483647, i32 2147483647>
; CHECK-LLVM22-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 2147483647)
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float>
; CHECK-PRE22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], <float 0x7FF0000000000000, float 0x7FF0000000000000>
; CHECK-LLVM22-NEXT:    [[TMP4:%.*]] = fcmp oeq <2 x float> [[TMP3]], splat (float 0x7FF0000000000000)
; CHECK-PRE22-NEXT:    [[TMP5:%.*]] = and <2 x i32> [[TMP1]], <i32 -2147483648, i32 -2147483648>
; CHECK-LLVM22-NEXT:    [[TMP5:%.*]] = and <2 x i32> [[TMP1]], splat (i32 -2147483648)
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne <2 x i32> [[TMP5]], zeroinitializer
; CHECK-NEXT:    [[TMP7:%.*]] = and <2 x i1> [[TMP6]], [[TMP4]]
; CHECK-NEXT:    ret <2 x i1> [[TMP7]]
;
  %val = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %x, i32 4)
  ret <2 x i1> %val
}

; check for normal
define i1 @test_class_is_normal(float %x) {
; CHECK-LABEL: @test_class_is_normal(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], 8388608
; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 2130706432
; CHECK-NEXT:    ret i1 [[TMP4]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 264)
  ret i1 %val
}

; check for pos normal
define i1 @test_constant_class_pnormal() {
; CHECK-LABEL: @test_constant_class_pnormal(
; CHECK-NEXT:    ret i1 true
;
  %val = call i1 @llvm.is.fpclass.f64(double 1.000000e+00, i32 256)
  ret i1 %val
}
; check for neg normal
define i1 @test_constant_class_nnormal() {
; CHECK-LABEL: @test_constant_class_nnormal(
; CHECK-NEXT:    ret i1 false
;
  %val = call i1 @llvm.is.fpclass.f64(double 1.000000e+00, i32 8)
  ret i1 %val
}

; check for subnormal
define i1 @test_class_subnormal(float %arg) {
; CHECK-LABEL: @test_class_subnormal(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], 1
; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 8388607
; CHECK-NEXT:    ret i1 [[TMP4]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
  ret i1 %val
}

; check for pos subnormal
define i1 @test_class_possubnormal(float %arg) {
; CHECK-LABEL: @test_class_possubnormal(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], 1
; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 8388607
; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TMP6]], true
; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP4]]
; CHECK-NEXT:    ret i1 [[TMP8]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 128)
  ret i1 %val
}

; check for neg subnormal
define i1 @test_class_negsubnormal(float %arg) {
; CHECK-LABEL: @test_class_negsubnormal(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 [[TMP2]], 1
; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 [[TMP3]], 8388607
; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
; CHECK-NEXT:    [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP4]]
; CHECK-NEXT:    ret i1 [[TMP7]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 16)
  ret i1 %val
}

; check for zero
define i1 @test_class_zero(float %arg) {
; CHECK-LABEL: @test_class_zero(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT:    ret i1 [[TMP3]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 96)
  ret i1 %val
}

; check for pos zero
define i1 @test_class_poszero(float %arg) {
; CHECK-LABEL: @test_class_poszero(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP4]], 0
; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TMP5]], true
; CHECK-NEXT:    [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP3]]
; CHECK-NEXT:    ret i1 [[TMP7]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 64)
  ret i1 %val
}

; check for neg zero
define i1 @test_class_negzero(float %arg) {
; CHECK-LABEL: @test_class_negzero(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[ARG:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP4]], 0
; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP3]]
; CHECK-NEXT:    ret i1 [[TMP6]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %arg, i32 32)
  ret i1 %val
}

; check for neg inf or nan
define i1 @test_class_is_ninf_or_nan_f32(float %x) {
; CHECK-LABEL: @test_class_is_ninf_or_nan_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], 2139095040
; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT:    [[TMP5:%.*]] = fcmp oeq float [[TMP4]], 0x7FF0000000000000
; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[TMP1]], -2147483648
; CHECK-NEXT:    [[TMP7:%.*]] = icmp ne i32 [[TMP6]], 0
; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP5]]
; CHECK-NEXT:    [[TMP9:%.*]] = or i1 [[TMP3]], [[TMP8]]
; CHECK-NEXT:    ret i1 [[TMP9]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 7)
  ret i1 %val
}

; check for neg inf, pos normal, neg subnormal pos zero and snan scalar
define i1 @test_class_neginf_posnormal_negsubnormal_poszero_snan_f64(double %arg) {
; CHECK-LABEL: @test_class_neginf_posnormal_negsubnormal_poszero_snan_f64(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast double [[ARG:%.*]] to i64
; CHECK-NEXT:    [[TMP2:%.*]] = and i64 [[TMP1]], 9223372036854775807
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i64 [[TMP2]], 9218868437227405312
; CHECK-NEXT:    [[TMP4:%.*]] = icmp uge i64 [[TMP2]], 9221120237041090560
; CHECK-NEXT:    [[TMP5:%.*]] = xor i1 [[TMP4]], true
; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP5]]
; CHECK-NEXT:    [[TMP7:%.*]] = bitcast i64 [[TMP2]] to double
; CHECK-NEXT:    [[TMP8:%.*]] = fcmp oeq double [[TMP7]], 0x7FF0000000000000
; CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP1]], -9223372036854775808
; CHECK-NEXT:    [[TMP10:%.*]] = icmp ne i64 [[TMP9]], 0
; CHECK-NEXT:    [[TMP11:%.*]] = and i1 [[TMP10]], [[TMP8]]
; CHECK-NEXT:    [[TMP12:%.*]] = or i1 [[TMP6]], [[TMP11]]
; CHECK-NEXT:    [[TMP13:%.*]] = sub i64 [[TMP2]], 4503599627370496
; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult i64 [[TMP13]], 9214364837600034816
; CHECK-NEXT:    [[TMP15:%.*]] = xor i1 [[TMP10]], true
; CHECK-NEXT:    [[TMP16:%.*]] = and i1 [[TMP15]], [[TMP14]]
; CHECK-NEXT:    [[TMP17:%.*]] = or i1 [[TMP12]], [[TMP16]]
; CHECK-NEXT:    [[TMP18:%.*]] = sub i64 [[TMP2]], 1
; CHECK-NEXT:    [[TMP19:%.*]] = icmp ult i64 [[TMP18]], 4503599627370495
; CHECK-NEXT:    [[TMP20:%.*]] = and i1 [[TMP10]], [[TMP19]]
; CHECK-NEXT:    [[TMP21:%.*]] = or i1 [[TMP17]], [[TMP20]]
; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP2]], 0
; CHECK-NEXT:    [[TMP23:%.*]] = and i1 [[TMP15]], [[TMP22]]
; CHECK-NEXT:    [[TMP24:%.*]] = or i1 [[TMP21]], [[TMP23]]
; CHECK-NEXT:    ret i1 [[TMP24]]
;
  %val = call i1 @llvm.is.fpclass.f64(double %arg, i32 341)
  ret i1 %val
}

; check for neg inf, pos normal, neg subnormal pos zero and snan scalar bfloat
define i1 @test_class_neginf_posnormal_negsubnormal_poszero_snan_bf16(bfloat %arg) {
; CHECK-LABEL: @test_class_neginf_posnormal_negsubnormal_poszero_snan_bf16(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast bfloat [[ARG:%.*]] to i16
; CHECK-NEXT:    [[TMP2:%.*]] = and i16 [[TMP1]], 32767
; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i16 [[TMP2]], 32640
; CHECK-NEXT:    [[TMP4:%.*]] = icmp uge i16 [[TMP2]], 32704
; CHECK-NEXT:    [[TMP5:%.*]] = xor i1 [[TMP4]], true
; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP5]]
; CHECK-NEXT:    [[TMP7:%.*]] = bitcast i16 [[TMP2]] to bfloat
; CHECK-NEXT:    [[TMP8:%.*]] = fcmp oeq bfloat [[TMP7]], 0xR7F80
; CHECK-NEXT:    [[TMP9:%.*]] = and i16 [[TMP1]], -32768
; CHECK-NEXT:    [[TMP10:%.*]] = icmp ne i16 [[TMP9]], 0
; CHECK-NEXT:    [[TMP11:%.*]] = and i1 [[TMP10]], [[TMP8]]
; CHECK-NEXT:    [[TMP12:%.*]] = or i1 [[TMP6]], [[TMP11]]
; CHECK-NEXT:    [[TMP13:%.*]] = sub i16 [[TMP2]], 128
; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult i16 [[TMP13]], 32512
; CHECK-NEXT:    [[TMP15:%.*]] = xor i1 [[TMP10]], true
; CHECK-NEXT:    [[TMP16:%.*]] = and i1 [[TMP15]], [[TMP14]]
; CHECK-NEXT:    [[TMP17:%.*]] = or i1 [[TMP12]], [[TMP16]]
; CHECK-NEXT:    [[TMP18:%.*]] = sub i16 [[TMP2]], 1
; CHECK-NEXT:    [[TMP19:%.*]] = icmp ult i16 [[TMP18]], 127
; CHECK-NEXT:    [[TMP20:%.*]] = and i1 [[TMP10]], [[TMP19]]
; CHECK-NEXT:    [[TMP21:%.*]] = or i1 [[TMP17]], [[TMP20]]
; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i16 [[TMP2]], 0
; CHECK-NEXT:    [[TMP23:%.*]] = and i1 [[TMP15]], [[TMP22]]
; CHECK-NEXT:    [[TMP24:%.*]] = or i1 [[TMP21]], [[TMP23]]
; CHECK-NEXT:    ret i1 [[TMP24]]
;
  %val = call i1 @llvm.is.fpclass.bf16(bfloat %arg, i32 341)
  ret i1 %val
}

; check for neg inf, pos normal, neg subnormal pos zero and snan vector
define <2 x i1> @test_class_neginf_posnormal_negsubnormal_poszero_snan_v2f16(<2 x half> %arg) {
; CHECK-LABEL: @test_class_neginf_posnormal_negsubnormal_poszero_snan_v2f16(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x half> [[ARG:%.*]] to <2 x i16>
; CHECK-PRE22-NEXT:    [[TMP2:%.*]] = and <2 x i16> [[TMP1]], <i16 32767, i16 32767>
; CHECK-LLVM22-NEXT:    [[TMP2:%.*]] = and <2 x i16> [[TMP1]], splat (i16 32767)
; CHECK-PRE22-NEXT:    [[TMP3:%.*]] = icmp ugt <2 x i16> [[TMP2]], <i16 31744, i16 31744>
; CHECK-LLVM22-NEXT:    [[TMP3:%.*]] = icmp ugt <2 x i16> [[TMP2]], splat (i16 31744)
; CHECK-PRE22-NEXT:    [[TMP4:%.*]] = icmp uge <2 x i16> [[TMP2]], <i16 32256, i16 32256>
; CHECK-LLVM22-NEXT:    [[TMP4:%.*]] = icmp uge <2 x i16> [[TMP2]], splat (i16 32256)
; CHECK-PRE22-NEXT:    [[TMP5:%.*]] = xor <2 x i1> [[TMP4]], <i1 true, i1 true>
; CHECK-LLVM22-NEXT:    [[TMP5:%.*]] = xor <2 x i1> [[TMP4]], splat (i1 true)
; CHECK-NEXT:    [[TMP6:%.*]] = and <2 x i1> [[TMP3]], [[TMP5]]
; CHECK-NEXT:    [[TMP7:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half>
; CHECK-PRE22-NEXT:    [[TMP8:%.*]] = fcmp oeq <2 x half> [[TMP7]], <half 0xH7C00, half 0xH7C00>
; CHECK-LLVM22-NEXT:    [[TMP8:%.*]] = fcmp oeq <2 x half> [[TMP7]], splat (half 0xH7C00)
; CHECK-PRE22-NEXT:    [[TMP9:%.*]] = and <2 x i16> [[TMP1]], <i16 -32768, i16 -32768>
; CHECK-LLVM22-NEXT:    [[TMP9:%.*]] = and <2 x i16> [[TMP1]], splat (i16 -32768)
; CHECK-NEXT:    [[TMP10:%.*]] = icmp ne <2 x i16> [[TMP9]], zeroinitializer
; CHECK-NEXT:    [[TMP11:%.*]] = and <2 x i1> [[TMP10]], [[TMP8]]
; CHECK-NEXT:    [[TMP12:%.*]] = or <2 x i1> [[TMP6]], [[TMP11]]
; CHECK-PRE22-NEXT:    [[TMP13:%.*]] = sub <2 x i16> [[TMP2]], <i16 1024, i16 1024>
; CHECK-LLVM22-NEXT:    [[TMP13:%.*]] = sub <2 x i16> [[TMP2]], splat (i16 1024)
; CHECK-PRE22-NEXT:    [[TMP14:%.*]] = icmp ult <2 x i16> [[TMP13]], <i16 30720, i16 30720>
; CHECK-LLVM22-NEXT:    [[TMP14:%.*]] = icmp ult <2 x i16> [[TMP13]], splat (i16 30720)
; CHECK-PRE22-NEXT:    [[TMP15:%.*]] = xor <2 x i1> [[TMP10]], <i1 true, i1 true>
; CHECK-LLVM22-NEXT:    [[TMP15:%.*]] = xor <2 x i1> [[TMP10]], splat (i1 true)
; CHECK-NEXT:    [[TMP16:%.*]] = and <2 x i1> [[TMP15]], [[TMP14]]
; CHECK-NEXT:    [[TMP17:%.*]] = or <2 x i1> [[TMP12]], [[TMP16]]
; CHECK-PRE22-NEXT:    [[TMP18:%.*]] = sub <2 x i16> [[TMP2]], <i16 1, i16 1>
; CHECK-LLVM22-NEXT:    [[TMP18:%.*]] = sub <2 x i16> [[TMP2]], splat (i16 1)
; CHECK-PRE22-NEXT:    [[TMP19:%.*]] = icmp ult <2 x i16> [[TMP18]], <i16 1023, i16 1023>
; CHECK-LLVM22-NEXT:    [[TMP19:%.*]] = icmp ult <2 x i16> [[TMP18]], splat (i16 1023)
; CHECK-NEXT:    [[TMP20:%.*]] = and <2 x i1> [[TMP10]], [[TMP19]]
; CHECK-NEXT:    [[TMP21:%.*]] = or <2 x i1> [[TMP17]], [[TMP20]]
; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq <2 x i16> [[TMP2]], zeroinitializer
; CHECK-NEXT:    [[TMP23:%.*]] = and <2 x i1> [[TMP15]], [[TMP22]]
; CHECK-NEXT:    [[TMP24:%.*]] = or <2 x i1> [[TMP21]], [[TMP23]]
; CHECK-NEXT:    ret <2 x i1> [[TMP24]]
;
  %val = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %arg, i32 341)
  ret <2 x i1> %val
}

; inverted check for not nan
define i1 @test_class_inverted_is_not_nan_f32(float %x) {
; CHECK-LABEL: @test_class_inverted_is_not_nan_f32(
; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float [[X:%.*]] to i32
; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-NEXT:    [[TMP4:%.*]] = fcmp oeq float [[TMP3]], 0x7FF0000000000000
; CHECK-NEXT:    [[TMP5:%.*]] = sub i32 [[TMP2]], 8388608
; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult i32 [[TMP5]], 2130706432
; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP4]], [[TMP6]]
; CHECK-NEXT:    [[TMP8:%.*]] = sub i32 [[TMP2]], 1
; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult i32 [[TMP8]], 8388607
; CHECK-NEXT:    [[TMP10:%.*]] = or i1 [[TMP7]], [[TMP9]]
; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP2]], 0
; CHECK-NEXT:    [[TMP12:%.*]] = or i1 [[TMP10]], [[TMP11]]
; CHECK-NEXT:    ret i1 [[TMP12]]
;
  %val = call i1 @llvm.is.fpclass.f32(float %x, i32 1020)
  ret i1 %val
}

declare i1 @llvm.is.fpclass.f32(float, i32 immarg)

declare i1 @llvm.is.fpclass.f64(double, i32 immarg)

declare i1 @llvm.is.fpclass.bf16(bfloat, i32 immarg)

declare <2 x i1> @llvm.is.fpclass.v2f32(<2 x float>, i32 immarg)

declare <2 x i1> @llvm.is.fpclass.v2f16(<2 x half>, i32 immarg)

