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]

fix rtl-opt/15289, part 1


This is the beginning of a fix for rtl-opt/15289.

The end to which I am working is to remove gen_realpart/gen_imagpart.

The problem with these routines is that they're required to provide a
value that can be read *or* written, and in some cases (such as the
test case in the pr) we have no way at all to represent this.

I intend to replace these routines with separate routines to read and
write the components.  We can then generate non-trivial code in order
to insert and extract values from a composite object.

The first step toward this appears to be to update expand_assignment
in order to recognize writes to a component of a complex value, and
the easiest way to do that is to use the bits within that function 
that already call get_inner_reference.

Which is nicely sympathetic with a previously stated goal that
get_inner_reference should handle REAL/IMAGPART_EXPR simply because
doing so is very like handling COMPONENT_REF, and that many places
that check handled_component_p were having to check for these codes
separately by hand.

So this patch is just the change to get_inner_reference in order
to handle REAL/IMAGPART_EXPR, plus the associated cleanup.  I expect
there to be at least two more patches to be generated and tested
individually before this PR is actually fixed.

Side note: In looking at all the places that reference handled_component_p,
I came across can_address_p, and a very curious test therein.  Namely,

           && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0

which says that an aggregate with alias set zero cannot be addressed.
A very curious thing to suggest, since 

	typedef struct { int x; } __attribute__((may_alias)) S;

has alias set zero, and yet is addressable.  Indeed, zero typically
means "may alias anything", not "may alias nothing" (by means of not
being addressable).  I find this HIGHLY confusing.

Kenner added this test here:

revision 1.147
date: 2001/10/23 18:51:00;  author: kenner;  state: Exp;  lines: +21 -23
        * alias.c (can_address_p): Compnonents are not addressable if
        the containing type has alias set 0.
	[ rest of very large changelog elided ]

I can find no reference to this patch ever being posted to the gcc
lists at all, nor any discussion of the patch in any form.  All I can
find is the message sent to the gcc-cvs list confirming the commit.

Given that I believe can_address_p to be of the form "return true unless
you know for certain that it isn't", I believe it to be safe to arbitrarily
remove this test.  Presumably there is some construct that the Ada front
end generates that will now not be optimized as well as Kenner intended.
On the other hand, we'll also no longer do the wrong thing for the may_alias
attribute.  I'm sure that whatever it was that he was after can be addressed
in some less counterintuitive manner.

Bootstrapped and tested on i686-linux.


r~


        * expr.c (get_inner_reference): Handle REAL/IMAGPART_EXPR.
        (handled_component_p): Likewise.
        * alias.c (can_address_p): Reformat and simplify.  Handle
        REAL/IMAGPART_EXPR.  Do not disable addressability based on
        alias set zero.
        * fold-const.c (build_fold_addr_expr_with_type): Remove duplicate
        check for REAL/IMAGPART_EXPR.
        * gimplify.c (gimplify_compound_lval): Likewise.
        * tree-cfg.c (verify_expr): Likewise.
        * tree-gimple.c (is_gimple_addressable, get_base_address): Likewise.
        * tree-nested.c (build_addr, convert_nonlocal_reference): Likewise.
        (convert_local_reference): Likewise.
        * tree-ssa-loop-ivopts.c (prepare_decl_rtl): Likewise.

Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.246
diff -c -p -d -r1.246 alias.c
*** alias.c	11 Nov 2004 23:08:55 -0000	1.246
--- alias.c	30 Nov 2004 03:47:02 -0000
*************** find_base_decl (tree t)
*** 384,413 ****
  int
  can_address_p (tree t)
  {
!   /* If we're at the end, it is vacuously addressable.  */
!   if (! handled_component_p (t))
!     return 1;
  
!   /* Bitfields are never addressable.  */
!   else if (TREE_CODE (t) == BIT_FIELD_REF)
!     return 0;
  
!   /* Fields are addressable unless they are marked as nonaddressable or
!      the containing type has alias set 0.  */
!   else if (TREE_CODE (t) == COMPONENT_REF
! 	   && ! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))
! 	   && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
! 	   && can_address_p (TREE_OPERAND (t, 0)))
!     return 1;
  
!   /* Likewise for arrays.  */
!   else if ((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
! 	   && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
! 	   && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
! 	   && can_address_p (TREE_OPERAND (t, 0)))
!     return 1;
  
!   return 0;
  }
  
  /* Return the alias set for T, which may be either a type or an
--- 384,419 ----
  int
  can_address_p (tree t)
  {
!   while (1)
!     {
!       /* If we're at the end, it is vacuously addressable.  */
!       if (!handled_component_p (t))
! 	return true;
  
!       switch (TREE_CODE (t))
! 	{
! 	case COMPONENT_REF:
! 	  if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
! 	    return false;
! 	  break;
  
! 	case ARRAY_REF:
! 	case ARRAY_RANGE_REF:
! 	  if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
! 	    return false;
! 	  break;
  
! 	case REALPART_EXPR:
! 	case IMAGPART_EXPR:
! 	  break;
  
! 	default:
! 	  /* Bitfields and casts are never addressable.  */
! 	  return false;
! 	}
! 
!       t = TREE_OPERAND (t, 0);
!     }
  }
  
  /* Return the alias set for T, which may be either a type or an
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.746
diff -c -p -d -r1.746 expr.c
*** expr.c	30 Nov 2004 00:01:45 -0000	1.746
--- expr.c	30 Nov 2004 03:47:03 -0000
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5309,5373 ****
       and find the ultimate containing object.  */
    while (1)
      {
!       if (TREE_CODE (exp) == BIT_FIELD_REF)
! 	bit_offset = size_binop (PLUS_EXPR, bit_offset, TREE_OPERAND (exp, 2));
!       else if (TREE_CODE (exp) == COMPONENT_REF)
  	{
! 	  tree field = TREE_OPERAND (exp, 1);
! 	  tree this_offset = component_ref_field_offset (exp);
  
! 	  /* If this field hasn't been filled in yet, don't go
! 	     past it.  This should only happen when folding expressions
! 	     made during type construction.  */
! 	  if (this_offset == 0)
! 	    break;
  
! 	  offset = size_binop (PLUS_EXPR, offset, this_offset);
! 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 				   DECL_FIELD_BIT_OFFSET (field));
  
! 	  /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
! 	}
  
!       else if (TREE_CODE (exp) == ARRAY_REF
! 	       || TREE_CODE (exp) == ARRAY_RANGE_REF)
! 	{
! 	  tree index = TREE_OPERAND (exp, 1);
! 	  tree low_bound = array_ref_low_bound (exp);
! 	  tree unit_size = array_ref_element_size (exp);
  
! 	  /* We assume all arrays have sizes that are a multiple of a byte.
! 	     First subtract the lower bound, if any, in the type of the
! 	     index, then convert to sizetype and multiply by the size of the
! 	     array element.  */
! 	  if (! integer_zerop (low_bound))
! 	    index = fold (build2 (MINUS_EXPR, TREE_TYPE (index),
! 				  index, low_bound));
  
! 	  offset = size_binop (PLUS_EXPR, offset,
! 			       size_binop (MULT_EXPR,
! 					   convert (sizetype, index),
! 					   unit_size));
! 	}
  
!       /* We can go inside most conversions: all NON_VALUE_EXPRs, all normal
! 	 conversions that don't change the mode, and all view conversions
! 	 except those that need to "step up" the alignment.  */
!       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
! 	       && ! (TREE_CODE (exp) == VIEW_CONVERT_EXPR
! 		     && ! ((TYPE_ALIGN (TREE_TYPE (exp))
! 			    > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
! 			   && STRICT_ALIGNMENT
! 			   && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
! 			       < BIGGEST_ALIGNMENT)
! 			   && (TYPE_ALIGN_OK (TREE_TYPE (exp))
! 			       || TYPE_ALIGN_OK (TREE_TYPE
! 						 (TREE_OPERAND (exp, 0))))))
! 	       && ! ((TREE_CODE (exp) == NOP_EXPR
! 		      || TREE_CODE (exp) == CONVERT_EXPR)
! 		     && (TYPE_MODE (TREE_TYPE (exp))
! 			 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
! 	break;
  
        /* If any reference in the chain is volatile, the effect is volatile.  */
        if (TREE_THIS_VOLATILE (exp))
--- 5309,5398 ----
       and find the ultimate containing object.  */
    while (1)
      {
!       switch (TREE_CODE (exp))
  	{
! 	case BIT_FIELD_REF:
! 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 				   TREE_OPERAND (exp, 2));
! 	  break;
  
! 	case COMPONENT_REF:
! 	  {
! 	    tree field = TREE_OPERAND (exp, 1);
! 	    tree this_offset = component_ref_field_offset (exp);
  
! 	    /* If this field hasn't been filled in yet, don't go past it.
! 	       This should only happen when folding expressions made during
! 	       type construction.  */
! 	    if (this_offset == 0)
! 	      break;
  
! 	    offset = size_binop (PLUS_EXPR, offset, this_offset);
! 	    bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 				     DECL_FIELD_BIT_OFFSET (field));
  
! 	    /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
! 	  }
! 	  break;
  
! 	case ARRAY_REF:
! 	case ARRAY_RANGE_REF:
! 	  {
! 	    tree index = TREE_OPERAND (exp, 1);
! 	    tree low_bound = array_ref_low_bound (exp);
! 	    tree unit_size = array_ref_element_size (exp);
  
! 	    /* We assume all arrays have sizes that are a multiple of a byte.
! 	       First subtract the lower bound, if any, in the type of the
! 	       index, then convert to sizetype and multiply by the size of
! 	       the array element.  */
! 	    if (! integer_zerop (low_bound))
! 	      index = fold (build2 (MINUS_EXPR, TREE_TYPE (index),
! 				    index, low_bound));
  
! 	    offset = size_binop (PLUS_EXPR, offset,
! 			         size_binop (MULT_EXPR,
! 					     convert (sizetype, index),
! 					     unit_size));
! 	  }
! 	  break;
! 
! 	case REALPART_EXPR:
! 	  bit_offset = bitsize_zero_node;
! 	  break;
! 
! 	case IMAGPART_EXPR:
! 	  bit_offset = build_int_cst (bitsizetype, *pbitsize);
! 	  break;
! 
! 	/* We can go inside most conversions: all NON_VALUE_EXPRs, all normal
! 	   conversions that don't change the mode, and all view conversions
! 	   except those that need to "step up" the alignment.  */
! 
! 	case NON_LVALUE_EXPR:
! 	  break;
! 
! 	case NOP_EXPR:
! 	case CONVERT_EXPR:
! 	  if (TYPE_MODE (TREE_TYPE (exp))
! 	      != TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
! 	    goto done;
! 	  break;
! 
! 	case VIEW_CONVERT_EXPR:
! 	  if ((TYPE_ALIGN (TREE_TYPE (exp))
! 	       > TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0))))
! 	      && STRICT_ALIGNMENT
! 	      && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
! 		  < BIGGEST_ALIGNMENT)
! 	      && (TYPE_ALIGN_OK (TREE_TYPE (exp))
! 		  || TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (exp, 0)))))
! 	    goto done;
! 	  break;
! 
! 	default:
! 	  goto done;
! 	}
  
        /* If any reference in the chain is volatile, the effect is volatile.  */
        if (TREE_THIS_VOLATILE (exp))
*************** get_inner_reference (tree exp, HOST_WIDE
*** 5375,5380 ****
--- 5400,5406 ----
  
        exp = TREE_OPERAND (exp, 0);
      }
+  done:
  
    /* If OFFSET is constant, see if we can return the whole thing as a
       constant bit position.  Otherwise, split it up.  */
*************** handled_component_p (tree t)
*** 5497,5502 ****
--- 5523,5530 ----
      case ARRAY_RANGE_REF:
      case NON_LVALUE_EXPR:
      case VIEW_CONVERT_EXPR:
+     case REALPART_EXPR:
+     case IMAGPART_EXPR:
        return 1;
  
      /* ??? Sure they are handled, but get_inner_reference may return
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.480
diff -c -p -d -r1.480 fold-const.c
*** fold-const.c	27 Nov 2004 20:54:33 -0000	1.480
--- fold-const.c	30 Nov 2004 03:47:05 -0000
*************** build_fold_addr_expr_with_type (tree t, 
*** 10799,10807 ****
      {
        tree base = t;
  
!       while (handled_component_p (base)
! 	     || TREE_CODE (base) == REALPART_EXPR
! 	     || TREE_CODE (base) == IMAGPART_EXPR)
  	base = TREE_OPERAND (base, 0);
        if (DECL_P (base))
  	TREE_ADDRESSABLE (base) = 1;
--- 10799,10805 ----
      {
        tree base = t;
  
!       while (handled_component_p (base))
  	base = TREE_OPERAND (base, 0);
        if (DECL_P (base))
  	TREE_ADDRESSABLE (base) = 1;
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.88
diff -c -p -d -r2.88 gimplify.c
*** gimplify.c	29 Nov 2004 02:21:12 -0000	2.88
--- gimplify.c	30 Nov 2004 03:47:06 -0000
*************** gimplify_compound_lval (tree *expr_p, tr
*** 1427,1438 ****
       it VARRAY_TREE.  */
    VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack");
  
!   /* We can either handle REALPART_EXPR, IMAGEPART_EXPR anything that
!      handled_components can deal with.  */
!   for (p = expr_p;
!        (handled_component_p (*p)
! 	|| TREE_CODE (*p) == REALPART_EXPR || TREE_CODE (*p) == IMAGPART_EXPR);
!        p = &TREE_OPERAND (*p, 0))
      VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
  
    gcc_assert (VARRAY_ACTIVE_SIZE (stack));
--- 1427,1434 ----
       it VARRAY_TREE.  */
    VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack");
  
!   /* We can handle anything that get_inner_reference can deal with.  */
!   for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0))
      VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
  
    gcc_assert (VARRAY_ACTIVE_SIZE (stack));
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.128
diff -c -p -d -r2.128 tree-cfg.c
*** tree-cfg.c	29 Nov 2004 21:06:11 -0000	2.128
--- tree-cfg.c	30 Nov 2004 03:47:07 -0000
*************** verify_expr (tree *tp, int *walk_subtree
*** 3238,3246 ****
  	 tree) and ensure that any variable used as a prefix is marked
  	 addressable.  */
        for (x = TREE_OPERAND (t, 0);
! 	   (handled_component_p (x)
! 	    || TREE_CODE (x) == REALPART_EXPR
! 	    || TREE_CODE (x) == IMAGPART_EXPR);
  	   x = TREE_OPERAND (x, 0))
  	;
  
--- 3238,3244 ----
  	 tree) and ensure that any variable used as a prefix is marked
  	 addressable.  */
        for (x = TREE_OPERAND (t, 0);
! 	   handled_component_p (x);
  	   x = TREE_OPERAND (x, 0))
  	;
  
*************** verify_expr (tree *tp, int *walk_subtree
*** 3288,3295 ****
  	 that determine where to reference is either a constant or a variable,
  	 verify that the base is valid, and then show we've already checked
  	 the subtrees.  */
!       while (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR
! 	     || handled_component_p (t))
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF && TREE_OPERAND (t, 2))
  	    CHECK_OP (2, "Invalid COMPONENT_REF offset operator");
--- 3286,3292 ----
  	 that determine where to reference is either a constant or a variable,
  	 verify that the base is valid, and then show we've already checked
  	 the subtrees.  */
!       while (handled_component_p (t))
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF && TREE_OPERAND (t, 2))
  	    CHECK_OP (2, "Invalid COMPONENT_REF offset operator");
