public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used
@ 2022-09-03 22:48 benjamin.meier70 at gmail dot com
  2022-09-03 22:55 ` [Bug c/106822] " benjamin.meier70 at gmail dot com
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: benjamin.meier70 at gmail dot com @ 2022-09-03 22:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

            Bug ID: 106822
           Summary: "Boolean-or" optimization opportunity not consistently
                    used
           Product: gcc
           Version: 12.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: benjamin.meier70 at gmail dot com
  Target Milestone: ---

Hello

Assume the following code is given:

-----------------------------
#include <stdio.h>
#include <stdbool.h>

typedef struct {
    bool a;
    bool b;
} MyStruct;

bool f(const MyStruct *s)
{
    return s->a || s->b;
}

int main()
{
}
-----------------------------

If the code is compiled with -O3 I would assume it does not include any jumps,
because it should be valid to always read s->b (even if s->a is already true).
However, the function compiles into this:

-----------------------------
f:
        movzx   eax, BYTE PTR [rdi]
        test    al, al
        jne     .L1
        movzx   eax, BYTE PTR [rdi+1]
.L1:
        ret
-----------------------------
(see: https://godbolt.org/z/KdnzWb9Wh)


Interestingly, gcc will produce code without any jumps if MyStruct is slightly
modified:

-----------------------------
#include <stdio.h>
#include <stdbool.h>

typedef struct {
    int x;
    bool a;
    bool b;
} MyStruct;

bool f(const MyStruct *s)
{
    return s->a || s ->b;
}

int main()
{
}
-----------------------------

Generated code:

-----------------------------
f:
        cmp     WORD PTR [rdi+4], 0
        setne   al
        ret
-----------------------------
(see: https://godbolt.org/z/P78daxhhe)

It's not a bug, but I think it's a missed optimization opportunity.

Thanks

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug c/106822] "Boolean-or" optimization opportunity not consistently used
  2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
@ 2022-09-03 22:55 ` benjamin.meier70 at gmail dot com
  2022-09-03 23:08 ` [Bug tree-optimization/106822] " pinskia at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: benjamin.meier70 at gmail dot com @ 2022-09-03 22:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

--- Comment #1 from Benjamin B. Meier <benjamin.meier70 at gmail dot com> ---
It might also be worth to note that the following code always compiles without
any jumps:
--------------------------------
bool f2(const MyStruct *s)
{
    return s->a | s ->b;
}
--------------------------------

Given that f and f2 should behave identical, I would assume that the optimized
code of them is similar "good" (e.g. does not contain any jumps)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug tree-optimization/106822] "Boolean-or" optimization opportunity not consistently used
  2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
  2022-09-03 22:55 ` [Bug c/106822] " benjamin.meier70 at gmail dot com
@ 2022-09-03 23:08 ` pinskia at gcc dot gnu.org
  2022-09-03 23:55 ` benjamin.meier70 at gmail dot com
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-09-03 23:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
The reason for the difference is because in the case where there is an int in
the structure, the alignment is 4 bytes so a 2 or 4 byte read for a and b will
not cause an fault while in the first case where there is no int, the alignment
is 1 and might cause a fault. Gcc is conservative here on doing the
optimization.

Also || is a short cutting or in c so I don't think this optimization can be
done for the original case in a well defined way.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug tree-optimization/106822] "Boolean-or" optimization opportunity not consistently used
  2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
  2022-09-03 22:55 ` [Bug c/106822] " benjamin.meier70 at gmail dot com
  2022-09-03 23:08 ` [Bug tree-optimization/106822] " pinskia at gcc dot gnu.org
@ 2022-09-03 23:55 ` benjamin.meier70 at gmail dot com
  2022-09-05 10:19 ` rguenth at gcc dot gnu.org
  2022-09-05 14:27 ` benjamin.meier70 at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: benjamin.meier70 at gmail dot com @ 2022-09-03 23:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

--- Comment #3 from Benjamin B. Meier <benjamin.meier70 at gmail dot com> ---
> The reason for the difference is because in the case where there is an int in the structure, the alignment is 4 bytes so a 2 or 4 byte read for a and b will not cause an fault while in the first case where there is no int, the alignment is 1 and might cause a fault. Gcc is conservative here on doing the optimization.

Okay, got it. The alignment actually makes a difference here. Thanks, for the
explanation.

> Also || is a short cutting or in c so I don't think this optimization can be done for the original case in a well defined way.

I see that as well, however reading the right hand side expression of the
||-operator has in this case no observable side-effect. Plus if we know that
s->a can be read, we know as well that s cannot be a NULL pointer. Given that,
I would assume the optimization should be valid (and applied).

Another supporting argument for ignoring the short cutting behavior is the
version of "MyStruct" with "int x;": In this case the compiler also always
reads both operands (and therefore ignores the short cut).

So if the compiler uses a nice optimization without jumps if it knows the
alignment is at least 2 bytes, it probably could also use an optimization for
the case that the alignment is only 1 byte. A possible optimization would then
look like the code of f2.

Finally, it's nothing really important, but I still do not yet completely see
why optimizing the jump away in f is an issue:)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug tree-optimization/106822] "Boolean-or" optimization opportunity not consistently used
  2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
                   ` (2 preceding siblings ...)
  2022-09-03 23:55 ` benjamin.meier70 at gmail dot com
@ 2022-09-05 10:19 ` rguenth at gcc dot gnu.org
  2022-09-05 14:27 ` benjamin.meier70 at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-09-05 10:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
           Keywords|                            |missed-optimization
   Last reconfirmed|                            |2022-09-05
     Ever confirmed|0                           |1

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed.  The alignment consideration shouldn't apply in this case - the
MyStruct object is either there or not.  Note

typedef struct {
    bool a[];
} MyStruct;

bool f(const MyStruct *s)
{
    return s->a[0] || s->a[1];
}

would be a different story.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug tree-optimization/106822] "Boolean-or" optimization opportunity not consistently used
  2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
                   ` (3 preceding siblings ...)
  2022-09-05 10:19 ` rguenth at gcc dot gnu.org
@ 2022-09-05 14:27 ` benjamin.meier70 at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: benjamin.meier70 at gmail dot com @ 2022-09-05 14:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106822

--- Comment #5 from Benjamin B. Meier <benjamin.meier70 at gmail dot com> ---
Thx for the very quick reaction and also you additional example:)!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-09-05 14:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-03 22:48 [Bug c/106822] New: "Boolean-or" optimization opportunity not consistently used benjamin.meier70 at gmail dot com
2022-09-03 22:55 ` [Bug c/106822] " benjamin.meier70 at gmail dot com
2022-09-03 23:08 ` [Bug tree-optimization/106822] " pinskia at gcc dot gnu.org
2022-09-03 23:55 ` benjamin.meier70 at gmail dot com
2022-09-05 10:19 ` rguenth at gcc dot gnu.org
2022-09-05 14:27 ` benjamin.meier70 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).