From 33ee5810003d5d7d6fb61b0af706cfac21d4ba6c Mon Sep 17 00:00:00 2001
From: Uros Bizjak <uros@gcc.gnu.org>
Date: Tue, 10 Jun 2008 12:29:36 +0200
Subject: [PATCH] re PR target/36473 (Generate bit test (bt) instructions)

	PR target/36473
	* config/i386/i386.c (ix86_tune_features) [TUNE_USE_BT]:
	Add m_CORE2 and m_GENERIC.
	* config/i386/predicates.md (bt_comparison_operator): New predicate.
	* config/i386/i386.md (*btdi_rex64): New instruction pattern.
	(*btsi): Ditto.
	(*jcc_btdi_rex64): New instruction and split pattern.
	(*jcc_btsi): Ditto.
	(*jcc_btsi_1): Ditto.
	(*btsq): Fix Intel asm dialect operand order.
	(*btrq): Ditto.
	(*btcq): Ditto.

testsuite/ChangeLog:

	PR target/36473
	* testsuite/gcc.target/i386/bt-1.c: New test.
	* testsuite/gcc.target/i386/bt-2.c: Ditto.

From-SVN: r136615
---
 gcc/ChangeLog                        |  15 ++++
 gcc/config/i386/i386.c               |   2 +-
 gcc/config/i386/i386.md              | 128 ++++++++++++++++++++++++++-
 gcc/config/i386/predicates.md        |   3 +
 gcc/testsuite/ChangeLog              |  24 +++--
 gcc/testsuite/gcc.target/i386/bt-1.c |  15 ++++
 gcc/testsuite/gcc.target/i386/bt-2.c |  16 ++++
 7 files changed, 190 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/bt-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/bt-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de089334244f..bd7d2048dc02 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2008-06-10  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR target/36473
+	* config/i386/i386.c (ix86_tune_features) [TUNE_USE_BT]:
+	Add m_CORE2 and m_GENERIC.
+	* config/i386/predicates.md (bt_comparison_operator): New predicate.
+	* config/i386/i386.md (*btdi_rex64): New instruction pattern.
+	(*btsi): Ditto.
+	(*jcc_btdi_rex64): New instruction and split pattern.
+	(*jcc_btsi): Ditto.
+	(*jcc_btsi_1): Ditto.
+	(*btsq): Fix Intel asm dialect operand order.
+	(*btrq): Ditto.
+	(*btcq): Ditto.
+
 2008-06-09  Andy Hutchinson  <hutchinsonandy@aim.com>
 
 	PR middle-end/36447
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e3feb30d01b6..6fd4c0266d00 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1390,7 +1390,7 @@ unsigned int ix86_tune_features[X86_TUNE_LAST] = {
   m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_CORE2 | m_GENERIC,
 
   /* X86_TUNE_USE_BT */
-  m_AMD_MULTIPLE,
+  m_AMD_MULTIPLE | m_CORE2 | m_GENERIC,
 
   /* X86_TUNE_USE_INCDEC */
   ~(m_PENT4 | m_NOCONA | m_GENERIC),
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 6debb18d2a0a..4da50afce285 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -13691,7 +13691,7 @@
 	(const_int 1))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
-  "bts{q} %1,%0"
+  "bts{q}\t{%1, %0|%0, %1}"
   [(set_attr "type" "alu1")])
 
 (define_insn "*btrq"
@@ -13701,7 +13701,7 @@
 	(const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
-  "btr{q} %1,%0"
+  "btr{q}\t{%1, %0|%0, %1}"
   [(set_attr "type" "alu1")])
 
 (define_insn "*btcq"
@@ -13711,7 +13711,7 @@
 	(not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
-  "btc{q} %1,%0"
+  "btc{q}\t{%1, %0|%0, %1}"
   [(set_attr "type" "alu1")])
 
 ;; Allow Nocona to avoid these instructions if a register is available.
@@ -13812,6 +13812,30 @@
   emit_insn (gen_xordi3 (operands[0], operands[0], op1));
   DONE;
 })
+
+(define_insn "*btdi_rex64"
+  [(set (reg:CCC FLAGS_REG)
+	(compare:CCC
+	  (zero_extract:DI
+	    (match_operand:DI 0 "register_operand" "r")
+	    (const_int 1)
+	    (match_operand:DI 1 "register_operand" "r"))
+	  (const_int 0)))]
+  "TARGET_64BIT && (TARGET_USE_BT || optimize_size)"
+  "bt{q}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")])
+
+(define_insn "*btsi"
+  [(set (reg:CCC FLAGS_REG)
+	(compare:CCC
+	  (zero_extract:SI
+	    (match_operand:SI 0 "register_operand" "r")
+	    (const_int 1)
+	    (match_operand:SI 1 "register_operand" "r"))
+	  (const_int 0)))]
+  "TARGET_USE_BT || optimize_size"
+  "bt{l}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")])
 
 ;; Store-flag instructions.
 
@@ -14057,6 +14081,104 @@
     FAIL;
 })
 
+;; zero_extend in SImode is correct, since this is what combine pass
+;; generates from shift insn with QImode operand.  Actually, the mode of
+;; operand 2 (bit offset operand) doesn't matter since bt insn takes
+;; appropriate modulo of the bit offset value.
+
+(define_insn_and_split "*jcc_btdi_rex64"
+  [(set (pc)
+  	(if_then_else (match_operator 0 "bt_comparison_operator"
+			[(zero_extract:DI
+			   (match_operand:DI 1 "register_operand" "r")
+			   (const_int 1)
+			   (zero_extend:SI
+			     (match_operand:QI 2 "register_operand" "r")))
+			 (const_int 0)])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  "TARGET_64BIT && (TARGET_USE_BT || optimize_size)"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+	(compare:CCC
+	  (zero_extract:DI
+	    (match_dup 1)
+	    (const_int 1)
+	    (match_dup 2))
+	  (const_int 0)))
+   (set (pc)
+	(if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))]
+{
+  operands[2] = simplify_gen_subreg (DImode, operands[2], QImode, 0);
+
+  PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
+})
+
+(define_insn_and_split "*jcc_btsi"
+  [(set (pc)
+  	(if_then_else (match_operator 0 "bt_comparison_operator"
+			[(zero_extract:SI
+			   (match_operand:SI 1 "register_operand" "r")
+			   (const_int 1)
+			   (zero_extend:SI
+			     (match_operand:QI 2 "register_operand" "r")))
+			 (const_int 0)])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  "TARGET_USE_BT || optimize_size"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+	(compare:CCC
+	  (zero_extract:SI
+	    (match_dup 1)
+	    (const_int 1)
+	    (match_dup 2))
+	  (const_int 0)))
+   (set (pc)
+	(if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))]
+{
+  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
+
+  PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
+})
+
+(define_insn_and_split "*jcc_btsi_1"
+  [(set (pc)
+  	(if_then_else (match_operator 0 "bt_comparison_operator"
+			[(and:SI
+			   (lshiftrt:SI
+			     (match_operand:SI 1 "register_operand" "r")
+			     (match_operand:QI 2 "register_operand" "r"))
+			   (const_int 1))
+			 (const_int 0)])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  "TARGET_USE_BT || optimize_size"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+	(compare:CCC
+	  (zero_extract:SI
+	    (match_dup 1)
+	    (const_int 1)
+	    (match_dup 2))
+	  (const_int 0)))
+   (set (pc)
+	(if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))]
+{
+  operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0);
+
+  PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
+})
+
 ;; Define combination compare-and-branch fp compare instructions to use
 ;; during early optimization.  Splitting the operation apart early makes
 ;; for bad code when we want to reverse the operation.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 5389aa998425..4f2ff6b7c9f6 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -920,6 +920,9 @@
 (define_predicate "ix86_comparison_uns_operator"
   (match_code "ne,eq,geu,gtu,leu,ltu"))
 
+(define_predicate "bt_comparison_operator"
+  (match_code "ne,eq"))
+
 ;; Return 1 if OP is a valid comparison operator in valid mode.
 (define_predicate "ix86_comparison_operator"
   (match_operand 0 "comparison_operator")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 09740f5b4f79..1f6c771fa30b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2008-06-10  Uros Bizjak  <ubizjak@gmail.com>
+
+	PR target/36473
+	* testsuite/gcc.target/i386/bt-1.c: New test.
+	* testsuite/gcc.target/i386/bt-2.c: Ditto.
+
 2008-06-09  Andy Hutchinson  <hutchinsonandy@aim.com>
 
 	* gcc.c-torture/execute/builtins/lib/chk.c: Only include sys/types.h
@@ -47,8 +53,8 @@
 
 2008-06-08  Paolo Carlini  <paolo.carlini@oracle.com>
 
-        PR c++/35242
-        * g++.dg/cpp0x/vt-35242.C: New.
+	PR c++/35242
+	* g++.dg/cpp0x/vt-35242.C: New.
 
 2008-06-08  Janus Weil  <janus@gcc.gnu.org>
 
@@ -127,8 +133,8 @@
 
 2008-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
 
-        PR c++/35327
-        * g++.dg/parse/crash41.C: New.
+	PR c++/35327
+	* g++.dg/parse/crash41.C: New.
 
 2008-06-06  Jakub Jelinek  <jakub@redhat.com>
 
@@ -184,7 +190,7 @@
 	* gfortran.dg/proc_decl_2.f90: Extended.
 
 2008-06-04  Joseph Myers  <joseph@codesourcery.com>
-            Maxim Kuvyrkov  <maxim@codesourcery.com>
+	    Maxim Kuvyrkov  <maxim@codesourcery.com>
 
 	* gcc.target/m68k/xgot-1.c: New test.
 
@@ -240,8 +246,8 @@
 
 2008-06-02  Paolo Carlini  <paolo.carlini@oracle.com>
 
-        PR c++/36404
-        * g++.dg/template/crash79.C: New.
+	PR c++/36404
+	* g++.dg/template/crash79.C: New.
 	* g++.dg/other/pr28114.C: Adjust.	
 
 2008-06-02  Daniel Kraft  <d@domob.eu>
@@ -304,8 +310,8 @@
 
 2008-05-29  Paolo Carlini  <paolo.carlini@oracle.com>
 
-        PR c++/35243
-        * g++.dg/cpp0x/vt-35243.C: New.	
+	PR c++/35243
+	* g++.dg/cpp0x/vt-35243.C: New.	
 
 2008-05-29  H.J. Lu  <hongjiu.lu@intel.com>
 
diff --git a/gcc/testsuite/gcc.target/i386/bt-1.c b/gcc/testsuite/gcc.target/i386/bt-1.c
new file mode 100644
index 000000000000..3727155d68f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bt-1.c
@@ -0,0 +1,15 @@
+/* PR target/36473 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+extern void foo (void);
+
+int test(int x, int n)
+{
+  if (x & ( 0x01 << n ))
+    foo ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler "btl\[ \t\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/bt-2.c b/gcc/testsuite/gcc.target/i386/bt-2.c
new file mode 100644
index 000000000000..34fa829e4068
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bt-2.c
@@ -0,0 +1,16 @@
+/* PR target/36473 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+extern void foo (void);
+
+int test(long x, long n)
+{
+  if (x & ( (long)0x01 << n ))
+    foo ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler "btl\[ \t\]" { target { ! lp64 } } } } */
+/* { dg-final { scan-assembler "btq\[ \t\]" { target lp64 } } } */
-- 
GitLab