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] Support for known unknown alignment


Hi,

two days ago I talked to Richi on IRC about the functions to determine
the expected alignment of objects and pointers we have and he
suggested that get_object_alignment_1 and get_pointer_alignment_1
should return whether the alignment is actually known and return the
actual alignment in a reference variable (as they currently return
bitpos).

I started with this idea, only changed it a little that if the
alignment is unknown, the functions still set the *alignp parameter to
byte alignment because majority of callers would assume that if
alignment is unknown.

Quickly I realized that in order for this idea to work, I'd also need
to add the ability to explicitely distinguish between known and
unknown alignments of SSA name pointers stored in ptr_info_def
structure.  Therefore I made the alignment value zero special, meaning
that we do not know and added a number of functions to get and
manipulate these values while taking care of this special value.

IIUC, the value zero did not have any really defined meaning
previously, still ccp_finalize in tree-ssa-ccp.c was happy to set it
to that value at least once during bootstrap.  I have not investigated
why because I did not have time, I simply assumed that value means we
do not know, just like when the assumed alignment is one byte.

A very similar patch to this one has passed bootstrap and testsuite on
x86_64-linux, bootstrap and testsuite of this exact patch on the same
platform and many others is currently running.

I suppose there will be comments, but eventually I'd like to ask for
permission to commit the patch to trunk.

Thanks,

Martin


2012-04-20  Martin Jambor  <mjambor@suse.cz>

	* builtins.c (get_object_alignment_1): Return whether we can determine
	the alignment or conservatively assume byte alignment.  Return the
	alignment by reference.  Use get_pointer_alignment_1 for dereference
	alignment.
	(get_pointer_alignment_1): Return whether we can determine the
	alignment or conservatively assume byte alignment.  Return the
	alignment by reference.  Use get_ptr_info_alignment to get SSA name
	alignment.
	(get_object_alignment): Update call to get_object_alignment_1.
	(get_object_or_type_alignment): Likewise, fall back to type alignment
	only when it returned false.
	(get_pointer_alignment): Update call to get_pointer_alignment_1.
	* fold-const.c (get_pointer_modulus_and_residue): Update call to
	get_object_alignment_1.
	* ipa-prop.c (ipa_modify_call_arguments): Update call to
	get_pointer_alignment_1.
	* tree-sra.c (build_ref_for_offset): Likewise, fall back to the type
	of MEM_REF or TARGET_MEM_REF only when it returns false.
	* tree-ssa-ccp.c (get_value_from_alignment): Update call to
	get_object_alignment_1.
	(ccp_finalize): Use set_ptr_info_alignment.
	* tree.h (get_object_alignment_1): Update declaration.
	(get_pointer_alignment_1): Likewise.
	* gimple-pretty-print.c (dump_gimple_phi): Use get_ptr_info_alignment.
	(dump_gimple_stmt): Likewise.
	* tree-flow.h (ptr_info_def): Updated comments of fields align and
	misalign.
	(get_ptr_info_alignment): Declared.
	(mark_ptr_info_alignment_unknown): Likewise.
	(set_ptr_info_alignment): Likewise.
	(increment_ptr_info_misalignment): Likewise.
	* tree-ssa-address.c (copy_ref_info): Use new access functions to get
	and set alignment of SSA names.
	* tree-ssa-loop-ivopts.c (rewrite_use_nonlinear_expr): Call
	mark_ptr_info_alignment_unknown.
	* tree-ssanames.c (get_ptr_info_alignment): New function.
	(mark_ptr_info_alignment_unknown): Likewise.
	(set_ptr_info_alignment): Likewise.
	(increment_ptr_info_misalignment): Likewise.
	(get_ptr_info): Call mark_ptr_info_alignment_unknown.
	* tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref):
	Likewise.
	(bump_vector_ptr): Likewise.
	* tree-vect-stmts.c (create_array_ref): Use set_ptr_info_alignment.
	(vectorizable_store): Likewise.
	(vectorizable_load): Likewise.


Index: src/gcc/builtins.c
===================================================================
*** src.orig/gcc/builtins.c
--- src/gcc/builtins.c
*************** called_as_built_in (tree node)
*** 263,270 ****
    return is_builtin_name (name);
  }
  
! /* Compute values M and N such that M divides (address of EXP - N) and
!    such that N < M.  Store N in *BITPOSP and return M.
  
     Note that the address (and thus the alignment) computed here is based
     on the address to which a symbol resolves, whereas DECL_ALIGN is based
--- 263,272 ----
    return is_builtin_name (name);
  }
  
! /* Compute values M and N such that M divides (address of EXP - N) and such
!    that N < M.  If these numbers can be determined, store M in alignp and N in
!    *BITPOSP and return true.  Otherwise return false and store BITS_PER_UNIT to
!    *alignp and any bit-offset to *bitposp.
  
     Note that the address (and thus the alignment) computed here is based
     on the address to which a symbol resolves, whereas DECL_ALIGN is based
*************** called_as_built_in (tree node)
*** 273,286 ****
     the address &foo of a Thumb function foo() has the lowest bit set,
     whereas foo() itself starts on an even address.  */
  
