Files
clang-p2996/llvm/test/Transforms/InstCombine/fcmp.ll
Nikita Popov a105877646 [InstCombine] Remove some of the complexity-based canonicalization (#91185)
The idea behind this canonicalization is that it allows us to handle less
patterns, because we know that some will be canonicalized away. This is
indeed very useful to e.g. know that constants are always on the right.

However, this is only useful if the canonicalization is actually
reliable. This is the case for constants, but not for arguments: Moving
these to the right makes it look like the "more complex" expression is
guaranteed to be on the left, but this is not actually the case in
practice. It fails as soon as you replace the argument with another
instruction.

The end result is that it looks like things correctly work in tests,
while they actually don't. We use the "thwart complexity-based
canonicalization" trick to handle this in tests, but it's often a
challenge for new contributors to get this right, and based on the
regressions this PR originally exposed, we clearly don't get this right
in many cases.

For this reason, I think that it's better to remove this complexity
canonicalization. It will make it much easier to write tests for
commuted cases and make sure that they are handled.
2024-08-21 12:02:54 +02:00

2353 lines
72 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
declare half @llvm.fabs.f16(half)
declare double @llvm.fabs.f64(double)
declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
declare double @llvm.copysign.f64(double, double)
declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>)
declare void @use(float)
define i1 @fpext_fpext(float %x, float %y) {
; CHECK-LABEL: @fpext_fpext(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext1 = fpext float %x to double
%ext2 = fpext float %y to double
%cmp = fcmp nnan ogt double %ext1, %ext2
ret i1 %cmp
}
define i1 @fpext_constant(float %a) {
; CHECK-LABEL: @fpext_constant(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[A:%.*]], 1.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ninf ogt double %ext, 1.000000e+00
ret i1 %cmp
}
define <2 x i1> @fpext_constant_vec_splat(<2 x half> %a) {
; CHECK-LABEL: @fpext_constant_vec_splat(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ole <2 x half> [[A:%.*]], <half 0xH5140, half 0xH5140>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%ext = fpext <2 x half> %a to <2 x double>
%cmp = fcmp nnan ole <2 x double> %ext, <double 42.0, double 42.0>
ret <2 x i1> %cmp
}
define i1 @fpext_constant_lossy(float %a) {
; CHECK-LABEL: @fpext_constant_lossy(
; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float.
ret i1 %cmp
}
define i1 @fpext_constant_denorm(float %a) {
; CHECK-LABEL: @fpext_constant_denorm(
; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float.
ret i1 %cmp
}
define i1 @fneg_constant_swap_pred(float %x) {
; CHECK-LABEL: @fneg_constant_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg = fsub float -0.0, %x
%cmp = fcmp ogt float %neg, 1.0
ret i1 %cmp
}
define i1 @unary_fneg_constant_swap_pred(float %x) {
; CHECK-LABEL: @unary_fneg_constant_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg = fneg float %x
%cmp = fcmp ogt float %neg, 1.0
ret i1 %cmp
}
define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) {
; CHECK-LABEL: @fneg_constant_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
%cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
ret <2 x i1> %cmp
}
define <2 x i1> @unary_fneg_constant_swap_pred_vec(<2 x float> %x) {
; CHECK-LABEL: @unary_fneg_constant_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg = fneg <2 x float> %x
%cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
ret <2 x i1> %cmp
}
define <2 x i1> @fneg_constant_swap_pred_vec_poison(<2 x float> %x) {
; CHECK-LABEL: @fneg_constant_swap_pred_vec_poison(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg = fsub <2 x float> <float poison, float -0.0>, %x
%cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
ret <2 x i1> %cmp
}
; The new fcmp should have the same FMF as the original.
define i1 @fneg_fmf(float %x) {
; CHECK-LABEL: @fneg_fmf(
; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01
; CHECK-NEXT: ret i1 [[R]]
;
%n = fsub fast float -0.0, %x
%r = fcmp fast oeq float %n, 42.0
ret i1 %r
}
define i1 @unary_fneg_fmf(float %x) {
; CHECK-LABEL: @unary_fneg_fmf(
; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01
; CHECK-NEXT: ret i1 [[R]]
;
%n = fneg fast float %x
%r = fcmp fast oeq float %n, 42.0
ret i1 %r
}
; The new fcmp should have the same FMF as the original, vector edition.
define <2 x i1> @fcmp_fneg_fmf_vec(<2 x float> %x) {
; CHECK-LABEL: @fcmp_fneg_fmf_vec(
; CHECK-NEXT: [[R:%.*]] = fcmp reassoc nnan ule <2 x float> [[X:%.*]], <float -4.200000e+01, float 1.900000e+01>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%n = fsub nsz <2 x float> zeroinitializer, %x
%r = fcmp nnan reassoc uge <2 x float> %n, <float 42.0, float -19.0>
ret <2 x i1> %r
}
define i1 @fneg_fneg_swap_pred(float %x, float %y) {
; CHECK-LABEL: @fneg_fneg_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg1 = fsub float -0.0, %x
%neg2 = fsub float -0.0, %y
%cmp = fcmp nnan olt float %neg1, %neg2
ret i1 %cmp
}
define i1 @unary_fneg_unary_fneg_swap_pred(float %x, float %y) {
; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg1 = fneg float %x
%neg2 = fneg float %y
%cmp = fcmp nnan olt float %neg1, %neg2
ret i1 %cmp
}
define i1 @unary_fneg_fneg_swap_pred(float %x, float %y) {
; CHECK-LABEL: @unary_fneg_fneg_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg1 = fneg float %x
%neg2 = fsub float -0.0, %y
%cmp = fcmp nnan olt float %neg1, %neg2
ret i1 %cmp
}
define i1 @fneg_unary_fneg_swap_pred(float %x, float %y) {
; CHECK-LABEL: @fneg_unary_fneg_swap_pred(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg1 = fsub float -0.0, %x
%neg2 = fneg float %y
%cmp = fcmp nnan olt float %neg1, %neg2
ret i1 %cmp
}
define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_fneg_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x
%neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y
%cmp = fcmp ninf olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @unary_fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fneg <2 x float> %x
%neg2 = fneg <2 x float> %y
%cmp = fcmp ninf olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @unary_fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fneg <2 x float> %x
%neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y
%cmp = fcmp ninf olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x
%neg2 = fneg <2 x float> %y
%cmp = fcmp ninf olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @fneg_fneg_swap_pred_vec_poison(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_fneg_swap_pred_vec_poison(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fsub <2 x float> <float -0.0, float poison>, %x
%neg2 = fsub <2 x float> <float poison, float -0.0>, %y
%cmp = fcmp olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @unary_fneg_fneg_swap_pred_vec_poison(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec_poison(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fneg <2 x float> %x
%neg2 = fsub <2 x float> <float poison, float -0.0>, %y
%cmp = fcmp olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define <2 x i1> @fneg_unary_fneg_swap_pred_vec_poison(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec_poison(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%neg1 = fsub <2 x float> <float -0.0, float poison>, %x
%neg2 = fneg <2 x float> %y
%cmp = fcmp olt <2 x float> %neg1, %neg2
ret <2 x i1> %cmp
}
define i1 @test7(float %x) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %x to ppc_fp128
%cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000
ret i1 %cmp
}
define float @test8(float %x) {
; CHECK-LABEL: @test8(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float
; CHECK-NEXT: ret float [[CONV2]]
;
%conv = fpext float %x to double
%cmp = fcmp olt double %conv, 0.000000e+00
%conv1 = zext i1 %cmp to i32
%conv2 = sitofp i32 %conv1 to float
ret float %conv2
; Float comparison to zero shouldn't cast to double.
}
define i1 @fabs_uge(double %a) {
; CHECK-LABEL: @fabs_uge(
; CHECK-NEXT: ret i1 true
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp uge double %call, 0.0
ret i1 %cmp
}
define i1 @fabs_olt(half %a) {
; CHECK-LABEL: @fabs_olt(
; CHECK-NEXT: ret i1 false
;
%call = call half @llvm.fabs.f16(half %a)
%cmp = fcmp olt half %call, 0.0
ret i1 %cmp
}
define <2 x i1> @fabs_ole(<2 x float> %a) {
; CHECK-LABEL: @fabs_ole(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oeq <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp ninf ole <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
define <2 x i1> @fabs_ule(<2 x float> %a) {
; CHECK-LABEL: @fabs_ule(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf arcp ueq <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp ninf arcp ule <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
define i1 @fabs_ogt(double %a) {
; CHECK-LABEL: @fabs_ogt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc one double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp reassoc ogt double %call, 0.0
ret i1 %cmp
}
define i1 @fabs_ugt(double %a) {
; CHECK-LABEL: @fabs_ugt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf une double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp ninf reassoc ugt double %call, 0.0
ret i1 %cmp
}
define i1 @fabs_oge(double %a) {
; CHECK-LABEL: @fabs_oge(
; CHECK-NEXT: [[CMP:%.*]] = fcmp afn ord double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp afn oge double %call, 0.0
ret i1 %cmp
}
define i1 @fabs_ult(double %a) {
; CHECK-LABEL: @fabs_ult(
; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc arcp uno double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp reassoc arcp ult double %call, 0.0
ret i1 %cmp
}
define <2 x i1> @fabs_ult_nnan(<2 x float> %a) {
; CHECK-LABEL: @fabs_ult_nnan(
; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp nnan reassoc arcp ult <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
define i1 @fabs_une(half %a) {
; CHECK-LABEL: @fabs_une(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une half [[A:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call half @llvm.fabs.f16(half %a)
%cmp = fcmp ninf une half %call, 0.0
ret i1 %cmp
}
define i1 @fabs_oeq(double %a) {
; CHECK-LABEL: @fabs_oeq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf oeq double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp ninf reassoc oeq double %call, 0.0
ret i1 %cmp
}
define i1 @fabs_one(double %a) {
; CHECK-LABEL: @fabs_one(
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast one double [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%call = call double @llvm.fabs.f64(double %a)
%cmp = fcmp fast one double %call, 0.0
ret i1 %cmp
}
define <2 x i1> @fabs_ueq(<2 x float> %a) {
; CHECK-LABEL: @fabs_ueq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ueq <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp arcp ueq <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
define <2 x i1> @fabs_ord(<2 x float> %a) {
; CHECK-LABEL: @fabs_ord(
; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ord <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp arcp ord <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
define <2 x i1> @fabs_uno(<2 x float> %a) {
; CHECK-LABEL: @fabs_uno(
; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp uno <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
%cmp = fcmp arcp uno <2 x float> %call, zeroinitializer
ret <2 x i1> %cmp
}
; Don't crash.
define i32 @test17(double %a, ptr %p) {
; CHECK-LABEL: @test17(
; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double %p(double %a)
%cmp = fcmp ueq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
}
; Can fold fcmp with undef on one side by choosing NaN for the undef
define i32 @test18_undef_unordered(float %a) {
; CHECK-LABEL: @test18_undef_unordered(
; CHECK-NEXT: ret i32 1
;
%cmp = fcmp ueq float %a, undef
%conv = zext i1 %cmp to i32
ret i32 %conv
}
; Can fold fcmp with undef on one side by choosing NaN for the undef
define i32 @test18_undef_ordered(float %a) {
; CHECK-LABEL: @test18_undef_ordered(
; CHECK-NEXT: ret i32 0
;
%cmp = fcmp oeq float %a, undef
%conv = zext i1 %cmp to i32
ret i32 %conv
}
; Can fold fcmp with undef on both side
; fcmp u_pred undef, undef -> true
; fcmp o_pred undef, undef -> false
; because whatever you choose for the first undef
; you can choose NaN for the other undef
define i1 @test19_undef_unordered() {
; CHECK-LABEL: @test19_undef_unordered(
; CHECK-NEXT: ret i1 true
;
%cmp = fcmp ueq float undef, undef
ret i1 %cmp
}
define i1 @test19_undef_ordered() {
; CHECK-LABEL: @test19_undef_ordered(
; CHECK-NEXT: ret i1 false
;
%cmp = fcmp oeq float undef, undef
ret i1 %cmp
}
; Can fold 1.0 / X < 0.0 --> X < 0 with ninf
define i1 @test20_recipX_olt_0(float %X) {
; CHECK-LABEL: @test20_recipX_olt_0(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float 1.0, %X
%cmp = fcmp ninf olt float %div, 0.0
ret i1 %cmp
}
; Can fold -2.0 / X <= 0.0 --> X >= 0 with ninf
define i1 @test21_recipX_ole_0(float %X) {
; CHECK-LABEL: @test21_recipX_ole_0(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float -2.0, %X
%cmp = fcmp ninf ole float %div, 0.0
ret i1 %cmp
}
; Can fold 2.0 / X > 0.0 --> X > 0 with ninf
define i1 @test22_recipX_ogt_0(float %X) {
; CHECK-LABEL: @test22_recipX_ogt_0(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float 2.0, %X
%cmp = fcmp ninf ogt float %div, 0.0
ret i1 %cmp
}
; Can fold -1.0 / X >= 0.0 --> X <= 0 with ninf
define i1 @test23_recipX_oge_0(float %X) {
; CHECK-LABEL: @test23_recipX_oge_0(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float -1.0, %X
%cmp = fcmp ninf oge float %div, 0.0
ret i1 %cmp
}
; Do not fold 1.0 / X > 0.0 when ninf is missing
define i1 @test24_recipX_noninf_cmp(float %X) {
; CHECK-LABEL: @test24_recipX_noninf_cmp(
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[DIV]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float 2.0, %X
%cmp = fcmp ogt float %div, 0.0
ret i1 %cmp
}
; Do not fold 1.0 / X > 0.0 when ninf is missing
define i1 @test25_recipX_noninf_div(float %X) {
; CHECK-LABEL: @test25_recipX_noninf_div(
; CHECK-NEXT: [[DIV:%.*]] = fdiv float 2.000000e+00, [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[DIV]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv float 2.0, %X
%cmp = fcmp ninf ogt float %div, 0.0
ret i1 %cmp
}
; Do not fold 1.0 / X > 0.0 with unordered predicates
define i1 @test26_recipX_unorderd(float %X) {
; CHECK-LABEL: @test26_recipX_unorderd(
; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ugt float [[DIV]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%div = fdiv ninf float 2.0, %X
%cmp = fcmp ninf ugt float %div, 0.0
ret i1 %cmp
}
; Fold <-1.0, -1.0> / X > <-0.0, -0.0>
define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) {
; CHECK-LABEL: @test27_recipX_gt_vecsplat(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%div = fdiv ninf <2 x float> <float -1.0, float -1.0>, %X
%cmp = fcmp ninf ogt <2 x float> %div, <float -0.0, float -0.0>
ret <2 x i1> %cmp
}
define i1 @is_signbit_set(double %x) {
; CHECK-LABEL: @is_signbit_set(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
%r = fcmp olt double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_set_1(double %x) {
; CHECK-LABEL: @is_signbit_set_1(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ult double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
%r = fcmp ult double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_set_2(double %x) {
; CHECK-LABEL: @is_signbit_set_2(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ole double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
%r = fcmp ole double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_set_3(double %x) {
; CHECK-LABEL: @is_signbit_set_3(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ule double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
%r = fcmp ule double %s, 0.0
ret i1 %r
}
; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number.
define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
; CHECK-LABEL: @is_signbit_set_anyzero(
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64>
; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%s = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 42.0, double 42.0>, <2 x double> %x)
%r = fcmp olt <2 x double> %s, <double -0.0, double 0.0>
ret <2 x i1> %r
}
; TODO: Handle different predicates.
define i1 @is_signbit_clear(double %x) {
; CHECK-LABEL: @is_signbit_clear(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double -42.0, double %x)
%r = fcmp ogt double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_clear_1(double %x) {
; CHECK-LABEL: @is_signbit_clear_1(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ugt double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double -42.0, double %x)
%r = fcmp ugt double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_clear_2(double %x) {
; CHECK-LABEL: @is_signbit_clear_2(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp oge double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double -42.0, double %x)
%r = fcmp oge double %s, 0.0
ret i1 %r
}
define i1 @is_signbit_clear_3(double %x) {
; CHECK-LABEL: @is_signbit_clear_3(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp uge double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double -42.0, double %x)
%r = fcmp uge double %s, 0.0
ret i1 %r
}
; Negative test - uses
define i1 @is_signbit_set_extra_use(double %x, ptr %p) {
; CHECK-LABEL: @is_signbit_set_extra_use(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
; CHECK-NEXT: store double [[S]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[S]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double 1.0, double %x)
store double %s, ptr %p
%r = fcmp olt double %s, 0.0
ret i1 %r
}
; TODO: Handle non-zero compare constant.
define i1 @is_signbit_clear_nonzero(double %x) {
; CHECK-LABEL: @is_signbit_clear_nonzero(
; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]])
; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 1.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%s = call double @llvm.copysign.f64(double -42.0, double %x)
%r = fcmp ogt double %s, 1.0
ret i1 %r
}
; TODO: Handle zero copysign constant.
define i1 @is_signbit_set_simplify_zero(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_zero(
; CHECK-NEXT: ret i1 false
;
%s = call double @llvm.copysign.f64(double 0.0, double %x)
%r = fcmp ogt double %s, 0.0
ret i1 %r
}
; TODO: Handle NaN copysign constant.
define i1 @is_signbit_set_simplify_nan(double %x) {
; CHECK-LABEL: @is_signbit_set_simplify_nan(
; CHECK-NEXT: ret i1 false
;
%s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
%r = fcmp ogt double %s, 0.0
ret i1 %r
}
define <2 x i1> @lossy_oeq(<2 x float> %x) {
; CHECK-LABEL: @lossy_oeq(
; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%e = fpext <2 x float> %x to <2 x double>
%r = fcmp oeq <2 x double> %e, <double 0.1, double 0.1>
ret <2 x i1> %r
}
define i1 @lossy_one(float %x, ptr %p) {
; CHECK-LABEL: @lossy_one(
; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double
; CHECK-NEXT: store double [[E]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[R:%.*]] = fcmp ord float [[X]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext float %x to double
store double %e, ptr %p
%r = fcmp one double %e, 0.1
ret i1 %r
}
define i1 @lossy_ueq(half %x) {
; CHECK-LABEL: @lossy_ueq(
; CHECK-NEXT: [[R:%.*]] = fcmp uno half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to double
%r = fcmp ueq double %e, 65536.0
ret i1 %r
}
define i1 @lossy_une(half %x) {
; CHECK-LABEL: @lossy_une(
; CHECK-NEXT: ret i1 true
;
%e = fpext half %x to float
%r = fcmp une float %e, 2049.0
ret i1 %r
}
define <2 x i1> @lossy_ogt(<2 x float> %x) {
; CHECK-LABEL: @lossy_ogt(
; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
; CHECK-NEXT: [[R:%.*]] = fcmp ogt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%e = fpext <2 x float> %x to <2 x double>
%r = fcmp ogt <2 x double> %e, <double 0.1, double 0.1>
ret <2 x i1> %r
}
define i1 @lossy_oge(float %x, ptr %p) {
; CHECK-LABEL: @lossy_oge(
; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double
; CHECK-NEXT: store double [[E]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[R:%.*]] = fcmp oge double [[E]], 1.000000e-01
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext float %x to double
store double %e, ptr %p
%r = fcmp oge double %e, 0.1
ret i1 %r
}
define i1 @lossy_olt(half %x) {
; CHECK-LABEL: @lossy_olt(
; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double
; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[E]], 6.553600e+04
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to double
%r = fcmp olt double %e, 65536.0
ret i1 %r
}
define i1 @lossy_ole(half %x) {
; CHECK-LABEL: @lossy_ole(
; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float
; CHECK-NEXT: [[R:%.*]] = fcmp ole float [[E]], 2.049000e+03
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to float
%r = fcmp ole float %e, 2049.0
ret i1 %r
}
define <2 x i1> @lossy_ugt(<2 x float> %x) {
; CHECK-LABEL: @lossy_ugt(
; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
; CHECK-NEXT: [[R:%.*]] = fcmp ugt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01>
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%e = fpext <2 x float> %x to <2 x double>
%r = fcmp ugt <2 x double> %e, <double 0.1, double 0.1>
ret <2 x i1> %r
}
define i1 @lossy_uge(float %x, ptr %p) {
; CHECK-LABEL: @lossy_uge(
; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double
; CHECK-NEXT: store double [[E]], ptr [[P:%.*]], align 8
; CHECK-NEXT: [[R:%.*]] = fcmp uge double [[E]], 1.000000e-01
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext float %x to double
store double %e, ptr %p
%r = fcmp uge double %e, 0.1
ret i1 %r
}
define i1 @lossy_ult(half %x) {
; CHECK-LABEL: @lossy_ult(
; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double
; CHECK-NEXT: [[R:%.*]] = fcmp ult double [[E]], 6.553600e+04
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to double
%r = fcmp ult double %e, 65536.0
ret i1 %r
}
define i1 @lossy_ule(half %x) {
; CHECK-LABEL: @lossy_ule(
; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float
; CHECK-NEXT: [[R:%.*]] = fcmp ule float [[E]], 2.049000e+03
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to float
%r = fcmp ule float %e, 2049.0
ret i1 %r
}
define i1 @lossy_ord(half %x) {
; CHECK-LABEL: @lossy_ord(
; CHECK-NEXT: [[R:%.*]] = fcmp ord half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to double
%r = fcmp ord double %e, 65536.0
ret i1 %r
}
define i1 @lossy_uno(half %x) {
; CHECK-LABEL: @lossy_uno(
; CHECK-NEXT: [[R:%.*]] = fcmp uno half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[R]]
;
%e = fpext half %x to float
%r = fcmp uno float %e, 2049.0
ret i1 %r
}
define i1 @fneg_oeq(float %a) {
; CHECK-LABEL: @fneg_oeq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp oeq float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ogt(half %a) {
; CHECK-LABEL: @fneg_ogt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt half [[A:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg half %a
%cmp = fcmp fast ogt half %fneg, %a
ret i1 %cmp
}
define <2 x i1> @fneg_oge(<2 x float> %a) {
; CHECK-LABEL: @fneg_oge(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ole <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%fneg = fneg fast <2 x float> %a
%cmp = fcmp oge <2 x float> %fneg, %a
ret <2 x i1> %cmp
}
define i1 @fneg_olt(float %a, ptr %q) {
; CHECK-LABEL: @fneg_olt(
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
; CHECK-NEXT: store float [[FNEG]], ptr [[Q:%.*]], align 4
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
store float %fneg, ptr %q
%cmp = fcmp olt float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ole(float %a) {
; CHECK-LABEL: @fneg_ole(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz oge float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp nsz ole float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_one(float %a) {
; CHECK-LABEL: @fneg_one(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp nnan one float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ord(float %a) {
; CHECK-LABEL: @fneg_ord(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp ninf ord float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_uno(float %a) {
; CHECK-LABEL: @fneg_uno(
; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp uno float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ueq(half %a) {
; CHECK-LABEL: @fneg_ueq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg half %a
%cmp = fcmp fast ueq half %fneg, %a
ret i1 %cmp
}
define <2 x i1> @fneg_ugt(<2 x float> %a) {
; CHECK-LABEL: @fneg_ugt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult <2 x float> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%fneg = fneg fast <2 x float> %a
%cmp = fcmp ugt <2 x float> %fneg, %a
ret <2 x i1> %cmp
}
define i1 @fneg_uge(float %a, ptr %q) {
; CHECK-LABEL: @fneg_uge(
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]]
; CHECK-NEXT: store float [[FNEG]], ptr [[Q:%.*]], align 4
; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
store float %fneg, ptr %q
%cmp = fcmp uge float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ult(float %a) {
; CHECK-LABEL: @fneg_ult(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ugt float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp nsz ult float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_ule(float %a) {
; CHECK-LABEL: @fneg_ule(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan uge float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp nnan ule float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_une(float %a) {
; CHECK-LABEL: @fneg_une(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fneg = fneg float %a
%cmp = fcmp ninf une float %fneg, %a
ret i1 %cmp
}
define i1 @fneg_oeq_swap(float %p) {
; CHECK-LABEL: @fneg_oeq_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp oeq float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ogt_swap(half %p) {
; CHECK-LABEL: @fneg_ogt_swap(
; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt half [[A]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd half %p, %p ; thwart complexity-based canonicalization
%fneg = fneg half %a
%cmp = fcmp fast ogt half %a, %fneg
ret i1 %cmp
}
define <2 x i1> @fneg_oge_swap(<2 x float> %p) {
; CHECK-LABEL: @fneg_oge_swap(
; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <2 x float> [[A]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
%fneg = fneg fast <2 x float> %a
%cmp = fcmp oge <2 x float> %a, %fneg
ret <2 x i1> %cmp
}
define i1 @fneg_olt_swap(float %p, ptr %q) {
; CHECK-LABEL: @fneg_olt_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
; CHECK-NEXT: store float [[FNEG]], ptr [[Q:%.*]], align 4
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
store float %fneg, ptr %q
%cmp = fcmp olt float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ole_swap(float %p) {
; CHECK-LABEL: @fneg_ole_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ole float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp nsz ole float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_one_swap(float %p) {
; CHECK-LABEL: @fneg_one_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp nnan one float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ord_swap(float %p) {
; CHECK-LABEL: @fneg_ord_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp ninf ord float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_uno_swap(float %p) {
; CHECK-LABEL: @fneg_uno_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp uno float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ueq_swap(half %p) {
; CHECK-LABEL: @fneg_ueq_swap(
; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd half %p, %p ; thwart complexity-based canonicalization
%fneg = fneg half %a
%cmp = fcmp fast ueq half %a, %fneg
ret i1 %cmp
}
define <2 x i1> @fneg_ugt_swap(<2 x float> %p) {
; CHECK-LABEL: @fneg_ugt_swap(
; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[A]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
%fneg = fneg fast <2 x float> %a
%cmp = fcmp ugt <2 x float> %a, %fneg
ret <2 x i1> %cmp
}
define i1 @fneg_uge_swap(float %p, ptr %q) {
; CHECK-LABEL: @fneg_uge_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]]
; CHECK-NEXT: store float [[FNEG]], ptr [[Q:%.*]], align 4
; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
store float %fneg, ptr %q
%cmp = fcmp uge float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ult_swap(float %p) {
; CHECK-LABEL: @fneg_ult_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp nsz ult float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_ule_swap(float %p) {
; CHECK-LABEL: @fneg_ule_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp nnan ule float %a, %fneg
ret i1 %cmp
}
define i1 @fneg_une_swap(float %p) {
; CHECK-LABEL: @fneg_une_swap(
; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = fadd float %p, %p ; thwart complexity-based canonicalization
%fneg = fneg float %a
%cmp = fcmp ninf une float %a, %fneg
ret i1 %cmp
}
define i1 @bitcast_eq0(i32 %x) {
; CHECK-LABEL: @bitcast_eq0(
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 2147483647
; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%f = bitcast i32 %x to float
%r = fcmp oeq float %f, 0.0
ret i1 %r
}
define <2 x i1> @bitcast_ne0(<2 x i32> %x) {
; CHECK-LABEL: @bitcast_ne0(
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 2147483647, i32 2147483647>
; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%f = bitcast <2 x i32> %x to <2 x float>
%r = fcmp une <2 x float> %f, <float 0.0, float 0.0>
ret <2 x i1> %r
}
; negative test - extra use
define i1 @bitcast_eq0_use(i32 %x) {
; CHECK-LABEL: @bitcast_eq0_use(
; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to float
; CHECK-NEXT: call void @use(float [[F]])
; CHECK-NEXT: [[R:%.*]] = fcmp oeq float [[F]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%f = bitcast i32 %x to float
call void @use(float %f)
%r = fcmp oeq float %f, 0.0
ret i1 %r
}
; negative test - this could be transformed, but requires a new bitcast
define i1 @bitcast_nonint_eq0(<2 x i16> %x) {
; CHECK-LABEL: @bitcast_nonint_eq0(
; CHECK-NEXT: [[F:%.*]] = bitcast <2 x i16> [[X:%.*]] to float
; CHECK-NEXT: [[R:%.*]] = fcmp ogt float [[F]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%f = bitcast <2 x i16> %x to float
%r = fcmp ogt float %f, 0.0
ret i1 %r
}
; negative test - wrong predicate
define i1 @bitcast_gt0(i32 %x) {
; CHECK-LABEL: @bitcast_gt0(
; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to float
; CHECK-NEXT: [[R:%.*]] = fcmp ogt float [[F]], 0.000000e+00
; CHECK-NEXT: ret i1 [[R]]
;
%f = bitcast i32 %x to float
%r = fcmp ogt float %f, 0.0
ret i1 %r
}
; negative test - this could be transformed, but requires a new bitcast
define <1 x i1> @bitcast_1vec_eq0(i32 %x) {
; CHECK-LABEL: @bitcast_1vec_eq0(
; CHECK-NEXT: [[F:%.*]] = bitcast i32 [[X:%.*]] to <1 x float>
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <1 x float> [[F]], zeroinitializer
; CHECK-NEXT: ret <1 x i1> [[CMP]]
;
%f = bitcast i32 %x to <1 x float>
%cmp = fcmp oeq <1 x float> %f, zeroinitializer
ret <1 x i1> %cmp
}
; Simplify fcmp (x + 0.0), y => fcmp x, y
define i1 @fcmp_fadd_zero_ugt(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ugt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ugt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_uge(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_uge(
; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp uge float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ogt(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ogt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ogt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_oge(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_oge(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp oge float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ult(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ult(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ult float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ule(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ule(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ule float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_olt(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_olt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp olt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ole(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ole(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ole float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ole float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_oeq(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_oeq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp oeq float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_one(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_one(
; CHECK-NEXT: [[CMP:%.*]] = fcmp one float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp one float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ueq(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ueq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ueq float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_une(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_une(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp une float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_ord(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_ord(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp ord float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_uno(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_uno(
; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp uno float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_neg_zero(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_neg_zero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, -0.000000e+00
%cmp = fcmp ugt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_zero_switched(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_zero_switched(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %y, 0.000000e+00
%cmp = fcmp ugt float %x, %add
ret i1 %cmp
}
define <2 x i1> @fcmp_fadd_zero_vec(<2 x float> %x, <2 x float> %y) {
; CHECK-LABEL: @fcmp_fadd_zero_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%add = fadd <2 x float> %x, <float 0.0, float -0.0>
%cmp = fcmp ugt <2 x float> %add, %y
ret <2 x i1> %cmp
}
define i1 @fcmp_fast_fadd_fast_zero(float %x, float %y) {
; CHECK-LABEL: @fcmp_fast_fadd_fast_zero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd fast float %x, 0.000000e+00
%cmp = fcmp fast ugt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fast_fadd_zero(float %x, float %y) {
; CHECK-LABEL: @fcmp_fast_fadd_zero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd float %x, 0.000000e+00
%cmp = fcmp fast ugt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_fadd_fast_zero(float %x, float %y) {
; CHECK-LABEL: @fcmp_fadd_fast_zero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add = fadd fast float %x, 0.000000e+00
%cmp = fcmp ugt float %add, %y
ret i1 %cmp
}
define i1 @fcmp_ueq_sel_x_negx(float %x) {
; CHECK-LABEL: @fcmp_ueq_sel_x_negx(
; CHECK-NEXT: [[RES:%.*]] = fcmp ueq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp ueq float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp ueq float %sel, 0.000000e+00
ret i1 %res
}
define i1 @fcmp_une_sel_x_negx(float %x) {
; CHECK-LABEL: @fcmp_une_sel_x_negx(
; CHECK-NEXT: [[RES:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp une float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp une float %sel, 0.000000e+00
ret i1 %res
}
define i1 @fcmp_oeq_sel_x_negx(float %x) {
; CHECK-LABEL: @fcmp_oeq_sel_x_negx(
; CHECK-NEXT: [[RES:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp oeq float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp oeq float %sel, 0.000000e+00
ret i1 %res
}
define i1 @fcmp_one_sel_x_negx(float %x) {
; CHECK-LABEL: @fcmp_one_sel_x_negx(
; CHECK-NEXT: [[RES:%.*]] = fcmp one float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp one float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp one float %sel, 0.000000e+00
ret i1 %res
}
define i1 @fcmp_ueq_sel_x_negx_nzero(float %x) {
; CHECK-LABEL: @fcmp_ueq_sel_x_negx_nzero(
; CHECK-NEXT: [[RES:%.*]] = fcmp ueq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp ueq float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp ueq float %sel, -0.000000e+00
ret i1 %res
}
define i1 @fcmp_une_sel_x_negx_nzero(float %x) {
; CHECK-LABEL: @fcmp_une_sel_x_negx_nzero(
; CHECK-NEXT: [[RES:%.*]] = fcmp une float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp une float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp une float %sel, -0.000000e+00
ret i1 %res
}
define i1 @fcmp_oeq_sel_x_negx_nzero(float %x) {
; CHECK-LABEL: @fcmp_oeq_sel_x_negx_nzero(
; CHECK-NEXT: [[RES:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp oeq float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp oeq float %sel, -0.000000e+00
ret i1 %res
}
define i1 @fcmp_one_sel_x_negx_nzero(float %x) {
; CHECK-LABEL: @fcmp_one_sel_x_negx_nzero(
; CHECK-NEXT: [[RES:%.*]] = fcmp one float [[X:%.*]], 0.000000e+00
; CHECK-NEXT: ret i1 [[RES]]
;
%f = fcmp one float %x, 0.000000e+00
%neg = fneg float %x
%sel = select i1 %f, float %x, float %neg
%res = fcmp one float %sel, -0.000000e+00
ret i1 %res
}
define <8 x i1> @fcmp_ueq_sel_x_negx_vec(<8 x float> %x) {
; CHECK-LABEL: @fcmp_ueq_sel_x_negx_vec(
; CHECK-NEXT: [[RES:%.*]] = fcmp ueq <8 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[RES]]
;
%f = fcmp ueq <8 x float> %x, zeroinitializer
%neg = fneg <8 x float> %x
%sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg
%res = fcmp ueq <8 x float> %sel, zeroinitializer
ret <8 x i1> %res
}
define <8 x i1> @fcmp_une_sel_x_negx_vec(<8 x float> %x) {
; CHECK-LABEL: @fcmp_une_sel_x_negx_vec(
; CHECK-NEXT: [[RES:%.*]] = fcmp une <8 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[RES]]
;
%f = fcmp une <8 x float> %x, zeroinitializer
%neg = fneg <8 x float> %x
%sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg
%res = fcmp une <8 x float> %sel, zeroinitializer
ret <8 x i1> %res
}
define <8 x i1> @fcmp_oeq_sel_x_negx_vec(<8 x float> %x) {
; CHECK-LABEL: @fcmp_oeq_sel_x_negx_vec(
; CHECK-NEXT: [[RES:%.*]] = fcmp oeq <8 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[RES]]
;
%f = fcmp oeq <8 x float> %x, zeroinitializer
%neg = fneg <8 x float> %x
%sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg
%res = fcmp oeq <8 x float> %sel, zeroinitializer
ret <8 x i1> %res
}
define <8 x i1> @fcmp_one_sel_x_negx_vec(<8 x float> %x) {
; CHECK-LABEL: @fcmp_one_sel_x_negx_vec(
; CHECK-NEXT: [[RES:%.*]] = fcmp one <8 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[RES]]
;
%f = fcmp one <8 x float> %x, zeroinitializer
%neg = fneg <8 x float> %x
%sel = select <8 x i1> %f, <8 x float> %x, <8 x float> %neg
%res = fcmp one <8 x float> %sel, zeroinitializer
ret <8 x i1> %res
}
define <2 x i1> @fcmp_oeq_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_oeq_sel_x_negx_with_any_fpzero_ninf_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf oeq <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp ninf oeq <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_one_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_one_sel_x_negx_with_any_fpzero_ninf_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf one <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp ninf one <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_ueq_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_ueq_sel_x_negx_with_any_fpzero_ninf_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf ueq <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp ninf ueq <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_une_sel_x_negx_with_any_fpzero_ninf_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_une_sel_x_negx_with_any_fpzero_ninf_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp ninf une <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp ninf une <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_oeq_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_oeq_sel_x_negx_with_any_fpzero_nnan_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan oeq <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp nnan oeq <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_one_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_one_sel_x_negx_with_any_fpzero_nnan_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan one <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp nnan one <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_ueq_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_ueq_sel_x_negx_with_any_fpzero_nnan_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan ueq <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp nnan ueq <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
define <2 x i1> @fcmp_une_sel_x_negx_with_any_fpzero_nnan_vec(<2 x i1> %cond, <2 x float> %x) {
; CHECK-LABEL: @fcmp_une_sel_x_negx_with_any_fpzero_nnan_vec(
; CHECK-NEXT: [[ICMP:%.*]] = fcmp nnan une <2 x float> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[ICMP]]
;
%fneg = fneg <2 x float> %x
%sel = select <2 x i1> %cond, <2 x float> %x, <2 x float> %fneg
%icmp = fcmp nnan une <2 x float> %sel, <float 0.0, float -0.0>
ret <2 x i1> %icmp
}
; negative test - extra use
define i1 @fcmp_ueq_fsub_nnan_const_extra_use(float %x, float %y) {
; CHECK-LABEL: @fcmp_ueq_fsub_nnan_const_extra_use(
; CHECK-NEXT: [[FS:%.*]] = fsub nnan float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[FS]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ueq float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub nnan float %x, %y
call void @use(float %fs)
%cmp = fcmp nnan ueq float %fs, 0.000000e+00
ret i1 %cmp
}
; negative test - extra use
define i1 @fcmp_oeq_fsub_ninf_const_extra_use(float %x, float %y) {
; CHECK-LABEL: @fcmp_oeq_fsub_ninf_const_extra_use(
; CHECK-NEXT: [[FS:%.*]] = fsub ninf float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[FS]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oeq float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub ninf float %x, %y
call void @use(float %fs)
%cmp = fcmp ninf oeq float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_oeq_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_oeq_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp oeq float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_oge_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_oge_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp oge float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_ole_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_ole_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ole float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp ole float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_ueq_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_ueq_fsub_const(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp ueq float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_uge_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_uge_fsub_const(
; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp uge float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_ule_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_ule_fsub_const(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp ule float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_ugt_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_ugt_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp ugt float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_ult_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_ult_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp ult float %fs, 0.000000e+00
ret i1 %cmp
}
define i1 @fcmp_une_fsub_const(float %x, float %y) {
; CHECK-LABEL: @fcmp_une_fsub_const(
; CHECK-NEXT: [[FS:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp une float [[FS]], 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%fs = fsub float %x, %y
%cmp = fcmp une float %fs, 0.000000e+00
ret i1 %cmp
}
define <8 x i1> @fcmp_uge_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_uge_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf uge <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf uge <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ule_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ule_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ule <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ule <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ueq_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ueq_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ueq <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ueq <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_oge_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_oge_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf oge <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ole_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ole_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ole <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_oeq_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_oeq_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oeq <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf oeq <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ogt_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ogt_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ogt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_olt_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_olt_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf olt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_one_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_one_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf one <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf one <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ugt_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ugt_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ugt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ugt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ult_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ult_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ult <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf ult <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_une_fsub_const_ninf_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_une_fsub_const_ninf_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub ninf <8 x float> %x, %y
%cmp = fcmp ninf une <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_uge_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_uge_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan uge <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan uge <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ule_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ule_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ule <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ueq_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ueq_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ueq <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ueq <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_oge_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_oge_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oge <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan oge <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ole_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ole_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ole <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ole <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_oeq_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_oeq_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan oeq <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan oeq <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ogt_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ogt_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ogt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_olt_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_olt_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan olt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan olt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_one_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_one_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan one <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ugt_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ugt_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ugt <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ugt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ult_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_ult_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ult <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan ult <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_une_fsub_const_nnan_vec(<8 x float> %x, <8 x float> %y) {
; CHECK-LABEL: @fcmp_une_fsub_const_nnan_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan une <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub nnan <8 x float> %x, %y
%cmp = fcmp nnan une <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ugt_fsub_const_vec_denormal_positive-zero(<8 x float> %x, <8 x float> %y) "denormal-fp-math"="positive-zero,positive-zero" {
; CHECK-LABEL: @fcmp_ugt_fsub_const_vec_denormal_positive-zero(
; CHECK-NEXT: [[FS:%.*]] = fsub <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <8 x float> [[FS]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub <8 x float> %x, %y
%cmp = fcmp ogt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ogt_fsub_const_vec_denormal_dynamic(<8 x float> %x, <8 x float> %y) "denormal-fp-math"="dynamic,dynamic" {
; CHECK-LABEL: @fcmp_ogt_fsub_const_vec_denormal_dynamic(
; CHECK-NEXT: [[FS:%.*]] = fsub <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <8 x float> [[FS]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub <8 x float> %x, %y
%cmp = fcmp ogt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define <8 x i1> @fcmp_ogt_fsub_const_vec_denormal_preserve-sign(<8 x float> %x, <8 x float> %y) "denormal-fp-math"="preserve-sign,preserve-sign" {
; CHECK-LABEL: @fcmp_ogt_fsub_const_vec_denormal_preserve-sign(
; CHECK-NEXT: [[FS:%.*]] = fsub <8 x float> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <8 x float> [[FS]], zeroinitializer
; CHECK-NEXT: ret <8 x i1> [[CMP]]
;
%fs = fsub <8 x float> %x, %y
%cmp = fcmp ogt <8 x float> %fs, zeroinitializer
ret <8 x i1> %cmp
}
define i1 @fcmp_sqrt_zero_olt(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_olt(
; CHECK-NEXT: ret i1 false
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp olt half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ult(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ult half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ult_fmf(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_fmf(
; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ninf nsz ult half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ult_fmf_sqrt_ninf(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_fmf_sqrt_ninf(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf nsz ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call ninf half @llvm.sqrt.f16(half %x)
%cmp = fcmp ninf nsz ult half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ult_nzero(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_nzero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ult half %sqrt, -0.0
ret i1 %cmp
}
define <2 x i1> @fcmp_sqrt_zero_ult_vec(<2 x half> %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_vec(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult <2 x half> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%sqrt = call <2 x half> @llvm.sqrt.v2f16(<2 x half> %x)
%cmp = fcmp ult <2 x half> %sqrt, zeroinitializer
ret <2 x i1> %cmp
}
define <2 x i1> @fcmp_sqrt_zero_ult_vec_mixed_zero(<2 x half> %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_vec_mixed_zero(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult <2 x half> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%sqrt = call <2 x half> @llvm.sqrt.v2f16(<2 x half> %x)
%cmp = fcmp ult <2 x half> %sqrt, <half 0.0, half -0.0>
ret <2 x i1> %cmp
}
define i1 @fcmp_sqrt_zero_ole(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ole(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ole half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ule(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ule(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ule half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ule half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ogt(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ogt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ogt half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ugt(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ugt(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ugt half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_oge(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_oge(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp oge half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_uge(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_uge(
; CHECK-NEXT: ret i1 true
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp uge half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_oeq(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_oeq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp oeq half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ueq(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ueq(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ule half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ueq half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_one(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_one(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp one half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_une(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_une(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp une half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ord(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ord(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oge half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ord half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_uno(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_uno(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp uno half %sqrt, 0.0
ret i1 %cmp
}
; Make sure that ninf is cleared.
define i1 @fcmp_sqrt_zero_uno_fmf(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_uno_fmf(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ninf uno half %sqrt, 0.0
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_uno_fmf_sqrt_ninf(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_uno_fmf_sqrt_ninf(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ult half [[X:%.*]], 0xH0000
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call ninf half @llvm.sqrt.f16(half %x)
%cmp = fcmp ninf uno half %sqrt, 0.0
ret i1 %cmp
}
; negative tests
define i1 @fcmp_sqrt_zero_ult_var(half %x, half %y) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_var(
; CHECK-NEXT: [[SQRT:%.*]] = call half @llvm.sqrt.f16(half [[X:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[SQRT]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ult half %sqrt, %y
ret i1 %cmp
}
define i1 @fcmp_sqrt_zero_ult_nonzero(half %x) {
; CHECK-LABEL: @fcmp_sqrt_zero_ult_nonzero(
; CHECK-NEXT: [[SQRT:%.*]] = call half @llvm.sqrt.f16(half [[X:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = fcmp ult half [[SQRT]], 0xH3C00
; CHECK-NEXT: ret i1 [[CMP]]
;
%sqrt = call half @llvm.sqrt.f16(half %x)
%cmp = fcmp ult half %sqrt, 1.000000e+00
ret i1 %cmp
}