aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Nemet <anemet@caviumnetworks.com>2009-07-01 21:34:58 +0000
committerAdam Nemet <nemet@gcc.gnu.org>2009-07-01 21:34:58 +0000
commit479b101323d7601d991a72ba79fc4f3a7dccaebc (patch)
tree7a605c8f7cca36b8978bff57e5aa90fb6575c756
parentc600a15524cc3200cd4ee3997e162e9205b79a70 (diff)
downloadgcc-479b101323d7601d991a72ba79fc4f3a7dccaebc.zip
gcc-479b101323d7601d991a72ba79fc4f3a7dccaebc.tar.gz
gcc-479b101323d7601d991a72ba79fc4f3a7dccaebc.tar.bz2
combine.c (force_to_mode): Handle TRUNCATE.
* combine.c (force_to_mode): Handle TRUNCATE. Factor out truncation from operands in binary operations. testsuite/ * gcc.target/mips/truncate-4.c: New testcase. From-SVN: r149154
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/combine.c24
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/truncate-4.c10
4 files changed, 37 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1273fb..93a912d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/combine.c b/gcc/combine.c
index b8c080c..a4f0d66 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e929100..6eea718 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..2958be8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/truncate-4.c
@@ -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;
+}