! unsigned int
! get_object_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
  {
    HOST_WIDE_INT bitsize, bitpos;
    tree offset;
    enum machine_mode mode;
    int unsignedp, volatilep;
!   unsigned int align, inner;
  
    /* Get the innermost object and the constant (bitpos) and possibly
       variable (offset) offset of the access.  */
--- 275,290 ----
     the address &foo of a Thumb function foo() has the lowest bit set,
     whereas foo() itself starts on an even address.  */
  
! bool
! get_object_alignment_1 (tree exp, unsigned int *alignp,
! 			unsigned HOST_WIDE_INT *bitposp)
  {
    HOST_WIDE_INT bitsize, bitpos;
    tree offset;
    enum machine_mode mode;
    int unsignedp, volatilep;
!   unsigned int inner, align = BITS_PER_UNIT;
!   bool known_alignment = false;
  
    /* Get the innermost object and the constant (bitpos) and possibly
       variable (offset) offset of the access.  */
*************** get_object_alignment_1 (tree exp, unsign
*** 301,384 ****
  	     allows the low bit to be used as a virtual bit, we know
  	     that the address itself must be 2-byte aligned.  */
  	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
! 	    align = 2 * BITS_PER_UNIT;
! 	  else
! 	    align = BITS_PER_UNIT;
  	}
        else
! 	align = DECL_ALIGN (exp);
      }
    else if (CONSTANT_CLASS_P (exp))
      {
        align = TYPE_ALIGN (TREE_TYPE (exp));
  #ifdef CONSTANT_ALIGNMENT
        align = (unsigned)CONSTANT_ALIGNMENT (exp, align);
  #endif
      }
    else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
!     align = TYPE_ALIGN (TREE_TYPE (exp));
    else if (TREE_CODE (exp) == INDIRECT_REF)
!     align = TYPE_ALIGN (TREE_TYPE (exp));
    else if (TREE_CODE (exp) == MEM_REF)
      {
        tree addr = TREE_OPERAND (exp, 0);
!       struct ptr_info_def *pi;
        if (TREE_CODE (addr) == BIT_AND_EXPR
  	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
  	{
  	  align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
  		    & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
  	  align *= BITS_PER_UNIT;
  	  addr = TREE_OPERAND (addr, 0);
  	}
!       else
! 	align = BITS_PER_UNIT;
!       if (TREE_CODE (addr) == SSA_NAME
! 	  && (pi = SSA_NAME_PTR_INFO (addr)))
  	{
! 	  bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
! 	  align = MAX (pi->align * BITS_PER_UNIT, align);
  	}
!       else if (TREE_CODE (addr) == ADDR_EXPR)
! 	align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0)));
        bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
      }
    else if (TREE_CODE (exp) == TARGET_MEM_REF)
      {
!       struct ptr_info_def *pi;
        tree addr = TMR_BASE (exp);
        if (TREE_CODE (addr) == BIT_AND_EXPR
  	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
  	{
  	  align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
  		   & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
  	  align *= BITS_PER_UNIT;
  	  addr = TREE_OPERAND (addr, 0);
  	}
!       else
! 	align = BITS_PER_UNIT;
!       if (TREE_CODE (addr) == SSA_NAME
! 	  && (pi = SSA_NAME_PTR_INFO (addr)))
  	{
! 	  bitpos += (pi->misalign * BITS_PER_UNIT) & ~(align - 1);
! 	  align = MAX (pi->align * BITS_PER_UNIT, align);
  	}
!       else if (TREE_CODE (addr) == ADDR_EXPR)
! 	align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0)));
        if (TMR_OFFSET (exp))
  	bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
!       if (TMR_INDEX (exp) && TMR_STEP (exp))
  	{
  	  unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp));
  	  align = MIN (align, (step & -step) * BITS_PER_UNIT);
  	}
-       else if (TMR_INDEX (exp))
- 	align = BITS_PER_UNIT;
-       if (TMR_INDEX2 (exp))
- 	align = BITS_PER_UNIT;
      }
-   else
-     align = BITS_PER_UNIT;
  
    /* If there is a non-constant offset part extract the maximum
       alignment that can prevail.  */
--- 305,396 ----
  	     allows the low bit to be used as a virtual bit, we know
  	     that the address itself must be 2-byte aligned.  */
  	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
! 	    {
! 	      known_alignment = true;
! 	      align = 2 * BITS_PER_UNIT;
! 	    }
  	}
        else
! 	{
! 	  known_alignment = true;
! 	  align = DECL_ALIGN (exp);
! 	}
      }
    else if (CONSTANT_CLASS_P (exp))
      {
+       known_alignment = true;
        align = TYPE_ALIGN (TREE_TYPE (exp));
  #ifdef CONSTANT_ALIGNMENT
        align = (unsigned)CONSTANT_ALIGNMENT (exp, align);
  #endif
      }
    else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
!     {
!       known_alignment = true;
!       align = TYPE_ALIGN (TREE_TYPE (exp));
!     }
    else if (TREE_CODE (exp) == INDIRECT_REF)
