This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
alpha block move fix
- To: egcs-patches at egcs dot cygnus dot com
- Subject: alpha block move fix
- From: Richard Henderson <rth at twiddle dot net>
- Date: Tue, 11 May 1999 21:00:29 -0700
We would abort on something like
struct foo { double a, b; };
void bar(void *dest)
{
struct foo reg;
memcpy(dest, ® sizeof(reg));
}
because we did not handle TImode registers.
r~
* alpha.c (alpha_expand_block_move): Handle TImode registers
used with ADDRESSOF.
(alpha_expand_block_clear): Handle ADDRESSOF specially.
Index: alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.85
diff -c -p -d -r1.85 alpha.c
*** alpha.c 1999/04/26 00:27:17 1.85
--- alpha.c 1999/05/12 03:45:09
*************** alpha_expand_block_move (operands)
*** 1961,1977 ****
enum machine_mode mode;
tmp = XEXP (XEXP (orig_src, 0), 0);
mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
if (mode != BLKmode
! && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes)
{
! /* Whee! Optimize the load to use the existing register. */
! 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)));
--- 2075,2098 ----
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)
{
! 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;
}
/* 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)));
*************** alpha_expand_block_move (operands)
*** 1988,1996 ****
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)));
}
nregs += words;
--- 2109,2117 ----
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)));
}
nregs += words;
*************** alpha_expand_block_move (operands)
*** 2007,2015 ****
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)));
}
nregs += words;
--- 2128,2136 ----
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)));
}
nregs += words;
*************** alpha_expand_block_move (operands)
*** 2023,2029 ****
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);
nregs += words;
bytes -= words * 8;
--- 2144,2151 ----
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);
nregs += words;
bytes -= words * 8;
*************** alpha_expand_block_move (operands)
*** 2092,2102 ****
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)
{
! emit_move_insn (tmp, data_regs[0]);
! i = 1;
! goto dst_done;
}
/* ??? If nregs > 1, consider reconstructing the word in regs. */
--- 2214,2253 ----
tmp = XEXP (XEXP (orig_dst, 0), 0);
mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
! if (GET_MODE (tmp) == mode)
{
! 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. */
*************** alpha_expand_block_move (operands)
*** 2114,2122 ****
{
while (i < nregs && GET_MODE (data_regs[i]) == DImode)
{
! emit_move_insn (change_address(orig_dst, DImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs)),
data_regs[i]);
ofs += 8;
i++;
--- 2265,2273 ----
{
while (i < nregs && GET_MODE (data_regs[i]) == DImode)
{
! emit_move_insn (change_address (orig_dst, DImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs)),
data_regs[i]);
ofs += 8;
i++;
*************** alpha_expand_block_move (operands)
*** 2131,2143 ****
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)),
gen_lowpart (SImode, data_regs[i]));
! emit_move_insn (change_address(orig_dst, SImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs+4)),
gen_lowpart (SImode, tmp));
ofs += 8;
i++;
--- 2282,2294 ----
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)),
gen_lowpart (SImode, data_regs[i]));
! emit_move_insn (change_address (orig_dst, SImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs+4)),
gen_lowpart (SImode, tmp));
ofs += 8;
i++;
*************** alpha_expand_block_clear (operands)
*** 2256,2262 ****
--- 2407,2429 ----
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. */
if (align >= 8 && bytes >= 8)
*************** alpha_expand_block_clear (operands)
*** 2280,2288 ****
for (i = 0; i < words; ++i)
{
! emit_move_insn (change_address(orig_dst, SImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs + i*4)),
const0_rtx);
}
--- 2447,2455 ----
for (i = 0; i < words; ++i)
{
! emit_move_insn (change_address (orig_dst, SImode,
! plus_constant (XEXP (orig_dst, 0),
! ofs + i*4)),
const0_rtx);
}