| ; 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 | |
| } |