aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/expr.c6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20040304-1.c45
4 files changed, 61 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f1dd35f..3c6aae3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2004-03-04 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR optimization/14235
+ * expr.c (convert_move): Copy the source to a new pseudo
+ when converting from a sub-word source to a larger-than-word
+ register which conflicts with the source.
+
2004-03-03 Zack Weinberg <zack@codesourcery.com>
PR 13728
diff --git a/gcc/expr.c b/gcc/expr.c
index e2063c1..1480949 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -682,7 +682,11 @@ convert_move (rtx to, rtx from, int unsignedp)
!= CODE_FOR_nothing))
{
if (GET_CODE (to) == REG)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
+ {
+ if (reg_overlap_mentioned_p (to, from))
+ from = force_reg (from_mode, from);
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
+ }
convert_move (gen_lowpart (word_mode, to), from, unsignedp);
emit_unop_insn (code, to,
gen_lowpart (word_mode, to), equiv_code);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b0edee4..931439d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-03-04 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * gcc.c-torture/compile/20040304-1.c: New test.
+
2004-03-03 Zack Weinberg <zack@codesourcery.com>
PR 13728
diff --git a/gcc/testsuite/gcc.c-torture/compile/20040304-1.c b/gcc/testsuite/gcc.c-torture/compile/20040304-1.c
new file mode 100644
index 0000000..146d42f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20040304-1.c
@@ -0,0 +1,45 @@
+/* PR optimization/14235 */
+/* Origin: <senor_fjord@yahoo.com> */
+
+typedef signed char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef unsigned long long uint64_t;
+
+static const uint64_t LOW_BYTE_MASK = 0x00000000000000ffULL;
+static const uint64_t HIGH_BYTE_MASK = 0x000000000000ff00ULL;
+static const uint64_t WORD_MASK = 0x000000000000ffffULL;
+static const uint64_t DWORD_MASK = 0x00000000ffffffffULL;
+
+extern uint64_t *srca_mask;
+extern int *assert_thrown;
+
+void foo()
+{
+ uint64_t tempA = 0; /* actually a bunch of code to set A */
+ uint64_t tempB = 0; /* actually a bunch of code to set B */
+
+ /* cast A to right size */
+ tempA = (((*srca_mask == LOW_BYTE_MASK) ||
+ (*srca_mask == HIGH_BYTE_MASK)) ?
+ ((int8_t)tempA) :
+ ((*srca_mask == WORD_MASK) ?
+ ((int16_t)tempA) :
+ ((*srca_mask == DWORD_MASK) ?
+ ((int32_t)tempA) :
+ tempA)));
+
+ /* cast B to right size */
+ tempB = (((*srca_mask == LOW_BYTE_MASK) ||
+ (*srca_mask == HIGH_BYTE_MASK)) ?
+ ((int8_t)tempB) :
+ ((*srca_mask == WORD_MASK) ?
+ ((int16_t)tempB) :
+ ((*srca_mask == DWORD_MASK) ?
+ ((int32_t)tempB) :
+ tempB)));
+
+ if ((int) tempA > (int) tempB) {
+ *assert_thrown = 1;
+ }
+}