diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-07-13 17:22:57 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-07-13 17:22:57 +0000 |
commit | 423a9cd9f2809b5aad20b7e73ca95a3fcdcd3612 (patch) | |
tree | c169c3debbb1f8812d7f4924e0c9d4fc042b87ef /gnu | |
parent | caaa004d3305f4bd44dfccc00895c7a3baa34e89 (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')
-rw-r--r-- | gnu/egcs/gcc/regmove.c | 10 |
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 |