* combine.c (force_to_mode): Handle TRUNCATE. Factor out
authornemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Jul 2009 21:34:58 +0000 (21:34 +0000)
committernemet <nemet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Jul 2009 21:34:58 +0000 (21:34 +0000)
truncation from operands in binary operations.

testsuite/
* gcc.target/mips/truncate-4.c: New testcase.

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

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/truncate-4.c [new file with mode: 0644]

index b1273fb..93a912d 100644 (file)
@@ -1,5 +1,10 @@
 2009-07-01  Adam Nemet  <anemet@caviumnetworks.com>
 
+       * combine.c (force_to_mode): Handle TRUNCATE.  Factor out
+       truncation from operands in binary operations.
+
+2009-07-01  Adam Nemet  <anemet@caviumnetworks.com>
+
        Revert:
        2009-01-11  Adam Nemet  <anemet@caviumnetworks.com>
        * expmed.c (store_bit_field_1): Properly truncate the paradoxical
index b8c080c..a4f0d66 100644 (file)
@@ -7358,6 +7358,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
        return force_to_mode (SUBREG_REG (x), mode, mask, next_select);
       break;
 
+    case TRUNCATE:
+      /* Similarly for a truncate.  */
+      return force_to_mode (XEXP (x, 0), mode, mask, next_select);
+
     case AND:
       /* If this is an AND with a constant, convert it into an AND
         whose constant is the AND of that constant with MASK.  If it
@@ -7502,12 +7506,20 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
       /* For most binary operations, just propagate into the operation and
         change the mode if we have an operation of that mode.  */
 
-      op0 = gen_lowpart_or_truncate (op_mode,
-                                    force_to_mode (XEXP (x, 0), mode, mask,
-                                                   next_select));
-      op1 = gen_lowpart_or_truncate (op_mode,
-                                    force_to_mode (XEXP (x, 1), mode, mask,
-                                       next_select));
+      op0 = force_to_mode (XEXP (x, 0), mode, mask, next_select);
+      op1 = force_to_mode (XEXP (x, 1), mode, mask, next_select);
+
+      /* If we ended up truncating both operands, truncate the result of the
+        operation instead.  */
+      if (GET_CODE (op0) == TRUNCATE
+         && GET_CODE (op1) == TRUNCATE)
+       {
+         op0 = XEXP (op0, 0);
+         op1 = XEXP (op1, 0);
+       }
+
+      op0 = gen_lowpart_or_truncate (op_mode, op0);
+      op1 = gen_lowpart_or_truncate (op_mode, op1);
 
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        x = simplify_gen_binary (code, op_mode, op0, op1);
index e929100..6eea718 100644 (file)
@@ -1,3 +1,7 @@
+2009-07-01  Adam Nemet  <anemet@caviumnetworks.com>
+
+       * gcc.target/mips/truncate-4.c: New testcase.
+
 2009-07-01  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/19831
diff --git a/gcc/testsuite/gcc.target/mips/truncate-4.c b/gcc/testsuite/gcc.target/mips/truncate-4.c
new file mode 100644 (file)
index 0000000..2958be8
--- /dev/null
@@ -0,0 +1,10 @@
+/* The and is performed in DI mode so there is no need for truncation.  */
+/* { dg-options "-O -mgp64" } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+
+unsigned long long
+f (unsigned long long s)
+{
+  unsigned u = s & 0xfff;
+  return u;
+}