public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch
@ 2020-07-20 4:20 gabravier at gmail dot com
2020-07-20 7:01 ` [Bug tree-optimization/96245] " rguenth at gcc dot gnu.org
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: gabravier at gmail dot com @ 2020-07-20 4:20 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Bug ID: 96245
Summary: Failure to optimize arithmetic pattern in switch
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: gabravier at gmail dot com
Target Milestone: ---
void f(int x)
{
switch (x)
{
case 0:
putchar('0');
break;
case 1:
putchar('1');
break;
case 2:
putchar('2');
break;
case 3:
putchar('3');
break;
case 4:
putchar('4');
break;
case 5:
putchar('5');
break;
case 6:
putchar('6');
break;
case 7:
putchar('7');
break;
case 8:
putchar('8');
break;
case 9:
putchar('9');
break;
}
}
This can be optimized to `if ((unsigned)x < 10) putchar('0' + x);`. This
transformation is done by LLVM, but not by GCC.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
@ 2020-07-20 7:01 ` rguenth at gcc dot gnu.org
2020-07-20 15:28 ` msebor at gcc dot gnu.org
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-07-20 7:01 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2020-07-20
CC| |marxin at gcc dot gnu.org
Keywords| |missed-optimization
Ever confirmed|0 |1
Status|UNCONFIRMED |NEW
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
switch-conversion(?), it does look like a very special case. Similar:
int y;
void f(int x)
{
switch (x)
{
case 0:
y = 0;
break;
case 1:
y = 1;
break;
...
converting to if (...) y = x; or more general to x + CST. The store
commoning patch should in this case sink this to y = PHI<...> where
switch-conversion would convert the PHI<...>. For the putchar case
there's nothing "commoming" the call (the same code doing the store
sinking could also sink calls if we want that). Not sure if
switch-conversion itself would want to do this (profitability increases
if we can eliminate the PHI<> by arithmetics).
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
2020-07-20 7:01 ` [Bug tree-optimization/96245] " rguenth at gcc dot gnu.org
@ 2020-07-20 15:28 ` msebor at gcc dot gnu.org
2020-07-20 15:49 ` josephcsible at gmail dot com
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: msebor at gcc dot gnu.org @ 2020-07-20 15:28 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Martin Sebor <msebor at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |msebor at gcc dot gnu.org
--- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> ---
I wonder if discouraging this pattern by warning on it and suggesting the
simpler alternative would be worthwhile (either in addition to or in lieu of
the optimization) to help avoid typos resulting from copy-and-paste mistakes
that cannot very well be detected. As in:
void f(int x)
{
switch (x)
{
case 0:
putchar('0');
break;
case 1:
putchar('1');
break;
...
case 7:
putchar('6'); <<< typo
break;
...
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
2020-07-20 7:01 ` [Bug tree-optimization/96245] " rguenth at gcc dot gnu.org
2020-07-20 15:28 ` msebor at gcc dot gnu.org
@ 2020-07-20 15:49 ` josephcsible at gmail dot com
2020-07-20 18:53 ` msebor at gcc dot gnu.org
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: josephcsible at gmail dot com @ 2020-07-20 15:49 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Joseph C. Sible <josephcsible at gmail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |josephcsible at gmail dot com
--- Comment #3 from Joseph C. Sible <josephcsible at gmail dot com> ---
(In reply to Martin Sebor from comment #2)
> I wonder if discouraging this pattern by warning on it and suggesting the
> simpler alternative would be worthwhile (either in addition to or in lieu of
> the optimization) to help avoid typos resulting from copy-and-paste mistakes
> that cannot very well be detected.
I don't see how such a warning would be particularly useful in practice.
Wouldn't one of these two things have to be true?
1. It would only warn you when you used the typo-prone pattern but didn't
actually make any typos in it
2. The warning would trigger in code where the author intentionally breaks the
pattern for some cases
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (2 preceding siblings ...)
2020-07-20 15:49 ` josephcsible at gmail dot com
@ 2020-07-20 18:53 ` msebor at gcc dot gnu.org
2020-07-23 9:10 ` marxin at gcc dot gnu.org
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: msebor at gcc dot gnu.org @ 2020-07-20 18:53 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
--- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> ---
Only (1) would be true. Like the optimization, the warning wouldn't trigger in
code that didn't follow the pattern because there's no way to tell if that's
deliberate or a bug.
I'd expect the warning to be useful by discouraging a questionable pattern. I
don't suppose this comes up a lot so like the optimization, the difference the
warning would make in practice can be debated. Unlike the optimization alone,
though, it would lead to less repetitive and so more readable code.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (3 preceding siblings ...)
2020-07-20 18:53 ` msebor at gcc dot gnu.org
@ 2020-07-23 9:10 ` marxin at gcc dot gnu.org
2020-09-22 12:24 ` marxin at gcc dot gnu.org
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-07-23 9:10 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Martin Liška <marxin at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Assignee|unassigned at gcc dot gnu.org |marxin at gcc dot gnu.org
Status|NEW |ASSIGNED
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (4 preceding siblings ...)
2020-07-23 9:10 ` marxin at gcc dot gnu.org
@ 2020-09-22 12:24 ` marxin at gcc dot gnu.org
2020-12-14 10:51 ` jakub at gcc dot gnu.org
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-09-22 12:24 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Martin Liška <marxin at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|ASSIGNED |NEW
Assignee|marxin at gcc dot gnu.org |unassigned at gcc dot gnu.org
--- Comment #5 from Martin Liška <marxin at gcc dot gnu.org> ---
Leaving for now as it's probably not material for switch-coversion (I mean the
putchar test-case).
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (5 preceding siblings ...)
2020-09-22 12:24 ` marxin at gcc dot gnu.org
@ 2020-12-14 10:51 ` jakub at gcc dot gnu.org
2020-12-14 11:19 ` jakub at gcc dot gnu.org
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-14 10:51 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org,
| |vries at gcc dot gnu.org
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think it isn't really a too special case, of course one shouldn't take it
literally and look for a particular call etc.
But, generally try to see if all the switch cases are the same except some
constant or two (same e.g. in the ICF sense) and if that constant or two is
linear vs. the corresponding case.
It can be done either in switchconv, or could be perhaps some kind of
GIMPLE_SWITCH aware parametrized tail merging/cross jumping.
As it would (or could) turn constant expressions into non-constant, I guess
we'd need to take some conservative approach with __builtin_constant_p, punt if
there is a __builtin_constant_p in the block, either altogether, or if it is
among (recursively) the immediate uses of the stmt where the constant(s)
appear.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (6 preceding siblings ...)
2020-12-14 10:51 ` jakub at gcc dot gnu.org
@ 2020-12-14 11:19 ` jakub at gcc dot gnu.org
2020-12-14 11:23 ` jakub at gcc dot gnu.org
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-14 11:19 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Looking at godbolt and LLVM release notes, this optimization appeared in LLVM 9
and looks to be a switch optimization:
LLVM can now sink similar instructions to a common successor block also when
the instructions have no uses, such as calls to void functions. This allows
code such as
void g(int);
enum e { A, B, C, D };
void f(e x, int y, int z) {
switch(x) {
case A: g(6); break;
case B: g(3); break;
case C: g(9); break;
case D: g(2); break;
}
}
to be optimized to a single call to g, with the argument loaded from a lookup
table.
I bet it is https://reviews.llvm.org/D59936
We don't optimize even:
void
foo (int *p, int x)
{
switch (x)
{
case 7: *p = 14; break;
case 8: *p = 15; break;
case 9: *p = 16; break;
case 10: *p = 17; break;
case 11: *p = 18; break;
case 12: *p = 19; break;
default: return;
}
}
but do optimize if one performs the switch parametrized tail merging manually:
void
bar (int *p, int x)
{
int y;
switch (x)
{
case 7: y = 14; break;
case 8: y = 15; break;
case 9: y = 16; break;
case 10: y = 17; break;
case 11: y = 18; break;
case 12: y = 19; break;
default: return;
}
*p = y;
}
So, do you prefer to do this in tree-ssa-tail-merge.c (for blocks starting with
switches) or in tree-switch-conversion.c, and should we handle both the case
where the constant(s) are linear vs. the switch expression, or also any other
(let the switchconv pass then create the arrays)?
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (7 preceding siblings ...)
2020-12-14 11:19 ` jakub at gcc dot gnu.org
@ 2020-12-14 11:23 ` jakub at gcc dot gnu.org
2020-12-14 13:48 ` rguenther at suse dot de
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-14 11:23 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |law at gcc dot gnu.org
--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Effectively it would be the inverse of jump threading optimization, though I
think we don't do it for switches, turning say:
void
foo (int *p, int x)
{
switch (x)
{
case 7:
case 8:
case 9:
case 10:
case 11:
case 12: *p = 12 + x; break;
default: return;
}
}
into the above foo.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (8 preceding siblings ...)
2020-12-14 11:23 ` jakub at gcc dot gnu.org
@ 2020-12-14 13:48 ` rguenther at suse dot de
2020-12-14 14:16 ` jakub at gcc dot gnu.org
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: rguenther at suse dot de @ 2020-12-14 13:48 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
--- Comment #9 from rguenther at suse dot de <rguenther at suse dot de> ---
On December 14, 2020 12:19:32 PM GMT+01:00, "jakub at gcc dot gnu.org"
<gcc-bugzilla@gcc.gnu.org> wrote:
>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
>
>--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
>Looking at godbolt and LLVM release notes, this optimization appeared
>in LLVM 9
>and looks to be a switch optimization:
>
>LLVM can now sink similar instructions to a common successor block also
>when
>the instructions have no uses, such as calls to void functions. This
>allows
>code such as
>
>void g(int);
>enum e { A, B, C, D };
>void f(e x, int y, int z) {
> switch(x) {
> case A: g(6); break;
> case B: g(3); break;
> case C: g(9); break;
> case D: g(2); break;
> }
>}
>
>to be optimized to a single call to g, with the argument loaded from a
>lookup
>table.
>I bet it is https://reviews.llvm.org/D59936
>
>We don't optimize even:
>void
>foo (int *p, int x)
>{
> switch (x)
> {
> case 7: *p = 14; break;
> case 8: *p = 15; break;
> case 9: *p = 16; break;
> case 10: *p = 17; break;
> case 11: *p = 18; break;
> case 12: *p = 19; break;
> default: return;
> }
>}
Store commoning in the sink pass should do this. But it would need to create a
forwarder because of the default case.
That's a missed piece there.
>but do optimize if one performs the switch parametrized tail merging
>manually:
>void
>bar (int *p, int x)
>{
> int y;
> switch (x)
> {
> case 7: y = 14; break;
> case 8: y = 15; break;
> case 9: y = 16; break;
> case 10: y = 17; break;
> case 11: y = 18; break;
> case 12: y = 19; break;
> default: return;
> }
> *p = y;
>}
>
>So, do you prefer to do this in tree-ssa-tail-merge.c (for blocks
>starting with
>switches) or in tree-switch-conversion.c, and should we handle both the
>case
>where the constant(s) are linear vs. the switch expression, or also any
>other
>(let the switchconv pass then create the arrays)?
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (9 preceding siblings ...)
2020-12-14 13:48 ` rguenther at suse dot de
@ 2020-12-14 14:16 ` jakub at gcc dot gnu.org
2021-11-29 20:35 ` pinskia at gcc dot gnu.org
2024-02-03 19:54 ` pinskia at gcc dot gnu.org
12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-12-14 14:16 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That is just one specific special case, it can be anything else, like
case 7: p[14] = 1; break;
case 8: p[13] = 1; break;
case 9: p[12] = 1; break;
case 10: p[11] = 1; break;
etc.
I think there are advantages of doing this in switchconv, namely that it would
be done only if the switchconv pass finds out it would be beneficial, but there
can be advantages doing that in tail-merging too, mainly for -Os or proven cold
code it is often but not always to optimize this (not only if either the code
is very small or if between pre and switchconv we can simplify it if it is
constant).
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (10 preceding siblings ...)
2020-12-14 14:16 ` jakub at gcc dot gnu.org
@ 2021-11-29 20:35 ` pinskia at gcc dot gnu.org
2024-02-03 19:54 ` pinskia at gcc dot gnu.org
12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-11-29 20:35 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |llvm at rifkin dot dev
--- Comment #11 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 103072 has been marked as a duplicate of this bug. ***
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Bug tree-optimization/96245] Failure to optimize arithmetic pattern in switch
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
` (11 preceding siblings ...)
2021-11-29 20:35 ` pinskia at gcc dot gnu.org
@ 2024-02-03 19:54 ` pinskia at gcc dot gnu.org
12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-02-03 19:54 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96245
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |b.buschinski at googlemail dot com
--- Comment #12 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 113741 has been marked as a duplicate of this bug. ***
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2024-02-03 19:54 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-20 4:20 [Bug tree-optimization/96245] New: Failure to optimize arithmetic pattern in switch gabravier at gmail dot com
2020-07-20 7:01 ` [Bug tree-optimization/96245] " rguenth at gcc dot gnu.org
2020-07-20 15:28 ` msebor at gcc dot gnu.org
2020-07-20 15:49 ` josephcsible at gmail dot com
2020-07-20 18:53 ` msebor at gcc dot gnu.org
2020-07-23 9:10 ` marxin at gcc dot gnu.org
2020-09-22 12:24 ` marxin at gcc dot gnu.org
2020-12-14 10:51 ` jakub at gcc dot gnu.org
2020-12-14 11:19 ` jakub at gcc dot gnu.org
2020-12-14 11:23 ` jakub at gcc dot gnu.org
2020-12-14 13:48 ` rguenther at suse dot de
2020-12-14 14:16 ` jakub at gcc dot gnu.org
2021-11-29 20:35 ` pinskia at gcc dot gnu.org
2024-02-03 19:54 ` pinskia at gcc dot gnu.org
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).