diff options
author | Richard Henderson <rth@cygnus.com> | 1999-05-11 13:48:40 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-05-11 13:48:40 -0700 |
commit | c576fce78d826c60697d5b4efe5661401f00ebcb (patch) | |
tree | 9f5094000886b485e7737e6f049bf5f6cdd9a431 | |
parent | a575e5d377c5cc1f020537b6315bc1a7dad2a6e7 (diff) | |
download | gcc-c576fce78d826c60697d5b4efe5661401f00ebcb.zip gcc-c576fce78d826c60697d5b4efe5661401f00ebcb.tar.gz gcc-c576fce78d826c60697d5b4efe5661401f00ebcb.tar.bz2 |
alpha.c (alpha_expand_block_move): Handle TImode registers used with ADDRESSOF.
* alpha.c (alpha_expand_block_move): Handle TImode registers
used with ADDRESSOF.
(alpha_expand_block_clear): Handle ADDRESSOF specially.
From-SVN: r26892
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 109 |
2 files changed, 87 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 38c1cb5..7812e47 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +Tue May 11 20:46:37 1999 Richard Henderson <rth@cygnus.com> + + * alpha.c (alpha_expand_block_move): Handle TImode registers + used with ADDRESSOF. + (alpha_expand_block_clear): Handle ADDRESSOF specially. + 1999-05-11 Ulrich Drepper <drepper@cygnus.com> * fixinc/fixinc.x86-linux-gnu (FD_ZERO): Remove unneccessary diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 13218fb..52e76ba 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1961,17 +1961,24 @@ alpha_expand_block_move (operands) enum machine_mode mode; tmp = XEXP (XEXP (orig_src, 0), 0); + /* Don't use the existing register if we're reading more than + is held in the register. Nor if there is not a mode that + handles the exact size. */ mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); if (mode != BLKmode - && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes) + && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes) { - /* Whee! Optimize the load to use the existing register. */ - data_regs[nregs++] = gen_lowpart (mode, tmp); + if (mode == TImode) + { + data_regs[nregs] = gen_lowpart (DImode, tmp); + data_regs[nregs+1] = gen_highpart (DImode, tmp); + nregs += 2; + } + else + data_regs[nregs++] = gen_lowpart (mode, tmp); goto src_done; } - /* ??? We could potentially be copying 3 bytes or whatnot from - a wider reg. Probably not worth worrying about. */ /* No appropriate mode; fall back on memory. */ orig_src = change_address (orig_src, GET_MODE (orig_src), copy_addr_to_reg (XEXP (orig_src, 0))); @@ -1988,9 +1995,9 @@ alpha_expand_block_move (operands) for (i = 0; i < words; ++i) { emit_move_insn (data_regs[nregs+i], - change_address(orig_src, DImode, - plus_constant (XEXP (orig_src, 0), - ofs + i*8))); + change_address (orig_src, DImode, + plus_constant (XEXP (orig_src, 0), + ofs + i*8))); } nregs += words; @@ -2007,9 +2014,9 @@ alpha_expand_block_move (operands) for (i = 0; i < words; ++i) { emit_move_insn (data_regs[nregs+i], - change_address(orig_src, SImode, - plus_constant (XEXP (orig_src, 0), - ofs + i*4))); + change_address (orig_src, SImode, + plus_constant (XEXP (orig_src, 0), + ofs + i*4))); } nregs += words; @@ -2023,7 +2030,8 @@ alpha_expand_block_move (operands) for (i = 0; i < words+1; ++i) data_regs[nregs+i] = gen_reg_rtx(DImode); - alpha_expand_unaligned_load_words(data_regs+nregs, orig_src, words, ofs); + alpha_expand_unaligned_load_words (data_regs + nregs, orig_src, + words, ofs); nregs += words; bytes -= words * 8; @@ -2092,11 +2100,40 @@ alpha_expand_block_move (operands) tmp = XEXP (XEXP (orig_dst, 0), 0); mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1); - if (GET_MODE (tmp) == mode && nregs == 1) + if (GET_MODE (tmp) == mode) { - emit_move_insn (tmp, data_regs[0]); - i = 1; - goto dst_done; + if (nregs == 1) + { + emit_move_insn (tmp, data_regs[0]); + i = 1; + goto dst_done; + } + else if (nregs == 2 && mode == TImode) + { + /* Undo the subregging done above when copying between + two TImode registers. */ + if (GET_CODE (data_regs[0]) == SUBREG + && GET_MODE (SUBREG_REG (data_regs[0])) == TImode) + { + emit_move_insn (tmp, SUBREG_REG (data_regs[0])); + } + else + { + rtx seq; + + start_sequence (); + emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]); + emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]); + seq = gen_sequence (); + end_sequence (); + + emit_no_conflict_block (seq, tmp, data_regs[0], + data_regs[1], NULL_RTX); + } + + i = 2; + goto dst_done; + } } /* ??? If nregs > 1, consider reconstructing the word in regs. */ @@ -2114,9 +2151,9 @@ alpha_expand_block_move (operands) { while (i < nregs && GET_MODE (data_regs[i]) == DImode) { - emit_move_insn (change_address(orig_dst, DImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), + emit_move_insn (change_address (orig_dst, DImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), data_regs[i]); ofs += 8; i++; @@ -2131,13 +2168,13 @@ alpha_expand_block_move (operands) tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32), NULL_RTX, 1, OPTAB_WIDEN); - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), + emit_move_insn (change_address (orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs)), gen_lowpart (SImode, data_regs[i])); - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs+4)), + emit_move_insn (change_address (orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs+4)), gen_lowpart (SImode, tmp)); ofs += 8; i++; @@ -2256,6 +2293,22 @@ alpha_expand_block_clear (operands) align = 2; } } + else if (GET_CODE (tmp) == ADDRESSOF) + { + enum machine_mode mode; + + mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); + if (GET_MODE (XEXP (tmp, 0)) == mode) + { + emit_move_insn (XEXP (tmp, 0), const0_rtx); + return 1; + } + + /* No appropriate mode; fall back on memory. */ + orig_dst = change_address (orig_dst, GET_MODE (orig_dst), + copy_addr_to_reg (tmp)); + align = GET_MODE_SIZE (GET_MODE (XEXP (tmp, 0))); + } /* Handle a block of contiguous words first. */ @@ -2280,9 +2333,9 @@ alpha_expand_block_clear (operands) for (i = 0; i < words; ++i) { - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs + i*4)), + emit_move_insn (change_address (orig_dst, SImode, + plus_constant (XEXP (orig_dst, 0), + ofs + i*4)), const0_rtx); } |