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 <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. > (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 <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer