[llvm] [X86] Use 16-bit BT to eliminate explicit AND mask on bit index (PR #219836)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 12:44:55 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/219836

>From 5ae4283af437f1f255b1f1c2281123566cd08153 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 30 Aug 2026 15:19:46 -0400
Subject: [PATCH 1/2] [X86] Pre-commit test for 16-bit BT optimization

---
 llvm/test/CodeGen/X86/bittest-16.ll | 114 ++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/bittest-16.ll

diff --git a/llvm/test/CodeGen/X86/bittest-16.ll b/llvm/test/CodeGen/X86/bittest-16.ll
new file mode 100644
index 0000000000000..269fe48bbde30
--- /dev/null
+++ b/llvm/test/CodeGen/X86/bittest-16.ll
@@ -0,0 +1,114 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
+; ModuleID = 'test_bt_sizes.c'
+source_filename = "test_bt_sizes.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
+define dso_local zeroext i1 @bt_test_16_16(i16 noundef zeroext %a, i16 noundef zeroext %b) local_unnamed_addr #0 {
+; CHECK-LABEL: bt_test_16_16:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $15, %esi
+; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    retq
+entry:
+  %conv = zext i16 %a to i32
+  %0 = and i16 %b, 15
+  %and = zext nneg i16 %0 to i32
+  %shl = shl nuw nsw i32 1, %and
+  %and2 = and i32 %shl, %conv
+  %tobool = icmp ne i32 %and2, 0
+  ret i1 %tobool
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
+define dso_local zeroext i1 @bt_test_16_32(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 {
+; CHECK-LABEL: bt_test_16_32:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $15, %esi
+; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    retq
+entry:
+  %and = and i32 %b, 15
+  %shl = shl nuw nsw i32 1, %and
+  %and1 = and i32 %shl, %a
+  %tobool = icmp ne i32 %and1, 0
+  ret i1 %tobool
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
+define dso_local zeroext i1 @bt_test_16_64(i64 noundef %a, i64 noundef %b) local_unnamed_addr #0 {
+; CHECK-LABEL: bt_test_16_64:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $15, %esi
+; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    retq
+entry:
+  %and = and i64 %b, 15
+  %shl = shl nuw nsw i64 1, %and
+  %and1 = and i64 %shl, %a
+  %tobool = icmp ne i64 %and1, 0
+  ret i1 %tobool
+}
+
+; Function Attrs: nounwind uwtable
+define dso_local zeroext i1 @bt_test_16_multiuse(i32 noundef %a, i32 noundef %b) local_unnamed_addr #1 {
+; CHECK-LABEL: bt_test_16_multiuse:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    pushq %rbx
+; CHECK-NEXT:    .cfi_def_cfa_offset 24
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    .cfi_def_cfa_offset 32
+; CHECK-NEXT:    .cfi_offset %rbx, -24
+; CHECK-NEXT:    .cfi_offset %rbp, -16
+; CHECK-NEXT:    movl %esi, %ebx
+; CHECK-NEXT:    movl %edi, %ebp
+; CHECK-NEXT:    andl $15, %ebx
+; CHECK-NEXT:    movl %ebx, %edi
+; CHECK-NEXT:    callq external_use at PLT
+; CHECK-NEXT:    btl %ebx, %ebp
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    addq $8, %rsp
+; CHECK-NEXT:    .cfi_def_cfa_offset 24
+; CHECK-NEXT:    popq %rbx
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:    retq
+entry:
+  %and = and i32 %b, 15
+  %call = tail call i32 @external_use(i32 noundef %and) #3
+  %shl = shl nuw nsw i32 1, %and
+  %and1 = and i32 %shl, %a
+  %tobool = icmp ne i32 %and1, 0
+  ret i1 %tobool
+}
+
+define i1 @bt_16_i16(i16 %a, i16 %b) {
+; CHECK-LABEL: bt_16_i16:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $15, %esi
+; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    retq
+entry:
+  %and = and i16 %b, 15
+  %shl = shl i16 1, %and
+  %and1 = and i16 %shl, %a
+  %cmp = icmp ne i16 %and1, 0
+  ret i1 %cmp
+}
+
+
+declare i32 @external_use(i32 noundef) local_unnamed_addr #2
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable }
+attributes #1 = { nounwind uwtable }
+attributes #2 = { "no-trapping-math"="true" }
+attributes #3 = { nounwind }

