This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Generate block moves for bitfield initialization


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  <ebotcazou@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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]