]> granicus.if.org Git - llvm/commitdiff
[X86] Add patterns to show more failures to use TBM instructions when we're trying...
authorCraig Topper <craig.topper@intel.com>
Fri, 25 Aug 2017 23:34:55 +0000 (23:34 +0000)
committerCraig Topper <craig.topper@intel.com>
Fri, 25 Aug 2017 23:34:55 +0000 (23:34 +0000)
We can probably add patterns to fix some of them. But the ones that use 'and' as their root node emit a X86ISD::CMP node in front of the 'and' and then pattern matching that to 'test' instruction. We can't use a tablegen pattern to fix that because we can't remap the cmp result to the flag output of a TBM instruction.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311819 91177308-0d34-0410-b5e6-96231b3b80d8

test/CodeGen/X86/tbm_patterns.ll

index 82160126f7f682a80df701502a2ec2da767e788d..ec4d2dee1ed1bb6eae709894e8b71c99a816dbf5 100644 (file)
@@ -37,6 +37,20 @@ define i32 @test_x86_tbm_bextri_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t3
 }
 
+define i32 @test_x86_tbm_bextri_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_bextri_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    bextr $3076, %edi, %eax # imm = 0xC04
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = lshr i32 %a, 4
+  %t1 = and i32 %t0, 4095
+  %t2 = icmp eq i32 %t1, 0
+  %t3 = select i1 %t2, i32 %b, i32 %c
+  ret i32 %t3
+}
+
 define i64 @test_x86_tbm_bextri_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_bextri_u64:
 ; CHECK:       # BB#0:
@@ -71,6 +85,20 @@ define i64 @test_x86_tbm_bextri_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t3
 }
 
+define i64 @test_x86_tbm_bextri_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_bextri_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    bextr $3076, %edi, %eax # imm = 0xC04
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = lshr i64 %a, 4
+  %t1 = and i64 %t0, 4095
+  %t2 = icmp eq i64 %t1, 0
+  %t3 = select i1 %t2, i64 %b, i64 %c
+  ret i64 %t3
+}
+
 define i32 @test_x86_tbm_blcfill_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcfill_u32:
 ; CHECK:       # BB#0:
@@ -94,6 +122,22 @@ define i32 @test_x86_tbm_blcfill_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t3
 }
 
+define i32 @test_x86_tbm_blcfill_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcfill_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal 1(%rdi), %eax
+; CHECK-NEXT:    testl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = add i32 %a, 1
+  %t1 = and i32 %t0, %a
+  %t2 = icmp eq i32 %t1, 0
+  %t3 = select i1 %t2, i32 %b, i32 %c
+  ret i32 %t3
+}
+
 define i64 @test_x86_tbm_blcfill_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcfill_u64:
 ; CHECK:       # BB#0:
@@ -117,6 +161,21 @@ define i64 @test_x86_tbm_blcfill_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t3
 }
 
+define i64 @test_x86_tbm_blcfill_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcfill_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    leaq 1(%rdi), %rax
+; CHECK-NEXT:    testq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = add i64 %a, 1
+  %t1 = and i64 %t0, %a
+  %t2 = icmp eq i64 %t1, 0
+  %t3 = select i1 %t2, i64 %b, i64 %c
+  ret i64 %t3
+}
+
 define i32 @test_x86_tbm_blci_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blci_u32:
 ; CHECK:       # BB#0:
@@ -142,6 +201,24 @@ define i32 @test_x86_tbm_blci_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t4
 }
 
+define i32 @test_x86_tbm_blci_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blci_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal 1(%rdi), %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    orl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = add i32 1, %a
+  %t1 = xor i32 %t0, -1
+  %t2 = or i32 %t1, %a
+  %t3 = icmp eq i32 %t2, 0
+  %t4 = select i1 %t3, i32 %b, i32 %c
+  ret i32 %t4
+}
+
 define i64 @test_x86_tbm_blci_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blci_u64:
 ; CHECK:       # BB#0:
@@ -167,6 +244,23 @@ define i64 @test_x86_tbm_blci_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t4
 }
 
+define i64 @test_x86_tbm_blci_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blci_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    leaq 1(%rdi), %rax
+; CHECK-NEXT:    notq %rax
+; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = add i64 1, %a
+  %t1 = xor i64 %t0, -1
+  %t2 = or i64 %t1, %a
+  %t3 = icmp eq i64 %t2, 0
+  %t4 = select i1 %t3, i64 %b, i64 %c
+  ret i64 %t4
+}
+
 define i32 @test_x86_tbm_blci_u32_b(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blci_u32_b:
 ; CHECK:       # BB#0:
@@ -212,6 +306,24 @@ define i32 @test_x86_tbm_blcic_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t4
 }
 
