OSDN Git Service

* config/mips/mips.h (ISA_HAS_EXTS): New macro.
authornemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Sep 2008 21:24:31 +0000 (21:24 +0000)
committernemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Sep 2008 21:24:31 +0000 (21:24 +0000)
* config/mips/mips.md (*ashr_trunc<mode>): Name the pattern
combining an arithmetic right shift by more than 31 and a
trunction.  Don't match for out-of-range shift amounts.  Set
attribute mode to <MODE>.
(*lshr32_trunc<mode>): Name the pattern combining a logical right
shift by 32 and and a truncation.  Set attribute mode to <MODE>.
(*<optab>_trunc<mode>_exts): New pattern for truncated right
shifts by less than 32.
(extv): Change predicate on first operand to accept registers.
Change predicate of the other operands from immediate_operand to
const_int_operand.  Expand exts when source is a register.
(extzv): Change predicate of the constant operands from
immediate_operand to const_int_operand.
(extzv<mode>): Change predicate of the constant operands from
immediate_operand to const_int_operand and no constraint. Also
remove mode.
(*extzv_trunc<mode>_exts): New pattern.

testsuite/
* gcc.target/mips/truncate-2.c: New test.
* gcc.target/mips/octeon-exts-1.c: New test.
* gcc.target/mips/octeon-exts-2.c: New test.
* gcc.target/mips/octeon-exts-3.c: New test.
* gcc.target/mips/octeon-exts-4.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140009 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/octeon-exts-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/octeon-exts-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/octeon-exts-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/octeon-exts-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/truncate-2.c [new file with mode: 0644]

index 2350a47..d035a4b 100644 (file)
@@ -1,5 +1,26 @@
 2008-09-04  Adam Nemet  <anemet@caviumnetworks.com>
 
+       * config/mips/mips.h (ISA_HAS_EXTS): New macro.
+       * config/mips/mips.md (*ashr_trunc<mode>): Name the pattern
+       combining an arithmetic right shift by more than 31 and a
+       trunction.  Don't match for out-of-range shift amounts.  Set
+       attribute mode to <MODE>.
+       (*lshr32_trunc<mode>): Name the pattern combining a logical right
+       shift by 32 and and a truncation.  Set attribute mode to <MODE>.
+       (*<optab>_trunc<mode>_exts): New pattern for truncated right
+       shifts by less than 32.
+       (extv): Change predicate on first operand to accept registers.
+       Change predicate of the other operands from immediate_operand to
+       const_int_operand.  Expand exts when source is a register.
+       (extzv): Change predicate of the constant operands from
+       immediate_operand to const_int_operand.
+       (extzv<mode>): Change predicate of the constant operands from
+       immediate_operand to const_int_operand and no constraint. Also
+       remove mode.
+       (*extzv_trunc<mode>_exts): New pattern.
+
+2008-09-04  Adam Nemet  <anemet@caviumnetworks.com>
+
        * config/mips/mips.h (ISA_HAS_CINS): New macro.
        * config/mips/mips-protos.h (mask_low_and_shift_p,
        mask_low_and_shift_len): Declare.
index a3f47f7..4677546 100644 (file)
@@ -1012,6 +1012,9 @@ enum mips_code_readable_setting {
 /* ISA includes the cins instruction.  */
 #define ISA_HAS_CINS           TARGET_OCTEON
 
+/* ISA includes the exts instruction.  */
+#define ISA_HAS_EXTS           TARGET_OCTEON
+
 /* ISA includes the pop instruction.  */
 #define ISA_HAS_POP            TARGET_OCTEON
 \f
index 04dd30a..0f478cf 100644 (file)
 ;; to use the same template.
 (define_code_iterator any_extend [sign_extend zero_extend])
 
+;; This code iterator allows the two right shift instructions to be
+;; generated from the same template.
+(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
+
 ;; This code iterator allows the three shift instructions to be generated
 ;; from the same template.
 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
 
 ;; Combiner patterns to optimize shift/truncate combinations.
 
-(define_insn ""
+(define_insn "*ashr_trunc<mode>"
   [(set (match_operand:SUBDI 0 "register_operand" "=d")
         (truncate:SUBDI
          (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
                       (match_operand:DI 2 "const_arith_operand" ""))))]
-  "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32"
+  "TARGET_64BIT && !TARGET_MIPS16 && IN_RANGE (INTVAL (operands[2]), 32, 63)"
   "dsra\t%0,%1,%2"
   [(set_attr "type" "shift")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "<MODE>")])
 
-(define_insn ""
+(define_insn "*lshr32_trunc<mode>"
   [(set (match_operand:SUBDI 0 "register_operand" "=d")
         (truncate:SUBDI
          (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
   "TARGET_64BIT && !TARGET_MIPS16"
   "dsra\t%0,%1,32"
   [(set_attr "type" "shift")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "<MODE>")])
 
+;; Logical shift by 32 or more results in proper SI values so
+;; truncation is removed by the middle end.
+(define_insn "*<optab>_trunc<mode>_exts"
+  [(set (match_operand:SUBDI 0 "register_operand" "=d")
+        (truncate:SUBDI
+        (any_shiftrt:DI (match_operand:DI 1 "register_operand" "d")
+                        (match_operand:DI 2 "const_arith_operand" ""))))]
+  "ISA_HAS_EXTS && TARGET_64BIT && UINTVAL (operands[2]) < 32"
+  "exts\t%0,%1,%2,31"
+  [(set_attr "type" "arith")
+   (set_attr "mode" "<MODE>")])
 
 ;; Combiner patterns for truncate/sign_extend combinations.  The SI versions
 ;; use the shift/truncate patterns above.
 
 (define_expand "extv"
   [(set (match_operand 0 "register_operand")
-       (sign_extract (match_operand:QI 1 "memory_operand")
-                     (match_operand 2 "immediate_operand")
-                     (match_operand 3 "immediate_operand")))]
+       (sign_extract (match_operand 1 "nonimmediate_operand")
+                     (match_operand 2 "const_int_operand")
+                     (match_operand 3 "const_int_operand")))]
   "!TARGET_MIPS16"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
                                         INTVAL (operands[2]),
                                         INTVAL (operands[3])))
     DONE;
+  else if (register_operand (operands[1], GET_MODE (operands[0]))
+          && ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32)
+    {
+      if (GET_MODE (operands[0]) == DImode)
+       emit_insn (gen_extvdi (operands[0], operands[1], operands[2],
+                              operands[3]));
+      else
+       emit_insn (gen_extvsi (operands[0], operands[1], operands[2],
+                              operands[3]));
+      DONE;
+    }
   else
     FAIL;
 })
 
+(define_insn "extv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+        (sign_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+                         (match_operand 2 "const_int_operand" "")
+                         (match_operand 3 "const_int_operand" "")))]
+  "ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32"
+  "exts\t%0,%1,%3,%m2"
+  [(set_attr "type"     "arith")
+   (set_attr "mode"     "<MODE>")])
+
+
 (define_expand "extzv"
   [(set (match_operand 0 "register_operand")
        (zero_extract (match_operand 1 "nonimmediate_operand")
-                     (match_operand 2 "immediate_operand")
-                     (match_operand 3 "immediate_operand")))]
+                     (match_operand 2 "const_int_operand")
+                     (match_operand 3 "const_int_operand")))]
   "!TARGET_MIPS16"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
 (define_insn "extzv<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=d")
        (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
-                         (match_operand:SI 2 "immediate_operand" "I")
-                         (match_operand:SI 3 "immediate_operand" "I")))]
+                         (match_operand 2 "const_int_operand" "")
+                         (match_operand 3 "const_int_operand" "")))]
   "mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
                       INTVAL (operands[3]))"
   "<d>ext\t%0,%1,%3,%2"
   [(set_attr "type"    "arith")
    (set_attr "mode"    "<MODE>")])
 
+(define_insn "*extzv_trunc<mode>_exts"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+        (truncate:GPR
+        (zero_extract:DI (match_operand:DI 1 "register_operand" "d")
+                         (match_operand 2 "const_int_operand" "")
+                         (match_operand 3 "const_int_operand" ""))))]
+  "ISA_HAS_EXTS && TARGET_64BIT && IN_RANGE (INTVAL (operands[2]), 32, 63)"
+  "exts\t%0,%1,%3,31"
+  [(set_attr "type"     "arith")
+   (set_attr "mode"     "<MODE>")])
+
 
 (define_expand "insv"
   [(set (zero_extract (match_operand 0 "nonimmediate_operand")
index b6f573e..9eeb9cc 100644 (file)
@@ -1,5 +1,13 @@
 2008-09-04  Adam Nemet  <anemet@caviumnetworks.com>
 
+       * gcc.target/mips/truncate-2.c: New test.
+       * gcc.target/mips/octeon-exts-1.c: New test.
+       * gcc.target/mips/octeon-exts-2.c: New test.
+       * gcc.target/mips/octeon-exts-3.c: New test.
+       * gcc.target/mips/octeon-exts-4.c: New test.
+
+2008-09-04  Adam Nemet  <anemet@caviumnetworks.com>
+
        * gcc.target/mips/octeon-cins-1.c: New test.
        * gcc.target/mips/octeon-cins-2.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-1.c b/gcc/testsuite/gcc.target/mips/octeon-exts-1.c
new file mode 100644 (file)
index 0000000..bdaa0b9
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-march=octeon" } */
+/* { dg-final { scan-assembler "\texts\t" } } */
+
+struct foo
+{
+  long long a:3;
+  long long b:23;
+  long long c:38;
+};
+
+NOMIPS16 int
+f (struct foo s)
+{
+  return s.b;
+}
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-2.c b/gcc/testsuite/gcc.target/mips/octeon-exts-2.c
new file mode 100644 (file)
index 0000000..a87c5fb
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O -march=octeon" } */
+/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
+
+struct bar
+{
+  unsigned long long a:1;
+  long long b:14;
+  unsigned long long c:48;
+  long long d:1;
+};
+
+NOMIPS16 int
+f1 (struct bar *s, int a)
+{
+  return (int) s->b + a;
+}
+
+NOMIPS16 char
+f2 (struct bar *s)
+{
+  return s->d + 1;
+}
+
+NOMIPS16 int
+f3 ()
+{
+  struct bar s;
+  asm ("" : "=r"(s));
+  return (int) s.b + 1;
+}
+
+NOMIPS16 long long
+f4 (struct bar *s)
+{
+  return s->d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-3.c b/gcc/testsuite/gcc.target/mips/octeon-exts-3.c
new file mode 100644 (file)
index 0000000..d7610f8
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-times "\texts\t" 3 } } */
+
+struct foo
+{
+  unsigned long long a:10;
+  unsigned long long b:32;
+  unsigned long long c:22;
+};
+
+NOMIPS16 unsigned
+f (struct foo s)
+{
+  return s.b;
+}
+
+struct bar
+{
+  unsigned long long a:15;
+  unsigned long long b:48;
+  unsigned long long c:1;
+};
+
+NOMIPS16 int
+g (struct bar s)
+{
+  return (int) s.b;
+}
+
+NOMIPS16 int
+h (int i)
+{
+  return (i << 4) >> 24;
+}
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-4.c b/gcc/testsuite/gcc.target/mips/octeon-exts-4.c
new file mode 100644 (file)
index 0000000..475fa21
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-not "\tsll\t\[^\n\]*,0" } } */
+/* { dg-final { scan-assembler-times "\texts\t" 6 } } */
+
+#define TEST(ID, TYPE, SHIFT)                          \
+  int NOMIPS16                                         \
+  f##ID (long long y)                                  \
+  {                                                    \
+    return (TYPE) ((TYPE) (y >> SHIFT) + 1);           \
+  }                                                    \
+  int NOMIPS16                                         \
+  g##ID (unsigned long long y)                         \
+  {                                                    \
+    return (TYPE) ((TYPE) (y >> SHIFT) + 1);           \
+  }
+
+TEST (1, int, 10)
+TEST (2, short, 5)
+TEST (3, char, 31)
diff --git a/gcc/testsuite/gcc.target/mips/truncate-2.c b/gcc/testsuite/gcc.target/mips/truncate-2.c
new file mode 100644 (file)
index 0000000..51125a4
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-mips-options "-O -mgp64" } */
+
+#define TEST(ID, TYPE, SHIFT)                          \
+  int NOMIPS16                                         \
+  f##ID (long long y)                                  \
+  {                                                    \
+    return (TYPE) ((TYPE) (y >> SHIFT) + 1);           \
+  }
+
+TEST (1, int, 32)
+TEST (2, short, 32)
+TEST (3, char, 32)
+TEST (4, int, 33)
+TEST (5, short, 33)
+TEST (6, char, 33)
+TEST (7, int, 61)
+TEST (8, short, 61)
+TEST (9, char, 61)
+
+/* { dg-final { scan-assembler-not "\tsll\t\[^\n\]*,0" } } */