Hi,
this patch has been in our tree for a while and helps in Ada where you can do
block assignments to structures at will. I've attached a C testcase. The
unpatch compiler generates for it on PowerPC at -O2:
foo:
lis 10,s@ha
li 8,27
la 9,s@l(10)
stb 8,s@l(10)
li 10,108
stb 10,1(9)
li 10,-79
stb 10,2(9)
li 10,-58
stb 10,3(9)
blr
.size foo, .-foo
.comm s,4,1
because it isn't able to put back together the individual initializations.
The patched compiler generates instead:
foo:
lis 9,.LANCHOR0@ha
lis 10,s@ha
lwz 9,.LANCHOR0@l(9)
stw 9,s@l(10)
blr
.size foo, .-foo
.comm s,4,1
.section .rodata
.set .LANCHOR0,. + 0
.LC0:
.byte 27
.byte 108
.byte 177
.byte 198
Bootstrapped/regtested on i586-suse-linux, OK for mainline?
2012-05-13 Eric Botcazou <[email protected]>
* gimplify.c (gimplify_init_constructor): Do a block move for very
small objects as well.
--
Eric Botcazou
Index: gimplify.c
===================================================================
--- gimplify.c (revision 187393)
+++ gimplify.c (working copy)
@@ -4033,9 +4033,13 @@ gimplify_init_constructor (tree *expr_p,
else
align = TYPE_ALIGN (type);
+ /* Do a block move either if the size is so small as to make
+ each individual move a sub-unit move on average, or if it
+ is so large as to make individual moves inefficient. */
if (size > 0
&& num_nonzero_elements > 1
- && !can_move_by_pieces (size, align))
+ && (size < num_nonzero_elements
+ || !can_move_by_pieces (size, align)))
{
if (notify_temp_creation)
return GS_ERROR;
struct __attribute__ ((packed)) S1 {
unsigned int a1 : 2;
unsigned int a2 : 2;
unsigned int a3 : 2;
unsigned int a4 : 2;
};
struct S {
struct S1 a[4];
};
struct S s;
extern foo (void)
{
struct S my_s = {{{ 0, 1, 2, 3 }, { 1, 2, 3, 0 }, { 2, 3, 0, 1 }, { 3, 0, 1, 2 }}};
s = my_s;
}