[backport from gcc-4.7.0 r183514 ] gcc/ 2012-01-25 Richard Guenther * tree.h (get_pointer_alignment_1): Declare. * builtins.c (get_pointer_alignment_1): New function. (get_pointer_alignment): Use it. --- gcc-4.6.3/gcc/builtins.c.~1~ 2012-06-22 13:20:03.000000000 +0200 +++ gcc-4.6.3/gcc/builtins.c 2012-06-22 13:45:51.000000000 +0200 @@ -442,38 +442,60 @@ can_trust_pointer_alignment (void) return (optimize && flag_tree_ter); } -/* Return the alignment in bits of EXP, a pointer valued expression. - But don't return more than MAX_ALIGN no matter what. - The alignment returned is, by default, the alignment of the thing that - EXP points to. If it is not a POINTER_TYPE, 0 is returned. +/* 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. - Otherwise, look at the expression to see if we can do better, i.e., if the - expression is actually pointing at an object whose alignment is tighter. */ + If EXP is not a pointer, 0 is returned. */ unsigned int -get_pointer_alignment (tree exp, unsigned int max_align) +get_pointer_alignment_1 (tree exp, unsigned HOST_WIDE_INT *bitposp) { STRIP_NOPS (exp); if (TREE_CODE (exp) == ADDR_EXPR) - return get_object_alignment (TREE_OPERAND (exp, 0), max_align); + 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); - unsigned align; if (!pi) - return BITS_PER_UNIT; - if (pi->misalign != 0) - align = (pi->misalign & -pi->misalign); - else - align = pi->align; - return MIN (max_align, align * BITS_PER_UNIT); + { + *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. + But don't return more than MAX_ALIGN no matter what. + The alignment returned is, by default, the alignment of the thing that + EXP points to. If it is not a POINTER_TYPE, 0 is returned. + + Otherwise, look at the expression to see if we can do better, i.e., if the + expression is actually pointing at an object whose alignment is tighter. */ + +unsigned int +get_pointer_alignment (tree exp, unsigned int max_align) +{ + 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. */ + + if (bitpos != 0) + align = (bitpos & -bitpos); + + return MIN (align, max_align); +} + /* Compute the length of a C string. TREE_STRING_LENGTH is not the right way, because it could contain a zero byte in the middle. TREE_STRING_LENGTH is the size of the character array, not the string. --- gcc-4.6.3/gcc/tree.h.~1~ 2012-06-22 13:20:03.000000000 +0200 +++ gcc-4.6.3/gcc/tree.h 2012-06-22 13:41:08.000000000 +0200 @@ -5165,6 +5165,7 @@ extern tree build_string_literal (int, c extern bool validate_arglist (const_tree, ...); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode); extern bool can_trust_pointer_alignment (void); +extern unsigned int get_pointer_alignment_1 (tree, unsigned HOST_WIDE_INT *); extern unsigned int get_pointer_alignment (tree, unsigned int); extern bool is_builtin_name (const char *); extern bool is_builtin_fn (tree);