This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, MIPS] Add widening version of scc patterns
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 7 Apr 2008 23:12:57 -0700
- Subject: [PATCH, MIPS] Add widening version of scc patterns
As rtl.texi says, the mode of the comparison operation is independent of the
mode of the data being compared. This patch adds DI <- cond:SI patterns to
optimize away the extensions we currently generate.
I was initially considering providing the "narrowing" version as well but as
it turns that's not necessary. Since the expanders set the destination always
in SI mode we get that for free. Or with RTL:
(set (subreg:DI (reg:SI 1) 0) (lt:DI ...))
The patch was tested on mipsisa64-elf.
OK?
Adam
* config/mips/mips.md (seq): Add comment.
(*seq_sidi, *seq_sidi_mips16, *sne_sidi, *sgt<u>_sidi,
*sgt<u>_sidi_mips16, *sge<u>_sidi, *slt<u>_sidi,
*slt<u>_sidi_mips16 *sle<u>_sidi, *sle<u>_sidi_mips16): New
patterns.
* config/mips/mips.c (mips_expand_scc): Fix comment.
testsuite/
* gcc.target/mips/scc-2.c: New test.
* gcc.target/mips/scc-3.c: New test.
Index: config/mips/mips.md
===================================================================
--- config/mips/mips.md (revision 133953)
+++ config/mips/mips.md (working copy)
@@ -5065,6 +5065,8 @@ (define_expand "condjump"
;;
;; ....................
+;; Destination is always set in SI mode.
+
(define_expand "seq"
[(set (match_operand:SI 0 "register_operand")
(eq:SI (match_dup 1)
@@ -5081,6 +5083,19 @@ (define_insn "*seq_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+;; The value generated by SEQ is valid both in SI and DI mode. The expander
+;; always sets destination in SI mode so it is sufficient to provide the
+;; "widening" pattern here.
+
+(define_insn "*seq_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (eq:DI (match_operand:SI 1 "register_operand" "d")
+ (const_int 0)))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "sltu\t%0,%1,1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_insn "*seq_<mode>_mips16"
[(set (match_operand:GPR 0 "register_operand" "=t")
(eq:GPR (match_operand:GPR 1 "register_operand" "d")
@@ -5090,6 +5105,15 @@ (define_insn "*seq_<mode>_mips16"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*seq_sidi_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=t")
+ (eq:DI (match_operand:SI 1 "register_operand" "d")
+ (const_int 0)))]
+ "TARGET_64BIT && TARGET_MIPS16"
+ "sltu\t%1,1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
;; "sne" uses sltu instructions in which the first operand is $0.
;; This isn't possible in mips16 code.
@@ -5109,6 +5133,15 @@ (define_insn "*sne_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*sne_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ne:DI (match_operand:SI 1 "register_operand" "d")
+ (const_int 0)))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "sltu\t%0,%.,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_expand "sgt<u>"
[(set (match_operand:SI 0 "register_operand")
(any_gt:SI (match_dup 1)
@@ -5125,6 +5158,15 @@ (define_insn "*sgt<u>_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*sgt<u>_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (any_gt:DI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "reg_or_0_operand" "dJ")))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "slt<u>\t%0,%z2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_insn "*sgt<u>_<mode>_mips16"
[(set (match_operand:GPR 0 "register_operand" "=t")
(any_gt:GPR (match_operand:GPR 1 "register_operand" "d")
@@ -5134,6 +5176,15 @@ (define_insn "*sgt<u>_<mode>_mips16"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*sgt<u>_sidi_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=t")
+ (any_gt:DI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+ "slt<u>\t%2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_expand "sge<u>"
[(set (match_operand:SI 0 "register_operand")
(any_ge:SI (match_dup 1)
@@ -5150,6 +5201,15 @@ (define_insn "*sge<u>_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*sge<u>_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (any_ge:DI (match_operand:SI 1 "register_operand" "d")
+ (const_int 1)))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "slt<u>\t%0,%.,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_expand "slt<u>"
[(set (match_operand:SI 0 "register_operand")
(any_lt:SI (match_dup 1)
@@ -5166,6 +5226,15 @@ (define_insn "*slt<u>_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*slt<u>_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (any_lt:DI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "arith_operand" "dI")))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "slt<u>\t%0,%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_insn "*slt<u>_<mode>_mips16"
[(set (match_operand:GPR 0 "register_operand" "=t,t")
(any_lt:GPR (match_operand:GPR 1 "register_operand" "d,d")
@@ -5180,6 +5249,20 @@ (define_insn "*slt<u>_<mode>_mips16"
(const_int 4)
(const_int 8))])])
+(define_insn "*slt<u>_sidi_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=t,t")
+ (any_lt:DI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "d,I")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+ "slt<u>\t%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))])])
+
(define_expand "sle<u>"
[(set (match_operand:SI 0 "register_operand")
(any_le:SI (match_dup 1)
@@ -5199,6 +5282,18 @@ (define_insn "*sle<u>_<mode>"
[(set_attr "type" "slt")
(set_attr "mode" "<MODE>")])
+(define_insn "*sle<u>_sidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (any_le:DI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "sle_operand" "")))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "slt<u>\t%0,%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")])
+
(define_insn "*sle<u>_<mode>_mips16"
[(set (match_operand:GPR 0 "register_operand" "=t")
(any_le:GPR (match_operand:GPR 1 "register_operand" "d")
@@ -5213,6 +5308,21 @@ (define_insn "*sle<u>_<mode>_mips16"
(set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
(const_int 4)
(const_int 8)))])
+
+(define_insn "*sle<u>_sidi_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=t")
+ (any_le:DI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "sle_operand" "")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "slt<u>\t%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "SI")
+ (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
+ (const_int 4)
+ (const_int 8)))])
;;
;; ....................
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c (revision 133953)
+++ config/mips/mips.c (working copy)
@@ -3868,7 +3868,7 @@ mips_emit_compare (enum rtx_code *code,
/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE.
Store the result in TARGET and return true if successful.
- On 64-bit targets, TARGET may be wider than cmp_operands[0]. */
+ On 64-bit targets, TARGET may be narrower than cmp_operands[0]. */
bool
mips_expand_scc (enum rtx_code code, rtx target)
Index: testsuite/gcc.target/mips/scc-2.c
===================================================================
--- testsuite/gcc.target/mips/scc-2.c (revision 0)
+++ testsuite/gcc.target/mips/scc-2.c (revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O -mgp64" } */
+
+/* { dg-final { scan-assembler-not "and\t\|andi\t\|ext\t\|sll\t\|srl\t" } } */
+/* { dg-final { scan-assembler-times "slt\t\|sltu\t" 12 } } */
+
+
+#define TEST(N, LHS, REL, RHS) \
+ NOMIPS16 long long w##N (int a, int b) {return LHS REL RHS;} \
+ NOMIPS16 int n##N (long long a, long long b) {return LHS REL RHS;} \
+
+TEST (eq, a, ==, 0);
+TEST (ne, a, !=, 0);
+TEST (gt, a, >, b);
+TEST (ge, a, >=, 1);
+TEST (lt, a, <, b);
+TEST (le, a, <=, 11);
Index: testsuite/gcc.target/mips/scc-3.c
===================================================================
--- testsuite/gcc.target/mips/scc-3.c (revision 0)
+++ testsuite/gcc.target/mips/scc-3.c (revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O -mabi=o64" } */
+
+/* { dg-final { scan-assembler-not "and\t\|andi\t\|ext\t\|sll\t\|srl\t" } } */
+/* { dg-final { scan-assembler-times "slt\t\|sltu\t" 8 } } */
+
+
+#define TEST(N, LHS, REL, RHS) \
+ MIPS16 long long w##N (int a, int b) {return LHS REL RHS;} \
+ MIPS16 int n##N (long long a, long long b) {return LHS REL RHS;} \
+
+TEST (eq, a, ==, 0);
+
+TEST (gt, a, >, b);
+
+TEST (lt, a, <, b);
+TEST (le, a, <=, 11);