Files
clang-p2996/llvm/test/Transforms/InstCombine/fadd.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

1148 lines
42 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
declare void @use(float)
declare void @use_vec(<2 x float>)
declare float @llvm.vector.reduce.fadd.v4f32(float, <4 x float>)
; -x + y => y - x
define float @fneg_op0(float %x, float %y) {
; CHECK-LABEL: @fneg_op0(
; CHECK-NEXT: [[ADD:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
%neg = fsub float -0.0, %x
%add = fadd float %neg, %y
ret float %add
}
; x + -y => x - y
define float @fneg_op1(float %x, float %y) {
; CHECK-LABEL: @fneg_op1(
; CHECK-NEXT: [[ADD:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
%neg = fsub float -0.0, %y
%add = fadd float %x, %neg
ret float %add
}
; Z + (-X / Y) --> Z - (X / Y)
define double @fdiv_fneg1(double %x, double %y, double %pz) {
; CHECK-LABEL: @fdiv_fneg1(
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%div = fdiv double %neg, %y
%r = fadd double %z, %div
ret double %r
}
; Z + (Y / -X) --> Z - (Y / X)
define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
; CHECK-LABEL: @fdiv_fneg2(
; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
; CHECK-NEXT: ret <2 x double> [[R]]
;
%z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
%neg = fsub <2 x double> <double -0.0, double -0.0>, %x
%div = fdiv <2 x double> %y, %neg
%r = fadd <2 x double> %z, %div
ret <2 x double> %r
}
; Z + (-X * Y) --> Z - (X * Y)
define double @fmul_fneg1(double %x, double %y, double %pz) {
; CHECK-LABEL: @fmul_fneg1(
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%mul = fmul double %neg, %y
%r = fadd double %z, %mul
ret double %r
}
; Z + (Y * -X) --> Z - (Y * X)
define double @fmul_fneg2(double %x, double %py, double %pz) {
; CHECK-LABEL: @fmul_fneg2(
; CHECK-NEXT: [[Y:%.*]] = frem double -4.200000e+01, [[PY:%.*]]
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%y = frem double -42.0, %py ; thwart complexity-based canonicalization
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%mul = fmul double %y, %neg
%r = fadd double %z, %mul
ret double %r
}
; (-X / Y) + Z --> Z - (X / Y)
define double @fdiv_fneg1_commute(double %x, double %y, double %pz) {
; CHECK-LABEL: @fdiv_fneg1_commute(
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%div = fdiv double %neg, %y
%r = fadd double %div, %z
ret double %r
}
; (Y / -X) + Z --> Z - (Y / X)
define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
; CHECK-LABEL: @fdiv_fneg2_commute(
; CHECK-NEXT: [[Z:%.*]] = frem <2 x double> <double 4.200000e+01, double 8.000000e+00>, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub <2 x double> [[Z]], [[TMP1]]
; CHECK-NEXT: ret <2 x double> [[R]]
;
%z = frem <2 x double> <double 42.0, double 8.0>, %pz ; thwart complexity-based canonicalization
%neg = fsub <2 x double> <double -0.0, double -0.0>, %x
%div = fdiv <2 x double> %y, %neg
%r = fadd <2 x double> %div, %z
ret <2 x double> %r
}
; (-X * Y) + Z --> Z - (X * Y)
define double @fmul_fneg1_commute(double %x, double %y, double %pz) {
; CHECK-LABEL: @fmul_fneg1_commute(
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%mul = fmul double %neg, %y
%r = fadd double %mul, %z
ret double %r
}
; (Y * -X) + Z --> Z - (Y * X)
define double @fmul_fneg2_commute(double %x, double %py, double %pz) {
; CHECK-LABEL: @fmul_fneg2_commute(
; CHECK-NEXT: [[Y:%.*]] = frem double 4.100000e+01, [[PY:%.*]]
; CHECK-NEXT: [[Z:%.*]] = frem double 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y]]
; CHECK-NEXT: [[R:%.*]] = fsub double [[Z]], [[TMP1]]
; CHECK-NEXT: ret double [[R]]
;
%y = frem double 41.0, %py ; thwart complexity-based canonicalization
%z = frem double 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub double -0.000000e+00, %x
%mul = fmul double %y, %neg
%r = fadd double %mul, %z
ret double %r
}
; Z + (-X / Y) - extra use means we can't transform to fsub without an extra instruction
define float @fdiv_fneg1_extra_use(float %x, float %y, float %pz) {
; CHECK-LABEL: @fdiv_fneg1_extra_use(
; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[DIV]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
; CHECK-NEXT: ret float [[R]]
;
%z = frem float 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub float -0.000000e+00, %x
%div = fdiv float %neg, %y
call void @use(float %div)
%r = fadd float %z, %div
ret float %r
}
; Z + (Y / -X) - extra use means we can't transform to fsub without an extra instruction
define float @fdiv_fneg2_extra_use(float %x, float %py, float %pz) {
; CHECK-LABEL: @fdiv_fneg2_extra_use(
; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y]], [[NEG]]
; CHECK-NEXT: call void @use(float [[DIV]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[DIV]]
; CHECK-NEXT: ret float [[R]]
;
%y = frem float -42.0, %py ; thwart complexity-based canonicalization
%z = frem float 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub float -0.000000e+00, %x
%div = fdiv float %y, %neg
call void @use(float %div)
%r = fadd float %z, %div
ret float %r
}
; Z + (-X * Y) - extra use means we can't transform to fsub without an extra instruction
define <2 x float> @fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %pz) {
; CHECK-LABEL: @fmul_fneg1_extra_use(
; CHECK-NEXT: [[Z:%.*]] = frem <2 x float> <float 4.200000e+01, float -1.000000e+00>, [[PZ:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[Z]], [[MUL]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%z = frem <2 x float> <float 42.0, float -1.0>, %pz ; thwart complexity-based canonicalization
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
%mul = fmul <2 x float> %neg, %y
call void @use_vec(<2 x float> %mul)
%r = fadd <2 x float> %z, %mul
ret <2 x float> %r
}
; Z + (Y * -X) - extra use means we can't transform to fsub without an extra instruction
define float @fmul_fneg2_extra_use(float %x, float %py, float %pz) {
; CHECK-LABEL: @fmul_fneg2_extra_use(
; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
; CHECK-NEXT: [[Z:%.*]] = frem float 4.200000e+01, [[PZ:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
; CHECK-NEXT: call void @use(float [[MUL]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[Z]], [[MUL]]
; CHECK-NEXT: ret float [[R]]
;
%y = frem float -42.0, %py ; thwart complexity-based canonicalization
%z = frem float 42.0, %pz ; thwart complexity-based canonicalization
%neg = fsub float -0.000000e+00, %x
%mul = fmul float %y, %neg
call void @use(float %mul)
%r = fadd float %z, %mul
ret float %r
}
; (-X / Y) + Z --> Z - (X / Y)
define float @fdiv_fneg1_extra_use2(float %x, float %y, float %z) {
; CHECK-LABEL: @fdiv_fneg1_extra_use2(
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
; CHECK-NEXT: ret float [[R]]
;
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%div = fdiv float %neg, %y
%r = fadd float %div, %z
ret float %r
}
; (Y / -X) + Z --> Z - (Y / X)
define float @fdiv_fneg2_extra_use2(float %x, float %y, float %z) {
; CHECK-LABEL: @fdiv_fneg2_extra_use2(
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
; CHECK-NEXT: ret float [[R]]
;
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%div = fdiv float %y, %neg
%r = fadd float %div, %z
ret float %r
}
; (-X * Y) + Z --> Z - (X * Y)
define <2 x float> @fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
; CHECK-LABEL: @fmul_fneg1_extra_use2(
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])
; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]
; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[TMP1]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
call void @use_vec(<2 x float> %neg)
%mul = fmul <2 x float> %neg, %y
%r = fadd <2 x float> %mul, %z
ret <2 x float> %r
}
; (Y * -X) + Z --> Z - (Y * X)
define float @fmul_fneg2_extra_use2(float %x, float %py, float %z) {
; CHECK-LABEL: @fmul_fneg2_extra_use2(
; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X]], [[Y]]
; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[TMP1]]
; CHECK-NEXT: ret float [[R]]
;
%y = frem float -42.0, %py ; thwart complexity-based canonicalization
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%mul = fmul float %y, %neg
%r = fadd float %mul, %z
ret float %r
}
; (-X / Y) + Z --> Z - (X / Y)
define float @fdiv_fneg1_extra_use3(float %x, float %y, float %z) {
; CHECK-LABEL: @fdiv_fneg1_extra_use3(
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[DIV]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%div = fdiv float %neg, %y
call void @use(float %div)
%r = fadd float %div, %z
ret float %r
}
; (Y / -X) + Z --> Z - (Y / X)
define float @fdiv_fneg2_extra_use3(float %x, float %y, float %z) {
; CHECK-LABEL: @fdiv_fneg2_extra_use3(
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]
; CHECK-NEXT: call void @use(float [[DIV]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[DIV]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%div = fdiv float %y, %neg
call void @use(float %div)
%r = fadd float %div, %z
ret float %r
}
; (-X * Y) + Z --> Z - (X * Y)
define <2 x float> @fmul_fneg1_extra_use3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
; CHECK-LABEL: @fmul_fneg1_extra_use3(
; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])
; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])
; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[MUL]], [[Z:%.*]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%neg = fsub <2 x float> <float -0.0, float -0.0>, %x
call void @use_vec(<2 x float> %neg)
%mul = fmul <2 x float> %neg, %y
call void @use_vec(<2 x float> %mul)
%r = fadd <2 x float> %mul, %z
ret <2 x float> %r
}
; (Y * -X) + Z --> Z - (Y * X)
define float @fmul_fneg2_extra_use3(float %x, float %py, float %z) {
; CHECK-LABEL: @fmul_fneg2_extra_use3(
; CHECK-NEXT: [[Y:%.*]] = frem float -4.200000e+01, [[PY:%.*]]
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[NEG]])
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y]], [[NEG]]
; CHECK-NEXT: call void @use(float [[MUL]])
; CHECK-NEXT: [[R:%.*]] = fadd float [[MUL]], [[Z:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%y = frem float -42.0, %py ; thwart complexity-based canonicalization
%neg = fsub float -0.000000e+00, %x
call void @use(float %neg)
%mul = fmul float %y, %neg
call void @use(float %mul)
%r = fadd float %mul, %z
ret float %r
}
define float @fadd_rdx(float %x, <4 x float> %v) {
; CHECK-LABEL: @fadd_rdx(
; CHECK-NEXT: [[ADD:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float [[X:%.*]], <4 x float> [[V:%.*]])
; CHECK-NEXT: ret float [[ADD]]
;
%rdx = call fast float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
%add = fadd fast float %rdx, %x
ret float %add
}
define float @fadd_rdx_commute(float %x, <4 x float> %v) {
; CHECK-LABEL: @fadd_rdx_commute(
; CHECK-NEXT: [[D:%.*]] = fdiv float 4.200000e+01, [[X:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = call reassoc nsz float @llvm.vector.reduce.fadd.v4f32(float [[D]], <4 x float> [[V:%.*]])
; CHECK-NEXT: ret float [[ADD]]
;
%d = fdiv float 42.0, %x
%rdx = call float @llvm.vector.reduce.fadd.v4f32(float -0.0, <4 x float> %v)
%add = fadd reassoc nsz float %d, %rdx
ret float %add
}
; Negative test - require nsz to be safer (and reassoc obviously).
define float @fadd_rdx_fmf(float %x, <4 x float> %v) {
; CHECK-LABEL: @fadd_rdx_fmf(
; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]])
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc float [[RDX]], [[X:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
%rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
%add = fadd reassoc float %rdx, %x
ret float %add
}
; Negative test - don't replace a single add with another reduction.
define float @fadd_rdx_extra_use(float %x, <4 x float> %v) {
; CHECK-LABEL: @fadd_rdx_extra_use(
; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 0.000000e+00, <4 x float> [[V:%.*]])
; CHECK-NEXT: call void @use(float [[RDX]])
; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
%rdx = call float @llvm.vector.reduce.fadd.v4f32(float 0.0, <4 x float> %v)
call void @use(float %rdx)
%add = fadd fast float %rdx, %x
ret float %add
}
define float @fadd_rdx_nonzero_start_const_op(<4 x float> %v) {
; CHECK-LABEL: @fadd_rdx_nonzero_start_const_op(
; CHECK-NEXT: [[ADD:%.*]] = call reassoc ninf nsz float @llvm.vector.reduce.fadd.v4f32(float 3.300000e+01, <4 x float> [[V:%.*]])
; CHECK-NEXT: ret float [[ADD]]
;
%rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v)
%add = fadd reassoc nsz ninf float %rdx, -9.0
ret float %add
}
; Negative test - we don't change the order of ops unless it saves an instruction.
define float @fadd_rdx_nonzero_start_variable_op(float %x, <4 x float> %v) {
; CHECK-LABEL: @fadd_rdx_nonzero_start_variable_op(
; CHECK-NEXT: [[RDX:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float 4.200000e+01, <4 x float> [[V:%.*]])
; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[RDX]], [[X:%.*]]
; CHECK-NEXT: ret float [[ADD]]
;
%rdx = call float @llvm.vector.reduce.fadd.v4f32(float 42.0, <4 x float> %v)
%add = fadd fast float %rdx, %x
ret float %add
}
; (X * C) + X --> X * (C + 1)
define float @fadd_fmul_common_op(float %x) {
; CHECK-LABEL: @fadd_fmul_common_op(
; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.300000e+01
; CHECK-NEXT: ret float [[A]]
;
%m = fmul reassoc nsz float %x, 42.0
%a = fadd reassoc nsz float %m, %x
ret float %a
}
; Splat constant is ok.
define <2 x float> @fadd_fmul_common_op_vec(<2 x float> %x) {
; CHECK-LABEL: @fadd_fmul_common_op_vec(
; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], <float 4.300000e+01, float 4.300000e+01>
; CHECK-NEXT: ret <2 x float> [[A]]
;
%m = fmul reassoc nsz <2 x float> %x, <float 42.0, float 42.0>
%a = fadd reassoc nsz <2 x float> %m, %x
ret <2 x float> %a
}
; Non-splat constant is ok.
define <2 x float> @fadd_fmul_common_op_commute_vec(<2 x float> %px) {
; CHECK-LABEL: @fadd_fmul_common_op_commute_vec(
; CHECK-NEXT: [[X:%.*]] = fmul <2 x float> [[PX:%.*]], [[PX]]
; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz <2 x float> [[X]], <float 4.300000e+01, float -4.200000e+01>
; CHECK-NEXT: ret <2 x float> [[A]]
;
%x = fmul <2 x float> %px, %px ; thwart complexity-based canonicalization
%m = fmul reassoc nsz <2 x float> %x, <float 42.0, float -43.0>
%a = fadd reassoc nsz <2 x float> %x, %m
ret <2 x float> %a
}
; Extra use is ok.
define float @fadd_fmul_common_op_use(float %x) {
; CHECK-LABEL: @fadd_fmul_common_op_use(
; CHECK-NEXT: [[M:%.*]] = fmul reassoc nsz float [[X:%.*]], 4.200000e+01
; CHECK-NEXT: call void @use(float [[M]])
; CHECK-NEXT: [[A:%.*]] = fmul reassoc nsz float [[X]], 4.300000e+01
; CHECK-NEXT: ret float [[A]]
;
%m = fmul reassoc nsz float %x, 42.0
call void @use(float %m)
%a = fadd reassoc nsz float %m, %x
ret float %a
}
; Negative test - must have 'reassoc' FMF
define float @fadd_fmul_common_op_wrong_fmf(float %x) {
; CHECK-LABEL: @fadd_fmul_common_op_wrong_fmf(
; CHECK-NEXT: [[M:%.*]] = fmul ninf nsz float [[X:%.*]], 4.200000e+01
; CHECK-NEXT: [[A:%.*]] = fadd ninf nsz float [[M]], [[X]]
; CHECK-NEXT: ret float [[A]]
;
%m = fmul ninf nsz float %x, 42.0
%a = fadd ninf nsz float %m, %x
ret float %a
}
; (-x - y) + (x + z) --> z - y
define float @fadd_fneg_reass_commute0(float %x, float %y, float %z) {
; CHECK-LABEL: @fadd_fneg_reass_commute0(
; CHECK-NEXT: [[N:%.*]] = fneg reassoc nsz float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[N]])
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret float [[R]]
;
%n = fneg reassoc nsz float %x
call void @use(float %n)
%s = fsub reassoc nsz float %n, %y
%a = fadd reassoc nsz float %x, %z
%r = fadd reassoc nsz float %s, %a
ret float %r
}
define float @fadd_fneg_reass_commute1(float %x, float %y, float %z) {
; CHECK-LABEL: @fadd_fneg_reass_commute1(
; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[N]])
; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[S]])
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float [[Z:%.*]], [[Y]]
; CHECK-NEXT: ret float [[R]]
;
%n = fneg float %x
call void @use(float %n)
%s = fsub float %n, %y
call void @use(float %s)
%a = fadd float %x, %z
%r = fadd reassoc nsz float %a, %s
ret float %r
}
define float @fadd_fneg_reass_commute2(float %x, float %y, float %z) {
; CHECK-LABEL: @fadd_fneg_reass_commute2(
; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[N]])
; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
; CHECK-NEXT: call void @use(float [[S]])
; CHECK-NEXT: [[A:%.*]] = fadd float [[Z:%.*]], [[X]]
; CHECK-NEXT: call void @use(float [[A]])
; CHECK-NEXT: [[R:%.*]] = fsub fast float [[Z]], [[Y]]
; CHECK-NEXT: ret float [[R]]
;
%n = fneg float %x
call void @use(float %n)
%s = fsub float %n, %y
call void @use(float %s)
%a = fadd float %z, %x
call void @use(float %a)
%r = fadd fast float %s, %a
ret float %r
}
define <2 x float> @fadd_fneg_reass_commute3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {
; CHECK-LABEL: @fadd_fneg_reass_commute3(
; CHECK-NEXT: [[N:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]]
; CHECK-NEXT: call void @use_vec(<2 x float> [[N]])
; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x float> [[R]]
;
%n = fneg reassoc nsz <2 x float> %x
call void @use_vec(<2 x float> %n)
%s = fsub reassoc nsz <2 x float> %n, %y
%a = fadd reassoc nsz <2 x float> %z, %x
%r = fadd reassoc nsz <2 x float> %a, %s
ret <2 x float> %r
}
; negative test - need reassoc (+ nsz)
define float @fadd_fneg_commute0(float %x, float %y, float %z) {
; CHECK-LABEL: @fadd_fneg_commute0(
; CHECK-NEXT: [[N:%.*]] = fneg float [[X:%.*]]
; CHECK-NEXT: call void @use(float [[N]])
; CHECK-NEXT: [[S:%.*]] = fsub float [[N]], [[Y:%.*]]
; CHECK-NEXT: [[A:%.*]] = fadd float [[X]], [[Z:%.*]]
; CHECK-NEXT: [[R:%.*]] = fadd nsz float [[S]], [[A]]
; CHECK-NEXT: ret float [[R]]
;
%n = fneg float %x
call void @use(float %n)
%s = fsub float %n, %y
%a = fadd float %x, %z
%r = fadd nsz float %s, %a
ret float %r
}
define float @fadd_reduce_sqr_sum_varA(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_order2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order2(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %a_sq, %mul
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_order3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order3(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %b, %two_a_plus_b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_order4(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order4(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %b, %two_a
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_order5(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_order5(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float 2.0, %a
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_order1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order1(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_order2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order2(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %b_sq, %a_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_order3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_order3(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %b, %a
%a_b_2 = fmul float 2.0, %a_b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float %a, 2.0
%a_b_2 = fmul float %a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_order1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order1(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float %a, 2.0
%a_b_2 = fmul float %a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_sq_b_sq, %a_b_2
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_order2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order2(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float %a, 2.0
%a_b_2 = fmul float %b, %a_2
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_order3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_order3(
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[TMP1]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float 2.0, %a
%a_b_2 = fmul float %a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_not_one_use1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use1(
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
; CHECK-NEXT: tail call void @fake_func(float [[MUL]])
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
tail call void @fake_func (float %mul)
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_not_one_use2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use2(
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
; CHECK-NEXT: tail call void @fake_func(float [[A_SQ]])
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
tail call void @fake_func (float %a_sq)
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_not_one_use1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use1(
; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: tail call void @fake_func(float [[A_B_2]])
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
tail call void @fake_func (float %a_b_2)
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_not_one_use2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_not_one_use2(
; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: tail call void @fake_func(float [[A_SQ_B_SQ]])
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
tail call void @fake_func (float %a_sq_b_sq)
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_not_one_use(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_not_one_use(
; CHECK-NEXT: [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_2]], [[B:%.*]]
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: tail call void @fake_func(float [[A_B_2]])
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float %a, 2.0
%a_b_2 = fmul float %a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
tail call void @fake_func (float %a_b_2)
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_invalid1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid1(
; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[A]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %a
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_invalid2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid2(
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
; CHECK-NEXT: [[NOT_TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[A]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[NOT_TWO_A_PLUS_B]], [[B:%.*]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
%not_two_a_plus_b = fadd float %two_a, %a
%mul = fmul float %not_two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_invalid3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid3(
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[NOT_TWO_A:%.*]] = fmul float [[A]], 0x4000CCCCC0000000
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%not_two_a = fmul float %a, 0x4000CCCCC0000000 ; 2.1
%two_a_plus_b = fadd float %not_two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_invalid4(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid4(
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[NOT_TWO_A:%.*]] = fmul float [[B:%.*]], 2.000000e+00
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[NOT_TWO_A]], [[B]]
; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_sq = fmul float %a, %a
%not_two_a = fmul float %b, 2.0
%two_a_plus_b = fadd float %not_two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varA_invalid5(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_invalid5(
; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A:%.*]], 2.000000e+00
; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[TWO_A_PLUS_B]], [[A]]
; CHECK-NEXT: [[ADD:%.*]] = fmul reassoc nsz float [[TMP1]], [[B]]
; CHECK-NEXT: ret float [[ADD]]
;
%not_a_sq = fmul float %a, %b
%two_a = fmul float %a, 2.0
%two_a_plus_b = fadd float %two_a, %b
%mul = fmul float %two_a_plus_b, %b
%add = fadd reassoc nsz float %mul, %not_a_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_invalid1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid1(
; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[NOT_B_SQ:%.*]] = fmul float [[B]], [[A]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[NOT_B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%a_sq = fmul float %a, %a
%not_b_sq = fmul float %b, %a
%a_sq_b_sq = fadd float %a_sq, %not_b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_invalid2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid2(
; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[A_B]], 2.000000e+00
; CHECK-NEXT: [[NOT_A_SQ:%.*]] = fmul float [[A]], [[B]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[NOT_A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%a_b_2 = fmul float %a_b, 2.0
%not_a_sq = fmul float %a, %b
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %not_a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_invalid3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid3(
; CHECK-NEXT: [[A_B:%.*]] = fmul float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[NOT_A_B_2:%.*]] = fmul float [[A_B]], 0x4000CCCCC0000000
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_b = fmul float %a, %b
%not_a_b_2 = fmul float %a_b, 0x4000CCCCC0000000 ; 2.1
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_invalid4(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid4(
; CHECK-NEXT: [[NOT_A_B:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%not_a_b = fmul float %a, %a
%a_b_2 = fmul float %not_a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB_invalid5(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB_invalid5(
; CHECK-NEXT: [[NOT_A_B:%.*]] = fmul float [[B:%.*]], [[B]]
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_B]], 2.000000e+00
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%not_a_b = fmul float %b, %b
%a_b_2 = fmul float %not_a_b, 2.0
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_invalid1(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid1(
; CHECK-NEXT: [[A_2:%.*]] = fmul float [[A:%.*]], 2.000000e+00
; CHECK-NEXT: [[NOT_A_B_2:%.*]] = fmul float [[A_2]], [[A]]
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B:%.*]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[NOT_A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%a_2 = fmul float %a, 2.0
%not_a_b_2 = fmul float %a_2, %a
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %not_a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_invalid2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid2(
; CHECK-NEXT: [[NOT_A_2:%.*]] = fmul float [[A:%.*]], 0x4000CCCCC0000000
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B:%.*]]
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%not_a_2 = fmul float %a, 0x4000CCCCC0000000 ; 2.1
%a_b_2 = fmul float %not_a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
define float @fadd_reduce_sqr_sum_varB2_invalid3(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varB2_invalid3(
; CHECK-NEXT: [[NOT_A_2:%.*]] = fmul float [[B:%.*]], 2.000000e+00
; CHECK-NEXT: [[A_B_2:%.*]] = fmul float [[NOT_A_2]], [[B]]
; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
; CHECK-NEXT: [[B_SQ:%.*]] = fmul float [[B]], [[B]]
; CHECK-NEXT: [[A_SQ_B_SQ:%.*]] = fadd float [[A_SQ]], [[B_SQ]]
; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[A_B_2]], [[A_SQ_B_SQ]]
; CHECK-NEXT: ret float [[ADD]]
;
%not_a_2 = fmul float %b, 2.0
%a_b_2 = fmul float %not_a_2, %b
%a_sq = fmul float %a, %a
%b_sq = fmul float %b, %b
%a_sq_b_sq = fadd float %a_sq, %b_sq
%add = fadd reassoc nsz float %a_b_2, %a_sq_b_sq
ret float %add
}
declare void @fake_func(float)