public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops
@ 2021-03-21 12:07 rafal at bursig dot org
  2021-03-21 12:28 ` [Bug c/99693] " rafal at bursig dot org
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: rafal at bursig dot org @ 2021-03-21 12:07 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 99693
           Summary: -O2 not move 'if' checks on const data outside the
                    loops
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rafal at bursig dot org
  Target Milestone: ---

-g -o /tmp/compiler-explorer-compiler2021221-5538-b8yy15.yzw9n/output.s
-masm=intel -S -fdiagnostics-color=always -O2
/tmp/compiler-explorer-compiler2021221-5538-b8yy15.yzw9n/example.c

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

* [Bug c/99693] -O2 not move 'if' checks on const data outside the loops
  2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
@ 2021-03-21 12:28 ` rafal at bursig dot org
  2021-03-21 16:41 ` pinskia at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: rafal at bursig dot org @ 2021-03-21 12:28 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from rafal at bursig dot org ---
I'm not saying that this is a regression because I see proper results on -O3
level but IMHO such results should be available in -O2 level... but to topic:

I have such code:

typedef struct Update {
    int m_update;
    //...
} Update;

extern void antagonizer( Update * );

void antagonize(Update *data, unsigned int n)
{
    while(--n)
    {
        if (data->m_update)
        {
            antagonizer( data );
        }
    }
}

then -O2 level give me such asm:

antagonize:
        sub     esi, 1
        je      .L10
        push    rbp
        mov     rbp, rdi
        push    rbx
        mov     ebx, esi
        sub     rsp, 8
        jmp     .L4
.L3:
        sub     ebx, 1
        je      .L14
.L4:
        mov     eax, DWORD PTR [rbp+0]
        test    eax, eax
        je      .L3
        mov     rdi, rbp
        call    antagonizer
        sub     ebx, 1
        jne     .L4
.L14:
        add     rsp, 8
        pop     rbx
        pop     rbp
        ret
.L10:
        ret


Which is OK because the "antagonizer( data );" call can change "Update *data"
struct and the "if (data->m_update)" can't be moved outside loop.

But when If I create local copy of "data->m_update" then this check could be
moved outside loop without problem. But below code:

typedef struct Update {
    int m_update;
    //...
} Update;

extern void antagonizer( Update * );

void antagonize(Update *data, unsigned int n)
{
    const int _update = data->m_update;

    while(--n)
    {
        if (_update)
        {
            antagonizer( data );
        }
    }
}

Do not move "if (_update)" outside the loop and asm looks like:

antagonize:
        push    r12
        push    rbp
        push    rbx
        mov     ebp, DWORD PTR [rdi]
        sub     esi, 1
        je      .L1
        mov     r12, rdi
        mov     ebx, esi
        jmp     .L4
.L3:
        sub     ebx, 1
        je      .L1
.L4:
        test    ebp, ebp      // the check 
        je      .L3           // is still in loop
        mov     rdi, r12
        call    antagonizer
        sub     ebx, 1
        jne     .L4
.L1:
        pop     rbx
        pop     rbp
        pop     r12
        ret

When I build this code with -O3 level then the check is moved out the loop
properly, but I got several others effects which I don't know if it will have
proper impact in my application (I will prefer stay with -O2). The asm for -O3
level:

antagonize:
        mov     eax, DWORD PTR [rdi]
        sub     esi, 1
        je      .L12
        push    rbp
        mov     rbp, rdi
        push    rbx
        mov     ebx, esi
        sub     rsp, 8
        test    eax, eax
        jne     .L3
.L1:
        add     rsp, 8
        pop     rbx
        pop     rbp
        ret
.L3:
        mov     rdi, rbp
        call    antagonizer
        sub     ebx, 1
        je      .L1
        mov     rdi, rbp
        call    antagonizer
        sub     ebx, 1
        jne     .L3
        jmp     .L1
.L12:
        ret

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

* [Bug c/99693] -O2 not move 'if' checks on const data outside the loops
  2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
  2021-03-21 12:28 ` [Bug c/99693] " rafal at bursig dot org
@ 2021-03-21 16:41 ` pinskia at gcc dot gnu.org
  2021-03-22  9:04 ` rguenth at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-03-21 16:41 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Loop unswitching is correctly only turned on at -O3+. So you want to move it to
-O2. Note loop unswitching can cause performance problems due to increase of
usage of the icache and such.

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

* [Bug c/99693] -O2 not move 'if' checks on const data outside the loops
  2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
  2021-03-21 12:28 ` [Bug c/99693] " rafal at bursig dot org
  2021-03-21 16:41 ` pinskia at gcc dot gnu.org
@ 2021-03-22  9:04 ` rguenth at gcc dot gnu.org
  2021-03-22  9:23 ` rafal at bursig dot org
  2021-03-22  9:43 ` rafal at bursig dot org
  4 siblings, 0 replies; 6+ messages in thread
From: rguenth at gcc dot gnu.org @ 2021-03-22  9:04 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |WONTFIX
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
Yes, if you want to stick to -O2 use -funswitch-loops.

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

* [Bug c/99693] -O2 not move 'if' checks on const data outside the loops
  2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
                   ` (2 preceding siblings ...)
  2021-03-22  9:04 ` rguenth at gcc dot gnu.org
@ 2021-03-22  9:23 ` rafal at bursig dot org
  2021-03-22  9:43 ` rafal at bursig dot org
  4 siblings, 0 replies; 6+ messages in thread
From: rafal at bursig dot org @ 2021-03-22  9:23 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from rafal at bursig dot org ---
but using  -O2 -funswitch-loops will bring me those problems why this flag is
not in default -O2. Which is not a solution.

Maybe -O2 may have weaken version of this optimization and will work only if
one of if brock is empty. And -O3 will have full version. 

Example:

form:
for(...)
{
 if (local_value)
 {
   logic;
 }
}
To:
if (local_value)
for(...)
{
   logic;
}

I know that such code could be fixed by developer but gcc don't generate any
diagnostic message about such constructions and for a large project it's
difficult to find all of such places

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

* [Bug c/99693] -O2 not move 'if' checks on const data outside the loops
  2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
                   ` (3 preceding siblings ...)
  2021-03-22  9:23 ` rafal at bursig dot org
@ 2021-03-22  9:43 ` rafal at bursig dot org
  4 siblings, 0 replies; 6+ messages in thread
From: rafal at bursig dot org @ 2021-03-22  9:43 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from rafal at bursig dot org ---
Additional when I use c++ variant of this code and throw exception in else then
in  -O2 level the 'if' is removed outside loop:

typedef struct Update {
    int m_update;
    //...
} Update;

extern void antagonizer( Update * );

void antagonize(Update *data, unsigned int n)
{
    int _update = data->m_update;
    while(--n)
    {

        if (_update)
        {
            antagonizer( data );
        } else throw  std::runtime_error("error");

    }
}

The asm looks like:


.LC0:
        .string "error"
antagonize(Update*, unsigned int):
        mov     eax, DWORD PTR [rdi]
        sub     esi, 1
        je      .L12
        push    r12
        push    rbp
        mov     rbp, rdi
        push    rbx
        mov     ebx, esi
        test    eax, eax
        je      .L3
.L4:
        mov     rdi, rbp
        call    antagonizer(Update*)
        sub     ebx, 1
        jne     .L4
        pop     rbx
        pop     rbp
        pop     r12
        ret
.L12:
        ret
antagonize(Update*, unsigned int) [clone .cold]:
.L3:
        mov     edi, 16
        call    __cxa_allocate_exception
        mov     esi, OFFSET FLAT:.LC0
        mov     rdi, rax
        mov     rbp, rax
        call    std::runtime_error::runtime_error(char const*) [complete object
constructor]
        mov     edx, OFFSET FLAT:_ZNSt13runtime_errorD1Ev
        mov     esi, OFFSET FLAT:_ZTISt13runtime_error
        mov     rdi, rbp
        call    __cxa_throw
        mov     r12, rax
        mov     rdi, rbp
        call    __cxa_free_exception
        mov     rdi, r12
        call    _Unwind_Resume


when I comment the "else throw ..." then the if check return int loop

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

end of thread, other threads:[~2021-03-22  9:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-21 12:07 [Bug c/99693] New: -O2 not move 'if' checks on const data outside the loops rafal at bursig dot org
2021-03-21 12:28 ` [Bug c/99693] " rafal at bursig dot org
2021-03-21 16:41 ` pinskia at gcc dot gnu.org
2021-03-22  9:04 ` rguenth at gcc dot gnu.org
2021-03-22  9:23 ` rafal at bursig dot org
2021-03-22  9:43 ` rafal at bursig dot 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).