Index: tree-gimple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-gimple.c,v
retrieving revision 2.30
diff -c -p -d -r2.30 tree-gimple.c
*** tree-gimple.c	31 Oct 2004 09:17:40 -0000	2.30
--- tree-gimple.c	30 Nov 2004 03:47:07 -0000
*************** bool
*** 161,170 ****
  is_gimple_addressable (tree t)
  {
    return (is_gimple_id (t) || handled_component_p (t)
- 	  || TREE_CODE (t) == REALPART_EXPR
- 	  || TREE_CODE (t) == IMAGPART_EXPR
  	  || INDIRECT_REF_P (t));
- 
  }
  
  /* Return true if T is function invariant.  Or rather a restricted
--- 161,167 ----
*************** get_call_expr_in (tree t)
*** 430,437 ****
  tree
  get_base_address (tree t)
  {
!   while (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR
! 	 || handled_component_p (t))
      t = TREE_OPERAND (t, 0);
    
    if (SSA_VAR_P (t)
--- 427,433 ----
  tree
  get_base_address (tree t)
  {
!   while (handled_component_p (t))
      t = TREE_OPERAND (t, 0);
    
    if (SSA_VAR_P (t)
Index: tree-nested.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-nested.c,v
retrieving revision 2.21
diff -c -p -d -r2.21 tree-nested.c
*** tree-nested.c	29 Nov 2004 01:03:15 -0000	2.21
--- tree-nested.c	30 Nov 2004 03:47:07 -0000
*************** build_addr (tree exp)
*** 155,162 ****
  {
    tree base = exp;
  
!   while (TREE_CODE (base) == REALPART_EXPR || TREE_CODE (base) == IMAGPART_EXPR
! 	 || handled_component_p (base))
      base = TREE_OPERAND (base, 0);
  
    if (DECL_P (base))
--- 155,161 ----
  {
    tree base = exp;
  
!   while (handled_component_p (base))
      base = TREE_OPERAND (base, 0);
  
    if (DECL_P (base))
*************** convert_nonlocal_reference (tree *tp, in
*** 849,857 ****
  	 anything that describes the references.  Otherwise, we lose track
  	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
        wi->val_only = true;
!       for (; handled_component_p (t)
! 	   || TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR;
! 	   tp = &TREE_OPERAND (t, 0), t = *tp)
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF)
  	    walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
--- 848,854 ----
  	 anything that describes the references.  Otherwise, we lose track
  	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
        wi->val_only = true;
!       for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF)
  	    walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
*************** convert_local_reference (tree *tp, int *
*** 966,974 ****
  	 anything that describes the references.  Otherwise, we lose track
  	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
        wi->val_only = true;
!       for (; handled_component_p (t)
! 	   || TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR;
! 	   tp = &TREE_OPERAND (t, 0), t = *tp)
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF)
  	    walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
--- 963,969 ----
  	 anything that describes the references.  Otherwise, we lose track
  	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
        wi->val_only = true;
!       for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
  	{
  	  if (TREE_CODE (t) == COMPONENT_REF)
  	    walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.33
diff -c -p -d -r2.33 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c	25 Nov 2004 22:31:09 -0000	2.33
--- tree-ssa-loop-ivopts.c	30 Nov 2004 03:47:08 -0000
*************** prepare_decl_rtl (tree *expr_p, int *ws,
*** 2162,2171 ****
      {
      case ADDR_EXPR:
        for (expr_p = &TREE_OPERAND (*expr_p, 0);
! 	   (handled_component_p (*expr_p)
! 	    || TREE_CODE (*expr_p) == REALPART_EXPR
! 	    || TREE_CODE (*expr_p) == IMAGPART_EXPR);
! 	   expr_p = &TREE_OPERAND (*expr_p, 0));
        obj = *expr_p;
        if (DECL_P (obj))
          x = produce_memory_decl_rtl (obj, regno);
--- 2162,2170 ----
      {
      case ADDR_EXPR:
        for (expr_p = &TREE_OPERAND (*expr_p, 0);
! 	   handled_component_p (*expr_p);
! 	   expr_p = &TREE_OPERAND (*expr_p, 0))
! 	continue;
        obj = *expr_p;
        if (DECL_P (obj))
          x = produce_memory_decl_rtl (obj, regno);


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