!     {
!       known_alignment = true;
!       align = TYPE_ALIGN (TREE_TYPE (exp));
!     }
    else if (TREE_CODE (exp) == MEM_REF)
      {
        tree addr = TREE_OPERAND (exp, 0);
!       unsigned ptr_align;
!       unsigned HOST_WIDE_INT ptr_bitpos;
! 
        if (TREE_CODE (addr) == BIT_AND_EXPR
  	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
  	{
+ 	  known_alignment = true;
  	  align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
  		    & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
  	  align *= BITS_PER_UNIT;
  	  addr = TREE_OPERAND (addr, 0);
  	}
! 
!       if (get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos))
  	{
! 	  known_alignment = true;
! 	  bitpos += ptr_bitpos & ~(align - 1);
! 	  align = MAX (ptr_align, align);
  	}
! 
        bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
      }
    else if (TREE_CODE (exp) == TARGET_MEM_REF)
      {
!       unsigned ptr_align;
!       unsigned HOST_WIDE_INT ptr_bitpos;
        tree addr = TMR_BASE (exp);
+ 
        if (TREE_CODE (addr) == BIT_AND_EXPR
  	  && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
  	{
+ 	  known_alignment = true;
  	  align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
  		   & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
  	  align *= BITS_PER_UNIT;
  	  addr = TREE_OPERAND (addr, 0);
  	}
! 
!       if (get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos))
  	{
! 	  known_alignment = true;
! 	  bitpos += ptr_bitpos & ~(align - 1);
! 	  align = MAX (ptr_align, align);
  	}
! 
        if (TMR_OFFSET (exp))
  	bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
!       if (!TMR_INDEX2 (exp) && TMR_INDEX (exp) && TMR_STEP (exp))
  	{
  	  unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp));
  	  align = MIN (align, (step & -step) * BITS_PER_UNIT);
+ 	  known_alignment = true;
  	}
      }
  
    /* If there is a non-constant offset part extract the maximum
       alignment that can prevail.  */
*************** get_object_alignment_1 (tree exp, unsign
*** 418,436 ****
  	}
        else
  	{
! 	  inner = MIN (inner, BITS_PER_UNIT);
  	  break;
  	}
        offset = next_offset;
      }
  
!   /* Alignment is innermost object alignment adjusted by the constant
!      and non-constant offset parts.  */
!   align = MIN (align, inner);
!   bitpos = bitpos & (align - 1);
! 
    *bitposp = bitpos;
!   return align;
  }
  
  /* Return the alignment in bits of EXP, an object.  */
--- 430,456 ----
  	}
        else
  	{
! 	  known_alignment = false;
  	  break;
  	}
        offset = next_offset;
      }
  
!   if (known_alignment)
!     {
!       /* Alignment is innermost object alignment adjusted by the constant
! 	 and non-constant offset parts.  */
!       align = MIN (align, inner);
!       bitpos = bitpos & (align - 1);
!       *alignp = align;
!     }
!   else
!     {
!       bitpos = bitpos & (BITS_PER_UNIT - 1);
!       *alignp = BITS_PER_UNIT;
!     }
    *bitposp = bitpos;
!   return known_alignment;
  }
  
  /* Return the alignment in bits of EXP, an object.  */
*************** get_object_alignment (tree exp)
*** 441,454 ****
    unsigned HOST_WIDE_INT bitpos = 0;
    unsigned int align;
  
!   align = get_object_alignment_1 (exp, &bitpos);
  
    /* align and bitpos now specify known low bits of the pointer.
       ptr & (align - 1) == bitpos.  */
  
    if (bitpos != 0)
      align = (bitpos & -bitpos);
- 
    return align;
  }
  
--- 461,473 ----
    unsigned HOST_WIDE_INT bitpos = 0;
    unsigned int align;
  
!   get_object_alignment_1 (exp, &align, &bitpos);
  
    /* align and bitpos now specify known low bits of the pointer.
       ptr & (align - 1) == bitpos.  */
  
    if (bitpos != 0)
      align = (bitpos & -bitpos);
    return align;
  }
  
*************** unsigned int
*** 465,509 ****
  get_object_or_type_alignment (tree exp)
  {
    unsigned HOST_WIDE_INT misalign;
!   unsigned int align = get_object_alignment_1 (exp, &misalign);
  
    gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
! 
    if (misalign != 0)
      align = (misalign & -misalign);
!   else
!     align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
  
    return align;
  }
  
! /* For a pointer valued expression EXP compute values M and N such that
!    M divides (EXP - N) and such that N < M.  Store N in *BITPOSP and return M.
! 
!    If EXP is not a pointer, 0 is returned.  */
! 
! unsigned int
! get_pointer_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp)
  {
    STRIP_NOPS (exp);
  
    if (TREE_CODE (exp) == ADDR_EXPR)
!     return get_object_alignment_1 (TREE_OPERAND (exp, 0), bitposp);
    else if (TREE_CODE (exp) == SSA_NAME
  	   && POINTER_TYPE_P (TREE_TYPE (exp)))
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
!       if (!pi)
  	{
  	  *bitposp = 0;
! 	  return BITS_PER_UNIT;
  	}
-       *bitposp = pi->misalign * BITS_PER_UNIT;
-       return pi->align * BITS_PER_UNIT;
      }
  
    *bitposp = 0;
