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]