>From a2f22853f1781c4c5990f0417ac42f204f7a818d Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 30 Aug 2026 15:21:31 -0400
Subject: [PATCH 2/2] [X86] Use 16-bit BT instruction when index is masked by
 0xF

---
 llvm/lib/Target/X86/X86ISelLowering.cpp     |  26 ++++-
 llvm/lib/Target/X86/X86InstrCompiler.td     |   3 +
 llvm/test/CodeGen/X86/atomic-rm-bit-test.ll | 103 ++++++++------------
 llvm/test/CodeGen/X86/bittest-16.ll         |  12 +--
 llvm/test/CodeGen/X86/setcc.ll              |  12 +--
 5 files changed, 76 insertions(+), 80 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c8a38aa1bb154..ac3497e2aa270 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57511,10 +57511,10 @@ static SDValue combineBTToBitOpFlag(SDNode *N, SelectionDAG &DAG) {
   EVT VT = Src.getValueType();
   SDLoc DL(N);
 
-  // X86ISD::BT is only emitted for i32/i64 (smaller widths are promoted in
+  // X86ISD::BT is only emitted for i16/i32/i64 (smaller widths are promoted in
   // getBT before the node is created).
-  assert((VT == MVT::i32 || VT == MVT::i64) &&
-         "X86ISD::BT is only emitted for i32/i64");
+  assert((VT == MVT::i16 || VT == MVT::i32 || VT == MVT::i64) &&
+         "X86ISD::BT is only emitted for i16/i32/i64");
 
   unsigned BW = VT.getScalarSizeInBits();
   SDValue PeeledBitNo = peekThroughBitPosExtTrunc(BitNo, BW);
@@ -57576,6 +57576,26 @@ static SDValue combineBT(SDNode *N, SelectionDAG &DAG,
     return SDValue(N, 0);
   }
 
+  // If the bit index is masked by 0xF, we can use a 16-bit BT instruction to
+  // eliminate the masking operation. The 16-bit instruction has a size penalty
+  // (0x66 prefix), but it's worth it if we can drop an explicit AND
+  // instruction.
+  if (BitWidth == 32 || BitWidth == 64) {
+    if (N1.getOpcode() == ISD::AND && N1.hasOneUse()) {
+      if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N1.getOperand(1))) {
+        uint64_t Mask = C->getZExtValue();
+        if ((Mask & (BitWidth - 1)) == 15) {
+          SDLoc DL(N);
+          SDValue Src =
+              DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, N->getOperand(0));
+          SDValue BitNo =
+              DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, N1.getOperand(0));
+          return DAG.getNode(X86ISD::BT, DL, MVT::i32, Src, BitNo);
+        }
+      }
+    }
+  }
+
   if (SDValue V = combineBTToBitOpFlag(N, DAG))
     return V;
 
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index 40ad1eb9b72cb..5c1146c5e2130 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -2121,6 +2121,9 @@ defm : OneBitPats<GR64, i64, BTR64rr, BTS64rr, BTC64rr, shiftMask64>;
 // since getBT promotes <32-bit Src to i32 before creating X86ISD::BT. Unlike
 // the OneBitPats above, the bit index here is already a same-width register
 // (combineBTToBitOpFlag emits it that way), so no GR8 sub-reg insertion.
+def : Pat<(X86btr GR16:$src1, GR16:$src2), (BTR16rr GR16:$src1, GR16:$src2)>;
+def : Pat<(X86bts GR16:$src1, GR16:$src2), (BTS16rr GR16:$src1, GR16:$src2)>;
+def : Pat<(X86btc GR16:$src1, GR16:$src2), (BTC16rr GR16:$src1, GR16:$src2)>;
 def : Pat<(X86btr GR32:$src1, GR32:$src2), (BTR32rr GR32:$src1, GR32:$src2)>;
 def : Pat<(X86bts GR32:$src1, GR32:$src2), (BTS32rr GR32:$src1, GR32:$src2)>;
 def : Pat<(X86btc GR32:$src1, GR32:$src2), (BTC32rr GR32:$src1, GR32:$src2)>;
