public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x
@ 2022-11-09 15:37 jakub at gcc dot gnu.org
2022-11-09 15:49 ` [Bug tree-optimization/107591] " aldyh at gcc dot gnu.org
` (19 more replies)
0 siblings, 20 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 15:37 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
Bug ID: 107591
Summary: range-op{,-float}.cc for x * x
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: jakub at gcc dot gnu.org
Target Milestone: ---
int
foo (int x)
{
if (x < -13 || x > 26)
return -1;
return x * x;
}
results in
x_4(D) : [irange] int [-13, 26]
_5 : [irange] int [-338, 676]
That is unnecessarily pessimized, because it only computes [-13, 26] * [-13,
26]
range without taking into account that both operands are the same.
For the powi (x, 2) case the range is actually [0, 26 * 26], i.e. we shouldn't
do a cross product for it, just compute the -13 * -13, 0 * 0 (if 0 is in the
range) and 26 * 26 products and form from that the range (I admit I haven't
thought about unsigned or wrapping stuff).
On the PR107569 testcase it is on frange:
_3 = u_2(D)->x;
_6 = _3 * _3;
_7 = u_2(D)->y;
_8 = _7 * _7;
_9 = _6 + _8;
if (_9 u>= 0.0)
If we don't know anything further about u_2(D)->x and u_2(D)->y, VARYING *
VARYING is [0, +Inf] +-NAN, added twice is the same (note, unless
-fno-signed-zeros, it should be really [+0, +Inf] +-NAN, not [-0, +Inf] +-NAN,
but it doesn't matter for the u>= 0.0 comparison).
And then we can fold u>= 0.0 to true.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
@ 2022-11-09 15:49 ` aldyh at gcc dot gnu.org
2022-11-09 15:55 ` aldyh at gcc dot gnu.org
` (18 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: aldyh at gcc dot gnu.org @ 2022-11-09 15:49 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
Aldy Hernandez <aldyh at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2022-11-09
Ever confirmed|0 |1
Status|UNCONFIRMED |NEW
CC| |aldyh at gcc dot gnu.org,
| |amacleod at redhat dot com
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
2022-11-09 15:49 ` [Bug tree-optimization/107591] " aldyh at gcc dot gnu.org
@ 2022-11-09 15:55 ` aldyh at gcc dot gnu.org
2022-11-09 15:57 ` jakub at gcc dot gnu.org
` (17 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: aldyh at gcc dot gnu.org @ 2022-11-09 15:55 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #1 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
pinskia is a god. How does he keep track of all these bugs, plus the cross
reference between them? I knew PR91645 was related, but it was specifically
something on my radar, not the 5 trillion bugs in pinskia's head :-). Kudos!
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
2022-11-09 15:49 ` [Bug tree-optimization/107591] " aldyh at gcc dot gnu.org
2022-11-09 15:55 ` aldyh at gcc dot gnu.org
@ 2022-11-09 15:57 ` jakub at gcc dot gnu.org
2022-11-09 15:59 ` pinskia at gcc dot gnu.org
` (16 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 15:57 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Perhaps before we try to map MULT_EXPR into some irange/frange op the usual
way,
while we still have access to gimple statement check if it is MULT_EXPR with
the same operands and use a different artificial unary op for pow2.
We could do this for PLUS_EXPR x + x as well and handle it as 2 * x if we don't
do that already or if match.pd doesn't already canonicalize x + x that way.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (2 preceding siblings ...)
2022-11-09 15:57 ` jakub at gcc dot gnu.org
@ 2022-11-09 15:59 ` pinskia at gcc dot gnu.org
2022-11-09 16:01 ` pinskia at gcc dot gnu.org
` (15 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-11-09 15:59 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Aldy Hernandez from comment #1)
> pinskia is a god. How does he keep track of all these bugs, plus the cross
> reference between them? I knew PR91645 was related, but it was specifically
> something on my radar, not the 5 trillion bugs in pinskia's head :-). Kudos!
I remembered seeing a different "x * x" issue and I just did a search. There is
at least one more about "x * x" too but I need to find it still.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (3 preceding siblings ...)
2022-11-09 15:59 ` pinskia at gcc dot gnu.org
@ 2022-11-09 16:01 ` pinskia at gcc dot gnu.org
2022-11-09 16:02 ` aldyh at gcc dot gnu.org
` (14 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-11-09 16:01 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
See Also| |https://gcc.gnu.org/bugzill
| |a/show_bug.cgi?id=56355
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
PR 56355 is related but it is definitely more complex.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (4 preceding siblings ...)
2022-11-09 16:01 ` pinskia at gcc dot gnu.org
@ 2022-11-09 16:02 ` aldyh at gcc dot gnu.org
2022-11-09 16:04 ` aldyh at gcc dot gnu.org
` (13 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: aldyh at gcc dot gnu.org @ 2022-11-09 16:02 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #5 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #3)
> (In reply to Aldy Hernandez from comment #1)
> > pinskia is a god. How does he keep track of all these bugs, plus the cross
> > reference between them? I knew PR91645 was related, but it was specifically
> > something on my radar, not the 5 trillion bugs in pinskia's head :-). Kudos!
>
> I remembered seeing a different "x * x" issue and I just did a search. There
> is at least one more about "x * x" too but I need to find it still.
I think you're just being humble. Either that or maybe you're just a bot with
superpowers :-P.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (5 preceding siblings ...)
2022-11-09 16:02 ` aldyh at gcc dot gnu.org
@ 2022-11-09 16:04 ` aldyh at gcc dot gnu.org
2022-11-09 16:31 ` jakub at gcc dot gnu.org
` (12 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: aldyh at gcc dot gnu.org @ 2022-11-09 16:04 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #6 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #2)
> Perhaps before we try to map MULT_EXPR into some irange/frange op the usual
> way,
> while we still have access to gimple statement check if it is MULT_EXPR with
> the same operands and use a different artificial unary op for pow2.
> We could do this for PLUS_EXPR x + x as well and handle it as 2 * x if we
> don't do that already or if match.pd doesn't already canonicalize x + x that
> way.
FYI, the range operators have a relation field, so it should be able to tell
you that both operands are equal with VREL_EQ (?). You could use that to
optimize things.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (6 preceding siblings ...)
2022-11-09 16:04 ` aldyh at gcc dot gnu.org
@ 2022-11-09 16:31 ` jakub at gcc dot gnu.org
2022-11-09 16:40 ` jakub at gcc dot gnu.org
` (11 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 16:31 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
To answer my own question:
int
foo (int x)
{
return x + x;
}
int
bar (int x)
{
return x * x * x * x * x * x;
}
float
baz (float x)
{
return x + x;
}
float
qux (float x)
{
return x * x * x * x * x * x;
}
float
corge (float x)
{
return x * x;
}
match.pd or fold-const.cc canonicalizes x + x to x * 2, so no need to special
case that, x * x isn't canonicalized for integral types nor without -ffast-math
for floats either, with -ffast-math reassoc1 canonicalizes the multiplications
into __builtin_powif (x, 6) resp. __builtin_powif (x, 2) until powcabs pass
later on splits those into multiplications again.
So, for frange, if we implement good range op for CASE_CFN_POWI, we could just
use that, perhaps for VREL_EQ on mult.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (7 preceding siblings ...)
2022-11-09 16:31 ` jakub at gcc dot gnu.org
@ 2022-11-09 16:40 ` jakub at gcc dot gnu.org
2022-11-09 17:45 ` amacleod at redhat dot com
` (10 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 16:40 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Aldy Hernandez from comment #6)
> FYI, the range operators have a relation field, so it should be able to tell
> you that both operands are equal with VREL_EQ (?). You could use that to
> optimize things.
You're right, at least for irange trio.op1_op2 () in the mult fold_range is
VREL_EQ and we could just go from that.
For frange perhaps it isn't as perfect because of signed zeros, so in
float
foo (float x, float y)
{
if (x == y)
return x * y;
return 42.0f;
}
trio.op1_op2 () could be VREL_EQ even if one is signed and the other unsigned
zero, and in that case -0.0 would need to be in the range too. But maybe that
is good enough for now.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (8 preceding siblings ...)
2022-11-09 16:40 ` jakub at gcc dot gnu.org
@ 2022-11-09 17:45 ` amacleod at redhat dot com
2022-11-09 17:49 ` jakub at gcc dot gnu.org
` (9 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: amacleod at redhat dot com @ 2022-11-09 17:45 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #9 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Jakub Jelinek from comment #8)
> (In reply to Aldy Hernandez from comment #6)
> > FYI, the range operators have a relation field, so it should be able to tell
> > you that both operands are equal with VREL_EQ (?). You could use that to
> > optimize things.
>
> You're right, at least for irange trio.op1_op2 () in the mult fold_range is
> VREL_EQ and we could just go from that.
> For frange perhaps it isn't as perfect because of signed zeros, so in
> float
> foo (float x, float y)
> {
> if (x == y)
> return x * y;
> return 42.0f;
> }
> trio.op1_op2 () could be VREL_EQ even if one is signed and the other
> unsigned zero, and in that case -0.0 would need to be in the range too. But
> maybe that is good enough for now.
you could also test whether op1_range contains + and/or - 0, as well as
op2_range. VREL_EQ is a symbolic equality.. the ranges can still be distinct
and individually testable to see if you have a +0 and -0.. I guess you could
also test for equality of the ranges.. op1_range == op2_range
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (9 preceding siblings ...)
2022-11-09 17:45 ` amacleod at redhat dot com
@ 2022-11-09 17:49 ` jakub at gcc dot gnu.org
2022-11-09 18:22 ` amacleod at redhat dot com
` (8 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 17:49 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Andrew Macleod from comment #9)
> you could also test whether op1_range contains + and/or - 0, as well as
> op2_range. VREL_EQ is a symbolic equality.. the ranges can still be
> distinct and individually testable to see if you have a +0 and -0.. I
> guess you could also test for equality of the ranges.. op1_range == op2_range
Equality of the ranges doesn't imply equality of the values.
int
foo (int x, y)
{
if (x < -13 || x > 26)
return -1;
if (y < -13 || y > 26)
return -1;
return x * y;
}
In the above testcase, both x and y have [-13, 26] ranges, but here the range
[-338, 676] is correct, while [0, 676] is right for the #c0 testcase.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (10 preceding siblings ...)
2022-11-09 17:49 ` jakub at gcc dot gnu.org
@ 2022-11-09 18:22 ` amacleod at redhat dot com
2022-11-09 18:35 ` jakub at gcc dot gnu.org
` (7 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: amacleod at redhat dot com @ 2022-11-09 18:22 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #11 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Jakub Jelinek from comment #10)
> (In reply to Andrew Macleod from comment #9)
> > you could also test whether op1_range contains + and/or - 0, as well as
> > op2_range. VREL_EQ is a symbolic equality.. the ranges can still be
> > distinct and individually testable to see if you have a +0 and -0.. I
> > guess you could also test for equality of the ranges.. op1_range == op2_range
>
> Equality of the ranges doesn't imply equality of the values.
>
> int
> foo (int x, y)
> {
> if (x < -13 || x > 26)
> return -1;
> if (y < -13 || y > 26)
> return -1;
> return x * y;
> }
>
> In the above testcase, both x and y have [-13, 26] ranges, but here the
> range [-338, 676] is correct, while [0, 676] is right for the #c0 testcase.
no, I meant in addition to the VREL_EQ. so
if (rel == VREL_EQ && op1_range != op2_range)
then you know you have something like if (x == y) z=x*y and may have to
check for various signed zero cobinations in each range,
whereas is op1_range == op2_range in this case, it should be perfectly safe..
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (11 preceding siblings ...)
2022-11-09 18:22 ` amacleod at redhat dot com
@ 2022-11-09 18:35 ` jakub at gcc dot gnu.org
2022-11-09 19:20 ` amacleod at redhat dot com
` (6 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 18:35 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Andrew Macleod from comment #11)
> no, I meant in addition to the VREL_EQ. so
> if (rel == VREL_EQ && op1_range != op2_range)
> then you know you have something like if (x == y) z=x*y and may have
> to check for various signed zero cobinations in each range,
> whereas is op1_range == op2_range in this case, it should be perfectly safe..
I don't understand. Let's modify the testcase to:
float
foo (float x, y)
{
if (x < -13.f || x > 26.f)
return -1.0f;
if (y < -13.f || y > 26.f)
return -1.0f;
if (x == y)
return x * y;
return 42.0f;
}
I'd expect that fold_range on the x * y should see trio.op1_op2 () == VREL_EQ
because of the guarding x == y condition. And the ranges of both are [-13.f,
26.f] +-NAN too. Still, x could be -0.0f and y 0.0f or vice versa, and so
x * y could be -0.0f, so we need [-0.f, 676.f] +-NAN. While if it is x * x, we
know the result will have always sign bit of 0 (except if NAN), so [0.f, 676.f]
+-NAN.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (12 preceding siblings ...)
2022-11-09 18:35 ` jakub at gcc dot gnu.org
@ 2022-11-09 19:20 ` amacleod at redhat dot com
2022-11-09 20:24 ` jakub at gcc dot gnu.org
` (5 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: amacleod at redhat dot com @ 2022-11-09 19:20 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #13 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Jakub Jelinek from comment #12)
> (In reply to Andrew Macleod from comment #11)
> > no, I meant in addition to the VREL_EQ. so
> > if (rel == VREL_EQ && op1_range != op2_range)
> > then you know you have something like if (x == y) z=x*y and may have
> > to check for various signed zero cobinations in each range,
> > whereas is op1_range == op2_range in this case, it should be perfectly safe..
>
> I don't understand. Let's modify the testcase to:
> I'd expect that fold_range on the x * y should see trio.op1_op2 () == VREL_EQ
> because of the guarding x == y condition. And the ranges of both are
> [-13.f, 26.f] +-NAN too. Still, x could be -0.0f and y 0.0f or vice versa,
> and so
> x * y could be -0.0f, so we need [-0.f, 676.f] +-NAN. While if it is x * x,
> we know the result will have always sign bit of 0 (except if NAN), so [0.f,
> 676.f] +-NAN.
gah. Clearly it is I who does not understand. -0.0 and +0.0 interactions remind
me of all the signed single bit crud we (ie Aldy) went thru. The same team
must have come up with both concepts :-P At least they deserve the same award.
Move along and ignore me.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (13 preceding siblings ...)
2022-11-09 19:20 ` amacleod at redhat dot com
@ 2022-11-09 20:24 ` jakub at gcc dot gnu.org
2022-11-09 20:45 ` jakub at gcc dot gnu.org
` (4 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 20:24 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Incremental patch on top of the
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107569#c18 patch which optimizes
the floating point x * x:
--- gcc/range-op-float.cc.jj 2022-11-09 19:06:11.075716000 +0100
+++ gcc/range-op-float.cc 2022-11-09 21:11:52.468256045 +0100
@@ -51,7 +51,7 @@ along with GCC; see the file COPYING3.
bool
range_operator_float::fold_range (frange &r, tree type,
const frange &op1, const frange &op2,
- relation_trio) const
+ relation_trio trio) const
{
if (empty_range_varying (r, type, op1, op2))
return true;
@@ -65,7 +65,7 @@ range_operator_float::fold_range (frange
bool maybe_nan;
rv_fold (lb, ub, maybe_nan, type,
op1.lower_bound (), op1.upper_bound (),
- op2.lower_bound (), op2.upper_bound ());
+ op2.lower_bound (), op2.upper_bound (), trio);
// Handle possible NANs by saturating to the appropriate INF if only
// one end is a NAN. If both ends are a NAN, just return a NAN.
@@ -103,8 +103,8 @@ range_operator_float::rv_fold (REAL_VALU
const REAL_VALUE_TYPE &lh_lb ATTRIBUTE_UNUSED,
const REAL_VALUE_TYPE &lh_ub ATTRIBUTE_UNUSED,
const REAL_VALUE_TYPE &rh_lb ATTRIBUTE_UNUSED,
- const REAL_VALUE_TYPE &rh_ub ATTRIBUTE_UNUSED)
- const
+ const REAL_VALUE_TYPE &rh_ub ATTRIBUTE_UNUSED,
+ relation_trio) const
{
lb = dconstninf;
ub = dconstinf;
@@ -1868,7 +1868,8 @@ class foperator_plus : public range_oper
const REAL_VALUE_TYPE &lh_lb,
const REAL_VALUE_TYPE &lh_ub,
const REAL_VALUE_TYPE &rh_lb,
- const REAL_VALUE_TYPE &rh_ub) const final override
+ const REAL_VALUE_TYPE &rh_ub,
+ relation_trio) const final override
{
frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
@@ -1892,7 +1893,8 @@ class foperator_minus : public range_ope
const REAL_VALUE_TYPE &lh_lb,
const REAL_VALUE_TYPE &lh_ub,
const REAL_VALUE_TYPE &rh_lb,
- const REAL_VALUE_TYPE &rh_ub) const final override
+ const REAL_VALUE_TYPE &rh_ub,
+ relation_trio) const final override
{
frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
@@ -1910,7 +1912,7 @@ class foperator_minus : public range_ope
/* Wrapper around frange_arithmetics, that computes the result
if inexact rounded to both directions. Also, if one of the
- operands is +-0.0 and another +-inf, return +-0.0 rather than
+ operands is +-0.0 and another +-INF, return +-0.0 rather than
NAN. */
static void
@@ -1945,13 +1947,42 @@ class foperator_mult : public range_oper
const REAL_VALUE_TYPE &lh_lb,
const REAL_VALUE_TYPE &lh_ub,
const REAL_VALUE_TYPE &rh_lb,
- const REAL_VALUE_TYPE &rh_ub) const final override
+ const REAL_VALUE_TYPE &rh_ub,
+ relation_trio trio) const final override
{
REAL_VALUE_TYPE cp[8];
+ bool is_square
+ = (trio.op1_op2 () == VREL_EQ
+ && real_equal (&lh_lb, &rh_lb)
+ && real_equal (&lh_ub, &rh_ub)
+ && real_isneg (&lh_lb) == real_isneg (&rh_lb)
+ && real_isneg (&lh_ub) == real_isneg (&rh_ub));
// Do a cross-product.
frange_mult (type, cp[0], cp[4], lh_lb, rh_lb);
- frange_mult (type, cp[1], cp[5], lh_lb, rh_ub);
- frange_mult (type, cp[2], cp[6], lh_ub, rh_lb);
+ if (is_square)
+ {
+ // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
+ // as maximum and -0.0 as minimum if 0.0 is in the range,
+ // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
+ // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
+ // x and y are bitwise equal, just that they compare equal.
+ if (real_compare (LE_EXPR, &lh_lb, &dconst0)
+ && real_compare (GE_EXPR, &lh_ub, &dconst0))
+ {
+ cp[1] = dconst0;
+ real_value_negate (&cp[1]);
+ }
+ else
+ cp[1] = cp[0];
+ cp[2] = cp[0];
+ cp[5] = cp[4];
+ cp[6] = cp[4];
+ }
+ else
+ {
+ frange_mult (type, cp[1], cp[5], lh_lb, rh_ub);
+ frange_mult (type, cp[2], cp[6], lh_ub, rh_lb);
+ }
frange_mult (type, cp[3], cp[7], lh_ub, rh_ub);
for (int i = 1; i < 3; ++i)
{
@@ -1965,18 +1996,27 @@ class foperator_mult : public range_oper
lb = cp[0];
ub = cp[4];
- // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NaN.
- if ((real_iszero (&lh_lb) && real_iszero (&lh_ub)
- && real_isinf (&rh_lb) && real_isinf (&rh_ub, real_isneg (&rh_lb)))
- || (real_iszero (&rh_lb) && real_iszero (&rh_ub)
- && real_isinf (&lh_lb) && real_isinf (&lh_ub, real_isneg
(&lh_lb))))
+ // If both operands are the same, then we know it can be +-0.0, or +-INF,
+ // but not both at the same time, so it will never be invalid unless
+ // operand was already NAN.
+ if (is_square)
+ maybe_nan = false;
+ // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
+ else if ((real_iszero (&lh_lb)
+ && real_iszero (&lh_ub)
+ && real_isinf (&rh_lb)
+ && real_isinf (&rh_ub, real_isneg (&rh_lb)))
+ || (real_iszero (&rh_lb)
+ && real_iszero (&rh_ub)
+ && real_isinf (&lh_lb)
+ && real_isinf (&lh_ub, real_isneg (&lh_lb))))
{
real_nan (&lb, NULL, 0, TYPE_MODE (type));
ub = lb;
maybe_nan = true;
}
// Otherwise, if one range includes zero and the other ends with +-INF,
- // it is a maybe NaN.
+ // it is a maybe NAN.
else if (real_compare (LE_EXPR, &lh_lb, &dconst0)
&& real_compare (GE_EXPR, &lh_ub, &dconst0)
&& (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
--- gcc/range-op.h.jj 2022-11-09 11:22:42.867624633 +0100
+++ gcc/range-op.h 2022-11-09 20:20:02.266964633 +0100
@@ -123,7 +123,8 @@ public:
const REAL_VALUE_TYPE &lh_lb,
const REAL_VALUE_TYPE &lh_ub,
const REAL_VALUE_TYPE &rh_lb,
- const REAL_VALUE_TYPE &rh_ub) const;
+ const REAL_VALUE_TYPE &rh_ub,
+ relation_trio) const;
// Unary operations have the range of the LHS as op2.
virtual bool fold_range (irange &r, tree type,
const frange &lh,
We determine the right range (I think), but then it helps just to optimize away
the call to sqrt function, not the actual comparison (bet for a fear that a
sNaN
could appear there).
If frange also tracked maybe sNaN (and cleared it say on all binops or unops
other than the operations that might not trigger exception/quiet it), perhaps
we could optimize that. Or say without frange help just by assuming that say
result of a binary floating point operation can't ever be a sNaN.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (14 preceding siblings ...)
2022-11-09 20:24 ` jakub at gcc dot gnu.org
@ 2022-11-09 20:45 ` jakub at gcc dot gnu.org
2022-11-09 22:25 ` amacleod at redhat dot com
` (3 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 20:45 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #15 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I've screwed up the real_value_negate calls, they need to assign the result.
Anyway, yet another option would be for cdce to ask the ranger if the sqrt
argument can be smaller than -0.0 (and only if it can, emit the comparison).
Then we don't need to deal with removing the comparison again.
Of course, such removals might be still useful for user code.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (15 preceding siblings ...)
2022-11-09 20:45 ` jakub at gcc dot gnu.org
@ 2022-11-09 22:25 ` amacleod at redhat dot com
2022-11-09 23:27 ` jakub at gcc dot gnu.org
` (2 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: amacleod at redhat dot com @ 2022-11-09 22:25 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #16 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Jakub Jelinek from comment #15)
> I've screwed up the real_value_negate calls, they need to assign the result.
>
> Anyway, yet another option would be for cdce to ask the ranger if the sqrt
> argument can be smaller than -0.0 (and only if it can, emit the comparison).
> Then we don't need to deal with removing the comparison again.
> Of course, such removals might be still useful for user code.
even checking the global range from cdce at this point should show that its >=
-0.0...
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (16 preceding siblings ...)
2022-11-09 22:25 ` amacleod at redhat dot com
@ 2022-11-09 23:27 ` jakub at gcc dot gnu.org
2022-11-12 8:42 ` cvs-commit at gcc dot gnu.org
2023-04-05 7:14 ` pilarlatiesa at gmail dot com
19 siblings, 0 replies; 21+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-11-09 23:27 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Andrew Macleod from comment #16)
> (In reply to Jakub Jelinek from comment #15)
> > I've screwed up the real_value_negate calls, they need to assign the result.
> >
> > Anyway, yet another option would be for cdce to ask the ranger if the sqrt
> > argument can be smaller than -0.0 (and only if it can, emit the comparison).
> > Then we don't need to deal with removing the comparison again.
> > Of course, such removals might be still useful for user code.
>
> even checking the global range from cdce at this point should show that its
> >= -0.0...
Without larger changes in tree-call-cdce.cc, perhaps we could change
gen_one_condition to check the global or even non-global frange (but in the
latter case the question is at what stmt) and if the range indicates that tcode
of arg against (float_type) lbub (aka lbub_real_cst) is always true or always
false, simply emit an always true or always false condition (though the domain
ranges aren't exact but rounded up/down to integers and I think even there is
sometimes an off by one conservatively, so probably only always true
conditions)
rather than actual arg comparison. Even better would be not to emit any and/or
propagate a stmt to it, but am not sure about either (the code treats nconds ==
0 differently and there are separators in between sometimes; and for stmt, it
uses some code for better placement of a check, but not sure if say a range
could be true on the sqrt etc. call and then not on the placement of the
condition which it picks).
In any case, not much familiar with the range_of_expr etc. APIs.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (17 preceding siblings ...)
2022-11-09 23:27 ` jakub at gcc dot gnu.org
@ 2022-11-12 8:42 ` cvs-commit at gcc dot gnu.org
2023-04-05 7:14 ` pilarlatiesa at gmail dot com
19 siblings, 0 replies; 21+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-11-12 8:42 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #18 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:
https://gcc.gnu.org/g:2f7f9edd28d75a85a33599978f23811e679e443d
commit r13-3923-g2f7f9edd28d75a85a33599978f23811e679e443d
Author: Jakub Jelinek <jakub@redhat.com>
Date: Sat Nov 12 09:33:01 2022 +0100
range-op: Implement floating point multiplication fold_range [PR107569]
The following patch implements frange multiplication, including the
special case of x * x. The callers don't tell us that it is x * x,
just that it is either z = x * x or if (x == y) z = x * y;
For irange that makes no difference, but for frange it can mean
x is -0.0 and y is 0.0 if they have the same range that includes both
signed and unsigned zeros, so we need to assume result could be -0.0.
The patch causes one regression:
+FAIL: gcc.dg/fold-overflow-1.c scan-assembler-times 2139095040 2
but that is already tracked in PR107608 and affects not just the newly
added multiplication, but addition and other floating point operations
(and doesn't seem like a ranger bug but dce or whatever else).
2022-11-12 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/107569
PR tree-optimization/107591
* range-op.h (range_operator_float::rv_fold): Add relation_kind
argument.
* range-op-float.cc (range_operator_float::fold_range): Name
last argument trio and pass trio.op1_op2 () as last argument to
rv_fold.
(range_operator_float::rv_fold): Add relation_kind argument.
(foperator_plus::rv_fold, foperator_minus::rv_fold): Likewise.
(foperator_mult): New class.
(floating_op_table::floating_op_table): Use foperator_mult for
MULT_EXPR.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [Bug tree-optimization/107591] range-op{,-float}.cc for x * x
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
` (18 preceding siblings ...)
2022-11-12 8:42 ` cvs-commit at gcc dot gnu.org
@ 2023-04-05 7:14 ` pilarlatiesa at gmail dot com
19 siblings, 0 replies; 21+ messages in thread
From: pilarlatiesa at gmail dot com @ 2023-04-05 7:14 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107591
--- Comment #19 from Pilar Latiesa <pilarlatiesa at gmail dot com> ---
The testcase:
#include <cmath>
struct TVec { double x, y, z; };
double dot(TVec const &u, TVec const &v)
{ return u.x * v.x + u.y * v.y + u.y * v.y + u.z * v.z; }
double mag(TVec const &u)
{ return std::sqrt(dot(u, u)); }
with current trunk is compiled as:
vmovsd 8(%rdi), %xmm0
vmovsd (%rdi), %xmm1
vmulsd %xmm0, %xmm0, %xmm0
vmovsd %xmm1, %xmm1, %xmm2
vfmadd132sd %xmm1, %xmm0, %xmm2
vmovsd 16(%rdi), %xmm1
vaddsd %xmm2, %xmm0, %xmm0
vfmadd132sd %xmm1, %xmm0, %xmm1
vsqrtsd %xmm1, %xmm1, %xmm0
ret
That's excellent. Thanks
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2023-04-05 7:14 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-09 15:37 [Bug tree-optimization/107591] New: range-op{,-float}.cc for x * x jakub at gcc dot gnu.org
2022-11-09 15:49 ` [Bug tree-optimization/107591] " aldyh at gcc dot gnu.org
2022-11-09 15:55 ` aldyh at gcc dot gnu.org
2022-11-09 15:57 ` jakub at gcc dot gnu.org
2022-11-09 15:59 ` pinskia at gcc dot gnu.org
2022-11-09 16:01 ` pinskia at gcc dot gnu.org
2022-11-09 16:02 ` aldyh at gcc dot gnu.org
2022-11-09 16:04 ` aldyh at gcc dot gnu.org
2022-11-09 16:31 ` jakub at gcc dot gnu.org
2022-11-09 16:40 ` jakub at gcc dot gnu.org
2022-11-09 17:45 ` amacleod at redhat dot com
2022-11-09 17:49 ` jakub at gcc dot gnu.org
2022-11-09 18:22 ` amacleod at redhat dot com
2022-11-09 18:35 ` jakub at gcc dot gnu.org
2022-11-09 19:20 ` amacleod at redhat dot com
2022-11-09 20:24 ` jakub at gcc dot gnu.org
2022-11-09 20:45 ` jakub at gcc dot gnu.org
2022-11-09 22:25 ` amacleod at redhat dot com
2022-11-09 23:27 ` jakub at gcc dot gnu.org
2022-11-12 8:42 ` cvs-commit at gcc dot gnu.org
2023-04-05 7:14 ` pilarlatiesa at gmail dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).