!   return POINTER_TYPE_P (TREE_TYPE (exp)) ? BITS_PER_UNIT : 0;
  }
  
  /* Return the alignment in bits of EXP, a pointer valued expression.
--- 484,540 ----
  get_object_or_type_alignment (tree exp)
  {
    unsigned HOST_WIDE_INT misalign;
!   unsigned int align;
!   bool known_alignment;
  
    gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
!   known_alignment = get_object_alignment_1 (exp, &align, &misalign);
    if (misalign != 0)
      align = (misalign & -misalign);
!   else if (!known_alignment)
!     align = TYPE_ALIGN (TREE_TYPE (exp));
  
    return align;
  }
  
! /* For a pointer valued expression EXP compute values M and N such that M
!    divides (EXP - N) and such that N < M.  If these numbers can be determined,
!    store M in alignp and N in *BITPOSP and return true.  Otherwise return false
!    and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp.
! 
!    If EXP is not a pointer, false is returned too.  */
! 
! bool
! get_pointer_alignment_1 (tree exp, unsigned int *alignp,
! 			 unsigned HOST_WIDE_INT *bitposp)
  {
    STRIP_NOPS (exp);
  
    if (TREE_CODE (exp) == ADDR_EXPR)
!     return get_object_alignment_1 (TREE_OPERAND (exp, 0), alignp, bitposp);
    else if (TREE_CODE (exp) == SSA_NAME
  	   && POINTER_TYPE_P (TREE_TYPE (exp)))
      {
+       unsigned int ptr_align, ptr_misalign;
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (exp);
! 
!       if (pi && get_ptr_info_alignment (pi, &ptr_align, &ptr_misalign))
! 	{
! 	  *bitposp = ptr_misalign * BITS_PER_UNIT;
! 	  *alignp = ptr_align * BITS_PER_UNIT;
! 	  return true;
! 	}
!       else
  	{
  	  *bitposp = 0;
! 	  *alignp = BITS_PER_UNIT;
! 	  return false;
  	}
      }
  
    *bitposp = 0;
!   *alignp = BITS_PER_UNIT;
!   return false;
  }
  
  /* Return the alignment in bits of EXP, a pointer valued expression.
*************** get_pointer_alignment (tree exp)
*** 518,525 ****
  {
    unsigned HOST_WIDE_INT bitpos = 0;
    unsigned int align;
!   
!   align = get_pointer_alignment_1 (exp, &bitpos);
  
    /* align and bitpos now specify known low bits of the pointer.
       ptr & (align - 1) == bitpos.  */
