diff options
author | Joseph Myers <joseph@codesourcery.com> | 2006-05-23 19:54:37 +0100 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2006-05-23 19:54:37 +0100 |
commit | 550ab0c644e22dd5521ed75a5da8f73b15d274df (patch) | |
tree | 05e8cc0a327ace7c6d12591051e952ef38b0d69c /gcc/expr.c | |
parent | e5d7a5205e0d8d6483fa3deee424267624c683bb (diff) | |
download | gcc-550ab0c644e22dd5521ed75a5da8f73b15d274df.tar.gz |
expr.c (undefined_operand_subword_p): New.
* expr.c (undefined_operand_subword_p): New.
(emit_move_multi_word): Do not generate move from undefined bits
of a paradoxical subreg.
From-SVN: r114021
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index f0a05e907c4..94e8586dc35 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -3096,6 +3096,38 @@ emit_move_ccmode (enum machine_mode mode, rtx x, rtx y) return ret; } +/* Return true if word I of OP lies entirely in the + undefined bits of a paradoxical subreg. */ + +static bool +undefined_operand_subword_p (rtx op, int i) +{ + enum machine_mode innermode, innermostmode; + int offset; + if (GET_CODE (op) != SUBREG) + return false; + innermode = GET_MODE (op); + innermostmode = GET_MODE (SUBREG_REG (op)); + offset = i * UNITS_PER_WORD + SUBREG_BYTE (op); + /* The SUBREG_BYTE represents offset, as if the value were stored in + memory, except for a paradoxical subreg where we define + SUBREG_BYTE to be 0; undo this exception as in + simplify_subreg. */ + if (SUBREG_BYTE (op) == 0 + && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) + { + int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); + if (WORDS_BIG_ENDIAN) + offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset += difference % UNITS_PER_WORD; + } + if (offset >= GET_MODE_SIZE (innermostmode) + || offset <= -GET_MODE_SIZE (word_mode)) + return true; + return false; +} + /* A subroutine of emit_move_insn_1. Generate a move from Y into X. MODE is any multi-word or full-word mode that lacks a move_insn pattern. Note that you will get better code if you define such @@ -3133,7 +3165,14 @@ emit_move_multi_word (enum machine_mode mode, rtx x, rtx y) i++) { rtx xpart = operand_subword (x, i, 1, mode); - rtx ypart = operand_subword (y, i, 1, mode); + rtx ypart; + + /* Do not generate code for a move if it would come entirely + from the undefined bits of a paradoxical subreg. */ + if (undefined_operand_subword_p (y, i)) + continue; + + ypart = operand_subword (y, i, 1, mode); /* If we can't get a part of Y, put Y into memory if it is a constant. Otherwise, force it into a register. Then we must |