blob: d52ff1ce66440bd2f8c37e9ac9d1c7e29592853d [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instsimplify -march=nvptx64 --mcpu=sm_86 --mattr=+ptx72 -S | FileCheck %s
; Check constant-folding for NVVM FMA intrinsics with different rounding modes
;###############################################################
;# FMA(2.0, 3.0, 4.0) #
;###############################################################
; Tests FMA with regular numbers that produce a precise result
define double @test_fma_2_3_4_rm_d() {
; CHECK-LABEL: define double @test_fma_2_3_4_rm_d() {
; CHECK-NEXT: ret double 1.000000e+01
;
%res = call double @llvm.nvvm.fma.rm.d(double 2.0, double 3.0, double 4.0)
ret double %res
}
define double @test_fma_2_3_4_rn_d() {
; CHECK-LABEL: define double @test_fma_2_3_4_rn_d() {
; CHECK-NEXT: ret double 1.000000e+01
;
%res = call double @llvm.nvvm.fma.rn.d(double 2.0, double 3.0, double 4.0)
ret double %res
}
define double @test_fma_2_3_4_rp_d() {
; CHECK-LABEL: define double @test_fma_2_3_4_rp_d() {
; CHECK-NEXT: ret double 1.000000e+01
;
%res = call double @llvm.nvvm.fma.rp.d(double 2.0, double 3.0, double 4.0)
ret double %res
}
define double @test_fma_2_3_4_rz_d() {
; CHECK-LABEL: define double @test_fma_2_3_4_rz_d() {
; CHECK-NEXT: ret double 1.000000e+01
;
%res = call double @llvm.nvvm.fma.rz.d(double 2.0, double 3.0, double 4.0)
ret double %res
}
define float @test_fma_2_3_4_rm_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rm_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rm.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rn_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rn_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rn.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rp_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rp_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rp.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rz_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rz_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rz.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rm_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rn_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rp_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
define float @test_fma_2_3_4_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_2_3_4_rz_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+01
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 2.0, float 3.0, float 4.0)
ret float %res
}
;###############################################################
;# FMA(Subnormal, 2.0, 0.0) -> Normal #
;###############################################################
; Tests FMA with subnormal multiplier that produces a normal result
; For float: 2^-127 * 2.0 = 2^-126 (smallest normal)
; For double: 2^-1023 * 2.0 = 2^-1022 (smallest normal)
; The FTZ variants should return 0.0, as they flush their input to zero.
define double @test_fma_subnorm_to_norm_rm_d() {
; CHECK-LABEL: define double @test_fma_subnorm_to_norm_rm_d() {
; CHECK-NEXT: ret double 0x10000000000000
;
%res = call double @llvm.nvvm.fma.rm.d(double 0x0008000000000000, double 2.0, double 0.0)
ret double %res
}
define double @test_fma_subnorm_to_norm_rn_d() {
; CHECK-LABEL: define double @test_fma_subnorm_to_norm_rn_d() {
; CHECK-NEXT: ret double 0x10000000000000
;
%res = call double @llvm.nvvm.fma.rn.d(double 0x0008000000000000, double 2.0, double 0.0)
ret double %res
}
define double @test_fma_subnorm_to_norm_rp_d() {
; CHECK-LABEL: define double @test_fma_subnorm_to_norm_rp_d() {
; CHECK-NEXT: ret double 0x10000000000000
;
%res = call double @llvm.nvvm.fma.rp.d(double 0x0008000000000000, double 2.0, double 0.0)
ret double %res
}
define double @test_fma_subnorm_to_norm_rz_d() {
; CHECK-LABEL: define double @test_fma_subnorm_to_norm_rz_d() {
; CHECK-NEXT: ret double 0x10000000000000
;
%res = call double @llvm.nvvm.fma.rz.d(double 0x0008000000000000, double 2.0, double 0.0)
ret double %res
}
define float @test_fma_subnorm_to_norm_rm_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rm_f() {
; CHECK-NEXT: ret float 0x3810000000000000
;
%res = call float @llvm.nvvm.fma.rm.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rn_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rn_f() {
; CHECK-NEXT: ret float 0x3810000000000000
;
%res = call float @llvm.nvvm.fma.rn.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rp_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rp_f() {
; CHECK-NEXT: ret float 0x3810000000000000
;
%res = call float @llvm.nvvm.fma.rp.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rz_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rz_f() {
; CHECK-NEXT: ret float 0x3810000000000000
;
%res = call float @llvm.nvvm.fma.rz.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rm_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rn_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rp_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
define float @test_fma_subnorm_to_norm_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_subnorm_to_norm_rz_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 0x3800000000000000, float 2.0, float 0.0)
ret float %res
}
;###############################################################
;# FMA(Normal, 0.5, 0.0) -> Subnormal #
;###############################################################
; Tests FMA with normal inputs that produce a subnormal result
; For float: 2^-126 * 0.5 = 2^-127 (subnormal)
; For double: 2^-1022 * 0.5 = 2^-1023 (subnormal)
; With FTZ mode, the subnormal output should be flushed to zero.
define double @test_fma_norm_to_subnorm_rm_d() {
; CHECK-LABEL: define double @test_fma_norm_to_subnorm_rm_d() {
; CHECK-NEXT: ret double 0x8000000000000
;
%res = call double @llvm.nvvm.fma.rm.d(double 0x10000000000000, double 0.5, double 0.0)
ret double %res
}
define double @test_fma_norm_to_subnorm_rn_d() {
; CHECK-LABEL: define double @test_fma_norm_to_subnorm_rn_d() {
; CHECK-NEXT: ret double 0x8000000000000
;
%res = call double @llvm.nvvm.fma.rn.d(double 0x10000000000000, double 0.5, double 0.0)
ret double %res
}
define double @test_fma_norm_to_subnorm_rp_d() {
; CHECK-LABEL: define double @test_fma_norm_to_subnorm_rp_d() {
; CHECK-NEXT: ret double 0x8000000000000
;
%res = call double @llvm.nvvm.fma.rp.d(double 0x10000000000000, double 0.5, double 0.0)
ret double %res
}
define double @test_fma_norm_to_subnorm_rz_d() {
; CHECK-LABEL: define double @test_fma_norm_to_subnorm_rz_d() {
; CHECK-NEXT: ret double 0x8000000000000
;
%res = call double @llvm.nvvm.fma.rz.d(double 0x10000000000000, double 0.5, double 0.0)
ret double %res
}
define float @test_fma_norm_to_subnorm_rm_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rm_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.fma.rm.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rn_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rn_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.fma.rn.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rp_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rp_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.fma.rp.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rz_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rz_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.fma.rz.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rm_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rn_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rp_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
define float @test_fma_norm_to_subnorm_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_norm_to_subnorm_rz_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 0x3810000000000000, float 0.5, float 0.0)
ret float %res
}
;###############################################################
;# FMA(NaN, 1.0, 0.0) #
;###############################################################
; Tests FMA with NaN input to verify that the instruction is preserved
; since the result would be NaN. The instruction should not be folded.
define double @test_fma_nan_rm_d() {
; CHECK-LABEL: define double @test_fma_nan_rm_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.fma.rm.d(double 0x7FF8000000000000, double 1.000000e+00, double 0.000000e+00)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.fma.rm.d(double 0x7FF8000000000000, double 1.0, double 0.0)
ret double %res
}
define double @test_fma_nan_rn_d() {
; CHECK-LABEL: define double @test_fma_nan_rn_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.fma.rn.d(double 0x7FF8000000000000, double 1.000000e+00, double 0.000000e+00)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.fma.rn.d(double 0x7FF8000000000000, double 1.0, double 0.0)
ret double %res
}
define double @test_fma_nan_rp_d() {
; CHECK-LABEL: define double @test_fma_nan_rp_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.fma.rp.d(double 0x7FF8000000000000, double 1.000000e+00, double 0.000000e+00)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.fma.rp.d(double 0x7FF8000000000000, double 1.0, double 0.0)
ret double %res
}
define double @test_fma_nan_rz_d() {
; CHECK-LABEL: define double @test_fma_nan_rz_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.fma.rz.d(double 0x7FF8000000000000, double 1.000000e+00, double 0.000000e+00)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.fma.rz.d(double 0x7FF8000000000000, double 1.0, double 0.0)
ret double %res
}
define float @test_fma_nan_rm_f() {
; CHECK-LABEL: define float @test_fma_nan_rm_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rm.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rm.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rn_f() {
; CHECK-LABEL: define float @test_fma_nan_rn_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rn.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rn.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rp_f() {
; CHECK-LABEL: define float @test_fma_nan_rp_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rp.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rp.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rz_f() {
; CHECK-LABEL: define float @test_fma_nan_rz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rz.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rz.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_nan_rm_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rm.ftz.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_nan_rn_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rn.ftz.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_nan_rp_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rp.ftz.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
define float @test_fma_nan_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_nan_rz_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fma.rz.ftz.f(float 0x7FFC000000000000, float 1.000000e+00, float 0.000000e+00)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 0x7FFC000000000000, float 1.0, float 0.0)
ret float %res
}
;###############################################################
;# FMA(1.0, 1.0, 2^(-25)) #
;###############################################################
; Tests FMA with 1.0 and 2^(-25) where different rounding modes produce different results.
; The exact result falls between 1.0 and 1.0 + 2^(-23).
; RM, RN, and RZ return 1.0, while RP returns 1.0 + 2^(-23) (0x3F800001).
define float @test_fma_1_plus_ulp_rm_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rm_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rn_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rn_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rp_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rp_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.fma.rp.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rz_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rm_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rn_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rp_ftz_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_1_plus_ulp_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_plus_ulp_rz_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 1.0, float 1.0, float 0x3E60000000000000)
ret float %res
}
;###############################################################
;# FMA(1.0, 1.0, 2^(-54)) #
;###############################################################
; Tests FMA with 1.0 and 2^(-54) where different rounding modes produce different results.
; The exact result falls between 1.0 and 1.0 + 2^(-52).
; - RN, RZ, RM: Return 1.0 (rounding to nearest/zero/down)
; - RP: Returns 1.0 + 2^(-52) (rounding up)
define double @test_fma_1_plus_ulp_rm_d() {
; CHECK-LABEL: define double @test_fma_1_plus_ulp_rm_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.fma.rm.d(double 1.0, double 1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_1_plus_ulp_rn_d() {
; CHECK-LABEL: define double @test_fma_1_plus_ulp_rn_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.fma.rn.d(double 1.0, double 1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_1_plus_ulp_rp_d() {
; CHECK-LABEL: define double @test_fma_1_plus_ulp_rp_d() {
; CHECK-NEXT: ret double 0x3FF0000000000001
;
%res = call double @llvm.nvvm.fma.rp.d(double 1.0, double 1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_1_plus_ulp_rz_d() {
; CHECK-LABEL: define double @test_fma_1_plus_ulp_rz_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.fma.rz.d(double 1.0, double 1.0, double 0x3C90000000000000)
ret double %res
}
;###############################################################
;# FMA(1.0, -1.0, 2^(-25)) #
;###############################################################
; Tests FMA with -1.0 and 2^(-25) where different rounding modes produce different results.
; The exact result falls between -1.0 and -1.0 + 2^(-23).
; - RN, RM: Returns -1.0 (rounding toward nearest/down)
; - RZ, RP: Return -1.0 + 2^(-23) (rounding toward zero/up)
define float @test_fma_neg_1_plus_ulp_rm_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rm_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rn_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rn_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rp_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rp_f() {
; CHECK-NEXT: ret float 0xBFEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rp.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rz_f() {
; CHECK-NEXT: ret float 0xBFEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rz.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rm_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rn_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rp_ftz_f() {
; CHECK-NEXT: ret float 0xBFEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
define float @test_fma_neg_1_plus_ulp_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_plus_ulp_rz_ftz_f() {
; CHECK-NEXT: ret float 0xBFEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 1.0, float -1.0, float 0x3E60000000000000)
ret float %res
}
;###############################################################
;# FMA(1.0, -1.0, 2^(-54)) #
;###############################################################
; Tests FMA with -1.0 and 2^(-54) where different rounding modes produce different results.
; The exact result falls between -1.0 and -1.0 + 2^(-52).
; - RN, RM: Return -1.0 (rounding toward nearest/down)
; - RZ, RP: Return -1.0 + 2^(-52) (rounding toward zero/up)
define double @test_fma_neg_1_plus_ulp_rm_d() {
; CHECK-LABEL: define double @test_fma_neg_1_plus_ulp_rm_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.fma.rm.d(double 1.0, double -1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_neg_1_plus_ulp_rn_d() {
; CHECK-LABEL: define double @test_fma_neg_1_plus_ulp_rn_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.fma.rn.d(double 1.0, double -1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_neg_1_plus_ulp_rp_d() {
; CHECK-LABEL: define double @test_fma_neg_1_plus_ulp_rp_d() {
; CHECK-NEXT: ret double 0xBFEFFFFFFFFFFFFF
;
%res = call double @llvm.nvvm.fma.rp.d(double 1.0, double -1.0, double 0x3C90000000000000)
ret double %res
}
define double @test_fma_neg_1_plus_ulp_rz_d() {
; CHECK-LABEL: define double @test_fma_neg_1_plus_ulp_rz_d() {
; CHECK-NEXT: ret double 0xBFEFFFFFFFFFFFFF
;
%res = call double @llvm.nvvm.fma.rz.d(double 1.0, double -1.0, double 0x3C90000000000000)
ret double %res
}
;###############################################################
;# FMA(1.0, 1.0, -2^(-25)) #
;###############################################################
; Tests FMA with 1.0 and -2^(-25) where different rounding modes produce different results.
; The exact result falls between 1.0 and 1.0 - 2^(-23).
; - RN, RP: Return 1.0 (rounding toward nearest/up)
; - RZ, RM: Return 1.0 - 2^(-23) (rounding toward zero/down)
define float @test_fma_1_minus_ulp_rm_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rm_f() {
; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rm.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rn_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rn_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rp_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rp_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rz_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rz_f() {
; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rz.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rm_ftz_f() {
; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rn_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rp_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_1_minus_ulp_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_1_minus_ulp_rz_ftz_f() {
; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 1.0, float 1.0, float 0xBE60000000000000)
ret float %res
}
;###############################################################
;# FMA(1.0, 1.0, -2^(-54)) #
;###############################################################
; Tests FMA with 1.0 and -2^(-54) where different rounding modes produce different results.
; The exact result falls between 1.0 and 1.0 - 2^(-52).
; - RN, RP: Return 1.0 (rounding toward nearest/up)
; - RZ, RM: Return 1.0 - 2^(-52) (rounding toward zero/down)
define double @test_fma_1_minus_ulp_rm_d() {
; CHECK-LABEL: define double @test_fma_1_minus_ulp_rm_d() {
; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
;
%res = call double @llvm.nvvm.fma.rm.d(double 1.0, double 1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_1_minus_ulp_rn_d() {
; CHECK-LABEL: define double @test_fma_1_minus_ulp_rn_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.fma.rn.d(double 1.0, double 1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_1_minus_ulp_rp_d() {
; CHECK-LABEL: define double @test_fma_1_minus_ulp_rp_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.fma.rp.d(double 1.0, double 1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_1_minus_ulp_rz_d() {
; CHECK-LABEL: define double @test_fma_1_minus_ulp_rz_d() {
; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
;
%res = call double @llvm.nvvm.fma.rz.d(double 1.0, double 1.0, double 0xBC90000000000000)
ret double %res
}
;###############################################################
;# FMA(1.0, -1.0, -2^(-25)) #
;###############################################################
; Tests FMA with -1.0 and -2^(-25) where different rounding modes produce different results.
; The exact result falls between -1.0 and -1.0 - 2^(-23).
; - RN, RZ, RP: Return -1.0 (rounding to nearest/zero/up)
; - RM: Return -1.0 - 2^(-23) (rounding down)
define float @test_fma_neg_1_minus_ulp_rm_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rm_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.fma.rm.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rn_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rn_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rp_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rp_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rm_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rm_ftz_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.fma.rm.ftz.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rn_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rn_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rn.ftz.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rp_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rp_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rp.ftz.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
define float @test_fma_neg_1_minus_ulp_rz_ftz_f() {
; CHECK-LABEL: define float @test_fma_neg_1_minus_ulp_rz_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.fma.rz.ftz.f(float 1.0, float -1.0, float 0xBE60000000000000)
ret float %res
}
;###############################################################
;# FMA(1.0, -1.0, -2^(-54)) #
;###############################################################
; Tests FMA with -1.0 and -2^(-54) where different rounding modes produce different results.
; The exact result falls between -1.0 and -1.0 - 2^(-52).
; - RN, RZ, RP: Return -1.0 (rounding to nearest/zero/up)
; - RM: Return -1.0 - 2^(-52) (rounding down)
define double @test_fma_neg_1_minus_ulp_rm_d() {
; CHECK-LABEL: define double @test_fma_neg_1_minus_ulp_rm_d() {
; CHECK-NEXT: ret double 0xBFF0000000000001
;
%res = call double @llvm.nvvm.fma.rm.d(double 1.0, double -1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_neg_1_minus_ulp_rn_d() {
; CHECK-LABEL: define double @test_fma_neg_1_minus_ulp_rn_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.fma.rn.d(double 1.0, double -1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_neg_1_minus_ulp_rp_d() {
; CHECK-LABEL: define double @test_fma_neg_1_minus_ulp_rp_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.fma.rp.d(double 1.0, double -1.0, double 0xBC90000000000000)
ret double %res
}
define double @test_fma_neg_1_minus_ulp_rz_d() {
; CHECK-LABEL: define double @test_fma_neg_1_minus_ulp_rz_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.fma.rz.d(double 1.0, double -1.0, double 0xBC90000000000000)
ret double %res
}