This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: powerpc & unaligned block moves with fp registers
- To: DJ Delorie <dj at redhat dot com>
- Subject: Re: powerpc & unaligned block moves with fp registers
- From: David Edelsohn <dje at watson dot ibm dot com>
- Date: Thu, 08 Nov 2001 01:48:23 -0500
- cc: gcc at gcc dot gnu dot org
I did a little more investigation about why GCC is using DImode
to move the 64-bit structure. It appears to come from the mode GCC
assigns to the expression. Maybe someone who understands the GCC
front-end and tree can explain what the following output means:
(gdb) pt
<indirect_ref 300a2978
type <record_type 30020e00 x type_0 DI
size <integer_cst 30007300 constant 64>
unit size <integer_cst 30007380 constant 8>
align 8 symtab 0 alias set -1
fields <field_decl 300a3000 c type <array_type 30020f80>
DI file dale.c line 1 size <integer_cst 30007300 64> unit size
<integer_cst 30007380 8>
align 8 offset_align 64
offset <integer_cst 30007500 constant 0>
bit offset <integer_cst 300076c0 constant 0> context
<record_type 30020e00 x> arguments <integer_cst 30007500 0>>
pointer_to_this <pointer_type 300a3080> chain <type_decl
30020e80>>
arg 0 <parm_decl 300a3100 a
type <pointer_type 300a3080 type <record_type 30020e00 x>
unsigned DI size <integer_cst 30007300 64> unit size
<integer_cst 30007380 8>
align 64 symtab 0 alias set 2>
unsigned used DI file dale.c line 2 size <integer_cst 30007300 64>
unit size <integer_cst 30007380 8>
align 64 context <function_decl 300a3280 quux> result
<pointer_type 300a3080> initial <pointer_type 300a3080>
(reg/v/f:DI 83) arg-type <pointer_type 300a3080>
arg-type-as-written <pointer_type 300a3080>
incoming-rtl (reg:DI 3 r3)
chain <parm_decl 300a3180 b type <pointer_type 300a3080>
unsigned used DI file dale.c line 2 size <integer_cst 30007300
64> unit size <integer_cst 30007380 8>
align 64 context <function_decl 300a3280 quux> result
<pointer_type 300a3080> initial <pointer_type 300a3080>
(reg/v/f:DI 84) arg-type <pointer_type 300a3080>
arg-type-as-written <pointer_type 300a3080>
incoming-rtl (reg:DI 4 r4)>>>
In expr.c:expand_expr(), the following occurs:
tree type = TREE_TYPE (exp);
mode = TYPE_MODE (type);
case INDIRECT_REF:
op0 = memory_address (mode, op0);
temp = gen_rtx_MEM (mode, op0);
Note that in the expression above is DImode but the alignment is 8 bits.
Should the expression not be DImode or should expand_expr() take
the alignment into account and not blindly use the mode for the MEM? I
don't think the type should have been layed out as DImode if the alignment
didn't support that. I think the record should have the right mode to
begin with instead of throwing heuristics later in the process such as
expand_expr() or rs6000_emit_move().
stor-layout.c comments about not using BLKmode for better
optimization:
/* Most RECORD_TYPEs have BLKmode, so we start off assuming that.
However, if possible, we use a mode that fits in a register
instead, in order to allow for better optimization down the
line. */
and later:
/* If structure's known alignment is less than what the scalar
mode would need, and it matters, then stick with BLKmode. */
if (TYPE_MODE (type) != BLKmode
&& STRICT_ALIGNMENT
&& ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
|| TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
{
/* If this is the only reason this type is BLKmode, then
don't force containing types to be BLKmode. */
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
Maybe the STRICT_ALIGNMENT test above should be SLOW_UNALIGNED_ACCESS?
Changing that one line, does change the type to BLKmode and does generate
a block move instead of a DImode move.
I think GCC's heuristics for choosing the mode of a struct is
wrong. Any comments?
Thanks, David