This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Support for known unknown alignment
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 <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.
(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: