Files
clang-p2996/llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal.ll
Matt Arsenault bc37be1855 LangRef: Add "dynamic" option to "denormal-fp-math"
This is stricter than the default "ieee", and should probably be the
default. This patch leaves the default alone. I can change this in a
future patch.

There are non-reversible transforms I would like to perform which are
legal under IEEE denormal handling, but illegal with flushing zero
behavior. Namely, conversions between llvm.is.fpclass and fcmp with
zeroes.

Under "ieee" handling, it is legal to translate between
llvm.is.fpclass(x, fcZero) and fcmp x, 0.

Under "preserve-sign" handling, it is legal to translate between
llvm.is.fpclass(x, fcSubnormal|fcZero) and fcmp x, 0.

I would like to compile and distribute some math library functions in
a mode where it's callable from code with and without denormals
enabled, which requires not changing the compares with denormals or
zeroes.

If an IEEE function transforms an llvm.is.fpclass call into an fcmp 0,
it is no longer possible to call the function from code with denormals
enabled, or write an optimization to move the function into a denormal
flushing mode. For the original function, if x was a denormal, the
class would evaluate to false. If the function compiled with denormal
handling was converted to or called from a preserve-sign function, the
fcmp now evaluates to true.

This could also be of use for strictfp handling, where code may be
changing the denormal mode.

Alternative name could be "unknown".

Replaces the old AMDGPU custom inlining logic with more conservative
logic which tries to permit inlining for callees with dynamic handling
and avoids inlining other mismatched modes.
2023-04-29 08:44:59 -04:00

1219 lines
35 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
; Test cases for denormal handling mode when constant folding floating point
; operations. Input and output modes are checked seperately.
; ============================================================================ ;
; fadd tests
; Denormal operand added to normal operand produces denormal result.
; If denormal outputs should be flushed to zero, the result should be zero.
; If denormal inputs should be treated as zero, the result should be the
; normal operand (a number plus zero is the same number).
; ============================================================================ ;
define float @test_float_fadd_ieee() #0 {
; CHECK-LABEL: @test_float_fadd_ieee(
; CHECK-NEXT: ret float 0xB800000000000000
;
; default ieee mode leaves result as a denormal
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_pzero_out() #1 {
; CHECK-LABEL: @test_float_fadd_pzero_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_psign_out() #2 {
; CHECK-LABEL: @test_float_fadd_psign_out(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_pzero_in() #3 {
; CHECK-LABEL: @test_float_fadd_pzero_in(
; CHECK-NEXT: ret float 0xB810000000000000
;
; denormal operand is treated as zero
; normal operand added to zero results in the same operand as a result
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_psign_in() #4 {
; CHECK-LABEL: @test_float_fadd_psign_in(
; CHECK-NEXT: ret float 0xB810000000000000
;
; denormal operand is treated as zero
; normal operand added to zero results in the same operand as a result
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_pzero_f32_out() #5 {
; CHECK-LABEL: @test_float_fadd_pzero_f32_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; f32 only attribute should flush float output
; default ieee mode leaves result as a denormal
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define double @test_double_fadd_ieee() #0 {
; CHECK-LABEL: @test_double_fadd_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; default ieee mode leaves result as a denormal
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
define double @test_double_fadd_pzero_out() #1 {
; CHECK-LABEL: @test_double_fadd_pzero_out(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
define double @test_double_fadd_psign_out() #2 {
; CHECK-LABEL: @test_double_fadd_psign_out(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
define double @test_double_fadd_pzero_in() #3 {
; CHECK-LABEL: @test_double_fadd_pzero_in(
; CHECK-NEXT: ret double 0x8010000000000000
;
; denormal operand is treated as zero
; normal operand added to zero results in the same operand as a result
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
define double @test_double_fadd_psign_in() #4 {
; CHECK-LABEL: @test_double_fadd_psign_in(
; CHECK-NEXT: ret double 0x8010000000000000
;
; denormal operand is treated as zero
; normal operand added to zero results in the same operand as a result
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
define double @test_double_fadd_f32_ieee() #5 {
; CHECK-LABEL: @test_double_fadd_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; f32 only attribute should not flush doubles
; default ieee mode leaves result as a denormal
%result = fadd double 0x8010000000000000, 0x0008000000000000
ret double %result
}
; ============================================================================ ;
; fsub tests
; Normal operand subtracted from denormal operand produces denormal result
; If denormal outputs should be flushed to zero, the result should be zero.
; If denormal inputs should be treated as zero, the result should be the
; negated normal operand (zero minus the original operand).
; ============================================================================ ;
define float @test_float_fsub_ieee() #0 {
; CHECK-LABEL: @test_float_fsub_ieee(
; CHECK-NEXT: ret float 0xB800000000000000
;
; default ieee mode leaves result as a denormal
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_fsub_pzero_out() #1 {
; CHECK-LABEL: @test_float_fsub_pzero_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_fsub_psign_out() #2 {
; CHECK-LABEL: @test_float_fsub_psign_out(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_fsub_pzero_in() #3 {
; CHECK-LABEL: @test_float_fsub_pzero_in(
; CHECK-NEXT: ret float 0xB810000000000000
;
; denormal operand is treated as zero
; normal operand subtracted from zero produces the same operand, negated
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_fsub_psign_in() #4 {
; CHECK-LABEL: @test_float_fsub_psign_in(
; CHECK-NEXT: ret float 0xB810000000000000
;
; denormal operand is treated as zero
; normal operand subtracted from zero produces the same operand, negated
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_fsub_pzero_f32_out() #5 {
; CHECK-LABEL: @test_float_fsub_pzero_f32_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; f32 only attribute should flush float output
; same as pzero_out above
%result = fsub float 0x3800000000000000, 0x3810000000000000
ret float %result
}
define double @test_double_fsub_ieee() #0 {
; CHECK-LABEL: @test_double_fsub_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; default ieee mode leaves result as a denormal
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_fsub_pzero_out() #1 {
; CHECK-LABEL: @test_double_fsub_pzero_out(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_fsub_psign_out() #2 {
; CHECK-LABEL: @test_double_fsub_psign_out(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_fsub_pzero_in() #3 {
; CHECK-LABEL: @test_double_fsub_pzero_in(
; CHECK-NEXT: ret double 0x8010000000000000
;
; denormal operand is treated as zero
; normal operand subtracted from zero produces the same operand, negated
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_fsub_psign_in() #4 {
; CHECK-LABEL: @test_double_fsub_psign_in(
; CHECK-NEXT: ret double 0x8010000000000000
;
; denormal operand is treated as zero
; normal operand subtracted from zero produces the same operand, negated
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_fsub_f32_ieee() #5 {
; CHECK-LABEL: @test_double_fsub_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; f32 only attribute should not flush doubles
; default ieee mode leaves result as a denormal
%result = fsub double 0x0008000000000000, 0x0010000000000000
ret double %result
}
; ============================================================================ ;
; fmul tests
; Output modes are tested by multiplying the smallest normal number by 0.5,
; producing a denormal result. If denormal outputs should be flushed to zero,
; the result should be zero.
; Input modes are tested by the reverse operation: taking the denormal and
; multiplying by 2 to produce a normal number. If denormal inputs should be
; treated as zero, the result should also be zero.
; ============================================================================ ;
define float @test_float_fmul_ieee() #0 {
; CHECK-LABEL: @test_float_fmul_ieee(
; CHECK-NEXT: ret float 0xB800000000000000
;
; default ieee mode leaves result as a denormal
%result = fmul float 0x3810000000000000, -5.000000e-01
ret float %result
}
define float @test_float_fmul_pzero_out() #1 {
; CHECK-LABEL: @test_float_fmul_pzero_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fmul float 0x3810000000000000, -5.000000e-01
ret float %result
}
define float @test_float_fmul_psign_out() #2 {
; CHECK-LABEL: @test_float_fmul_psign_out(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fmul float 0x3810000000000000, -5.000000e-01
ret float %result
}
define float @test_float_fmul_pzero_in() #3 {
; CHECK-LABEL: @test_float_fmul_pzero_in(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal operand is treated as positive zero
; anything multiplied by zero gives a zero result
%result = fmul float 0xB800000000000000, 2.000000e-00
ret float %result
}
define float @test_float_fmul_psign_in() #4 {
; CHECK-LABEL: @test_float_fmul_psign_in(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal operand is treated as signed zero
; anything multiplied by zero gives a zero result
%result = fmul float 0xB800000000000000, 2.000000e-00
ret float %result
}
define float @test_float_fmul_pzero_f32_out() #1 {
; CHECK-LABEL: @test_float_fmul_pzero_f32_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; f32 only attribute should flush float output
; same as pzero_out above
%result = fmul float 0x3810000000000000, -5.000000e-01
ret float %result
}
define double @test_double_fmul_ieee() #0 {
; CHECK-LABEL: @test_double_fmul_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; default ieee mode leaves result as a denormal
%result = fmul double 0x00010000000000000, -5.000000e-01
ret double %result
}
define double @test_double_fmul_pzero_out() #1 {
; CHECK-LABEL: @test_double_fmul_pzero_out(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fmul double 0x00010000000000000, -5.000000e-01
ret double %result
}
define double @test_double_fmul_psign_out() #2 {
; CHECK-LABEL: @test_double_fmul_psign_out(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fmul double 0x0010000000000000, -5.000000e-01
ret double %result
}
define double @test_double_fmul_pzero_in() #3 {
; CHECK-LABEL: @test_double_fmul_pzero_in(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal operand is treated as positive zero
; anything multiplied by zero gives a zero result
%result = fmul double 0x8008000000000000, 2.000000e-00
ret double %result
}
define double @test_double_fmul_psign_in() #4 {
; CHECK-LABEL: @test_double_fmul_psign_in(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal operand is treated as signed zero
; anything multiplied by zero gives a zero result
%result = fmul double 0x8008000000000000, 2.000000e-00
ret double %result
}
define double @test_double_fmul_f32_ieee() #5 {
; CHECK-LABEL: @test_double_fmul_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; f32 only attribute should not flush doubles
; default ieee mode leaves result as a denormal
%result = fmul double 0x0010000000000000, -5.000000e-01
ret double %result
}
; ============================================================================ ;
; fdiv tests
; Output modes are tested by dividing the smallest normal number by 2,
; producing a denormal result. If denormal outputs should be flushed to zero,
; the result should be zero.
; Input modes are tested by the reverse operation: taking the denormal and
; dividing by 0.5 to produce a normal number. If denormal inputs should be
; treated as zero, the result should also be zero.
; ============================================================================ ;
define float @test_float_fdiv_ieee() #0 {
; CHECK-LABEL: @test_float_fdiv_ieee(
; CHECK-NEXT: ret float 0xB800000000000000
;
; default ieee mode leaves result as a denormal
%result = fdiv float 0x3810000000000000, -2.000000e-00
ret float %result
}
define float @test_float_fdiv_pzero_out() #1 {
; CHECK-LABEL: @test_float_fdiv_pzero_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fdiv float 0x3810000000000000, -2.000000e-00
ret float %result
}
define float @test_float_fdiv_psign_out() #2 {
; CHECK-LABEL: @test_float_fdiv_psign_out(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fdiv float 0x3810000000000000, -2.000000e-00
ret float %result
}
define float @test_float_fdiv_pzero_in() #3 {
; CHECK-LABEL: @test_float_fdiv_pzero_in(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal operand is treated as zero
; zero divided by anything gives a zero result
%result = fdiv float 0xB800000000000000, 5.000000e-01
ret float %result
}
define float @test_float_fdiv_psign_in() #4 {
; CHECK-LABEL: @test_float_fdiv_psign_in(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal operand is treated as zero
; zero divided by anything gives a zero result
%result = fmul float 0xB800000000000000, 5.000000e-01
ret float %result
}
define float @test_float_fdiv_pzero_f32_out() #1 {
; CHECK-LABEL: @test_float_fdiv_pzero_f32_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; f32 only attribute should flush float output
; same as pzero_out above
%result = fdiv float 0x3810000000000000, -2.000000e-00
ret float %result
}
define double @test_double_fdiv_ieee() #0 {
; CHECK-LABEL: @test_double_fdiv_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; default ieee mode leaves result as a denormal
%result = fdiv double 0x0010000000000000, -2.000000e-00
ret double %result
}
define double @test_double_fdiv_pzero_out() #1 {
; CHECK-LABEL: @test_double_fdiv_pzero_out(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal result is flushed to positive zero
%result = fdiv double 0x0010000000000000, -2.000000e-00
ret double %result
}
define double @test_double_fdiv_psign_out() #2 {
; CHECK-LABEL: @test_double_fdiv_psign_out(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = fdiv double 0x0010000000000000, -2.000000e-00
ret double %result
}
define double @test_double_fdiv_pzero_in() #3 {
; CHECK-LABEL: @test_double_fdiv_pzero_in(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal operand is treated as zero
; zero divided by anything gives a zero result
%result = fdiv double 0x8008000000000000, 5.000000e-01
ret double %result
}
define double @test_double_fdiv_psign_in() #4 {
; CHECK-LABEL: @test_double_fdiv_psign_in(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal operand is treated as zero
; zero divided by anything gives a zero result
%result = fdiv double 0x8008000000000000, 5.000000e-01
ret double %result
}
define double @test_double_fdiv_f32_ieee() #5 {
; CHECK-LABEL: @test_double_fdiv_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; f32 only attribute should not flush doubles
; default ieee mode leaves result as a denormal
%result = fdiv double 0x0010000000000000, -2.000000e-00
ret double %result
}
; ============================================================================ ;
; frem tests
; Output modes are tested by using two small normal numbers to produce a
; denormal result. If denormal outputs should be flushed to zero, the result
; should be zero.
; Input modes are tested by calculating the remainder of a denormal number
; and a larger normal number. If denormal inputs should be treated as zero
; the result also becomes zero.
; ============================================================================ ;
define float @test_float_frem_ieee_out() #0 {
; CHECK-LABEL: @test_float_frem_ieee_out(
; CHECK-NEXT: ret float 0xB800000000000000
;
; default ieee mode leaves result as a denormal
%result = frem float 0xB818000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_frem_pzero_out() #1 {
; CHECK-LABEL: @test_float_frem_pzero_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal result is flushed to positive zero
%result = frem float 0xB818000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_frem_psign_out() #2 {
; CHECK-LABEL: @test_float_frem_psign_out(
; CHECK-NEXT: ret float -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = frem float 0xB818000000000000, 0x3810000000000000
ret float %result
}
define float @test_float_frem_ieee_in() #0 {
; CHECK-LABEL: @test_float_frem_ieee_in(
; CHECK-NEXT: ret float 0x3800000000000000
;
; default ieee mode leaves result same as input
%result = frem float 0x3800000000000000, 2.000000e+00
ret float %result
}
define float @test_float_frem_pzero_in() #3 {
; CHECK-LABEL: @test_float_frem_pzero_in(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal operand is treated as zero
; remainder is now zero
%result = frem float 0x3800000000000000, 2.000000e+00
ret float %result
}
define float @test_float_frem_psign_in() #4 {
; CHECK-LABEL: @test_float_frem_psign_in(
; CHECK-NEXT: ret float 0.000000e+00
;
; denormal operand is treated as zero
; remainder is now zero
%result = frem float 0x3800000000000000, 2.000000e+00
ret float %result
}
define float @test_float_frem_pzero_f32_out() #1 {
; CHECK-LABEL: @test_float_frem_pzero_f32_out(
; CHECK-NEXT: ret float 0.000000e+00
;
; f32 only attribute should flush float output
; same as pzero_out above
%result = frem float 0xB818000000000000, 0x3810000000000000
ret float %result
}
define double @test_double_frem_ieee_out() #0 {
; CHECK-LABEL: @test_double_frem_ieee_out(
; CHECK-NEXT: ret double 0x8008000000000000
;
; default ieee mode leaves result as a denormal
%result = frem double 0x8018000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_frem_pzero_out() #1 {
; CHECK-LABEL: @test_double_frem_pzero_out(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal result is flushed to positive zero
%result = frem double 0x8018000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_frem_psign_out() #2 {
; CHECK-LABEL: @test_double_frem_psign_out(
; CHECK-NEXT: ret double -0.000000e+00
;
; denormal result is flushed to sign preserved zero
%result = frem double 0x8018000000000000, 0x0010000000000000
ret double %result
}
define double @test_double_frem_ieee_in() #0 {
; CHECK-LABEL: @test_double_frem_ieee_in(
; CHECK-NEXT: ret double 0x8000000000000
;
; default ieee mode leaves result same as input
%result = frem double 0x0008000000000000, 2.000000e+00
ret double %result
}
define double @test_double_frem_pzero_in() #3 {
; CHECK-LABEL: @test_double_frem_pzero_in(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal operand is treated as zero
; remainder is now zero
%result = frem double 0x0008000000000000, 2.000000e+00
ret double %result
}
define double @test_double_frem_psign_in() #4 {
; CHECK-LABEL: @test_double_frem_psign_in(
; CHECK-NEXT: ret double 0.000000e+00
;
; denormal operand is treated as zero
; remainder is now zero
%result = frem double 0x0008000000000000, 2.000000e+00
ret double %result
}
define double @test_double_frem_f32_ieee() #5 {
; CHECK-LABEL: @test_double_frem_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
; f32 only attribute should not flush doubles
; default ieee mode leaves result as a denormal
%result = frem double 0x8018000000000000, 0x0010000000000000
ret double %result
}
; ============================================================================ ;
; fneg tests
; fneg should NOT be affected by denormal handling mode
; these tests confirm fneg results are unchanged
; ============================================================================ ;
define float @test_float_fneg_ieee() #0 {
; CHECK-LABEL: @test_float_fneg_ieee(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define float @test_float_fneg_pzero_out() #0 {
; CHECK-LABEL: @test_float_fneg_pzero_out(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define float @test_float_fneg_psign_out() #0 {
; CHECK-LABEL: @test_float_fneg_psign_out(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define float @test_float_fneg_pzero_in() #0 {
; CHECK-LABEL: @test_float_fneg_pzero_in(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define float @test_float_fneg_psign_in() #0 {
; CHECK-LABEL: @test_float_fneg_psign_in(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define float @test_float_fneg_pzero_f32_out() #5 {
; CHECK-LABEL: @test_float_fneg_pzero_f32_out(
; CHECK-NEXT: ret float 0xB800000000000000
;
%result = fneg float 0x3800000000000000
ret float %result
}
define double @test_double_fneg_ieee() #0 {
; CHECK-LABEL: @test_double_fneg_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define double @test_double_fneg_pzero_out() #1 {
; CHECK-LABEL: @test_double_fneg_pzero_out(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define double @test_double_fneg_psign_out() #2 {
; CHECK-LABEL: @test_double_fneg_psign_out(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define double @test_double_fneg_pzero_in() #3 {
; CHECK-LABEL: @test_double_fneg_pzero_in(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define double @test_double_fneg_psign_in() #4 {
; CHECK-LABEL: @test_double_fneg_psign_in(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define double @test_double_fneg_f32_ieee() #5 {
; CHECK-LABEL: @test_double_fneg_f32_ieee(
; CHECK-NEXT: ret double 0x8008000000000000
;
%result = fneg double 0x0008000000000000
ret double %result
}
define i1 @fcmp_double_ieee_in_ieee_out() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_float_ieee_in_ieee_out() #0 {
; CHECK-LABEL: @fcmp_float_ieee_in_ieee_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp une float 0x3800000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out() #6 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_float_pz_in_pz_out() #6 {
; CHECK-LABEL: @fcmp_float_pz_in_pz_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une float 0x3800000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out() #7 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_float_ps_in_ps_out() #7 {
; CHECK-LABEL: @fcmp_float_ps_in_ps_out(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une float 0x3800000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_out_ieee_in() #1 {
; CHECK-LABEL: @fcmp_double_pz_out_ieee_in(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ps_out_ieee_in() #2 {
; CHECK-LABEL: @fcmp_double_ps_out_ieee_in(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_out_pz_in() #3 {
; CHECK-LABEL: @fcmp_double_ieee_out_pz_in(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_out_ps_in() #4 {
; CHECK-LABEL: @fcmp_double_ieee_out_ps_in(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_f32_pz_in() #8 {
; CHECK-LABEL: @fcmp_double_f32_pz_in(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_two_denormal_ins() #6 {
; CHECK-LABEL: @fcmp_double_two_denormal_ins(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp une double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_false() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_false(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp false double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_false() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_false(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp false double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_true() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_true(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp true double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_true() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_true(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp true double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_oeq() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_oeq(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp oeq double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_oeq() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_oeq(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp oeq double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_one() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_one(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp one double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_one() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_one(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp one double 0x0008100000000000, 0x0008000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_ord1() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_ord1(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ord double 0x0008000000000000, 0x7ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_ord1() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_ord1(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ord double 0x0008000000000000, 0x7ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ps_in_ps_out_ord2() #6 {
; CHECK-LABEL: @fcmp_double_ps_in_ps_out_ord2(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp ord double 0x0008000000000000, 0x1ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_ord2() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_ord2(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp ord double 0x0008000000000000, 0x1ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_ugt() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_ugt(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ugt double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_ugt() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_ugt(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp ugt double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_ult() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_ult(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ult double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_ult() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_ult(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ult double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_uge() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_uge(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp uge double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_uge() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_uge(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp uge double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_ule() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_ule(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp ule double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_ule() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_ule(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp ule double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_uno() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_uno(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp uno double 0x0008000000000000, 0x7ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_uno() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_uno(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 true
;
entry:
%cmp = fcmp uno double 0x0008000000000000, 0x7ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_pz_in_pz_out_uno2() #7 {
; CHECK-LABEL: @fcmp_double_pz_in_pz_out_uno2(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp uno double 0x0008000000000000, 0x1ff1000000000000
ret i1 %cmp
}
define i1 @fcmp_double_ieee_in_ieee_out_uno2() #0 {
; CHECK-LABEL: @fcmp_double_ieee_in_ieee_out_uno2(
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i1 false
;
entry:
%cmp = fcmp uno double 0x0008000000000000, 0x1ff1000000000000
ret i1 %cmp
}
; ============================================================================ ;
; dynamic mode tests
; ============================================================================ ;
define float @test_float_fadd_dynamic_ieee() #9 {
; CHECK-LABEL: @test_float_fadd_dynamic_ieee(
; CHECK-NEXT: [[RESULT:%.*]] = fadd float 0xB810000000000000, 0x3800000000000000
; CHECK-NEXT: ret float [[RESULT]]
;
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_ieee_dynamic() #10 {
; CHECK-LABEL: @test_float_fadd_ieee_dynamic(
; CHECK-NEXT: [[RESULT:%.*]] = fadd float 0xB810000000000000, 0x3800000000000000
; CHECK-NEXT: ret float [[RESULT]]
;
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
define float @test_float_fadd_dynamic_dynamic() #11 {
; CHECK-LABEL: @test_float_fadd_dynamic_dynamic(
; CHECK-NEXT: [[RESULT:%.*]] = fadd float 0xB810000000000000, 0x3800000000000000
; CHECK-NEXT: ret float [[RESULT]]
;
%result = fadd float 0xB810000000000000, 0x3800000000000000
ret float %result
}
; Check for failed to fold on each operand
define float @test_float_fadd_dynamic_dynamic_commute() #11 {
; CHECK-LABEL: @test_float_fadd_dynamic_dynamic_commute(
; CHECK-NEXT: [[RESULT:%.*]] = fadd float 0x3800000000000000, 0xB810000000000000
; CHECK-NEXT: ret float [[RESULT]]
;
%result = fadd float 0x3800000000000000, 0xB810000000000000
ret float %result
}
define i1 @fcmp_double_dynamic_ieee() #9 {
; CHECK-LABEL: @fcmp_double_dynamic_ieee(
; CHECK-NEXT: ret i1 true
;
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_ieee_dynamic() #10 {
; CHECK-LABEL: @fcmp_double_ieee_dynamic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double 0x8000000000000, 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_dynamic_dynamic() #11 {
; CHECK-LABEL: @fcmp_double_dynamic_dynamic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double 0x8000000000000, 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
define i1 @fcmp_double_dynamic_dynamic_commute() #11 {
; CHECK-LABEL: @fcmp_double_dynamic_dynamic_commute(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double 0.000000e+00, 0x8000000000000
; CHECK-NEXT: ret i1 [[CMP]]
;
%cmp = fcmp une double 0x0, 0x0008000000000000
ret i1 %cmp
}
; Output doesn't matter.
define i1 @fcmp_double_dynamic_psz() #12 {
; CHECK-LABEL: @fcmp_double_dynamic_psz(
; CHECK-NEXT: ret i1 false
;
%cmp = fcmp une double 0x0008000000000000, 0x0
ret i1 %cmp
}
; Non-denormal values should fold
define float @test_float_fadd_dynamic_dynamic_normals() #11 {
; CHECK-LABEL: @test_float_fadd_dynamic_dynamic_normals(
; CHECK-NEXT: ret float 3.000000e+00
;
%result = fadd float 1.0, 2.0
ret float %result
}
; Non-denormal values should fold
define i1 @fcmp_double_dynamic_dynamic_normals() #11 {
; CHECK-LABEL: @fcmp_double_dynamic_dynamic_normals(
; CHECK-NEXT: ret i1 true
;
%cmp = fcmp une double 1.0, 2.0
ret i1 %cmp
}
attributes #0 = { nounwind "denormal-fp-math"="ieee,ieee" }
attributes #1 = { nounwind "denormal-fp-math"="positive-zero,ieee" }
attributes #2 = { nounwind "denormal-fp-math"="preserve-sign,ieee" }
attributes #3 = { nounwind "denormal-fp-math"="ieee,positive-zero" }
attributes #4 = { nounwind "denormal-fp-math"="ieee,preserve-sign" }
attributes #5 = { nounwind "denormal-fp-math"="ieee,ieee" "denormal-fp-math-f32"="positive-zero,ieee" }
attributes #6 = { nounwind "denormal-fp-math"="positive-zero,positive-zero" }
attributes #7 = { nounwind "denormal-fp-math"="preserve-sign,preserve-sign" }
attributes #8 = { nounwind "denormal-fp-math"="ieee,ieee" "denormal-fp-math-f32"="positive-zero,positive-zero" }
attributes #9 = { nounwind "denormal-fp-math"="dynamic,ieee" }
attributes #10 = { nounwind "denormal-fp-math"="ieee,dynamic" }
attributes #11 = { nounwind "denormal-fp-math"="dynamic,dynamic" }
attributes #12 = { nounwind "denormal-fp-math"="dynamic,preserve-sign" }