How can I tune gcc to move up simple common subexpression?

Richard Biener richard.guenther@gmail.com
Mon Nov 11 11:36:00 GMT 2013


On Fri, Nov 8, 2013 at 9:21 PM, Jeff Law <law@redhat.com> wrote:
> On 11/08/13 02:28, Konstantin Vladimirov wrote:
>>
>> typedef struct
>> {
>>    unsigned prev;
>>    unsigned next;
>> } foo_t;
>>
>> void
>> foo( unsigned x, unsigned y)
>>    {
>>      foo_t *ptr = (foo_t *)((void *)x);
>>
>>      if (y != 0)
>>        {
>>           ptr->prev = y;
>>           ptr->next = x;
>>         }
>>       else
>>         {
>>           ptr->prev = 0; /* or explicitly ptr->prev = y; no difference */
>>           ptr->next = 0;
>>         }
>> }
>
> Umm, you can't hoist ptr->prev before the conditional because that would
> change the meaning of this code.

We test y != 0 and thus know that y == 0 in the else block.  Thus we can
do

    ptr->prev = y;
    if (y != 0)
     ptr->next = x;
    else
     ptr->next = 0;

note that we already transform

    if (y != 0)
      ...
    else
      ptr->prev = y;

to ptr->prev = 0 AFAIK.

Richard.



>
> I think you wanted the conditional to test y == 0 which exposes the code
> hoisting opportunity for the ptr->prev assignment.  Once you fix the
> testcase the code in jump2 will hoist the assignment resulting in:
>
>
>
>
>
>         .cfi_startproc
>
>         testl   %esi, %esi
>         movl    %edi, %eax
>         movl    $0, (%edi)
>
>         je      .L5
>         movl    $0, 4(%rax)
>         ret
>         .p2align 4,,10
>         .p2align 3
>
> .L5:
>         movl    %edi, 4(%rax)
>         ret
>         .cfi_endproc
>
>
> Jeff



More information about the Gcc-help mailing list