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