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

            Bug ID: 87954
           Summary: VRP can transform a * b where a,b are [0,1] to a & b
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: marxin at gcc dot gnu.org
  Target Milestone: ---

Code snippet reported by kernel developers:

$ cat mul.c
#define __GFP_DMA 1u
#define __GFP_RECLAIM 0x10u

#define KMALLOC_DMA 2
#define KMALLOC_RECLAIM 1

unsigned int and(unsigned int flags)
{
        int is_dma, type_dma, is_rec;

        is_dma = !!(flags & __GFP_DMA);
        type_dma = is_dma * KMALLOC_DMA;
        is_rec = !!(flags & __GFP_RECLAIM);

        return type_dma + (is_rec & !is_dma) * KMALLOC_RECLAIM;
}

unsigned int imul(unsigned int flags)
{
        int is_dma, type_dma, is_rec;

        is_dma = !!(flags & __GFP_DMA);
        type_dma = is_dma * KMALLOC_DMA;
        is_rec = !!(flags & __GFP_RECLAIM);

        return type_dma + (is_rec * !is_dma) * KMALLOC_RECLAIM;
}

The first function ends with fast and operation:
and:
.LFB0:
        .cfi_startproc
        movl    %edi, %edx
        movl    %edi, %eax
        andl    $1, %edi
        shrl    $4, %edx
        notl    %eax
        andl    %edx, %eax
        andl    $1, %eax
        leal    (%rax,%rdi,2), %eax
        ret

while the second one with imull
imul:
.LFB1:
        .cfi_startproc
        movl    %edi, %eax
        movl    %edi, %edx
        andl    $1, %edi
        shrl    $4, %edx
        notl    %eax
        andl    $1, %eax
        andl    $1, %edx
        imull   %edx, %eax
        leal    (%rax,%rdi,2), %eax
        ret
        .cfi_endproc

VRP knows about the range of the operands:
  _7 = _6 * is_rec_12;

_6: [0, 1]
is_rec_12: [0, 1]

Reply via email to