diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd5acdbfa0e..d252a5ab351 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +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. + 2012-01-25 Ramana Radhakrishnan PR rtl-optimization/48308 diff --git a/gcc/builtins.c b/gcc/builtins.c index 44b8551b99d..d62b419075a 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -477,6 +477,35 @@ get_object_or_type_alignment (tree 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. 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. 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. @@ -487,25 +516,18 @@ get_object_or_type_alignment (tree exp) unsigned int get_pointer_alignment (tree exp) { - STRIP_NOPS (exp); + unsigned HOST_WIDE_INT bitpos = 0; + unsigned int align; + + align = get_pointer_alignment_1 (exp, &bitpos); - if (TREE_CODE (exp) == ADDR_EXPR) - return get_object_alignment (TREE_OPERAND (exp, 0)); - 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 align * BITS_PER_UNIT; - } + /* align and bitpos now specify known low bits of the pointer. + ptr & (align - 1) == bitpos. */ - return POINTER_TYPE_P (TREE_TYPE (exp)) ? BITS_PER_UNIT : 0; + if (bitpos != 0) + align = (bitpos & -bitpos); + + return align; } /* Compute the length of a C string. TREE_STRING_LENGTH is not the right diff --git a/gcc/tree.h b/gcc/tree.h index 5719b8f6bbf..140f23ed29e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5450,6 +5450,7 @@ 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);