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: