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]

Refine store_constructor in bitfield cases


In cases of nested CONSTRUCTORs with bitfields in both cases, we can do
multiple CLOBBERs of a REG causing some stores to be lost.  Also, SIZE is
being passed in bytes, but might not be full bytes, so the size == 0 test
isn't doing the right thing.  I fixed it this way.

The testcase is a proprietary Ada program and it can't be reproduced in C.

Tested on x86_64-linux.

2004-04-30  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* expr.c (store_constructor): SIZE operand is now in bits; CLEARED
	less than zero now means emitted CLOBBER already.
	(store_constructor_field, expand_expr_real): Reflect above changes.

*** expr.c	25 Apr 2004 23:52:13 -0000	1.639
--- expr.c	30 Apr 2004 12:04:51 -0000
*************** store_constructor_field (rtx target, uns
*** 4516,4520 ****
  	}
  
!       store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
      }
    else
--- 4516,4520 ----
  	}
  
!       store_constructor (exp, target, cleared, bitsize);
      }
    else
*************** store_constructor_field (rtx target, uns
*** 4526,4531 ****
     TARGET is either a REG or a MEM; we know it cannot conflict, since
     safe_from_p has been called.
!    CLEARED is true if TARGET is known to have been zero'd.
!    SIZE is the number of bytes of TARGET we are allowed to modify: this
     may not be the same as the size of EXP if we are assigning to a field
     which has been packed to exclude padding bits.  */
--- 4526,4533 ----
     TARGET is either a REG or a MEM; we know it cannot conflict, since
     safe_from_p has been called.
!    CLEARED is positive if TARGET is known to have been zeroed, zero if
!    this is the top level of calls to store_constructor, and negative
!    if this is a recursive call but no clearing has been done.
!    SIZE is the number of bits of TARGET we are allowed to modify: this
     may not be the same as the size of EXP if we are assigning to a field
     which has been packed to exclude padding bits.  */
*************** store_constructor (tree exp, rtx target,
*** 4544,4549 ****
        tree elt;
  
!       /* If size is zero or the target is already cleared, do nothing.  */
!       if (size == 0 || cleared)
  	cleared = 1;
        /* We either clear the aggregate or indicate the value is dead.  */
--- 4546,4554 ----
        tree elt;
  
!       /* If this is not the top level, we don't do any initialization.  */
!       if (cleared)
! 	;
!       /* If the size is zero, pretend we've cleared it.  */
!       else if (size == 0)
  	cleared = 1;
        /* We either clear the aggregate or indicate the value is dead.  */
*************** store_constructor (tree exp, rtx target,
*** 4553,4557 ****
  	/* If the constructor is empty, clear the union.  */
  	{
! 	  clear_storage (target, expr_size (exp));
  	  cleared = 1;
  	}
--- 4558,4562 ----
  	/* If the constructor is empty, clear the union.  */
  	{
! 	  clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
  	  cleared = 1;
  	}
*************** store_constructor (tree exp, rtx target,
*** 4576,4580 ****
  		|| mostly_zeros_p (exp))
  	       && (GET_CODE (target) != REG
! 		   || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
  		       == size)))
  	{
--- 4581,4585 ----
  		|| mostly_zeros_p (exp))
  	       && (GET_CODE (target) != REG
! 		   || ((HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target))
  		       == size)))
  	{
*************** store_constructor (tree exp, rtx target,
*** 4587,4596 ****
  	    }
  
! 	  clear_storage (xtarget, GEN_INT (size));
  	  cleared = 1;
  	}
! 
!       if (! cleared)
! 	emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
  
        /* Store each element of the constructor into
--- 4592,4603 ----
  	    }
  
! 	  clear_storage (xtarget, GEN_INT (size / BITS_PER_UNIT));
  	  cleared = 1;
  	}
!       else
! 	{
! 	  emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
! 	  cleared = -1;
! 	}
  
        /* Store each element of the constructor into
*************** store_constructor (tree exp, rtx target,
*** 4613,4617 ****
  	    continue;
  
! 	  if (cleared && is_zeros_p (value))
  	    continue;
  
--- 4620,4624 ----
  	    continue;
  
! 	  if (cleared > 0 && is_zeros_p (value))
  	    continue;
  
*************** store_constructor (tree exp, rtx target,
*** 4823,4833 ****
  		emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
  	      else
! 		clear_storage (target, GEN_INT (size));
  	    }
- 	  cleared = 1;
  	}
        else if (REG_P (target))
! 	/* Inform later passes that the old value is dead.  */
! 	emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
  
        /* Store each element of the constructor into
--- 4830,4844 ----
  		emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
  	      else
! 		clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
! 
! 	      cleared = 1;
  	    }
  	}
        else if (REG_P (target))
! 	{
! 	  /* Inform later passes that the old value is dead.  */
! 	  emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
! 	  cleared = -1;
! 	}
  
        /* Store each element of the constructor into
*************** store_constructor (tree exp, rtx target,
*** 4846,4850 ****
  	  rtx xtarget = target;
  
! 	  if (cleared && is_zeros_p (value))
  	    continue;
  
--- 4857,4861 ----
  	  rtx xtarget = target;
  
! 	  if (cleared > 0 && is_zeros_p (value))
  	    continue;
  
*************** store_constructor (tree exp, rtx target,
*** 4940,4945 ****
  		  xtarget = adjust_address (xtarget, mode, 0);
  		  if (TREE_CODE (value) == CONSTRUCTOR)
! 		    store_constructor (value, xtarget, cleared,
! 				       bitsize / BITS_PER_UNIT);
  		  else
  		    store_expr (value, xtarget, 0);
--- 4951,4955 ----
  		  xtarget = adjust_address (xtarget, mode, 0);
  		  if (TREE_CODE (value) == CONSTRUCTOR)
! 		    store_constructor (value, xtarget, cleared, bitsize);
  		  else
  		    store_expr (value, xtarget, 0);
*************** store_constructor (tree exp, rtx target,
*** 5039,5044 ****
        if (elt == NULL_TREE && size > 0)
  	{
! 	  if (!cleared)
! 	    clear_storage (target, GEN_INT (size));
  	  return;
  	}
--- 5049,5054 ----
        if (elt == NULL_TREE && size > 0)
  	{
! 	  if (cleared <= 0)
! 	    clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
  	  return;
  	}
*************** store_constructor (tree exp, rtx target,
*** 5080,5084 ****
  	      if (bit_pos >= set_word_size || ibit == nbits)
  		{
! 		  if (word != 0 || ! cleared)
  		    {
  		      rtx datum = gen_int_mode (word, mode);
--- 5090,5094 ----
  	      if (bit_pos >= set_word_size || ibit == nbits)
  		{
! 		  if (word != 0 || cleared <= 0)
  		    {
  		      rtx datum = gen_int_mode (word, mode);
*************** store_constructor (tree exp, rtx target,
*** 5105,5109 ****
  	    }
  	}
!       else if (!cleared)
  	/* Don't bother clearing storage if the set is all ones.  */
  	if (TREE_CHAIN (elt) != NULL_TREE
--- 5115,5119 ----
  	    }
  	}
!       else if (cleared <= 0)
  	/* Don't bother clearing storage if the set is all ones.  */
  	if (TREE_CHAIN (elt) != NULL_TREE
*************** store_constructor (tree exp, rtx target,
*** 5115,5119 ****
  		       - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
  		       != (HOST_WIDE_INT) nbits))))
! 	  clear_storage (target, expr_size (exp));
  
        for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
--- 5125,5129 ----
  		       - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
  		       != (HOST_WIDE_INT) nbits))))
! 	  clear_storage (target, GEN_INT (size / BITS_PER_UNIT));
  
        for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
*************** expand_expr_real (tree exp, rtx target, 
*** 6743,6747 ****
  			     0, TREE_ADDRESSABLE (exp), 1);
  
! 	  store_constructor (exp, target, 0, int_expr_size (exp));
  	  return target;
  	}
--- 6753,6758 ----
  			     0, TREE_ADDRESSABLE (exp), 1);
  
! 	  store_constructor (exp, target, 0,
! 			     int_expr_size (exp) * BITS_PER_UNIT);
  	  return target;
  	}


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