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
- From: Richard Guenther <rguenther at suse dot de>
- To: Martin Jambor <mjambor at suse dot cz>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 23 Apr 2012 12:50:51 +0200 (CEST)
- Subject: Re: [PATCH] Support for known unknown alignment
- References: <20120420155409.GC24038@virgil.arch.suse.de>
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).
>
> 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.
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.
+ 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.
Ok with that changes.
Thanks,
Richard.
+ if (pi->align != 0)
+ {
+ pi->misalign += increment;
+ pi->misalign &= (pi->align - 1);
+ }
+ }
> 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:
>
>
--
Richard Guenther <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer