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 <ebotca...@adacore.com> * 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; }