i386.md (*scc_bt<mode>): New insn_and_split pattern.
authorUros Bizjak <ubizjak@gmail.com>
Tue, 19 Sep 2017 21:14:11 +0000 (23:14 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Tue, 19 Sep 2017 21:14:11 +0000 (23:14 +0200)
* config/i386/i386.md (*scc_bt<mode>): New insn_and_split pattern.
(*scc_bt<mode>_1): Ditto.
(*scc_bt<mode>_mask): Ditto.

testsuite/ChangeLog:

* 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.

From-SVN: r252986

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/bt-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/bt-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/bt-mask-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/bt-mask-4.c [new file with mode: 0644]

index 35a36024ec243901ca8bdacec219030e0490262f..9576c8c4f4773a7b2f669350d49220fef8453733 100644 (file)
@@ -1,3 +1,9 @@
+2017-09-19  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386.md (*scc_bt<mode>): New insn_and_split pattern.
+       (*scc_bt<mode>_1): Ditto.
+       (*scc_bt<mode>_mask): Ditto.
+
 2017-09-19  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.c (ix86_split_long_move): Do not handle
index 43227dc77ee94bc93f14baae737c3cad9174ed54..b1bde14ad5e8c75d718f296ca644f137c9053755 100644 (file)
          (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 4362138d2ca1cd1cd0859f77993be09329080bde..011420575b27935a86b8cc060418120fad2d9f15 100644 (file)
@@ -1,3 +1,10 @@
+2017-09-19  Uros Bizjak  <ubizjak@gmail.com>
+
+       * 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.
+
 2017-09-19  Jakub Jelinek  <jakub@redhat.com>
 
        * g++.dg/tree-ssa/pr31146-2.C: Only do scan-tree-dump for c++14_down.
diff --git a/gcc/testsuite/gcc.target/i386/bt-5.c b/gcc/testsuite/gcc.target/i386/bt-5.c
new file mode 100644 (file)
index 0000000..309adfe
--- /dev/null
@@ -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\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/bt-6.c b/gcc/testsuite/gcc.target/i386/bt-6.c
new file mode 100644 (file)
index 0000000..994ec43
--- /dev/null
@@ -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 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/bt-mask-3.c b/gcc/testsuite/gcc.target/i386/bt-mask-3.c
new file mode 100644 (file)
index 0000000..bf3a404
--- /dev/null
@@ -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\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/bt-mask-4.c b/gcc/testsuite/gcc.target/i386/bt-mask-4.c
new file mode 100644 (file)
index 0000000..8198646
--- /dev/null
@@ -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\]" } } */