aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2008-06-10 12:29:36 +0200
committerUros Bizjak <uros@gcc.gnu.org>2008-06-10 12:29:36 +0200
commit33ee5810003d5d7d6fb61b0af706cfac21d4ba6c (patch)
treeadb12f0c0cddf0e92f91c40cfd912d8549be148b /gcc/config
parentf1ebbb579c845765a4ca795bb82b58738f83b796 (diff)
downloadgcc-33ee5810003d5d7d6fb61b0af706cfac21d4ba6c.zip
gcc-33ee5810003d5d7d6fb61b0af706cfac21d4ba6c.tar.gz
gcc-33ee5810003d5d7d6fb61b0af706cfac21d4ba6c.tar.bz2
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
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c2
-rw-r--r--gcc/config/i386/i386.md128
-rw-r--r--gcc/config/i386/predicates.md3
3 files changed, 129 insertions, 4 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e3feb30..6fd4c02 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 6debb18..4da50af 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 5389aa9..4f2ff6b 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")