blob: 79bf70ad1a51b7ebef522c40bf84b3dc602e1d27 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes=reassociate -S < %s | FileCheck %s
define double @fsub_fmul_2(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fsub_fmul_2(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[Z0_NEG:%.*]] = fneg reassoc nsz contract double [[Z0]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz contract double [[M0]], [[Z0_NEG]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[Z1_NEG:%.*]] = fneg reassoc nsz contract double [[Z1]]
; CHECK-NEXT: [[S1:%.*]] = fadd reassoc nsz contract double [[M1]], [[Z1_NEG]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[S1]], [[S0]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%z0 = load double, ptr %z
%s0 = fsub reassoc nsz contract double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%s1 = fsub reassoc nsz contract double %m1, %z1
%r = fadd reassoc nsz contract double %s0, %s1
ret double %r
}
define double @fadd_fmul_2(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fadd_fmul_2(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[A0:%.*]] = fadd reassoc nsz contract double [[M0]], [[Z0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[A1:%.*]] = fadd reassoc nsz contract double [[M1]], [[Z1]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[A1]], [[A0]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%z0 = load double, ptr %z
%a0 = fadd reassoc nsz contract double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%a1 = fadd reassoc nsz contract double %m1, %z1
%r = fadd reassoc nsz contract double %a0, %a1
ret double %r
}
define double @fadd_fmul_2_right(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fadd_fmul_2_right(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[A0:%.*]] = fadd reassoc nsz contract double [[Z0]], [[M0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[A1:%.*]] = fadd reassoc nsz contract double [[Z1]], [[M1]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[A1]], [[A0]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%z0 = load double, ptr %z
%a0 = fadd reassoc nsz contract double %z0, %m0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%a1 = fadd reassoc nsz contract double %z1, %m1
%r = fadd reassoc nsz contract double %a0, %a1
ret double %r
}
define double @fsub_fmul_2_right(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fsub_fmul_2_right(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[M0_NEG:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[M1_NEG:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[REASS_ADD:%.*]] = fadd reassoc nsz contract double [[M1_NEG]], [[M0_NEG]]
; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul reassoc nsz contract double -1.000000e+00, [[REASS_ADD]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz contract double [[Z0]], [[Z1]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[S0]], [[REASS_MUL]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%z0 = load double, ptr %z
%s0 = fsub reassoc nsz contract double %z0, %m0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%s1 = fsub reassoc nsz contract double %z1, %m1
%r = fadd reassoc nsz contract double %s0, %s1
ret double %r
}
define double @fsub_fmul_4(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fsub_fmul_4(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[Z0_NEG:%.*]] = fneg reassoc nsz contract double [[Z0]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz contract double [[M0]], [[Z0_NEG]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[Z1_NEG:%.*]] = fneg reassoc nsz contract double [[Z1]]
; CHECK-NEXT: [[S1:%.*]] = fadd reassoc nsz contract double [[M1]], [[Z1_NEG]]
; CHECK-NEXT: [[X2P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 2
; CHECK-NEXT: [[X2:%.*]] = load double, ptr [[X2P]], align 8
; CHECK-NEXT: [[Y2P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 2
; CHECK-NEXT: [[Y2:%.*]] = load double, ptr [[Y2P]], align 8
; CHECK-NEXT: [[M2:%.*]] = fmul reassoc nsz contract double [[Y2]], [[X2]]
; CHECK-NEXT: [[Z2P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 2
; CHECK-NEXT: [[Z2:%.*]] = load double, ptr [[Z2P]], align 8
; CHECK-NEXT: [[Z2_NEG:%.*]] = fneg reassoc nsz contract double [[Z2]]
; CHECK-NEXT: [[S2:%.*]] = fadd reassoc nsz contract double [[M2]], [[Z2_NEG]]
; CHECK-NEXT: [[X3P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 3
; CHECK-NEXT: [[X3:%.*]] = load double, ptr [[X3P]], align 8
; CHECK-NEXT: [[Y3P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 3
; CHECK-NEXT: [[Y3:%.*]] = load double, ptr [[Y3P]], align 8
; CHECK-NEXT: [[M3:%.*]] = fmul reassoc nsz contract double [[Y3]], [[X3]]
; CHECK-NEXT: [[Z3P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 3
; CHECK-NEXT: [[Z3:%.*]] = load double, ptr [[Z3P]], align 8
; CHECK-NEXT: [[Z3_NEG:%.*]] = fneg reassoc nsz contract double [[Z3]]
; CHECK-NEXT: [[S3:%.*]] = fadd reassoc nsz contract double [[M3]], [[Z3_NEG]]
; CHECK-NEXT: [[R0:%.*]] = fadd reassoc nsz contract double [[S1]], [[S0]]
; CHECK-NEXT: [[R1:%.*]] = fadd reassoc nsz contract double [[R0]], [[S2]]
; CHECK-NEXT: [[R2:%.*]] = fadd reassoc nsz contract double [[R1]], [[S3]]
; CHECK-NEXT: ret double [[R2]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%z0 = load double, ptr %z
%s0 = fsub reassoc nsz contract double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%s1 = fsub reassoc nsz contract double %m1, %z1
%x2p = getelementptr inbounds double, ptr %x, i64 2
%x2 = load double, ptr %x2p
%y2p = getelementptr inbounds double, ptr %y, i64 2
%y2 = load double, ptr %y2p
%m2 = fmul reassoc nsz contract double %x2, %y2
%z2p = getelementptr inbounds double, ptr %z, i64 2
%z2 = load double, ptr %z2p
%s2 = fsub reassoc nsz contract double %m2, %z2
%x3p = getelementptr inbounds double, ptr %x, i64 3
%x3 = load double, ptr %x3p
%y3p = getelementptr inbounds double, ptr %y, i64 3
%y3 = load double, ptr %y3p
%m3 = fmul reassoc nsz contract double %x3, %y3
%z3p = getelementptr inbounds double, ptr %z, i64 3
%z3 = load double, ptr %z3p
%s3 = fsub reassoc nsz contract double %m3, %z3
%r0 = fadd reassoc nsz contract double %s0, %s1
%r1 = fadd reassoc nsz contract double %r0, %s2
%r2 = fadd reassoc nsz contract double %r1, %s3
ret double %r2
}
define <2 x double> @fsub_fmul_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z, <2 x double> %w) {
; CHECK-LABEL: define <2 x double> @fsub_fmul_vec(
; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]], <2 x double> [[Z:%.*]], <2 x double> [[W:%.*]]) {
; CHECK-NEXT: [[W_NEG:%.*]] = fmul reassoc nsz contract <2 x double> [[Y]], [[X]]
; CHECK-NEXT: [[Z_NEG:%.*]] = fneg reassoc nsz contract <2 x double> [[Z]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz contract <2 x double> [[W_NEG]], [[Z_NEG]]
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract <2 x double> [[W]], [[Z]]
; CHECK-NEXT: [[X_NEG:%.*]] = fneg reassoc nsz contract <2 x double> [[X]]
; CHECK-NEXT: [[S1:%.*]] = fadd reassoc nsz contract <2 x double> [[M1]], [[X_NEG]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract <2 x double> [[S1]], [[S0]]
; CHECK-NEXT: ret <2 x double> [[R]]
;
%m0 = fmul reassoc nsz contract <2 x double> %x, %y
%s0 = fsub reassoc nsz contract <2 x double> %m0, %z
%m1 = fmul reassoc nsz contract <2 x double> %z, %w
%s1 = fsub reassoc nsz contract <2 x double> %m1, %x
%r = fadd reassoc nsz contract <2 x double> %s0, %s1
ret <2 x double> %r
}
define float @factorize_first(float %a, float %b, float %c, float %d) {
; CHECK-LABEL: define float @factorize_first(
; CHECK-SAME: float [[A:%.*]], float [[B:%.*]], float [[C:%.*]], float [[D:%.*]]) {
; CHECK-NEXT: [[REASS_ADD:%.*]] = fadd reassoc nsz contract float [[C]], [[B]]
; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul reassoc nsz contract float [[REASS_ADD]], [[A]]
; CHECK-NEXT: [[T3:%.*]] = fadd reassoc nsz contract float [[REASS_MUL]], [[D]]
; CHECK-NEXT: ret float [[T3]]
;
%t0 = fmul reassoc nsz contract float %a, %b
%t1 = fmul reassoc nsz contract float %a, %c
%t2 = fadd reassoc nsz contract float %t1, %d
%t3 = fadd reassoc nsz contract float %t0, %t2
ret float %t3
}
define double @fadd_fmul_2_contract_only_mul(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @fadd_fmul_2_contract_only_mul(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul contract double [[X0]], [[Y0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[A0:%.*]] = fadd reassoc nsz contract double [[M0]], [[Z0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul contract double [[X1]], [[Y1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[A1:%.*]] = fadd reassoc nsz contract double [[M1]], [[Z1]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[A1]], [[A0]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul contract double %x0, %y0
%z0 = load double, ptr %z
%a0 = fadd reassoc nsz contract double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%a1 = fadd reassoc nsz contract double %m1, %z1
%r = fadd reassoc nsz contract double %a0, %a1
ret double %r
}
define float @factorize_contract_only_mul(float %a, float %b, float %c, float %d) {
; CHECK-LABEL: define float @factorize_contract_only_mul(
; CHECK-SAME: float [[A:%.*]], float [[B:%.*]], float [[C:%.*]], float [[D:%.*]]) {
; CHECK-NEXT: [[T0:%.*]] = fmul reassoc nsz contract float [[B]], [[A]]
; CHECK-NEXT: [[T1:%.*]] = fmul contract float [[A]], [[C]]
; CHECK-NEXT: [[T2:%.*]] = fadd reassoc nsz contract float [[T1]], [[D]]
; CHECK-NEXT: [[T3:%.*]] = fadd reassoc nsz contract float [[T2]], [[T0]]
; CHECK-NEXT: ret float [[T3]]
;
%t0 = fmul reassoc nsz contract float %a, %b
%t1 = fmul contract float %a, %c
%t2 = fadd reassoc nsz contract float %t1, %d
%t3 = fadd reassoc nsz contract float %t0, %t2
ret float %t3
}
define double @no_contract(ptr %x, ptr %y, ptr %z) {
; CHECK-LABEL: define double @no_contract(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz double [[Y0]], [[X0]]
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[Z0_NEG:%.*]] = fneg reassoc nsz double [[Z0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[Z1_NEG:%.*]] = fneg reassoc nsz double [[Z1]]
; CHECK-NEXT: [[S1:%.*]] = fadd reassoc nsz double [[M0]], [[Z0_NEG]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz double [[S1]], [[Z1_NEG]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz double [[S0]], [[M1]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz double %x0, %y0
%z0 = load double, ptr %z
%s0 = fsub reassoc nsz double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%s1 = fsub reassoc nsz double %m1, %z1
%r = fadd reassoc nsz double %s0, %s1
ret double %r
}
define double @multi_use_mul(ptr %x, ptr %y, ptr %z, ptr %p) {
; CHECK-LABEL: define double @multi_use_mul(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: store double [[M0]], ptr [[P]], align 8
; CHECK-NEXT: [[Z0:%.*]] = load double, ptr [[Z]], align 8
; CHECK-NEXT: [[Z0_NEG:%.*]] = fneg reassoc nsz contract double [[Z0]]
; CHECK-NEXT: [[S0:%.*]] = fadd reassoc nsz contract double [[Z0_NEG]], [[M0]]
; CHECK-NEXT: [[X1P:%.*]] = getelementptr inbounds double, ptr [[X]], i64 1
; CHECK-NEXT: [[X1:%.*]] = load double, ptr [[X1P]], align 8
; CHECK-NEXT: [[Y1P:%.*]] = getelementptr inbounds double, ptr [[Y]], i64 1
; CHECK-NEXT: [[Y1:%.*]] = load double, ptr [[Y1P]], align 8
; CHECK-NEXT: [[M1:%.*]] = fmul reassoc nsz contract double [[Y1]], [[X1]]
; CHECK-NEXT: [[Z1P:%.*]] = getelementptr inbounds double, ptr [[Z]], i64 1
; CHECK-NEXT: [[Z1:%.*]] = load double, ptr [[Z1P]], align 8
; CHECK-NEXT: [[Z1_NEG:%.*]] = fneg reassoc nsz contract double [[Z1]]
; CHECK-NEXT: [[S1:%.*]] = fadd reassoc nsz contract double [[M1]], [[Z1_NEG]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[S0]], [[S1]]
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
store double %m0, ptr %p
%z0 = load double, ptr %z
%s0 = fsub reassoc nsz contract double %m0, %z0
%x1p = getelementptr inbounds double, ptr %x, i64 1
%x1 = load double, ptr %x1p
%y1p = getelementptr inbounds double, ptr %y, i64 1
%y1 = load double, ptr %y1p
%m1 = fmul reassoc nsz contract double %x1, %y1
%z1p = getelementptr inbounds double, ptr %z, i64 1
%z1 = load double, ptr %z1p
%s1 = fsub reassoc nsz contract double %m1, %z1
%r = fadd reassoc nsz contract double %s0, %s1
ret double %r
}
define double @const_addend(ptr %x, ptr %y) {
; CHECK-LABEL: define double @const_addend(
; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]]) {
; CHECK-NEXT: [[X0:%.*]] = load double, ptr [[X]], align 8
; CHECK-NEXT: [[Y0:%.*]] = load double, ptr [[Y]], align 8
; CHECK-NEXT: [[M0:%.*]] = fmul reassoc nsz contract double [[Y0]], [[X0]]
; CHECK-NEXT: [[R:%.*]] = fadd reassoc nsz contract double [[M0]], 3.000000e+00
; CHECK-NEXT: ret double [[R]]
;
%x0 = load double, ptr %x
%y0 = load double, ptr %y
%m0 = fmul reassoc nsz contract double %x0, %y0
%a0 = fadd reassoc nsz contract double %m0, 1.0
%r = fadd reassoc nsz contract double %a0, 2.0
ret double %r
}
define double @hidden_fadd_tree(double %acc, double %a, double %b, double %c, double %d, double %e, double %f) {
; CHECK-LABEL: define double @hidden_fadd_tree(
; CHECK-SAME: double [[ACC:%.*]], double [[A:%.*]], double [[B:%.*]], double [[C:%.*]], double [[D:%.*]], double [[E:%.*]], double [[F:%.*]]) {
; CHECK-NEXT: [[M0:%.*]] = fmul fast double [[F]], [[E]]
; CHECK-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[B]], [[A]]
; CHECK-NEXT: [[REASS_ADD4:%.*]] = fadd fast double [[REASS_ADD]], [[C]]
; CHECK-NEXT: [[REASS_ADD5:%.*]] = fadd fast double [[REASS_ADD4]], [[D]]
; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD5]], 2.000000e+00
; CHECK-NEXT: [[ACC7:%.*]] = fadd fast double [[M0]], [[ACC]]
; CHECK-NEXT: [[RESULT:%.*]] = fadd fast double [[ACC7]], [[REASS_MUL]]
; CHECK-NEXT: ret double [[RESULT]]
;
%acc0 = fadd fast double %a, %b
%acc1 = fadd fast double %c, %d
%acc2 = fadd fast double %b, %c
%acc3 = fadd fast double %d, %a
%acc4 = fadd fast double %acc0, %acc1
%acc5 = fadd fast double %acc2, %acc3
%acc6 = fadd fast double %acc4, %acc5
%m0 = fmul fast double %e, %f
%acc7 = fadd fast double %m0, %acc6
%result = fadd fast double %acc, %acc7
ret double %result
}
define double @nested_fma_subtraction(double %acc, double %a, double %b, double %c, double %d, double %e, double %f) {
; CHECK-LABEL: define double @nested_fma_subtraction(
; CHECK-SAME: double [[ACC:%.*]], double [[A:%.*]], double [[B:%.*]], double [[C:%.*]], double [[D:%.*]], double [[E:%.*]], double [[F:%.*]]) {
; CHECK-NEXT: [[M0:%.*]] = fmul fast double [[B]], [[A]]
; CHECK-NEXT: [[M1_NEG_NEG:%.*]] = fmul fast double [[D]], [[C]]
; CHECK-NEXT: [[M2_NEG1:%.*]] = fmul fast double [[F]], [[E]]
; CHECK-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[M2_NEG1]], [[M0]]
; CHECK-NEXT: [[M2_NEG:%.*]] = fmul fast double -1.000000e+00, [[REASS_ADD]]
; CHECK-NEXT: [[ADD_NEG:%.*]] = fadd fast double [[ACC]], [[M1_NEG_NEG]]
; CHECK-NEXT: [[RESULT:%.*]] = fadd fast double [[M2_NEG]], [[ADD_NEG]]
; CHECK-NEXT: ret double [[RESULT]]
;
%m0 = fmul fast double %a, %b
%m1 = fmul fast double %c, %d
%sub = fsub fast double %m0, %m1
%m2 = fmul fast double %e, %f
%add = fadd fast double %m2, %sub
%result = fsub fast double %acc, %add
ret double %result
}
define float @multi_use_fmul_addend(float %a, float %c, float %d, float %e, float %f) {
; CHECK-LABEL: define float @multi_use_fmul_addend(
; CHECK-SAME: float [[A:%.*]], float [[C:%.*]], float [[D:%.*]], float [[E:%.*]], float [[F:%.*]]) {
; CHECK-NEXT: [[AC:%.*]] = fmul fast float [[C]], [[A]]
; CHECK-NEXT: [[AD:%.*]] = fmul fast float [[D]], [[A]]
; CHECK-NEXT: [[AE:%.*]] = fmul fast float [[E]], [[A]]
; CHECK-NEXT: [[E_SUM:%.*]] = fadd fast float [[AD]], [[AC]]
; CHECK-NEXT: [[T1:%.*]] = fmul fast float [[E_SUM]], [[E]]
; CHECK-NEXT: [[F_SUM0:%.*]] = fadd fast float [[AD]], [[AC]]
; CHECK-NEXT: [[F_SUM:%.*]] = fadd fast float [[F_SUM0]], [[AE]]
; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[F_SUM]], [[F]]
; CHECK-NEXT: [[R:%.*]] = fadd fast float [[T2]], [[T1]]
; CHECK-NEXT: ret float [[R]]
;
%ac = fmul fast float %a, %c
%ad = fmul fast float %a, %d
%ae = fmul fast float %a, %e
%e.sum = fadd fast float %ad, %ac
%t1 = fmul fast float %e.sum, %e
%f.sum0 = fadd fast float %ae, %ad
%f.sum = fadd fast float %f.sum0, %ac
%t2 = fmul fast float %f.sum, %f
%r = fadd fast float %t1, %t2
ret float %r
}
define float @shared_addend_chain(float %b, float %c) {
; CHECK-LABEL: define float @shared_addend_chain(
; CHECK-SAME: float [[B:%.*]], float [[C:%.*]]) {
; CHECK-NEXT: [[CC:%.*]] = fmul fast float [[C]], [[C]]
; CHECK-NEXT: [[BB:%.*]] = fmul fast float [[B]], [[B]]
; CHECK-NEXT: [[B_CC:%.*]] = fadd fast float [[BB]], [[B]]
; CHECK-NEXT: [[SUM0:%.*]] = fadd fast float [[B_CC]], [[C]]
; CHECK-NEXT: [[SUM:%.*]] = fadd fast float [[SUM0]], [[CC]]
; CHECK-NEXT: ret float [[SUM]]
;
%cc = fmul fast float %c, %c
%b.cc = fadd fast float %b, %cc
%bb = fmul fast float %b, %b
%sum0 = fadd fast float %b.cc, %bb
%sum = fadd fast float %sum0, %c
ret float %sum
}
define float @shared_addend_pairs(float %b, float %c) {
; CHECK-LABEL: define float @shared_addend_pairs(
; CHECK-SAME: float [[B:%.*]], float [[C:%.*]]) {
; CHECK-NEXT: [[BB:%.*]] = fmul fast float [[B]], [[B]]
; CHECK-NEXT: [[CC:%.*]] = fmul fast float [[C]], [[C]]
; CHECK-NEXT: [[B_CC:%.*]] = fadd fast float [[BB]], [[B]]
; CHECK-NEXT: [[C_BB:%.*]] = fadd fast float [[B_CC]], [[C]]
; CHECK-NEXT: [[SUM:%.*]] = fadd fast float [[C_BB]], [[CC]]
; CHECK-NEXT: ret float [[SUM]]
;
%bb = fmul fast float %b, %b
%cc = fmul fast float %c, %c
%b.cc = fadd fast float %b, %cc
%c.bb = fadd fast float %c, %bb
%sum = fadd fast float %b.cc, %c.bb
ret float %sum
}
define float @shared_addend_non_square(float %b, float %c, float %d, float %e) {
; CHECK-LABEL: define float @shared_addend_non_square(
; CHECK-SAME: float [[B:%.*]], float [[C:%.*]], float [[D:%.*]], float [[E:%.*]]) {
; CHECK-NEXT: [[CD:%.*]] = fmul fast float [[D]], [[C]]
; CHECK-NEXT: [[BE:%.*]] = fmul fast float [[E]], [[B]]
; CHECK-NEXT: [[B_CD:%.*]] = fadd fast float [[C]], [[B]]
; CHECK-NEXT: [[SUM0:%.*]] = fadd fast float [[B_CD]], [[CD]]
; CHECK-NEXT: [[SUM:%.*]] = fadd fast float [[SUM0]], [[BE]]
; CHECK-NEXT: ret float [[SUM]]
;
%cd = fmul fast float %c, %d
%b.cd = fadd fast float %b, %cd
%be = fmul fast float %b, %e
%sum0 = fadd fast float %b.cd, %be
%sum = fadd fast float %sum0, %c
ret float %sum
}