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]

[Committed] Improvements to RTL expansion of constructors


PR middle-end/22141 is a P2 regression affecting all 4.x releases
concerning the code generated for initializing structures from a
constant initializer.  The patch below, whilst not solving the
example code in that PR, does address several defficiencies in this
aspect of RTL expansion, and resolves the exact same issue in almost
identical code.

Consider, the very similar test case:

typedef unsigned char v4qi __attribute__ ((vector_size (4)));

v4qi u;

void f(void)
{
  u = (v4qi){ 1, 2, 3, 4 };
}

Currently with mainline we generate:

_f:     lis r9,ha16(_u)
        li r0,1
        la r11,lo16(_u)(r9)
        li r2,4
        stb r0,lo16(_u)(r9)
        li r0,2
        stb r2,3(r11)
        li r2,3
        stb r0,1(r11)
        stb r2,2(r11)
        blr

with the patch below, we now generate:

_f:     lis r0,0x102
        lis r2,ha16(_u)
        ori r0,r0,772
        stw r0,lo16(_u)(r2)
        blr

[These are exactly the regressed code sequences described by Andrew
Pinski in comment #1 of PR22141].


The patch below is actually a set of three related improvements that
get us closer to fixing 22141.  The first to tree.c correctly maintains
the TREE_CONSTANT flag on CONSTRUCTORs, such that a constructor of
constant elements is itself marked constant.  The second improvement
is that in expand_expr, if a VECTOR_CST has an integer mode, we use
the recently added folding of VIEW_CONVERT_EXPR, to convert the vector
into an integer constant of the correct mode.  Finally, the third
improvement is to fold-const.c's native_encode_vector to allow us to
convert more vectors to integers.

This final tweak allows us to handle code such as g++.dg/ext/vector2.C
which produces a VECTOR_CST where the first element is a NULL_TREE
(representing a zero value).  The existing code in fold obtained the
size of a vector's elements from the first element in the vector, and
therefore refused to convert the vector in vector2.C.  A simple
reorganization of the logic to get the element type from the vector
type allows us to catch this case.  Interestingly, the C front-end
compiled vector2.C fine, so it must be C++ front-end specific
"optimization" to use a NULL_TREE for zero in its tree representation
for this example.


The following code has been tested on powerpc-apple-darwin7.9.0 with a
full "make bootstrap", all default languages, and regression tested with
a top-level "make -k check" with no new failures.

Committed to mainline as revision 114815.



2006-06-20  Roger Sayle  <roger@eyesopen.com>

	* expr.c (expand_expr_real_1) <VECTOR_CST>: For vector constants with
	integer modes, attempt to directly construct an integer constant.

	* fold-const.c (native_encode_vector): Determine the size of each
	element from the vector type instead of the first vector element.

	* tree.c (build_constructor_single): Mark a CONSTRUCTOR as constant,
	if all of its elements/components are constant.
	(build_constructor_from_list): Likewise.


Index: expr.c
===================================================================
*** expr.c	(revision 114721)
--- expr.c	(working copy)
*************** expand_expr_real_1 (tree exp, rtx target
*** 6939,6952 ****
        return temp;

      case VECTOR_CST:
!       if (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_INT
! 	  || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
! 	return const_vector_from_tree (exp);
!       else
! 	return expand_expr (build_constructor_from_list
! 			    (TREE_TYPE (exp),
! 			     TREE_VECTOR_CST_ELTS (exp)),
! 			    ignore ? const0_rtx : target, tmode, modifier);

      case CONST_DECL:
        return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
--- 6939,6959 ----
        return temp;

      case VECTOR_CST:
!       {
! 	tree tmp = NULL_TREE;
! 	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
! 	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
! 	  return const_vector_from_tree (exp);
! 	if (GET_MODE_CLASS (mode) == MODE_INT)
! 	  tmp = fold_unary (VIEW_CONVERT_EXPR,
! 			    lang_hooks.types.type_for_mode (mode, 1),
! 			    exp);
! 	if (!tmp)
! 	  tmp = build_constructor_from_list (type,
! 					     TREE_VECTOR_CST_ELTS (exp));
! 	return expand_expr (tmp, ignore ? const0_rtx : target,
! 			    tmode, modifier);
!       }

      case CONST_DECL:
        return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
Index: fold-const.c
===================================================================
*** fold-const.c	(revision 114721)
--- fold-const.c	(working copy)
*************** static int
*** 6926,6937 ****
  native_encode_vector (tree expr, unsigned char *ptr, int len)
  {
    int i, size, offset, count;
!   tree elem, elements;

-   size = 0;
    offset = 0;
    elements = TREE_VECTOR_CST_ELTS (expr);
    count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr));
    for (i = 0; i < count; i++)
      {
        if (elements)
--- 6926,6938 ----
  native_encode_vector (tree expr, unsigned char *ptr, int len)
  {
    int i, size, offset, count;
!   tree itype, elem, elements;

    offset = 0;
    elements = TREE_VECTOR_CST_ELTS (expr);
    count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr));
+   itype = TREE_TYPE (TREE_TYPE (expr));
+   size = GET_MODE_SIZE (TYPE_MODE (itype));
    for (i = 0; i < count; i++)
      {
        if (elements)
*************** native_encode_vector (tree expr, unsigne
*** 6944,6961 ****

        if (elem)
  	{
! 	  size = native_encode_expr (elem, ptr+offset, len-offset);
! 	  if (size == 0)
  	    return 0;
  	}
!       else if (size != 0)
  	{
  	  if (offset + size > len)
  	    return 0;
  	  memset (ptr+offset, 0, size);
  	}
-       else
- 	return 0;
        offset += size;
      }
    return offset;
--- 6945,6959 ----

        if (elem)
  	{
! 	  if (native_encode_expr (elem, ptr+offset, len-offset) != size)
  	    return 0;
  	}
!       else
  	{
  	  if (offset + size > len)
  	    return 0;
  	  memset (ptr+offset, 0, size);
  	}
        offset += size;
      }
    return offset;
Index: tree.c
===================================================================
*** tree.c	(revision 114721)
--- tree.c	(working copy)
*************** build_constructor_single (tree type, tre
*** 1013,1025 ****
  {
    VEC(constructor_elt,gc) *v;
    constructor_elt *elt;

    v = VEC_alloc (constructor_elt, gc, 1);
    elt = VEC_quick_push (constructor_elt, v, NULL);
    elt->index = index;
    elt->value = value;

!   return build_constructor (type, v);
  }


--- 1013,1028 ----
  {
    VEC(constructor_elt,gc) *v;
    constructor_elt *elt;
+   tree t;

    v = VEC_alloc (constructor_elt, gc, 1);
    elt = VEC_quick_push (constructor_elt, v, NULL);
    elt->index = index;
    elt->value = value;

!   t = build_constructor (type, v);
!   TREE_CONSTANT (t) = TREE_CONSTANT (value);
!   return t;
  }


*************** build_constructor_single (tree type, tre
*** 1028,1035 ****
  tree
  build_constructor_from_list (tree type, tree vals)
  {
!   tree t;
    VEC(constructor_elt,gc) *v = NULL;

    if (vals)
      {
--- 1031,1039 ----
  tree
  build_constructor_from_list (tree type, tree vals)
  {
!   tree t, val;
    VEC(constructor_elt,gc) *v = NULL;
+   bool constant_p = true;

    if (vals)
      {
*************** build_constructor_from_list (tree type,
*** 1037,1048 ****
        for (t = vals; t; t = TREE_CHAIN (t))
  	{
  	  constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
  	  elt->index = TREE_PURPOSE (t);
! 	  elt->value = TREE_VALUE (t);
  	}
      }

!   return build_constructor (type, v);
  }


--- 1041,1057 ----
        for (t = vals; t; t = TREE_CHAIN (t))
  	{
  	  constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+ 	  val = TREE_VALUE (t);
  	  elt->index = TREE_PURPOSE (t);
! 	  elt->value = val;
! 	  if (!TREE_CONSTANT (val))
! 	    constant_p = false;
  	}
      }

!   t = build_constructor (type, v);
!   TREE_CONSTANT (t) = constant_p;
!   return t;
  }



Roger
--


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