+define i32 @test_x86_tbm_blcic_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcic_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    incl %edi
+; CHECK-NEXT:    testl %eax, %edi
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = xor i32 %a, -1
+  %t1 = add i32 %a, 1
+  %t2 = and i32 %t1, %t0
+  %t3 = icmp eq i32 %t2, 0
+  %t4 = select i1 %t3, i32 %b, i32 %c
+  ret i32 %t4
+}
+
 define i64 @test_x86_tbm_blcic_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcic_u64:
 ; CHECK:       # BB#0:
@@ -237,6 +349,24 @@ define i64 @test_x86_tbm_blcic_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t4
 }
 
+define i64 @test_x86_tbm_blcic_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcic_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    notq %rax
+; CHECK-NEXT:    incq %rdi
+; CHECK-NEXT:    testq %rax, %rdi
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = xor i64 %a, -1
+  %t1 = add i64 %a, 1
+  %t2 = and i64 %t1, %t0
+  %t3 = icmp eq i64 %t2, 0
+  %t4 = select i1 %t3, i64 %b, i64 %c
+  ret i64 %t4
+}
+
 define i32 @test_x86_tbm_blcmsk_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcmsk_u32:
 ; CHECK:       # BB#0:
@@ -260,6 +390,22 @@ define i32 @test_x86_tbm_blcmsk_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t3
 }
 
+define i32 @test_x86_tbm_blcmsk_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcmsk_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal 1(%rdi), %eax
+; CHECK-NEXT:    xorl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = add i32 %a, 1
+  %t1 = xor i32 %t0, %a
+  %t2 = icmp eq i32 %t1, 0
+  %t3 = select i1 %t2, i32 %b, i32 %c
+  ret i32 %t3
+}
+
 define i64 @test_x86_tbm_blcmsk_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcmsk_u64:
 ; CHECK:       # BB#0:
@@ -283,6 +429,21 @@ define i64 @test_x86_tbm_blcmsk_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t3
 }
 
+define i64 @test_x86_tbm_blcmsk_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcmsk_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    leaq 1(%rdi), %rax
+; CHECK-NEXT:    xorq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = add i64 %a, 1
+  %t1 = xor i64 %t0, %a
+  %t2 = icmp eq i64 %t1, 0
+  %t3 = select i1 %t2, i64 %b, i64 %c
+  ret i64 %t3
+}
+
 define i32 @test_x86_tbm_blcs_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcs_u32:
 ; CHECK:       # BB#0:
@@ -306,6 +467,22 @@ define i32 @test_x86_tbm_blcs_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t3
 }
 
+define i32 @test_x86_tbm_blcs_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcs_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal 1(%rdi), %eax
+; CHECK-NEXT:    orl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = add i32 %a, 1
+  %t1 = or i32 %t0, %a
+  %t2 = icmp eq i32 %t1, 0
+  %t3 = select i1 %t2, i32 %b, i32 %c
+  ret i32 %t3
+}
+
 define i64 @test_x86_tbm_blcs_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blcs_u64:
 ; CHECK:       # BB#0:
@@ -329,6 +506,21 @@ define i64 @test_x86_tbm_blcs_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t3
 }
 
+define i64 @test_x86_tbm_blcs_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blcs_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    leaq 1(%rdi), %rax
+; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = add i64 %a, 1
+  %t1 = or i64 %t0, %a
+  %t2 = icmp eq i64 %t1, 0
+  %t3 = select i1 %t2, i64 %b, i64 %c
+  ret i64 %t3
+}
+
 define i32 @test_x86_tbm_blsfill_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blsfill_u32:
 ; CHECK:       # BB#0:
@@ -352,6 +544,22 @@ define i32 @test_x86_tbm_blsfill_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t3
 }
 
+define i32 @test_x86_tbm_blsfill_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blsfill_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
+; CHECK-NEXT:    leal -1(%rdi), %eax
+; CHECK-NEXT:    orl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = add i32 %a, -1
+  %t1 = or i32 %t0, %a
+  %t2 = icmp eq i32 %t1, 0
+  %t3 = select i1 %t2, i32 %b, i32 %c
+  ret i32 %t3
+}
+
 define i64 @test_x86_tbm_blsfill_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blsfill_u64:
 ; CHECK:       # BB#0:
@@ -375,6 +583,21 @@ define i64 @test_x86_tbm_blsfill_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t3
 }
 
+define i64 @test_x86_tbm_blsfill_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blsfill_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    leaq -1(%rdi), %rax
+; CHECK-NEXT:    orq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = add i64 %a, -1
+  %t1 = or i64 %t0, %a
+  %t2 = icmp eq i64 %t1, 0
+  %t3 = select i1 %t2, i64 %b, i64 %c
+  ret i64 %t3
+}
+
 define i32 @test_x86_tbm_blsic_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blsic_u32:
 ; CHECK:       # BB#0:
@@ -400,6 +623,24 @@ define i32 @test_x86_tbm_blsic_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t4
 }
 
+define i32 @test_x86_tbm_blsic_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blsic_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    decl %edi
+; CHECK-NEXT:    orl %eax, %edi
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = xor i32 %a, -1
+  %t1 = add i32 %a, -1
+  %t2 = or i32 %t0, %t1
+  %t3 = icmp eq i32 %t2, 0
+  %t4 = select i1 %t3, i32 %b, i32 %c
+  ret i32 %t4
+}
+
 define i64 @test_x86_tbm_blsic_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_blsic_u64:
 ; CHECK:       # BB#0:
@@ -425,6 +666,24 @@ define i64 @test_x86_tbm_blsic_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t4
 }
 
+define i64 @test_x86_tbm_blsic_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_blsic_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    notq %rax
+; CHECK-NEXT:    decq %rdi
+; CHECK-NEXT:    orq %rax, %rdi
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = xor i64 %a, -1
+  %t1 = add i64 %a, -1
+  %t2 = or i64 %t0, %t1
+  %t3 = icmp eq i64 %t2, 0
+  %t4 = select i1 %t3, i64 %b, i64 %c
+  ret i64 %t4
+}
+
 define i32 @test_x86_tbm_t1mskc_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_t1mskc_u32:
 ; CHECK:       # BB#0:
@@ -451,6 +710,24 @@ define i32 @test_x86_tbm_t1mskc_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t4
 }
 
+define i32 @test_x86_tbm_t1mskc_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_t1mskc_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    incl %edi
+; CHECK-NEXT:    orl %eax, %edi
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = xor i32 %a, -1
+  %t1 = add i32 %a, 1
+  %t2 = or i32 %t0, %t1
+  %t3 = icmp eq i32 %t2, 0
+  %t4 = select i1 %t3, i32 %b, i32 %c
+  ret i32 %t4
+}
+
 define i64 @test_x86_tbm_t1mskc_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_t1mskc_u64:
 ; CHECK:       # BB#0:
@@ -477,6 +754,24 @@ define i64 @test_x86_tbm_t1mskc_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t4
 }
 
+define i64 @test_x86_tbm_t1mskc_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_t1mskc_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    notq %rax
+; CHECK-NEXT:    incq %rdi
+; CHECK-NEXT:    orq %rax, %rdi
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = xor i64 %a, -1
+  %t1 = add i64 %a, 1
+  %t2 = or i64 %t0, %t1
+  %t3 = icmp eq i64 %t2, 0
+  %t4 = select i1 %t3, i64 %b, i64 %c
+  ret i64 %t4
+}
+
 define i32 @test_x86_tbm_tzmsk_u32(i32 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_tzmsk_u32:
 ; CHECK:       # BB#0:
@@ -503,6 +798,24 @@ define i32 @test_x86_tbm_tzmsk_u32_z(i32 %a, i32 %b) nounwind {
   ret i32 %t4
 }
 
+define i32 @test_x86_tbm_tzmsk_u32_z2(i32 %a, i32 %b, i32 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_tzmsk_u32_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    decl %edi
+; CHECK-NEXT:    testl %edi, %eax
+; CHECK-NEXT:    cmovnel %edx, %esi
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    retq
+  %t0 = xor i32 %a, -1
+  %t1 = add i32 %a, -1
+  %t2 = and i32 %t0, %t1
+  %t3 = icmp eq i32 %t2, 0
+  %t4 = select i1 %t3, i32 %b, i32 %c
+  ret i32 %t4
+}
+
 define i64 @test_x86_tbm_tzmsk_u64(i64 %a) nounwind {
 ; CHECK-LABEL: test_x86_tbm_tzmsk_u64:
 ; CHECK:       # BB#0:
@@ -529,6 +842,24 @@ define i64 @test_x86_tbm_tzmsk_u64_z(i64 %a, i64 %b) nounwind {
   ret i64 %t4
 }
 
+define i64 @test_x86_tbm_tzmsk_u64_z2(i64 %a, i64 %b, i64 %c) nounwind {
+; CHECK-LABEL: test_x86_tbm_tzmsk_u64_z2:
+; CHECK:       # BB#0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    notq %rax
+; CHECK-NEXT:    decq %rdi
+; CHECK-NEXT:    testq %rdi, %rax
+; CHECK-NEXT:    cmovneq %rdx, %rsi
+; CHECK-NEXT:    movq %rsi, %rax
+; CHECK-NEXT:    retq
+  %t0 = xor i64 %a, -1
+  %t1 = add i64 %a, -1
+  %t2 = and i64 %t0, %t1
+  %t3 = icmp eq i64 %t2, 0
+  %t4 = select i1 %t3, i64 %b, i64 %c
+  ret i64 %t4
+}
+
 define i64 @test_and_large_constant_mask(i64 %x) {
 ; CHECK-LABEL: test_and_large_constant_mask:
 ; CHECK:       # BB#0: # %entry