--- 549,556 ----
  {
    unsigned HOST_WIDE_INT bitpos = 0;
    unsigned int align;
! 
!   get_pointer_alignment_1 (exp, &align, &bitpos);
  
    /* align and bitpos now specify known low bits of the pointer.
       ptr & (align - 1) == bitpos.  */
Index: src/gcc/fold-const.c
===================================================================
*** src.orig/gcc/fold-const.c
--- src/gcc/fold-const.c
*************** get_pointer_modulus_and_residue (tree ex
*** 9532,9538 ****
    if (code == ADDR_EXPR)
      {
        unsigned int bitalign;
!       bitalign = get_object_alignment_1 (TREE_OPERAND (expr, 0), residue);
        *residue /= BITS_PER_UNIT;
        return bitalign / BITS_PER_UNIT;
      }
--- 9532,9538 ----
    if (code == ADDR_EXPR)
      {
        unsigned int bitalign;
!       get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitalign, residue);
        *residue /= BITS_PER_UNIT;
        return bitalign / BITS_PER_UNIT;
      }
Index: src/gcc/ipa-prop.c
===================================================================
*** src.orig/gcc/ipa-prop.c
--- src/gcc/ipa-prop.c
*************** ipa_modify_call_arguments (struct cgraph
*** 2513,2519 ****
  	      tree type = adj->type;
  	      unsigned int align;
  	      unsigned HOST_WIDE_INT misalign;
! 	      align = get_pointer_alignment_1 (base, &misalign);
  	      misalign += (double_int_sext (tree_to_double_int (off),
  					    TYPE_PRECISION (TREE_TYPE (off))).low
  			   * BITS_PER_UNIT);
--- 2513,2520 ----
  	      tree type = adj->type;
  	      unsigned int align;
  	      unsigned HOST_WIDE_INT misalign;
! 
! 	      get_pointer_alignment_1 (base, &align, &misalign);
  	      misalign += (double_int_sext (tree_to_double_int (off),
  					    TYPE_PRECISION (TREE_TYPE (off))).low
  			   * BITS_PER_UNIT);
Index: src/gcc/tree-sra.c
===================================================================
*** src.orig/gcc/tree-sra.c
--- src/gcc/tree-sra.c
*************** build_ref_for_offset (location_t loc, tr
*** 1472,1482 ****
       by looking at the access mode.  That would constrain the
       alignment of base + base_offset which we would need to
       adjust according to offset.  */
!   align = get_pointer_alignment_1 (base, &misalign);
!   if (misalign == 0
!       && (TREE_CODE (prev_base) == MEM_REF
! 	  || TREE_CODE (prev_base) == TARGET_MEM_REF))
!     align = MAX (align, TYPE_ALIGN (TREE_TYPE (prev_base)));
    misalign += (double_int_sext (tree_to_double_int (off),
  				TYPE_PRECISION (TREE_TYPE (off))).low
  	       * BITS_PER_UNIT);
--- 1472,1484 ----
       by looking at the access mode.  That would constrain the
       alignment of base + base_offset which we would need to
       adjust according to offset.  */
!   if (!get_pointer_alignment_1 (base, &align, &misalign))
!     {
!       gcc_assert (misalign == 0);
!       if (TREE_CODE (prev_base) == MEM_REF
! 	  || TREE_CODE (prev_base) == TARGET_MEM_REF)
! 	align = TYPE_ALIGN (TREE_TYPE (prev_base));
!     }
    misalign += (double_int_sext (tree_to_double_int (off),
  				TYPE_PRECISION (TREE_TYPE (off))).low
  	       * BITS_PER_UNIT);
Index: src/gcc/tree-ssa-ccp.c
===================================================================
*** src.orig/gcc/tree-ssa-ccp.c
--- src/gcc/tree-ssa-ccp.c
*************** get_value_from_alignment (tree expr)
*** 513,519 ****
  
    gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
  
!   align = get_object_alignment_1 (TREE_OPERAND (expr, 0), &bitpos);
    val.mask
      = double_int_and_not (POINTER_TYPE_P (type) || TYPE_UNSIGNED (type)
  			  ? double_int_mask (TYPE_PRECISION (type))
--- 513,519 ----
  
    gcc_assert (TREE_CODE (expr) == ADDR_EXPR);
  
!   get_object_alignment_1 (TREE_OPERAND (expr, 0), &align, &bitpos);
    val.mask
      = double_int_and_not (POINTER_TYPE_P (type) || TYPE_UNSIGNED (type)
  			  ? double_int_mask (TYPE_PRECISION (type))
*************** ccp_finalize (void)
*** 807,813 ****
      {
        tree name = ssa_name (i);
        prop_value_t *val;
-       struct ptr_info_def *pi;
        unsigned int tem, align;
  
        if (!name
--- 807,812 ----
*************** ccp_finalize (void)
*** 823,834 ****
  	 bits the misalignment.  */
        tem = val->mask.low;
        align = (tem & -tem);
!       if (align == 1)
! 	continue;
! 
!       pi = get_ptr_info (name);
!       pi->align = align;
!       pi->misalign = TREE_INT_CST_LOW (val->value) & (align - 1);
      }
  
    /* Perform substitutions based on the known constant values.  */
--- 822,830 ----
  	 bits the misalignment.  */
        tem = val->mask.low;
        align = (tem & -tem);
!       if (align > 1)
! 	set_ptr_info_alignment (get_ptr_info (name), align,
! 				TREE_INT_CST_LOW (val->value) & (align - 1));
      }
  
    /* Perform substitutions based on the known constant values.  */
Index: src/gcc/tree.h
===================================================================
*** src.orig/gcc/tree.h
--- src/gcc/tree.h
*************** extern tree build_string_literal (int, c
*** 5460,5469 ****
  extern bool validate_arglist (const_tree, ...);
  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  extern bool is_builtin_fn (tree);
! extern unsigned int get_object_alignment_1 (tree, unsigned HOST_WIDE_INT *);
  extern unsigned int get_object_alignment (tree);
  extern unsigned int get_object_or_type_alignment (tree);
! extern unsigned int get_pointer_alignment_1 (tree, unsigned HOST_WIDE_INT *);
  extern unsigned int get_pointer_alignment (tree);
  extern tree fold_call_stmt (gimple, bool);
  extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
--- 5460,5471 ----
  extern bool validate_arglist (const_tree, ...);
  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  extern bool is_builtin_fn (tree);
! extern bool get_object_alignment_1 (tree, unsigned int *,
! 				    unsigned HOST_WIDE_INT *);
  extern unsigned int get_object_alignment (tree);
  extern unsigned int get_object_or_type_alignment (tree);
! extern bool get_pointer_alignment_1 (tree, unsigned int *,
! 				     unsigned HOST_WIDE_INT *);
  extern unsigned int get_pointer_alignment (tree);
  extern tree fold_call_stmt (gimple, bool);
  extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
Index: src/gcc/gimple-pretty-print.c
===================================================================
*** src.orig/gcc/gimple-pretty-print.c
--- src/gcc/gimple-pretty-print.c
*************** dump_gimple_phi (pretty_printer *buffer,
*** 1590,1603 ****
        && POINTER_TYPE_P (TREE_TYPE (lhs))
        && SSA_NAME_PTR_INFO (lhs))
      {
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
        pp_string (buffer, "PT = ");
        pp_points_to_solution (buffer, &pi->pt);
        newline_and_indent (buffer, spc);
!       if (pi->align != 1)
  	{
! 	  pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u",
! 		     pi->align, pi->misalign);
  	  newline_and_indent (buffer, spc);
  	}
        pp_string (buffer, "# ");
--- 1590,1603 ----
        && POINTER_TYPE_P (TREE_TYPE (lhs))
        && SSA_NAME_PTR_INFO (lhs))
      {
+       unsigned int align, misalign;
        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
        pp_string (buffer, "PT = ");
        pp_points_to_solution (buffer, &pi->pt);
        newline_and_indent (buffer, spc);
!       if (get_ptr_info_alignment (pi, &align, &misalign))
  	{
! 	  pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u", align, misalign);
  	  newline_and_indent (buffer, spc);
  	}
        pp_string (buffer, "# ");
*************** dump_gimple_stmt (pretty_printer *buffer
*** 1889,1902 ****
  	  && POINTER_TYPE_P (TREE_TYPE (lhs))
  	  && SSA_NAME_PTR_INFO (lhs))
  	{
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
  	  pp_string (buffer, "# PT = ");
  	  pp_points_to_solution (buffer, &pi->pt);
  	  newline_and_indent (buffer, spc);
! 	  if (pi->align != 1)
  	    {
  	      pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u",
! 			 pi->align, pi->misalign);
  	      newline_and_indent (buffer, spc);
  	    }
  	}
--- 1889,1903 ----
  	  && POINTER_TYPE_P (TREE_TYPE (lhs))
  	  && SSA_NAME_PTR_INFO (lhs))
  	{
+ 	  unsigned int align, misalign;
  	  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
  	  pp_string (buffer, "# PT = ");
  	  pp_points_to_solution (buffer, &pi->pt);
  	  newline_and_indent (buffer, spc);
! 	  if (get_ptr_info_alignment (pi, &align, &misalign))
  	    {
  	      pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u",
! 			 align, misalign);
  	      newline_and_indent (buffer, spc);
  	    }
  	}
Index: src/gcc/tree-flow.h
===================================================================
*** src.orig/gcc/tree-flow.h
--- src/gcc/tree-flow.h
*************** struct GTY(()) ptr_info_def
*** 136,147 ****
       align and misalign specify low known bits of the pointer.
       ptr & (align - 1) == misalign.  */
  
!   /* The power-of-two byte alignment of the object this pointer
!      points into.  This is usually DECL_ALIGN_UNIT for decls and
!      MALLOC_ABI_ALIGNMENT for allocated storage.  */
    unsigned int align;
  
!   /* The byte offset this pointer differs from the above alignment.  */
    unsigned int misalign;
  };
  
--- 136,152 ----
       align and misalign specify low known bits of the pointer.
       ptr & (align - 1) == misalign.  */
  
!   /* When known, this is the power-of-two byte alignment of the object this
!      pointer points into.  This is usually DECL_ALIGN_UNIT for decls and
!      MALLOC_ABI_ALIGNMENT for allocated storage.  When the alignment is not
!      known, it is zero.  Do not access directly but use functions
!      get_ptr_info_alignment, set_ptr_info_alignment,
!      mark_ptr_info_alignment_unknown and similar.  */
    unsigned int align;
  
!   /* When alignment is known, the byte offset this pointer differs from the
!      above alignment.  Access only through the same helper functions as align
!      above.  */
    unsigned int misalign;
  };
  
*************** extern void duplicate_ssa_name_ptr_info
*** 593,598 ****
--- 598,610 ----
  extern void release_ssa_name (tree);
  extern void release_defs (gimple);
  extern void replace_ssa_name_symbol (tree, tree);
+ extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
+ 				    unsigned int *);
+ extern void mark_ptr_info_alignment_unknown (struct ptr_info_def *);
+ extern void set_ptr_info_alignment (struct ptr_info_def *, unsigned int,
+ 				    unsigned int);
+ extern void increment_ptr_info_misalignment (struct ptr_info_def *,
+ 					     unsigned int);
  
  #ifdef GATHER_STATISTICS
  extern void ssanames_print_statistics (void);
Index: src/gcc/tree-ssa-address.c
===================================================================
*** src.orig/gcc/tree-ssa-address.c
--- src/gcc/tree-ssa-address.c
*************** copy_ref_info (tree new_ref, tree old_re
*** 863,888 ****
  	       && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
  	{
  	  struct ptr_info_def *new_pi;
  	  duplicate_ssa_name_ptr_info
  	    (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
  	  new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
  	  /* We have to be careful about transfering alignment information.  */
! 	  if (TREE_CODE (old_ref) == MEM_REF
  	      && !(TREE_CODE (new_ref) == TARGET_MEM_REF
  		   && (TMR_INDEX2 (new_ref)
  		       || (TMR_STEP (new_ref)
  			   && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
! 			       < new_pi->align)))))
  	    {
! 	      new_pi->misalign += double_int_sub (mem_ref_offset (old_ref),
! 						  mem_ref_offset (new_ref)).low;
! 	      new_pi->misalign &= (new_pi->align - 1);
  	    }
  	  else
! 	    {
! 	      new_pi->align = 1;
! 	      new_pi->misalign = 0;
! 	    }
  	}
        else if (TREE_CODE (base) == VAR_DECL
  	       || TREE_CODE (base) == PARM_DECL
--- 863,888 ----
  	       && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
  	{
  	  struct ptr_info_def *new_pi;
+ 	  unsigned int align, misalign;
+ 
  	  duplicate_ssa_name_ptr_info
  	    (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
  	  new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
  	  /* We have to be careful about transfering alignment information.  */
! 	  if (get_ptr_info_alignment (new_pi, &align, &misalign)
! 	      && TREE_CODE (old_ref) == MEM_REF
  	      && !(TREE_CODE (new_ref) == TARGET_MEM_REF
  		   && (TMR_INDEX2 (new_ref)
  		       || (TMR_STEP (new_ref)
  			   && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
! 			       < align)))))
  	    {
! 	      unsigned int inc = double_int_sub (mem_ref_offset (old_ref),
! 						 mem_ref_offset (new_ref)).low;
! 	      increment_ptr_info_misalignment (new_pi, inc);
  	    }
  	  else
! 	    mark_ptr_info_alignment_unknown (new_pi);
  	}
        else if (TREE_CODE (base) == VAR_DECL
  	       || TREE_CODE (base) == PARM_DECL
Index: src/gcc/tree-ssa-loop-ivopts.c
===================================================================
*** src.orig/gcc/tree-ssa-loop-ivopts.c
--- src/gcc/tree-ssa-loop-ivopts.c
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 6258,6267 ****
  	  /* As this isn't a plain copy we have to reset alignment
  	     information.  */
  	  if (SSA_NAME_PTR_INFO (comp))
! 	    {
! 	      SSA_NAME_PTR_INFO (comp)->align = 1;
! 	      SSA_NAME_PTR_INFO (comp)->misalign = 0;
! 	    }
  	}
      }
  
--- 6258,6264 ----
  	  /* As this isn't a plain copy we have to reset alignment
  	     information.  */
  	  if (SSA_NAME_PTR_INFO (comp))
! 	    mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (comp));
  	}
      }
  
Index: src/gcc/tree-ssanames.c
===================================================================
*** src.orig/gcc/tree-ssanames.c
--- src/gcc/tree-ssanames.c
*************** release_ssa_name (tree var)
*** 238,243 ****
--- 238,296 ----
      }
  }
  