diff --git a/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll b/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
index 71887e369bd18..d6ce76fc50ab1 100644
--- a/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
+++ b/llvm/test/CodeGen/X86/atomic-rm-bit-test.ll
@@ -1218,12 +1218,10 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_valz(ptr %v, i16 zeroext %c) no
 ; X86-NEXT:    # kill: def $ax killed $ax def $eax
 ; X86-NEXT:    jne .LBB21_1
 ; X86-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-NEXT:    movzwl %ax, %edx
-; X86-NEXT:    andl $15, %ecx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    btl %ecx, %edx
-; X86-NEXT:    setae %al
-; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    btw %cx, %ax
+; X86-NEXT:    setae %dl
+; X86-NEXT:    movl %edx, %eax
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    retl
@@ -1244,12 +1242,10 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_valz(ptr %v, i16 zeroext %c) no
 ; X64-NEXT:    # kill: def $ax killed $ax def $eax
 ; X64-NEXT:    jne .LBB21_1
 ; X64-NEXT:  # %bb.2: # %atomicrmw.end
-; X64-NEXT:    movzwl %ax, %edx
-; X64-NEXT:    andl $15, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    btl %ecx, %edx
-; X64-NEXT:    setae %al
-; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    xorl %edx, %edx
+; X64-NEXT:    btw %cx, %ax
+; X64-NEXT:    setae %dl
+; X64-NEXT:    movl %edx, %eax
 ; X64-NEXT:    retq
 entry:
   %conv = zext i16 %c to i32
@@ -1611,12 +1607,10 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_valnz(ptr %v, i16 zeroext %c) n
 ; X86-NEXT:    # kill: def $ax killed $ax def $eax
 ; X86-NEXT:    jne .LBB27_1
 ; X86-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-NEXT:    movzwl %ax, %edx
-; X86-NEXT:    andl $15, %ecx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    btl %ecx, %edx
-; X86-NEXT:    setb %al
-; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    btw %cx, %ax
+; X86-NEXT:    setb %dl
+; X86-NEXT:    movl %edx, %eax
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    retl
@@ -1637,12 +1631,10 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_valnz(ptr %v, i16 zeroext %c) n
 ; X64-NEXT:    # kill: def $ax killed $ax def $eax
 ; X64-NEXT:    jne .LBB27_1
 ; X64-NEXT:  # %bb.2: # %atomicrmw.end
-; X64-NEXT:    movzwl %ax, %edx
-; X64-NEXT:    andl $15, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    btl %ecx, %edx
-; X64-NEXT:    setb %al
-; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    xorl %edx, %edx
+; X64-NEXT:    btw %cx, %ax
+; X64-NEXT:    setb %dl
+; X64-NEXT:    movl %edx, %eax
 ; X64-NEXT:    retq
 entry:
   %conv = zext i16 %c to i32
@@ -2039,30 +2031,28 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_brz(ptr %v, i16 zeroext %c) nou
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
 ; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT:    movl $1, %esi
-; X86-NEXT:    shll %cl, %esi
-; X86-NEXT:    movzwl (%edx), %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT:    movl $1, %edx
+; X86-NEXT:    shll %cl, %edx
+; X86-NEXT:    movzwl (%esi), %eax
 ; X86-NEXT:    .p2align 4
 ; X86-NEXT:  .LBB33_1: # %atomicrmw.start
 ; X86-NEXT:    # =>This Inner Loop Header: Depth=1
 ; X86-NEXT:    movl %eax, %edi
-; X86-NEXT:    xorl %esi, %edi
+; X86-NEXT:    xorl %edx, %edi
 ; X86-NEXT:    # kill: def $ax killed $ax killed $eax
-; X86-NEXT:    lock cmpxchgw %di, (%edx)
+; X86-NEXT:    lock cmpxchgw %di, (%esi)
 ; X86-NEXT:    # kill: def $ax killed $ax def $eax
 ; X86-NEXT:    jne .LBB33_1
 ; X86-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-NEXT:    movzwl %ax, %esi
-; X86-NEXT:    movl %ecx, %edi
-; X86-NEXT:    andl $15, %edi
-; X86-NEXT:    movw $123, %ax
-; X86-NEXT:    btl %edi, %esi
+; X86-NEXT:    movw $123, %dx
+; X86-NEXT:    btw %cx, %ax
 ; X86-NEXT:    jb .LBB33_4
 ; X86-NEXT:  # %bb.3: # %if.then
 ; X86-NEXT:    movzwl %cx, %eax
-; X86-NEXT:    movzwl (%edx,%eax,2), %eax
+; X86-NEXT:    movzwl (%esi,%eax,2), %edx
 ; X86-NEXT:  .LBB33_4: # %return
+; X86-NEXT:    movl %edx, %eax
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    retl
@@ -2083,17 +2073,16 @@ define zeroext i16 @atomic_shl1_mask1_xor_16_gpr_brz(ptr %v, i16 zeroext %c) nou
 ; X64-NEXT:    # kill: def $ax killed $ax def $eax
 ; X64-NEXT:    jne .LBB33_1
 ; X64-NEXT:  # %bb.2: # %atomicrmw.end
-; X64-NEXT:    movzwl %ax, %edx
-; X64-NEXT:    movl %ecx, %esi
-; X64-NEXT:    andl $15, %esi
-; X64-NEXT:    movw $123, %ax
-; X64-NEXT:    btl %esi, %edx
+; X64-NEXT:    movw $123, %dx
+; X64-NEXT:    btw %cx, %ax
 ; X64-NEXT:    jae .LBB33_3
 ; X64-NEXT:  # %bb.4: # %return
+; X64-NEXT:    movl %edx, %eax
 ; X64-NEXT:    retq
 ; X64-NEXT:  .LBB33_3: # %if.then
 ; X64-NEXT:    movzwl %cx, %eax
-; X64-NEXT:    movzwl (%rdi,%rax,2), %eax
+; X64-NEXT:    movzwl (%rdi,%rax,2), %edx
+; X64-NEXT:    movl %edx, %eax
 ; X64-NEXT:    retq
 entry:
   %conv = zext i16 %c to i32
@@ -2821,12 +2810,10 @@ define zeroext i16 @atomic_shl1_mask1_and_16_gpr_valnz(ptr %v, i16 zeroext %c) n
 ; X86-NEXT:    # kill: def $ax killed $ax def $eax
 ; X86-NEXT:    jne .LBB45_1
 ; X86-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-NEXT:    movzwl %ax, %edx
-; X86-NEXT:    andl $15, %ecx
-; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    btl %ecx, %edx
-; X86-NEXT:    setb %al
-; X86-NEXT:    # kill: def $ax killed $ax killed $eax
+; X86-NEXT:    xorl %edx, %edx
+; X86-NEXT:    btw %cx, %ax
+; X86-NEXT:    setb %dl
+; X86-NEXT:    movl %edx, %eax
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    retl
@@ -2847,12 +2834,10 @@ define zeroext i16 @atomic_shl1_mask1_and_16_gpr_valnz(ptr %v, i16 zeroext %c) n
 ; X64-NEXT:    # kill: def $ax killed $ax def $eax
 ; X64-NEXT:    jne .LBB45_1
 ; X64-NEXT:  # %bb.2: # %atomicrmw.end
-; X64-NEXT:    movzwl %ax, %edx
-; X64-NEXT:    andl $15, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    btl %ecx, %edx
-; X64-NEXT:    setb %al
-; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    xorl %edx, %edx
+; X64-NEXT:    btw %cx, %ax
+; X64-NEXT:    setb %dl
+; X64-NEXT:    movl %edx, %eax
 ; X64-NEXT:    retq
 entry:
   %conv = zext i16 %c to i32
@@ -3288,10 +3273,7 @@ define zeroext i16 @atomic_shl1_mask1_and_16_gpr_brnz(ptr %v, i16 zeroext %c) no
 ; X86-NEXT:    # kill: def $ax killed $ax def $eax
 ; X86-NEXT:    jne .LBB51_1
 ; X86-NEXT:  # %bb.2: # %atomicrmw.end
-; X86-NEXT:    movzwl %ax, %eax
-; X86-NEXT:    movl %ecx, %esi
-; X86-NEXT:    andl $15, %esi
-; X86-NEXT:    btl %esi, %eax
+; X86-NEXT:    btw %cx, %ax
 ; X86-NEXT:    jae .LBB51_3
 ; X86-NEXT:  # %bb.4: # %if.then
 ; X86-NEXT:    movzwl %cx, %eax
