aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-10-09 10:17:08 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2008-10-09 10:17:08 +0200
commitdf96b059470a8ede40342b4b19c6da1a82851aaf (patch)
tree4b26de45565f6554ef5ed3f5f27def80b657ef53
parentcc2a64dd80513c1155fad3370bc639daa97b7404 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/builtins.c130
-rw-r--r--gcc/emit-rtl.c11
-rw-r--r--gcc/tree.h1
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
diff --git a/gcc/tree.h b/gcc/tree.h
index 44bc3f0..034be6a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);