diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index ba376f8..aa8946a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -16405,19 +16405,19 @@
         (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))])
 
 ;; Help combine recognize bt followed by setc
-(define_insn_and_split "*bt<mode>_setc<mode>_mask"
+(define_insn_and_split "*bt<SWI48:mode>_setc<SWI48:mode>_mask"
   [(set (match_operand:SWI48 0 "register_operand")
 	(zero_extract:SWI48
  	  (match_operand:SWI48 1 "register_operand")
 	  (const_int 1)
 	  (subreg:QI
-	    (and:SWI48
-	      (match_operand:SWI48 2 "register_operand")
+	    (and:SWI248
+	      (match_operand:SWI248 2 "register_operand")
 	      (match_operand 3 "const_int_operand")) 0)))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_USE_BT
-   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
-      == GET_MODE_BITSIZE (<MODE>mode)-1
+   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<SWI48:MODE>mode)-1))
+      == GET_MODE_BITSIZE (<SWI48:MODE>mode)-1
    && ix86_pre_reload_split ()"
   "#"
   "&& 1"
@@ -16432,6 +16432,90 @@
   operands[2] = gen_lowpart (QImode, operands[2]);
   operands[3] = gen_reg_rtx (QImode);
 })
+
+;; Help combine recognize bt followed by setnc
+(define_insn_and_split "*bt<SWI48:mode>_setnc<SWI48:mode>_mask"
+  [(set (match_operand:SWI48 0 "register_operand")
+	(and:SWI48
+	  (not:SWI48
+	    (lshiftrt:SWI48
+	      (match_operand:SWI48 1 "register_operand")
+	      (subreg:QI
+		(and:SWI248 (match_operand:SWI248 2 "register_operand")
+			    (match_operand 3 "const_int_operand")) 0)))
+	  (const_int 1)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_USE_BT
+   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<SWI48:MODE>mode)-1))
+      == GET_MODE_BITSIZE (<SWI48:MODE>mode)-1
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+        (compare:CCC
+         (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+         (const_int 0)))
+   (set (match_dup 3)
+        (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))
+   (set (match_dup 0) (zero_extend:SWI48 (match_dup 3)))]
+{
+  operands[2] = gen_lowpart (QImode, operands[2]);
+  operands[3] = gen_reg_rtx (QImode);
+})
+
+;; Help combine recognize bt followed by setnc
+(define_insn_and_split "*btdi_setncsi_mask"
+  [(set (match_operand:SI 0 "register_operand")
+	(and:SI
+	  (not:SI
+	    (subreg:SI
+	      (lshiftrt:DI (match_operand:DI 1 "register_operand")
+			   (subreg:QI
+			     (and:SWI248
+				(match_operand:SWI248 2 "register_operand")
+				(const_int 63)) 0)) 0))
+	  (const_int 1)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT && TARGET_USE_BT && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+        (compare:CCC
+         (zero_extract:DI (match_dup 1) (const_int 1) (match_dup 2))
+         (const_int 0)))
+   (set (match_dup 3)
+        (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))
+   (set (match_dup 0) (zero_extend:SI (match_dup 3)))]
+{
+  operands[2] = gen_lowpart (QImode, operands[2]);
+  operands[3] = gen_reg_rtx (QImode);
+})
+
+;; Help combine recognize bt followed by setnc
+(define_insn_and_split "*bt<SWI48:mode>_setncqi_mask_2"
+  [(set (match_operand:QI 0 "register_operand")
+	(eq:QI
+	  (zero_extract:SWI48
+ 	    (match_operand:SWI48 1 "register_operand")
+	    (const_int 1)
+	    (subreg:QI
+	      (and:SWI248 (match_operand:SWI248 2 "register_operand")
+			  (match_operand 3 "const_int_operand")) 0))
+	  (const_int 0)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_USE_BT
+   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<SWI48:MODE>mode)-1))
+      == GET_MODE_BITSIZE (<SWI48:MODE>mode)-1
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+        (compare:CCC
+         (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+         (const_int 0)))
+   (set (match_dup 0)
+        (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))]
+  "operands[2] = gen_lowpart (QImode, operands[2]);")
 
 ;; Store-flag instructions.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr107671-1.c b/gcc/testsuite/gcc.target/i386/pr107671-1.c
new file mode 100644
index 0000000..d05b178
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr107671-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+int bt32v_setb(const __UINT32_TYPE__ v, __UINT32_TYPE__ bitnum)
+{
+    return ((v & (1  << (bitnum & 31)))) != 0;
+}
+
+int bt32v_setb2(const __UINT32_TYPE__ v, __UINT32_TYPE__ bitnum)
+{
+    return (v >> (bitnum & 31)) & 1;
+}
+
+int bt32v_setae(const __UINT32_TYPE__ v, __UINT32_TYPE__ bitnum)
+{
+    return ((v & (1  << (bitnum & 31)))) == 0;
+}
+
+int bt32v_setae2(const __UINT32_TYPE__ v, __UINT32_TYPE__ bitnum)
+{
+    return !((v >> (bitnum & 31)) & 1);
+}
+
+/* { dg-final { scan-assembler-times "btl" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr107671-2.c b/gcc/testsuite/gcc.target/i386/pr107671-2.c
new file mode 100644
index 0000000..c90faea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr107671-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+int bt64v_setb(const __UINT64_TYPE__ v, __UINT64_TYPE__ bitnum)
+{
+    return ((v & (1LL << (bitnum & 63)))) != 0;
+}
+
+int bt64v_setb2(const __UINT64_TYPE__ v, __UINT64_TYPE__ bitnum)
+{
+    return (v >> (bitnum & 63)) & 1;
+}
+
+int bt64v_setae(const __UINT64_TYPE__ v, __UINT64_TYPE__ bitnum)
+{
+    return ((v & (1LL << (bitnum & 63)))) == 0;
+}
+
+int bt64v_setae2(const __UINT64_TYPE__ v, __UINT64_TYPE__ bitnum)
+{
+    return !((v >> (bitnum & 63)) & 1);
+}
+
+/* { dg-final { scan-assembler-times "btq" 4 } } */
