Re: [PATCH] match.pd: turn a product of two quotients into one division
Kyrylo Tkachov <[email protected]> Tue, 4 Aug 2026 10:21:19 +0000
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
> On 4 Aug 2026, at 12:03, Jakub Jelinek <[email protected]> wrote: >=20 > On Tue, Aug 04, 2026 at 11:40:28AM +0200, [email protected] wrote: >> --- a/gcc/match.pd >> +++ b/gcc/match.pd >> @@ -819,6 +819,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) >> || !HONOR_SIGNED_ZEROS (type))) >> (rdiv @0 (mult @1 @2)))) >>=20 >> + /* Convert (A/B) * (C/D) to (A*C) / (B*D). Two divisions become one >> + multiply and one division, and a division costs several multiplies = on >> + every target. >> + >> + The two products are new places for the exponent to leave the range= , so >> + the rule needs more than the rounding licence: with B and D both la= rge >> + B * D is an infinity and the quotient becomes inf / inf, and with b= oth >> + small it is a zero and the quotient becomes 0 / 0. Either way a fi= nite >> + result turns into a NaN, so the rule is restricted to the case wher= e >> + infinities and NaNs are excluded, as the cancellation rules above a= re. >> + >> + Both quotients have to be dead outside the product, otherwise a div= ision >> + would be added rather than removed, and a shared reciprocal is bett= er >> + left alone for the multiplications to reuse. That is a hard requir= ement >> + rather than a :s marker, because :s only forbids emitting new state= ments >> + and both products can fold away to nothing, as they do for X * X wh= ere X >> + is one reciprocal square root. Requiring two singly used quotients= also >> + excludes that case, since a value feeding both operands of the prod= uct >> + has two uses. */ >> + (simplify >> + (mult (rdiv@4 @0 @1) (rdiv@5 @2 @3)) >> + (if (!HONOR_NANS (type) && !HONOR_INFINITIES (type) >> + && (TREE_CODE (type) !=3D COMPLEX_TYPE >> + || !HONOR_SIGNED_ZEROS (type)) >> + && single_use (@4) && single_use (@5)) >> + (rdiv (mult @0 @2) (mult @1 @3)))) >=20 > Shouldn't this depend also on flag_unsafe_math_optimizations? > I mean, even if infinities, NaNs and signed zeros aren't involved, > the optimization changes the results due to different rounding, doesn't i= t? The rule is already inside a flag_reciprocal_math. I guess this reassociate= s multiplication across division so maybe it should also have a flag_associ= ative_math. I think that would be enough without going for the full flag_un= safe_math_optimizations?=20 Thanks, Kyrill >=20 > Jakub >=20