Hello!
As mentioned in PR 82259. These are similar to existing BT jcc patterns.
2017-09-19 Uros Bizjak <[email protected]>
* config/i386/i386.md (*scc_bt<mode>): New insn_and_split pattern.
(*scc_bt<mode>_1): Ditto.
(*scc_bt<mode>_mask): Ditto.
testsuite/ChangeLog:
2017-09-19 Uros Bizjak <[email protected]>
* gcc.target/i386/bt-5.c: New test.
* gcc.target/i386/bt-6.c: Ditto.
* gcc.target/i386/bt-mask-3.c: Ditto.
* gcc.target/i386/bt-mask-4.c: Ditto.
Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
Committed to mainline SVN.
Uros.
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 252984)
+++ config/i386/i386.md (working copy)
@@ -11246,6 +11246,98 @@
(const_string "SI")
(const_string "<MODE>")))])
+(define_insn_and_split "*scc_bt<mode>"
+ [(set (match_operand:QI 0 "nonimmediate_operand")
+ (match_operator 1 "bt_comparison_operator"
+ [(zero_extract:SWI48
+ (match_operand:SWI48 2 "nonimmediate_operand")
+ (const_int 1)
+ (match_operand:SI 3 "nonmemory_operand"))
+ (const_int 0)]))
+ (clobber (reg:CC FLAGS_REG))]
+ "(TARGET_USE_BT || optimize_function_for_size_p (cfun))
+ && (CONST_INT_P (operands[3])
+ ? (INTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
+ && INTVAL (operands[3])
+ >= (optimize_function_for_size_p (cfun) ? 8 : 32))
+ : !memory_operand (operands[2], <MODE>mode))
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48
+ (match_dup 2)
+ (const_int 1)
+ (match_dup 3))
+ (const_int 0)))
+ (set (match_dup 0)
+ (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]))]
+{
+ operands[1] = shallow_copy_rtx (operands[1]);
+ PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
+})
+
+(define_insn_and_split "*scc_bt<mode>_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand")
+ (match_operator 1 "bt_comparison_operator"
+ [(zero_extract:SWI48
+ (match_operand:SWI48 2 "register_operand")
+ (const_int 1)
+ (zero_extend:SI
+ (match_operand:QI 3 "register_operand")))
+ (const_int 0)]))
+ (clobber (reg:CC FLAGS_REG))]
+ "(TARGET_USE_BT || optimize_function_for_size_p (cfun))
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48
+ (match_dup 2)
+ (const_int 1)
+ (match_dup 3))
+ (const_int 0)))
+ (set (match_dup 0)
+ (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]))]
+{
+ operands[3] = lowpart_subreg (SImode, operands[3], QImode);
+ operands[1] = shallow_copy_rtx (operands[1]);
+ PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
+})
+
+;; Avoid useless masking of bit offset operand.
+(define_insn_and_split "*scc_bt<mode>_mask"
+ [(set (match_operand:QI 0 "nonimmediate_operand")
+ (match_operator 1 "bt_comparison_operator"
+ [(zero_extract:SWI48
+ (match_operand:SWI48 2 "register_operand")
+ (const_int 1)
+ (and:SI
+ (match_operand:SI 3 "register_operand")
+ (match_operand 4 "const_int_operand")))]))
+ (clobber (reg:CC FLAGS_REG))]
+ "(TARGET_USE_BT || optimize_function_for_size_p (cfun))
+ && (INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
+ == GET_MODE_BITSIZE (<MODE>mode)-1
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48
+ (match_dup 2)
+ (const_int 1)
+ (match_dup 3))
+ (const_int 0)))
+ (set (match_dup 0)
+ (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]))]
+{
+ operands[1] = shallow_copy_rtx (operands[1]);
+ PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
+})
+
(define_insn_and_split "*jcc_bt<mode>"
[(set (pc)
(if_then_else (match_operator 0 "bt_comparison_operator"
Index: testsuite/gcc.target/i386/bt-5.c
===================================================================
--- testsuite/gcc.target/i386/bt-5.c (nonexistent)
+++ testsuite/gcc.target/i386/bt-5.c (working copy)
@@ -0,0 +1,11 @@
+/* PR target/36473 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+/* { dg-additional-options "-mregparm=2" { target ia32 } } */
+
+int test(unsigned x, unsigned n)
+{
+ return !(x & ( 0x01 << n ));
+}
+
+/* { dg-final { scan-assembler "btl\[ \t\]" } } */
Index: testsuite/gcc.target/i386/bt-6.c
===================================================================
--- testsuite/gcc.target/i386/bt-6.c (nonexistent)
+++ testsuite/gcc.target/i386/bt-6.c (working copy)
@@ -0,0 +1,12 @@
+/* PR target/36473 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+/* { dg-additional-options "-mregparm=2" { target ia32 } } */
+
+int test(unsigned long x, unsigned long n)
+{
+ return !(x & ( (long)0x01 << n ));
+}
+
+/* { dg-final { scan-assembler "btl\[ \t\]" { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler "btq\[ \t\]" { target lp64 } } } */
Index: testsuite/gcc.target/i386/bt-mask-3.c
===================================================================
--- testsuite/gcc.target/i386/bt-mask-3.c (nonexistent)
+++ testsuite/gcc.target/i386/bt-mask-3.c (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+/* { dg-additional-options "-mregparm=2" { target ia32 } } */
+
+int test (unsigned x, unsigned n)
+{
+ n &= 0x1f;
+
+ return !(x & (0x01 << n));
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */
Index: testsuite/gcc.target/i386/bt-mask-4.c
===================================================================
--- testsuite/gcc.target/i386/bt-mask-4.c (nonexistent)
+++ testsuite/gcc.target/i386/bt-mask-4.c (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+/* { dg-additional-options "-mregparm=2" { target ia32 } } */
+
+int test (unsigned long x, unsigned long n)
+{
+ n &= 0x3f;
+
+ return !(x & ((long)0x01 << n));
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */