summaryrefslogtreecommitdiff
path: root/gnu/egcs/gcc
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-07-13 17:22:57 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-07-13 17:22:57 +0000
commit423a9cd9f2809b5aad20b7e73ca95a3fcdcd3612 (patch)
treec169c3debbb1f8812d7f4924e0c9d4fc042b87ef /gnu/egcs/gcc
parentcaaa004d3305f4bd44dfccc00895c7a3baa34e89 (diff)
A better fix for the m68k optimize_reg_copy_3() problem.
The problem really only arises when optimize_reg_copy_3() attempts to merge a load which fits in a register and a load which does not fit - in the m68k case, merging an int32_t foo and (int64_t)foo two lines later. In this case, and only if the backend provides its own expansion of the extendsidi2 insn (usually for performance and code size reasons) as embedded assembly statements but not rtl operations, then gcc at this point will ``fail to realize'' that when sign-extending (or zero-extending) the value of rN into rN and r(N+1), the value of rN is not preserved on big-endian architectures, and the optimization will produce bad code. Of all the OpenBSD-supported platforms, arm and m68k are the only affected; but further optimizations in gcc3 (on arm) apparently neuter this bug, which I have been unable to reproduce in an arm build with gcc3. This commit works around the problem by preventing expansions larger than the width of a general register, on m68k only. Other platforms are not affected.
Diffstat (limited to 'gnu/egcs/gcc')
-rw-r--r--gnu/egcs/gcc/regmove.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/gnu/egcs/gcc/regmove.c b/gnu/egcs/gcc/regmove.c
index b580f8665bd..6f5e1c0894a 100644
--- a/gnu/egcs/gcc/regmove.c
+++ b/gnu/egcs/gcc/regmove.c
@@ -708,6 +708,14 @@ optimize_reg_copy_3 (insn, dest, src)
GET_MODE_BITSIZE (GET_MODE (src_reg))))
return;
+#ifdef BROKEN_OPTIMIZE_REG_COPY_3_P
+ /* If we are on a big-endian target, do not expand to more than one
+ register. */
+ if (BYTES_BIG_ENDIAN &&
+ GET_MODE_BITSIZE (GET_MODE (src)) > BITS_PER_WORD)
+ return;
+#endif
+
old_mode = GET_MODE (src_reg);
PUT_MODE (src_reg, GET_MODE (src));
XEXP (src, 0) = SET_SRC (set);
@@ -1127,14 +1135,12 @@ regmove_optimize (f, nregs, regmove_dump_file)
if (! set)
continue;
-#ifndef BROKEN_OPTIMIZE_REG_COPY_3_P
if (flag_expensive_optimizations && ! pass
&& (GET_CODE (SET_SRC (set)) == SIGN_EXTEND
|| GET_CODE (SET_SRC (set)) == ZERO_EXTEND)
&& GET_CODE (XEXP (SET_SRC (set), 0)) == REG
&& GET_CODE (SET_DEST(set)) == REG)
optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set));
-#endif
if (flag_expensive_optimizations && ! pass
&& GET_CODE (SET_SRC (set)) == REG