diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-10-09 10:17:08 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-10-09 10:17:08 +0200 |
commit | df96b059470a8ede40342b4b19c6da1a82851aaf (patch) | |
tree | 4b26de45565f6554ef5ed3f5f27def80b657ef53 | |
parent | cc2a64dd80513c1155fad3370bc639daa97b7404 (diff) | |
download | gcc-df96b059470a8ede40342b4b19c6da1a82851aaf.zip gcc-df96b059470a8ede40342b4b19c6da1a82851aaf.tar.gz gcc-df96b059470a8ede40342b4b19c6da1a82851aaf.tar.bz2 |
re PR middle-end/37774 (Alignment information is lost for ARRAY_REFs)
PR middle-end/37774
* tree.h (get_object_alignment): Declare.
* emit-rtl.c (set_mem_attributes_minus_bitpos): Call
get_object_alignment if needed.
* builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling
to ...
(get_object_alignment): ... here. New function. Try harder to
determine alignment from get_inner_reference returned offset.
From-SVN: r141003
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/builtins.c | 130 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 11 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
4 files changed, 98 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c6053c4..8e9648a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -7,6 +7,15 @@ * tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Only set goto_block on edges if goto_locus is known. + PR middle-end/37774 + * tree.h (get_object_alignment): Declare. + * emit-rtl.c (set_mem_attributes_minus_bitpos): Call + get_object_alignment if needed. + * builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling + to ... + (get_object_alignment): ... here. New function. Try harder to + determine alignment from get_inner_reference returned offset. + 2008-10-08 Jakub Jelinek <jakub@redhat.com> * graphite.c (gloog): Don't call find_unreachable_blocks diff --git a/gcc/builtins.c b/gcc/builtins.c index ea1a16d..5ed60bb 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -253,6 +253,82 @@ static bool called_as_built_in (tree node) return false; } +/* Return the alignment in bits of EXP, an object. + Don't return more than MAX_ALIGN no matter what, ALIGN is the inital + guessed alignment e.g. from type alignment. */ + +int +get_object_alignment (tree exp, unsigned int align, unsigned int max_align) +{ + unsigned int inner; + + inner = max_align; + if (handled_component_p (exp)) + { + HOST_WIDE_INT bitsize, bitpos; + tree offset; + enum machine_mode mode; + int unsignedp, volatilep; + + exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, true); + if (bitpos) + inner = MIN (inner, (unsigned) (bitpos & -bitpos)); + while (offset) + { + tree next_offset; + + if (TREE_CODE (offset) == PLUS_EXPR) + { + next_offset = TREE_OPERAND (offset, 0); + offset = TREE_OPERAND (offset, 1); + } + else + next_offset = NULL; + if (host_integerp (offset, 1)) + { + /* Any overflow in calculating offset_bits won't change + the alignment. */ + unsigned offset_bits + = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT); + + if (offset_bits) + inner = MIN (inner, (offset_bits & -offset_bits)); + } + else if (TREE_CODE (offset) == MULT_EXPR + && host_integerp (TREE_OPERAND (offset, 1), 1)) + { + /* Any overflow in calculating offset_factor won't change + the alignment. */ + unsigned offset_factor + = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) + * BITS_PER_UNIT); + + if (offset_factor) + inner = MIN (inner, (offset_factor & -offset_factor)); + } + else + { + inner = MIN (inner, BITS_PER_UNIT); + break; + } + offset = next_offset; + } + } + if (DECL_P (exp)) + align = MIN (inner, DECL_ALIGN (exp)); +#ifdef CONSTANT_ALIGNMENT + else if (CONSTANT_CLASS_P (exp)) + align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align)); +#endif + else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR + || TREE_CODE (exp) == INDIRECT_REF) + align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner); + else + align = MIN (align, inner); + return MIN (align, max_align); +} + /* 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 @@ -306,59 +382,7 @@ get_pointer_alignment (tree exp, unsigned int max_align) case ADDR_EXPR: /* See what we are pointing at and look at its alignment. */ - exp = TREE_OPERAND (exp, 0); - inner = max_align; - if (handled_component_p (exp)) - { - HOST_WIDE_INT bitsize, bitpos; - tree offset; - enum machine_mode mode; - int unsignedp, volatilep; - - exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, true); - if (bitpos) - inner = MIN (inner, (unsigned) (bitpos & -bitpos)); - if (offset && TREE_CODE (offset) == PLUS_EXPR - && host_integerp (TREE_OPERAND (offset, 1), 1)) - { - /* Any overflow in calculating offset_bits won't change - the alignment. */ - unsigned offset_bits - = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) - * BITS_PER_UNIT); - - if (offset_bits) - inner = MIN (inner, (offset_bits & -offset_bits)); - offset = TREE_OPERAND (offset, 0); - } - if (offset && TREE_CODE (offset) == MULT_EXPR - && host_integerp (TREE_OPERAND (offset, 1), 1)) - { - /* Any overflow in calculating offset_factor won't change - the alignment. */ - unsigned offset_factor - = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1) - * BITS_PER_UNIT); - - if (offset_factor) - inner = MIN (inner, (offset_factor & -offset_factor)); - } - else if (offset) - inner = MIN (inner, BITS_PER_UNIT); - } - if (DECL_P (exp)) - align = MIN (inner, DECL_ALIGN (exp)); -#ifdef CONSTANT_ALIGNMENT - else if (CONSTANT_CLASS_P (exp)) - align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align)); -#endif - else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR - || TREE_CODE (exp) == INDIRECT_REF) - align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner); - else - align = MIN (align, inner); - return MIN (align, max_align); + return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align); default: return align; diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 318ae77..4564a0b 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1564,6 +1564,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, if (! TYPE_P (t)) { tree base; + bool align_computed = false; if (TREE_THIS_VOLATILE (t)) MEM_VOLATILE_P (ref) = 1; @@ -1620,6 +1621,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, && host_integerp (DECL_SIZE_UNIT (t), 1) ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0); align = DECL_ALIGN (t); + align_computed = true; } /* If this is a constant, we know the alignment. */ @@ -1629,6 +1631,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, #ifdef CONSTANT_ALIGNMENT align = CONSTANT_ALIGNMENT (t, align); #endif + align_computed = true; } /* If this is a field reference and not a bit-field, record it. */ @@ -1688,6 +1691,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, align = DECL_ALIGN (t2); if (aoff && (unsigned HOST_WIDE_INT) aoff < align) align = aoff; + align_computed = true; offset = GEN_INT (ioff); apply_bitpos = bitpos; } @@ -1721,6 +1725,13 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, expr = t; offset = NULL; } + + if (!align_computed && !INDIRECT_REF_P (t)) + { + unsigned int obj_align + = get_object_alignment (t, align, BIGGEST_ALIGNMENT); + align = MAX (align, obj_align); + } } /* If we modified OFFSET based on T, then subtract the outstanding @@ -4864,6 +4864,7 @@ extern tree build_string_literal (int, const char *); extern bool validate_arglist (const_tree, ...); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode); extern int get_pointer_alignment (tree, unsigned int); +extern int get_object_alignment (tree, unsigned int, unsigned int); extern tree fold_call_stmt (gimple, bool); extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function); |