* combine.c (simplify_shift_const_1): Split code to determine
authornemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Jul 2009 21:46:01 +0000 (21:46 +0000)
committernemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Jul 2009 21:46:01 +0000 (21:46 +0000)
shift_mode into ...
(try_widen_shift_mode): ... here.  Allow widening for ASHIFTRT if the
new bits shifted in are identical to the old sign bit.

testsuite/
* gcc.target/mips/octeon-exts-7.c: New test.
* gcc.target/mips/octeon-exts-2.c: Revert previous change.
* gcc.target/mips/octeon-exts-5.c: Likewise.

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

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/octeon-exts-2.c
gcc/testsuite/gcc.target/mips/octeon-exts-5.c
gcc/testsuite/gcc.target/mips/octeon-exts-7.c [new file with mode: 0644]

index 1c09316..9643005 100644 (file)
@@ -1,3 +1,10 @@
+2009-07-18  Adam Nemet  <anemet@caviumnetworks.com>
+
+       * combine.c (simplify_shift_const_1): Split code to determine
+       shift_mode into ...
+       (try_widen_shift_mode): ... here.  Allow widening for ASHIFTRT if the
+       new bits shifted in are identical to the old sign bit.
+
 2009-07-18  Richard Guenther  <rguenther@suse.de>
 
        PR c/40787
index a781484..a0157df 100644 (file)
@@ -8982,6 +8982,42 @@ merge_outer_ops (enum rtx_code *pop0, HOST_WIDE_INT *pconst0, enum rtx_code op1,
   return 1;
 }
 \f
+/* A helper to simplify_shift_const_1 to determine the mode we can perform
+   the shift in.  The original shift operation CODE is performed on OP in
+   ORIG_MODE.  Return the wider mode MODE if we can perform the operation
+   in that mode.  Return ORIG_MODE otherwise.  */
+
+static enum machine_mode
+try_widen_shift_mode (enum rtx_code code, rtx op,
+                     enum machine_mode orig_mode, enum machine_mode mode)
+{
+  if (orig_mode == mode)
+    return mode;
+  gcc_assert (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (orig_mode));
+
+  /* In general we can't perform in wider mode for right shift and rotate.  */
+  switch (code)
+    {
+    case ASHIFTRT:
+      /* We can still widen if the bits brought in from the left are identical
+        to the sign bit of ORIG_MODE.  */
+      if (num_sign_bit_copies (op, mode)
+         > (unsigned) (GET_MODE_BITSIZE (mode)
+                       - GET_MODE_BITSIZE (orig_mode)))
+       return mode;
+      /* fall through */
+    case LSHIFTRT:
+    case ROTATE:
+      return orig_mode;
+
+    case ROTATERT:
+      gcc_unreachable ();
+
+    default:
+      return mode;
+    }
+}
+
 /* Simplify a shift of VAROP by COUNT bits.  CODE says what kind of shift.
    The result of the shift is RESULT_MODE.  Return NULL_RTX if we cannot
    simplify it.  Otherwise, return a simplified value.
@@ -9041,13 +9077,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
            count = bitsize - count;
        }
 
-      /* We need to determine what mode we will do the shift in.  If the
-        shift is a right shift or a ROTATE, we must always do it in the mode
-        it was originally done in.  Otherwise, we can do it in MODE, the
-        widest mode encountered.  */
-      shift_mode
-       = (code == ASHIFTRT || code == LSHIFTRT || code == ROTATE
-          ? result_mode : mode);
+      shift_mode = try_widen_shift_mode (code, varop, result_mode, mode);
 
       /* Handle cases where the count is greater than the size of the mode
         minus 1.  For ASHIFT, use the size minus one as the count (this can
@@ -9645,14 +9675,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
       break;
     }
 
-  /* We need to determine what mode to do the shift in.  If the shift is
-     a right shift or ROTATE, we must always do it in the mode it was
-     originally done in.  Otherwise, we can do it in MODE, the widest mode
-     encountered.  The code we care about is that of the shift that will
-     actually be done, not the shift that was originally requested.  */
-  shift_mode
-    = (code == ASHIFTRT || code == LSHIFTRT || code == ROTATE
-       ? result_mode : mode);
+  shift_mode = try_widen_shift_mode (code, varop, result_mode, mode);
 
   /* We have now finished analyzing the shift.  The result should be
      a shift of type CODE with SHIFT_MODE shifting VAROP COUNT places.  If
index ac30e5b..3200817 100644 (file)
@@ -1,3 +1,9 @@
+2009-07-18  Adam Nemet  <anemet@caviumnetworks.com>
+
+       * gcc.target/mips/octeon-exts-7.c: New test.
+       * gcc.target/mips/octeon-exts-2.c: Revert previous change.
+       * gcc.target/mips/octeon-exts-5.c: Likewise.
+
 2009-07-18  Richard Guenther  <rguenther@suse.de>
 
        PR testsuite/40798
index 42f2a3f..fc5df63 100644 (file)
@@ -1,7 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -march=octeon -meb -dp" } */
-/* Don't match exts in sign-extension.  */
-/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
+/* { dg-options "-O -march=octeon -meb" } */
+/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
 
 struct bar
 {
index 6ec7ac7..e7a4738 100644 (file)
@@ -1,8 +1,7 @@
 /* -mel version of octeon-exts-2.c.  */
 /* { dg-do compile } */
-/* { dg-options "-O -march=octeon -mel -dp" } */
-/* Don't match exts in sign-extension.  */
-/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
+/* { dg-options "-O -march=octeon -mel" } */
+/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
 
 struct bar
 {
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-7.c b/gcc/testsuite/gcc.target/mips/octeon-exts-7.c
new file mode 100644 (file)
index 0000000..04805d0
--- /dev/null
@@ -0,0 +1,17 @@
+/* Remove the redundant sign-extension after the sign-extraction.  */
+/* { dg-do compile } */
+/* { dg-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-times "\texts\t" 1 } } */
+/* { dg-final { scan-assembler-not "sll|sra" } } */
+
+struct bar
+{
+  long long a:18;
+  long long b:14;
+};
+
+NOMIPS16 int
+f1 (struct bar *s)
+{
+  return s->b;
+}