@@ -3320,10 +3302,7 @@ define zeroext i16 @atomic_shl1_mask1_and_16_gpr_brnz(ptr %v, i16 zeroext %c) no
 ; X64-NEXT:    # kill: def $ax killed $ax def $eax
 ; X64-NEXT:    jne .LBB51_1
 ; X64-NEXT:  # %bb.2: # %atomicrmw.end
-; X64-NEXT:    movzwl %ax, %eax
-; X64-NEXT:    movl %ecx, %edx
-; X64-NEXT:    andl $15, %edx
-; X64-NEXT:    btl %edx, %eax
+; X64-NEXT:    btw %cx, %ax
 ; X64-NEXT:    jae .LBB51_3
 ; X64-NEXT:  # %bb.4: # %if.then
 ; X64-NEXT:    movzwl %cx, %eax
diff --git a/llvm/test/CodeGen/X86/bittest-16.ll b/llvm/test/CodeGen/X86/bittest-16.ll
index 269fe48bbde30..8b9a5f1461a75 100644
--- a/llvm/test/CodeGen/X86/bittest-16.ll
+++ b/llvm/test/CodeGen/X86/bittest-16.ll
@@ -9,8 +9,7 @@ target triple = "x86_64-unknown-linux-gnu"
 define dso_local zeroext i1 @bt_test_16_16(i16 noundef zeroext %a, i16 noundef zeroext %b) local_unnamed_addr #0 {
 ; CHECK-LABEL: bt_test_16_16:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    andl $15, %esi
-; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    btw %si, %di
 ; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    retq
 entry:
@@ -27,8 +26,7 @@ entry:
 define dso_local zeroext i1 @bt_test_16_32(i32 noundef %a, i32 noundef %b) local_unnamed_addr #0 {
 ; CHECK-LABEL: bt_test_16_32:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    andl $15, %esi
-; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    btw %si, %di
 ; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    retq
 entry:
@@ -43,8 +41,7 @@ entry:
 define dso_local zeroext i1 @bt_test_16_64(i64 noundef %a, i64 noundef %b) local_unnamed_addr #0 {
 ; CHECK-LABEL: bt_test_16_64:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    andl $15, %esi
-; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    btw %si, %di
 ; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    retq
 entry:
@@ -93,8 +90,7 @@ entry:
 define i1 @bt_16_i16(i16 %a, i16 %b) {
 ; CHECK-LABEL: bt_16_i16:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    andl $15, %esi
-; CHECK-NEXT:    btl %esi, %edi
+; CHECK-NEXT:    btw %si, %di
 ; CHECK-NEXT:    setb %al
 ; CHECK-NEXT:    retq
 entry:
diff --git a/llvm/test/CodeGen/X86/setcc.ll b/llvm/test/CodeGen/X86/setcc.ll
index 60ac6df3f77af..4cedf840f6f93 100644
--- a/llvm/test/CodeGen/X86/setcc.ll
+++ b/llvm/test/CodeGen/X86/setcc.ll
@@ -309,20 +309,18 @@ define i16 @shift_and(i16 %a) {
 define i32 @PR55138(i32 %x) {
 ; X86-LABEL: PR55138:
 ; X86:       ## %bb.0:
-; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    andl $15, %ecx
-; X86-NEXT:    movl $27030, %edx ## imm = 0x6996
+; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movw $27030, %dx ## imm = 0x6996
 ; X86-NEXT:    xorl %eax, %eax
-; X86-NEXT:    btl %ecx, %edx
+; X86-NEXT:    btw %cx, %dx
 ; X86-NEXT:    setb %al
 ; X86-NEXT:    retl
 ;
 ; X64-NOBMI2-LABEL: PR55138:
 ; X64-NOBMI2:       ## %bb.0:
-; X64-NOBMI2-NEXT:    andl $15, %edi
-; X64-NOBMI2-NEXT:    movl $27030, %ecx ## imm = 0x6996
+; X64-NOBMI2-NEXT:    movw $27030, %cx ## imm = 0x6996
 ; X64-NOBMI2-NEXT:    xorl %eax, %eax
-; X64-NOBMI2-NEXT:    btl %edi, %ecx
+; X64-NOBMI2-NEXT:    btw %di, %cx
 ; X64-NOBMI2-NEXT:    setb %al
 ; X64-NOBMI2-NEXT:    retq
 ;



More information about the llvm-commits mailing list