+ /* If the alignment of the pointer described by PI is known, return true and
+    store the alignment and the deviation from it into *ALIGNP and *MISALIGNP
+    respectively.  Otherwise return false.  */
+ 
+ bool
+ get_ptr_info_alignment (struct ptr_info_def *pi, unsigned int *alignp,
+ 			unsigned int *misalignp)
+ {
+   if (pi->align)
+     {
+       *alignp = pi->align;
+       *misalignp = pi->misalign;
+       return true;
+     }
+   else
+     return false;
+ }
+ 
+ /* State that the pointer described by PI has unknown alignment.  */
+ 
+ void
+ mark_ptr_info_alignment_unknown (struct ptr_info_def *pi)
+ {
+   pi->align = 0;
+   pi->misalign = 0;
+ }
+ 
+ /* Store the the power-of-two byte alignment and the deviation from that
+    alignment of pointer described by PI to ALIOGN and MISALIGN
+    respectively.  */
+ 
+ void
+ set_ptr_info_alignment (struct ptr_info_def *pi, unsigned int align,
+ 			    unsigned int misalign)
+ {
+   gcc_checking_assert (align != 0);
+   pi->align = align;
+   pi->misalign = misalign;
+ }
+ 
+ /* If pointer decribed by PI has known alignment, increase its known
+    misalignment by INCREMENT modulo its current alignment.  */
+ 
+ void
+ increment_ptr_info_misalignment (struct ptr_info_def *pi,
+ 				  unsigned int increment)
+ {
+   if (pi->align != 0)
+     {
+       pi->misalign += increment;
+       pi->misalign &= (pi->align - 1);
+     }
+ }
  
  /* Return the alias information associated with pointer T.  It creates a
     new instance if none existed.  */
*************** get_ptr_info (tree t)
*** 254,261 ****
      {
        pi = ggc_alloc_cleared_ptr_info_def ();
        pt_solution_reset (&pi->pt);
!       pi->align = 1;
!       pi->misalign = 0;
        SSA_NAME_PTR_INFO (t) = pi;
      }
  
--- 307,313 ----
      {
        pi = ggc_alloc_cleared_ptr_info_def ();
        pt_solution_reset (&pi->pt);
!       mark_ptr_info_alignment_unknown (pi);
        SSA_NAME_PTR_INFO (t) = pi;
      }
  
Index: src/gcc/tree-vect-data-refs.c
===================================================================
*** src.orig/gcc/tree-vect-data-refs.c
--- src/gcc/tree-vect-data-refs.c
*************** vect_create_addr_base_for_vector_ref (gi
*** 3342,3351 ****
      {
        duplicate_ssa_name_ptr_info (vec_stmt, DR_PTR_INFO (dr));
        if (offset)
! 	{
! 	  SSA_NAME_PTR_INFO (vec_stmt)->align = 1;
! 	  SSA_NAME_PTR_INFO (vec_stmt)->misalign = 0;
! 	}
      }
  
    if (vect_print_dump_info (REPORT_DETAILS))
--- 3342,3348 ----
      {
        duplicate_ssa_name_ptr_info (vec_stmt, DR_PTR_INFO (dr));
        if (offset)
! 	mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (vec_stmt));
      }
  
    if (vect_print_dump_info (REPORT_DETAILS))
*************** bump_vector_ptr (tree dataref_ptr, gimpl
*** 3744,3751 ****
    if (DR_PTR_INFO (dr))
      {
        duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
!       SSA_NAME_PTR_INFO (new_dataref_ptr)->align = 1;
!       SSA_NAME_PTR_INFO (new_dataref_ptr)->misalign = 0;
      }
  
    if (!ptr_incr)
--- 3741,3747 ----
    if (DR_PTR_INFO (dr))
      {
        duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
!       mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (new_dataref_ptr));
      }
  
    if (!ptr_incr)
Index: src/gcc/tree-vect-stmts.c
===================================================================
*** src.orig/gcc/tree-vect-stmts.c
--- src/gcc/tree-vect-stmts.c
*************** write_vector_array (gimple stmt, gimple_
*** 106,120 ****
  static tree
  create_array_ref (tree type, tree ptr, struct data_reference *first_dr)
  {
-   struct ptr_info_def *pi;
    tree mem_ref, alias_ptr_type;
  
    alias_ptr_type = reference_alias_ptr_type (DR_REF (first_dr));
    mem_ref = build2 (MEM_REF, type, ptr, build_int_cst (alias_ptr_type, 0));
    /* Arrays have the same alignment as their type.  */
!   pi = get_ptr_info (ptr);
!   pi->align = TYPE_ALIGN_UNIT (type);
!   pi->misalign = 0;
    return mem_ref;
  }
  
--- 106,117 ----
  static tree
  create_array_ref (tree type, tree ptr, struct data_reference *first_dr)
  {
    tree mem_ref, alias_ptr_type;
  
    alias_ptr_type = reference_alias_ptr_type (DR_REF (first_dr));
    mem_ref = build2 (MEM_REF, type, ptr, build_int_cst (alias_ptr_type, 0));
    /* Arrays have the same alignment as their type.  */
!   set_ptr_info_alignment (get_ptr_info (ptr), TYPE_ALIGN_UNIT (type), 0);
    return mem_ref;
  }
  
*************** vectorizable_store (gimple stmt, gimple_
*** 4029,4035 ****
  	  next_stmt = first_stmt;
  	  for (i = 0; i < vec_num; i++)
  	    {
! 	      struct ptr_info_def *pi;
  
  	      if (i > 0)
  		/* Bump the vector pointer.  */
--- 4026,4032 ----
  	  next_stmt = first_stmt;
  	  for (i = 0; i < vec_num; i++)
  	    {
! 	      unsigned align, misalign;
  
  	      if (i > 0)
  		/* Bump the vector pointer.  */
*************** vectorizable_store (gimple stmt, gimple_
*** 4046,4070 ****
  	      data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
  				 build_int_cst (reference_alias_ptr_type
  						(DR_REF (first_dr)), 0));
! 	      pi = get_ptr_info (dataref_ptr);
! 	      pi->align = TYPE_ALIGN_UNIT (vectype);
  	      if (aligned_access_p (first_dr))
! 		pi->misalign = 0;
  	      else if (DR_MISALIGNMENT (first_dr) == -1)
  		{
  		  TREE_TYPE (data_ref)
  		    = build_aligned_type (TREE_TYPE (data_ref),
  					  TYPE_ALIGN (elem_type));
! 		  pi->align = TYPE_ALIGN_UNIT (elem_type);
! 		  pi->misalign = 0;
  		}
  	      else
  		{
  		  TREE_TYPE (data_ref)
  		    = build_aligned_type (TREE_TYPE (data_ref),
  					  TYPE_ALIGN (elem_type));
! 		  pi->misalign = DR_MISALIGNMENT (first_dr);
  		}
  
  	      /* Arguments are ready.  Create the new vector stmt.  */
  	      new_stmt = gimple_build_assign (data_ref, vec_oprnd);
--- 4043,4068 ----
  	      data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
  				 build_int_cst (reference_alias_ptr_type
  						(DR_REF (first_dr)), 0));
! 	      align = TYPE_ALIGN_UNIT (vectype);
  	      if (aligned_access_p (first_dr))
! 		misalign = 0;
  	      else if (DR_MISALIGNMENT (first_dr) == -1)
  		{
  		  TREE_TYPE (data_ref)
  		    = build_aligned_type (TREE_TYPE (data_ref),
  					  TYPE_ALIGN (elem_type));
! 		  align = TYPE_ALIGN_UNIT (elem_type);
! 		  misalign = 0;
  		}
  	      else
  		{
  		  TREE_TYPE (data_ref)
  		    = build_aligned_type (TREE_TYPE (data_ref),
  					  TYPE_ALIGN (elem_type));
! 		  misalign = DR_MISALIGNMENT (first_dr);
  		}
+ 	      set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
+ 				      misalign);
  
  	      /* Arguments are ready.  Create the new vector stmt.  */
  	      new_stmt = gimple_build_assign (data_ref, vec_oprnd);
*************** vectorizable_load (gimple stmt, gimple_s
*** 4757,4789 ****
  		case dr_aligned:
  		case dr_unaligned_supported:
  		  {
! 		    struct ptr_info_def *pi;
  		    data_ref
  		      = build2 (MEM_REF, vectype, dataref_ptr,
  				build_int_cst (reference_alias_ptr_type
  					       (DR_REF (first_dr)), 0));
! 		    pi = get_ptr_info (dataref_ptr);
! 		    pi->align = TYPE_ALIGN_UNIT (vectype);
  		    if (alignment_support_scheme == dr_aligned)
  		      {
  			gcc_assert (aligned_access_p (first_dr));
! 			pi->misalign = 0;
  		      }
  		    else if (DR_MISALIGNMENT (first_dr) == -1)
  		      {
  			TREE_TYPE (data_ref)
  			  = build_aligned_type (TREE_TYPE (data_ref),
  						TYPE_ALIGN (elem_type));
! 			pi->align = TYPE_ALIGN_UNIT (elem_type);
! 			pi->misalign = 0;
  		      }
  		    else
  		      {
  			TREE_TYPE (data_ref)
  			  = build_aligned_type (TREE_TYPE (data_ref),
  						TYPE_ALIGN (elem_type));
! 			pi->misalign = DR_MISALIGNMENT (first_dr);
  		      }
  		    break;
  		  }
  		case dr_explicit_realign:
--- 4755,4789 ----
  		case dr_aligned:
  		case dr_unaligned_supported:
  		  {
! 		    unsigned int align, misalign;
! 
  		    data_ref
  		      = build2 (MEM_REF, vectype, dataref_ptr,
  				build_int_cst (reference_alias_ptr_type
  					       (DR_REF (first_dr)), 0));
! 		    align = TYPE_ALIGN_UNIT (vectype);
  		    if (alignment_support_scheme == dr_aligned)
  		      {
  			gcc_assert (aligned_access_p (first_dr));
! 			misalign = 0;
  		      }
  		    else if (DR_MISALIGNMENT (first_dr) == -1)
  		      {
  			TREE_TYPE (data_ref)
  			  = build_aligned_type (TREE_TYPE (data_ref),
  						TYPE_ALIGN (elem_type));
! 			align = TYPE_ALIGN_UNIT (elem_type);
! 			misalign = 0;
  		      }
  		    else
  		      {
  			TREE_TYPE (data_ref)
  			  = build_aligned_type (TREE_TYPE (data_ref),
  						TYPE_ALIGN (elem_type));
! 			misalign = DR_MISALIGNMENT (first_dr);
  		      }
+ 		    set_ptr_info_alignment (get_ptr_info (dataref_ptr),
+ 					    align, misalign);
  		    break;
  		  }
  		case dr_explicit_realign:


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