blob: 12391e8bf0631af5ae969345183ba6368d545d3d [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 multiply intrinsics with different rounding modes
;###############################################################
;# Mul(1.25, 2.0) #
;###############################################################
; Tests multiplication of two normal numbers (1.25 and 2.0) where the result
; is exactly representable. All rounding modes should produce the same result.
define double @test_1_25_times_2_rm_d() {
; CHECK-LABEL: define double @test_1_25_times_2_rm_d() {
; CHECK-NEXT: ret double 2.500000e+00
;
%res = call double @llvm.nvvm.mul.rm.d(double 1.25, double 2.0)
ret double %res
}
define double @test_1_25_times_2_rn_d() {
; CHECK-LABEL: define double @test_1_25_times_2_rn_d() {
; CHECK-NEXT: ret double 2.500000e+00
;
%res = call double @llvm.nvvm.mul.rn.d(double 1.25, double 2.0)
ret double %res
}
define double @test_1_25_times_2_rp_d() {
; CHECK-LABEL: define double @test_1_25_times_2_rp_d() {
; CHECK-NEXT: ret double 2.500000e+00
;
%res = call double @llvm.nvvm.mul.rp.d(double 1.25, double 2.0)
ret double %res
}
define double @test_1_25_times_2_rz_d() {
; CHECK-LABEL: define double @test_1_25_times_2_rz_d() {
; CHECK-NEXT: ret double 2.500000e+00
;
%res = call double @llvm.nvvm.mul.rz.d(double 1.25, double 2.0)
ret double %res
}
define float @test_1_25_times_2_rm_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rm_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rm.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rn_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rn_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rn.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rp_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rp_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rp.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rz_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rz_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rz.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rm_ftz_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rm_ftz_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rn_ftz_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rn_ftz_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rp_ftz_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rp_ftz_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 1.25, float 2.0)
ret float %res
}
define float @test_1_25_times_2_rz_ftz_f() {
; CHECK-LABEL: define float @test_1_25_times_2_rz_ftz_f() {
; CHECK-NEXT: ret float 2.500000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 1.25, float 2.0)
ret float %res
}
;###############################################################
;# Mul(1.0, Subnormal) #
;###############################################################
; Tests multiplication of 1.0 by a subnormal number to verify FTZ behavior.
; For float, we use 2^-149 (smallest subnormal float).
; For double, we use 2^-1074 (smallest subnormal double).
; Without FTZ, the result should be the subnormal number.
; With FTZ, the result should be 0.0.
define double @test_1_times_subnorm_rm_d() {
; CHECK-LABEL: define double @test_1_times_subnorm_rm_d() {
; CHECK-NEXT: ret double 4.940660e-324
;
%res = call double @llvm.nvvm.mul.rm.d(double 1.0, double 0x0000000000000001)
ret double %res
}
define double @test_1_times_subnorm_rn_d() {
; CHECK-LABEL: define double @test_1_times_subnorm_rn_d() {
; CHECK-NEXT: ret double 4.940660e-324
;
%res = call double @llvm.nvvm.mul.rn.d(double 1.0, double 0x0000000000000001)
ret double %res
}
define double @test_1_times_subnorm_rp_d() {
; CHECK-LABEL: define double @test_1_times_subnorm_rp_d() {
; CHECK-NEXT: ret double 4.940660e-324
;
%res = call double @llvm.nvvm.mul.rp.d(double 1.0, double 0x0000000000000001)
ret double %res
}
define double @test_1_times_subnorm_rz_d() {
; CHECK-LABEL: define double @test_1_times_subnorm_rz_d() {
; CHECK-NEXT: ret double 4.940660e-324
;
%res = call double @llvm.nvvm.mul.rz.d(double 1.0, double 0x0000000000000001)
ret double %res
}
define float @test_1_times_subnorm_rm_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rm_f() {
; CHECK-NEXT: ret float 0x36A0000000000000
;
%res = call float @llvm.nvvm.mul.rm.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rn_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rn_f() {
; CHECK-NEXT: ret float 0x36A0000000000000
;
%res = call float @llvm.nvvm.mul.rn.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rp_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rp_f() {
; CHECK-NEXT: ret float 0x36A0000000000000
;
%res = call float @llvm.nvvm.mul.rp.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rz_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rz_f() {
; CHECK-NEXT: ret float 0x36A0000000000000
;
%res = call float @llvm.nvvm.mul.rz.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rm_ftz_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rm_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rn_ftz_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rn_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rp_ftz_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rp_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
define float @test_1_times_subnorm_rz_ftz_f() {
; CHECK-LABEL: define float @test_1_times_subnorm_rz_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 1.0, float 0x36A0000000000000)
ret float %res
}
;###############################################################
;# Mul(1.0, -Subnormal) #
;###############################################################
; Tests multiplication of 1.0 by a negative subnormal number to verify FTZ behavior.
; For float, we use -2^-149 (negative smallest subnormal).
; For double, we use -2^-1074 (negative smallest subnormal).
; Without FTZ, the result should be the negative subnormal number.
; With FTZ, the result should be -0.0.
define double @test_1_times_neg_subnorm_rm_d() {
; CHECK-LABEL: define double @test_1_times_neg_subnorm_rm_d() {
; CHECK-NEXT: ret double -4.940660e-324
;
%res = call double @llvm.nvvm.mul.rm.d(double 1.0, double 0x8000000000000001)
ret double %res
}
define double @test_1_times_neg_subnorm_rn_d() {
; CHECK-LABEL: define double @test_1_times_neg_subnorm_rn_d() {
; CHECK-NEXT: ret double -4.940660e-324
;
%res = call double @llvm.nvvm.mul.rn.d(double 1.0, double 0x8000000000000001)
ret double %res
}
define double @test_1_times_neg_subnorm_rp_d() {
; CHECK-LABEL: define double @test_1_times_neg_subnorm_rp_d() {
; CHECK-NEXT: ret double -4.940660e-324
;
%res = call double @llvm.nvvm.mul.rp.d(double 1.0, double 0x8000000000000001)
ret double %res
}
define double @test_1_times_neg_subnorm_rz_d() {
; CHECK-LABEL: define double @test_1_times_neg_subnorm_rz_d() {
; CHECK-NEXT: ret double -4.940660e-324
;
%res = call double @llvm.nvvm.mul.rz.d(double 1.0, double 0x8000000000000001)
ret double %res
}
define float @test_1_times_neg_subnorm_rm_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rm_f() {
; CHECK-NEXT: ret float 0xB6A0000000000000
;
%res = call float @llvm.nvvm.mul.rm.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rn_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rn_f() {
; CHECK-NEXT: ret float 0xB6A0000000000000
;
%res = call float @llvm.nvvm.mul.rn.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rp_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rp_f() {
; CHECK-NEXT: ret float 0xB6A0000000000000
;
%res = call float @llvm.nvvm.mul.rp.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rz_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rz_f() {
; CHECK-NEXT: ret float 0xB6A0000000000000
;
%res = call float @llvm.nvvm.mul.rz.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rm_ftz_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rm_ftz_f() {
; CHECK-NEXT: ret float -0.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rn_ftz_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rn_ftz_f() {
; CHECK-NEXT: ret float -0.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rp_ftz_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rp_ftz_f() {
; CHECK-NEXT: ret float -0.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
define float @test_1_times_neg_subnorm_rz_ftz_f() {
; CHECK-LABEL: define float @test_1_times_neg_subnorm_rz_ftz_f() {
; CHECK-NEXT: ret float -0.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 1.0, float 0xB6A0000000000000)
ret float %res
}
;###############################################################
;# Mul(Normal, Normal) -> Subnormal #
;###############################################################
; Tests multiplication of two normal numbers that produces a subnormal result.
; We multiply the smallest normal float (2^-126 = 0x3810000000000000) by 0.5 to get 2^-127,
; which is subnormal. This tests the transition from normal to subnormal numbers.
; For double precision, we just use the same float value since there is no FTZ variant.
define double @test_normal_times_normal_to_subnorm_rm_d() {
; CHECK-LABEL: define double @test_normal_times_normal_to_subnorm_rm_d() {
; CHECK-NEXT: ret double 0x3800000000000000
;
%res = call double @llvm.nvvm.mul.rm.d(double 0x3810000000000000, double 0.5)
ret double %res
}
define double @test_normal_times_normal_to_subnorm_rn_d() {
; CHECK-LABEL: define double @test_normal_times_normal_to_subnorm_rn_d() {
; CHECK-NEXT: ret double 0x3800000000000000
;
%res = call double @llvm.nvvm.mul.rn.d(double 0x3810000000000000, double 0.5)
ret double %res
}
define double @test_normal_times_normal_to_subnorm_rp_d() {
; CHECK-LABEL: define double @test_normal_times_normal_to_subnorm_rp_d() {
; CHECK-NEXT: ret double 0x3800000000000000
;
%res = call double @llvm.nvvm.mul.rp.d(double 0x3810000000000000, double 0.5)
ret double %res
}
define double @test_normal_times_normal_to_subnorm_rz_d() {
; CHECK-LABEL: define double @test_normal_times_normal_to_subnorm_rz_d() {
; CHECK-NEXT: ret double 0x3800000000000000
;
%res = call double @llvm.nvvm.mul.rz.d(double 0x3810000000000000, double 0.5)
ret double %res
}
define float @test_normal_times_normal_to_subnorm_rm_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rm_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.mul.rm.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rn_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rn_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.mul.rn.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rp_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rp_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.mul.rp.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rz_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rz_f() {
; CHECK-NEXT: ret float 0x3800000000000000
;
%res = call float @llvm.nvvm.mul.rz.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rm_ftz_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rm_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rn_ftz_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rn_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rp_ftz_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rp_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 0x3810000000000000, float 0.5)
ret float %res
}
define float @test_normal_times_normal_to_subnorm_rz_ftz_f() {
; CHECK-LABEL: define float @test_normal_times_normal_to_subnorm_rz_ftz_f() {
; CHECK-NEXT: ret float 0.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 0x3810000000000000, float 0.5)
ret float %res
}
;###############################################################
;# Mul(2.0, NaN) #
;###############################################################
; Tests multiplication with NaN to verify that we do not fold these,
; as host and device NaNs may be different.
define double @test_2_times_nan_rm_d() {
; CHECK-LABEL: define double @test_2_times_nan_rm_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.mul.rm.d(double 2.000000e+00, double 0x7FF4444400000000)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.mul.rm.d(double 2.0, double 0x7FF4444400000000)
ret double %res
}
define double @test_2_times_nan_rn_d() {
; CHECK-LABEL: define double @test_2_times_nan_rn_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.mul.rn.d(double 2.000000e+00, double 0x7FF4444400000000)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.mul.rn.d(double 2.0, double 0x7FF4444400000000)
ret double %res
}
define double @test_2_times_nan_rp_d() {
; CHECK-LABEL: define double @test_2_times_nan_rp_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.mul.rp.d(double 2.000000e+00, double 0x7FF4444400000000)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.mul.rp.d(double 2.0, double 0x7FF4444400000000)
ret double %res
}
define double @test_2_times_nan_rz_d() {
; CHECK-LABEL: define double @test_2_times_nan_rz_d() {
; CHECK-NEXT: [[RES:%.*]] = call double @llvm.nvvm.mul.rz.d(double 2.000000e+00, double 0x7FF4444400000000)
; CHECK-NEXT: ret double [[RES]]
;
%res = call double @llvm.nvvm.mul.rz.d(double 2.0, double 0x7FF4444400000000)
ret double %res
}
define float @test_2_times_nan_rm_f() {
; CHECK-LABEL: define float @test_2_times_nan_rm_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rm.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rm.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rn_f() {
; CHECK-LABEL: define float @test_2_times_nan_rn_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rn.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rn.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rp_f() {
; CHECK-LABEL: define float @test_2_times_nan_rp_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rp.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rp.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rz_f() {
; CHECK-LABEL: define float @test_2_times_nan_rz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rz.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rz.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rm_ftz_f() {
; CHECK-LABEL: define float @test_2_times_nan_rm_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rm.ftz.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rn_ftz_f() {
; CHECK-LABEL: define float @test_2_times_nan_rn_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rn.ftz.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rp_ftz_f() {
; CHECK-LABEL: define float @test_2_times_nan_rp_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rp.ftz.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
define float @test_2_times_nan_rz_ftz_f() {
; CHECK-LABEL: define float @test_2_times_nan_rz_ftz_f() {
; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.mul.rz.ftz.f(float 2.000000e+00, float 0x7FFF444400000000)
; CHECK-NEXT: ret float [[RES]]
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 2.0, float 0x7FFF444400000000)
ret float %res
}
;###############################################################
;# Mul(0.75, 4/3 + epsilon) #
;###############################################################
; Tests multiplication of 0.75 (3/4) by a value slightly above 4/3,
; where different rounding modes produce different results.
; The exact result would be 1.0, but since 4/3 cannot be exactly encoded
; as a float, the calculated result falls between 1.0 and 1.0 + 2^-23.
; - RN, RZ, RM round to 1.0 (rounding to nearest/zero/down)
; - RP rounds to 1.0 + 2^-23 (rounding up)
define float @test_mul_just_above_1_rm_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rm_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rn_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rn_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rp_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rp_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rp.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rz_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rm_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rm_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rn_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rn_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rp_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rp_ftz_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_above_1_rz_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_above_1_rz_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 0.75, float 0x3FF5555560000000)
ret float %res
}
;###############################################################
;# Mul(0.75, 4/3 + epsilon) #
;###############################################################
; Tests multiplication of 0.75 by a value slightly above 4/3,
; where different rounding modes produce different results.
; The exact result would be 1.0, but since 4/3 cannot be exactly encoded
; as a double, the calculated result falls between 1.0 and 1.0 + 2^-52.
; - RN, RZ, RM round to 1.0 (rounding to nearest/zero/down)
; - RP rounds to 1.0 + 2^-52 (rounding up)
define double @test_mul_just_above_1_rm_d() {
; CHECK-LABEL: define double @test_mul_just_above_1_rm_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.mul.rm.d(double 0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_above_1_rn_d() {
; CHECK-LABEL: define double @test_mul_just_above_1_rn_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.mul.rn.d(double 0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_above_1_rp_d() {
; CHECK-LABEL: define double @test_mul_just_above_1_rp_d() {
; CHECK-NEXT: ret double 0x3FF0000000000001
;
%res = call double @llvm.nvvm.mul.rp.d(double 0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_above_1_rz_d() {
; CHECK-LABEL: define double @test_mul_just_above_1_rz_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.mul.rz.d(double 0.75, double 0x3FF5555555555556)
ret double %res
}
;###############################################################
;# Mul(-0.75, 4/3 + epsilon) #
;###############################################################
; Tests multiplication of -0.75 by a value slightly above 4/3,
; where different rounding modes produce different results.
; The exact result would be -1.0, but since 4/3 cannot be exactly encoded
; as a double, the calculated result falls between -1.0 and -1.0 - 2^-23.
; - RN, RZ, RP round to -1.0 (rounding to nearest/zero/up)
; - RM rounds to -1.0 - 2^-23 (rounding down)
define float @test_mul_just_below_negative_1_rm_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rm_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rm.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rn_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rn_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rp_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rp_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rz_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rm_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rm_ftz_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rn_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rn_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rp_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rp_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
define float @test_mul_just_below_negative_1_rz_ftz_f() {
; CHECK-LABEL: define float @test_mul_just_below_negative_1_rz_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float -0.75, float 0x3FF5555560000000)
ret float %res
}
;###############################################################
;# Mul(-0.75, 4/3 + epsilon) #
;###############################################################
; Tests multiplication of -0.75 by a value slightly above 4/3,
; where different rounding modes produce different results.
; The exact result would be -1.0, but since 4/3 cannot be exactly encoded
; as a double, the calculated result falls between -1.0 and -1.0 - 2^-52.
; - RN, RZ, RP round to -1.0 (rounding to nearest/zero/up)
; - RM rounds to -1.0 - 2^-52 (rounding down)
define double @test_mul_just_below_negative_1_rm_d() {
; CHECK-LABEL: define double @test_mul_just_below_negative_1_rm_d() {
; CHECK-NEXT: ret double 0xBFF0000000000001
;
%res = call double @llvm.nvvm.mul.rm.d(double -0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_below_negative_1_rn_d() {
; CHECK-LABEL: define double @test_mul_just_below_negative_1_rn_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.mul.rn.d(double -0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_below_negative_1_rp_d() {
; CHECK-LABEL: define double @test_mul_just_below_negative_1_rp_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.mul.rp.d(double -0.75, double 0x3FF5555555555556)
ret double %res
}
define double @test_mul_just_below_negative_1_rz_d() {
; CHECK-LABEL: define double @test_mul_just_below_negative_1_rz_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.mul.rz.d(double -0.75, double 0x3FF5555555555556)
ret double %res
}
;###############################################################
;# Mul(0.625, 1.6 + epsilon) #
;###############################################################
; Tests multiplication of 5/8 * ~8/5 with different rounding modes.
; Multiply 0.625 (5/8) by a value very slightly above 8/5 = 1.6 + epsilon.
; The exact result is between 1.0 and 1.0 + 2^-23
; - RN, RP round to 1.0 + 2^-23 (rounding towards nearest/up)
; - RZ, RM round to 1.0 (rounding towards zero/down)
define float @test_mul_slightly_more_above_1_rm_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rm_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.f(float 0x3FE4000000000000, float 0x3FF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_above_1_rn_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rn_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rn.f(float 0x3FE4000000000000, float 0x3FF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_above_1_rp_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rp_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rp.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
define float @test_mul_slightly_more_above_1_rz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
define float @test_mul_slightly_more_above_1_rm_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rm_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
define float @test_mul_slightly_more_above_1_rn_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rn_ftz_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
define float @test_mul_slightly_more_above_1_rp_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rp_ftz_f() {
; CHECK-NEXT: ret float 0x3FF0000020000000
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
define float @test_mul_slightly_more_above_1_rz_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_above_1_rz_ftz_f() {
; CHECK-NEXT: ret float 1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 0x3FE4000000000000, float 0x3FF99999C0000000 )
ret float %res
}
;###############################################################
;# Mul(0.625, 1.6 + epsilon) #
;###############################################################
; Tests multiplication of 5/8 * ~8/5 with different rounding modes.
; Multiply 0.625 (5/8) by a value very slightly above 8/5 = 1.6 + epsilon.
; The exact result is between 1.0 and 1.0 + 2^-52
; - RN, RP round to 1.0 + 2^-52 (rounding towards nearest/up)
; - RZ, RM round to 1.0 (rounding towards zero/down)
define double @test_mul_slightly_more_above_1_rm_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_above_1_rm_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.mul.rm.d(double 0x3FE4000000000000, double 0x3FF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_above_1_rn_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_above_1_rn_d() {
; CHECK-NEXT: ret double 0x3FF0000000000001
;
%res = call double @llvm.nvvm.mul.rn.d(double 0x3FE4000000000000, double 0x3FF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_above_1_rp_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_above_1_rp_d() {
; CHECK-NEXT: ret double 0x3FF0000000000001
;
%res = call double @llvm.nvvm.mul.rp.d(double 0x3FE4000000000000, double 0x3FF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_above_1_rz_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_above_1_rz_d() {
; CHECK-NEXT: ret double 1.000000e+00
;
%res = call double @llvm.nvvm.mul.rz.d(double 0x3FE4000000000000, double 0x3FF999999999999B)
ret double %res
}
;###############################################################
;# Mul(0.625, -(1.6 + epsilon) #
;###############################################################
; Tests multiplication of 5/8 * ~-8/5 with different rounding modes.
; Multiply 0.625 (5/8) by a value very slightly below -8/5 = -(1.6 + epsilon).
; The exact result is between -1.0 and -1.0 + 2^-23
; - RN, RM round to -1.0 - 2^-23 (rounding towards nearest/down)
; - RZ, RP round to -1.0 (rounding towards zero/up)
define float @test_mul_slightly_more_below_negative_1_rm_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rm_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rm.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rn_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rn_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rn.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rp_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rp_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rm_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rm_ftz_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rm.ftz.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rn_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rn_ftz_f() {
; CHECK-NEXT: ret float 0xBFF0000020000000
;
%res = call float @llvm.nvvm.mul.rn.ftz.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rp_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rp_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rp.ftz.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
define float @test_mul_slightly_more_below_negative_1_rz_ftz_f() {
; CHECK-LABEL: define float @test_mul_slightly_more_below_negative_1_rz_ftz_f() {
; CHECK-NEXT: ret float -1.000000e+00
;
%res = call float @llvm.nvvm.mul.rz.ftz.f(float 0x3FE4000000000000, float 0xBFF99999C0000000)
ret float %res
}
;###############################################################
;# Mul(0.625, -(1.6 + epsilon) #
;###############################################################
; Tests multiplication of 5/8 * ~-8/5 with different rounding modes.
; Multiply 0.625 (5/8) by a value very slightly below -8/5 = -(1.6 + epsilon).
; The exact result is between -1.0 and -1.0 + 2^-52
; - RN, RM round to -1.0 - 2^-52 (rounding towards nearest/down)
; - RZ, RP round to -1.0 (rounding towards zero/up)
define double @test_mul_slightly_more_below_negative_1_rm_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_below_negative_1_rm_d() {
; CHECK-NEXT: ret double 0xBFF0000000000001
;
%res = call double @llvm.nvvm.mul.rm.d(double 0x3FE4000000000000, double 0xBFF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_below_negative_1_rn_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_below_negative_1_rn_d() {
; CHECK-NEXT: ret double 0xBFF0000000000001
;
%res = call double @llvm.nvvm.mul.rn.d(double 0x3FE4000000000000, double 0xBFF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_below_negative_1_rp_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_below_negative_1_rp_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.mul.rp.d(double 0x3FE4000000000000, double 0xBFF999999999999B)
ret double %res
}
define double @test_mul_slightly_more_below_negative_1_rz_d() {
; CHECK-LABEL: define double @test_mul_slightly_more_below_negative_1_rz_d() {
; CHECK-NEXT: ret double -1.000000e+00
;
%res = call double @llvm.nvvm.mul.rz.d(double 0x3FE4000000000000, double 0xBFF999999999999B)
ret double %res
}