Hi,

On Mon, Apr 23, 2012 at 03:30:19PM +0200, Richard Guenther wrote:
> On Mon, 23 Apr 2012, Martin Jambor wrote:
> 
> > Hi,
> > 
> > On Mon, Apr 23, 2012 at 12:50:51PM +0200, Richard Guenther wrote:
> > > On Fri, 20 Apr 2012, Martin Jambor wrote:
> > > 
> > > > 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).
> > > > 

...

> > > 
> > > This looks all good apart from
> > > 
> > > + void
> > > + set_ptr_info_alignment (struct ptr_info_def *pi, unsigned int align,
> > > +                           unsigned int misalign)
> > > + {
> > > +   gcc_checking_assert (align != 0);
> > > 
> > > Why this assert?  If we assert sth then we should assert that
> > > misalign & ~(align - 1) == 0 and that align is a power-of-two or 0.
> > 
> > Because the patch makes zero value special, meaning "we do not know,"
> > and my intention was that this should be announced using
> > mark_ptr_info_alignment_unknown, mainly to prevent bugs when somebody
> > miscalculated the alignment.  Without the assert, the subsystem would
> > silently accept zero as its internal flag which would not ICE or
> > miscompile stuff, but perhaps unnecessarily pessimistic alignment
> > assumptions would be used.  Moreover, the smallest sensible alignment
> > is 1, the misalign component is also byte-based (after all, they
> > describe pointers) and zero alignment does not really have any
> > meaning, or does it?
> 
> Hmm, indeed (given the docs mention ptr & (align - 1)).
> 
> > I'll add a FIXME to the place where CCP previously attempted setting
> > alignment zero, but I won't have time to investigate that anytime
> > soon.
> 
> Well, CCP simply tracks known-bits and derives the alignment
> value from that.  If tem & -tem computes as zero that means
> val->mask.low is all zeros.  Thus the if (align == 1) check
> should have been if (align <= 1) from the start.  No fixme necessary
> I think.
> 
> > Asserting alignment is a power of two and that misalign
> > is not bigger than align are good ideas.
> > 
> > > 
> > > +   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)
> > > + {
> > > 
> > > Hmm, I'd call it adjust_ptr_info_misalignment instead.
> > > 
> > 
> > Fine with me.
> > 
> > > Ok with that changes.
> > > 
> > 
> > Unfortunately, the testsuite results from ppc64 look like there are
> > some problems.  Hopefully they are not too complex or I'll have to
> > postpone this for a few weeks as I have more pressing tasks to do now.

The testsuite differences I got on Friday were probably noise, tonight
(on an updated svn tree) I did not get any on ppc64-linux,
x86_64-linux or i686-linux.  Considering that and the OK above, I'm
going to bootstrap and test also on sparc64-linux and ia64-linux and
if those pass too, I'll commit the patch tomorrow, unless there are
any objections.

Of course, I have renamed increment_ptr_info_misalignment to
adjust_ptr_info_misalignment and changed the asserts at the beginning
of set_ptr_info_alignment to:

  gcc_checking_assert (align != 0);
  gcc_assert ((align & (align - 1)) == 0);
  gcc_assert ((misalign & ~(align - 1)) == 0);

Those were the only changes, the whole updated patch is below.

Thanks,

Martin

2012-04-23  Martin Jambor  <mjam...@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.
        (adjust_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.
        (adjust_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
*** 5464,5473 ****
  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);
--- 5464,5475 ----
  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 adjust_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;
!             adjust_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,299 ----
      }
  }
  
+ /* 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);
+   gcc_assert ((align & (align - 1)) == 0);
+   gcc_assert ((misalign & ~(align - 1)) == 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
+ adjust_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;
      }
  
--- 310,316 ----
      {
        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
*** 3397,3406 ****
      {
        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))
--- 3397,3403 ----
      {
        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
*** 3799,3806 ****
    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)
--- 3796,3802 ----
    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
*** 4860,4892 ****
                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:
--- 4858,4892 ----
                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:

Reply via email to