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

            Bug ID: 66872
           Summary: fold a & ((1 << b) - 1) to a & ~(-1 << b)
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bonzini at gnu dot org
  Target Milestone: ---

This can save one or two instructions on some architectures.  For example, when
compiling

int f(int x, int t)
{
        return x & ((1 << t) - 1);
}

vs.

int f(int x, int t)
{
        return x & ~(-1 << t);
}

with -march=haswell you get before:

        movl    $1, %edx
        shlx    %esi, %edx, %esi
        subl    $1, %esi               # not sure why no lea here?
        movl    %esi, %eax
        andl    %edi, %eax
        ret

and after:

        movl    $-1, %edx
        shlx    %esi, %edx, %esi
        andn    %edi, %esi, %eax
        ret

Even if you account for the strange register allocation in the first assembly
listing, using andn can save one instruction.  Also, with -mtune=generic the
size is the same.  Before:

        movl    %esi, %ecx
        movl    $1, %edx
        sall    %cl, %edx
        subl    $1, %edx
        movl    %edx, %eax
        andl    %edi, %eax
        ret

After:

        movl    %esi, %ecx
        movl    $-1, %edx
        sall    %cl, %edx
        notl    %edx
        movl    %edx, %eax
        andl    %edi, %eax
        ret

Reply via email to