This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, MIPS] Sign-extend with EXTS if we can't use SEB/SEH


This is the patch I've been working toward with my earlier patches.  In the
extend{si,di}_truncate<mode> pattern we can use the octeon instruction exts.

We're missing the a qi->hi variant so I am adding that too along with a test
(extend-1.c).  I am also adding an octeon test for exts.

The testcases octeon-exts-2.c and octeon-exts-5.c need adjustment.  These
tests are identical other than that they are compiled with with different
endianness.  When sign-extracting a bitfield in HI mode we use truncate to
convert from word/DI mode to HI.  Later the value is sign-extended which after
the patch generates EXTS rather than the DSLL/DSRA pair.

(BTW, TARGET_MODE_REP_EXTENDED can already remove this truncation but there
seems to be a bad interaction between force_to_mode and
make_compound_operation so the pattern produced is not currently recognized.
I was going to address this before submitting this patch but fixing the
interaction opens up another set of problems in combine.  So I postponed it
until after this patch.)

Bootstrapped and regtested on mips64octeon-linux-gnu.  Also regtested
mipsisa64r2-elf without fortran.  Additionally, I checked that before the new
hi->qi pattern assembly output was identical for cc1files using the
mipsisa64r2-elf compiler.

OK to install?

Adam


	* config/mips/mips.md (*extenddi_truncate<mode>,
	*extendsi_truncate<mode>): Emit exts if supported.  Add attribute
	defintions.
	(*extendhi_truncateqi): New define_insn_and_sptit.

testsuite/
	* gcc.target/mips/octeon-exts-6.c: New test.
	* gcc.target/mips/extend-1.c: New test.
	* gcc.target/mips/octeon-exts-2.c: Adjust to not match sign-extension
	EXTS.
	* gcc.target/mips/octeon-exts-5.c: Likewise.

Index: gcc/config/mips/mips.md
===================================================================
--- gcc.orig/config/mips/mips.md	2009-05-18 20:28:16.000000000 -0700
+++ gcc/config/mips/mips.md	2009-05-18 20:37:55.000000000 -0700
@@ -3020,8 +3020,13 @@ (define_insn_and_split "*extenddi_trunca
 	(sign_extend:DI
 	    (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
   "TARGET_64BIT && !TARGET_MIPS16"
-  "#"
-  "&& reload_completed"
+{
+  if (!ISA_HAS_EXTS)
+    return "#";
+  operands[2] = GEN_INT (GET_MODE_BITSIZE (<SHORT:MODE>mode));
+  return "exts\t%0,%1,0,%m2";
+}
+  "&& reload_completed && !ISA_HAS_EXTS"
   [(set (match_dup 2)
 	(ashift:DI (match_dup 1)
 		   (match_dup 3)))
@@ -3031,15 +3036,22 @@ (define_insn_and_split "*extenddi_trunca
 {
   operands[2] = gen_lowpart (DImode, operands[0]);
   operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
+}
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
 
 (define_insn_and_split "*extendsi_truncate<mode>"
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(sign_extend:SI
 	    (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
   "TARGET_64BIT && !TARGET_MIPS16"
-  "#"
-  "&& reload_completed"
+{
+  if (!ISA_HAS_EXTS)
+    return "#";
+  operands[2] = GEN_INT (GET_MODE_BITSIZE (<SHORT:MODE>mode));
+  return "exts\t%0,%1,0,%m2";
+}
+  "&& reload_completed && !ISA_HAS_EXTS"
   [(set (match_dup 2)
 	(ashift:DI (match_dup 1)
 		   (match_dup 3)))
@@ -3049,7 +3061,30 @@ (define_insn_and_split "*extendsi_trunca
 {
   operands[2] = gen_lowpart (DImode, operands[0]);
   operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
+}
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "*extendhi_truncateqi"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+	(sign_extend:HI
+	    (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+  "TARGET_64BIT && !TARGET_MIPS16"
+{
+  return ISA_HAS_EXTS ? "exts\t%0,%1,0,7" : "#";
+}
+  "&& reload_completed && !ISA_HAS_EXTS"
+  [(set (match_dup 2)
+	(ashift:DI (match_dup 1)
+		   (const_int 56)))
+   (set (match_dup 0)
+	(truncate:HI (ashiftrt:DI (match_dup 2)
+				  (const_int 56))))]
+{
+  operands[2] = gen_lowpart (DImode, operands[0]);
+}
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
 
 (define_insn "extendsfdf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
Index: gcc/testsuite/gcc.target/mips/octeon-exts-6.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.target/mips/octeon-exts-6.c	2009-05-18 20:37:55.000000000 -0700
@@ -0,0 +1,14 @@
+/* { dg-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-times "\texts\t" 5 } } */
+/* { dg-final { scan-assembler-not "\t(dsll|dsra)\t" } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+
+#define TEST_CHAR(T, N)	\
+  NOMIPS16 T f##N (long long d, T *a, T *r) { T b = (char) d;  *r = b + *a; }
+#define TEST_SHORT(T, N) \
+  NOMIPS16 T g##N (long long d, T *a, T *r) { T b = (short) d; *r = b + *a; }
+#define TEST(T, N) TEST_CHAR (T, N) TEST_SHORT (T, N)
+
+TEST (int, 1);
+TEST (long long, 2);
+TEST_CHAR (short, 3);
Index: gcc/testsuite/gcc.target/mips/extend-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.target/mips/extend-1.c	2009-05-18 20:37:55.000000000 -0700
@@ -0,0 +1,14 @@
+/* { dg-options "-O -mgp64 isa=!octeon" } */
+/* { dg-final { scan-assembler-times "\tdsll\t" 5 } } */
+/* { dg-final { scan-assembler-times "\tdsra\t" 5 } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+
+#define TEST_CHAR(T, N)	\
+  NOMIPS16 T f##N (long long d, T *a, T *r) { T b = (char) d;  *r = b + *a; }
+#define TEST_SHORT(T, N) \
+  NOMIPS16 T g##N (long long d, T *a, T *r) { T b = (short) d; *r = b + *a; }
+#define TEST(T, N) TEST_CHAR (T, N) TEST_SHORT (T, N)
+
+TEST (int, 1);
+TEST (long long, 2);
+TEST_CHAR (short, 3);
Index: gcc/testsuite/gcc.target/mips/octeon-exts-2.c
===================================================================
--- gcc.orig/testsuite/gcc.target/mips/octeon-exts-2.c	2009-05-18 20:28:16.000000000 -0700
+++ gcc/testsuite/gcc.target/mips/octeon-exts-2.c	2009-05-18 20:37:55.000000000 -0700
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O -march=octeon -meb" } */
-/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
+/* { dg-options "-O -march=octeon -meb -dp" } */
+/* Don't match exts in sign-extension.  */
+/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
 
 struct bar
 {
Index: gcc/testsuite/gcc.target/mips/octeon-exts-5.c
===================================================================
--- gcc.orig/testsuite/gcc.target/mips/octeon-exts-5.c	2009-05-18 20:28:16.000000000 -0700
+++ gcc/testsuite/gcc.target/mips/octeon-exts-5.c	2009-05-18 20:37:55.000000000 -0700
@@ -1,7 +1,8 @@
 /* -mel version of octeon-exts-2.c.  */
 /* { dg-do compile } */
-/* { dg-options "-O -march=octeon -mel" } */
-/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
+/* { dg-options "-O -march=octeon -mel -dp" } */
+/* Don't match exts in sign-extension.  */
+/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
 
 struct bar
 {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]