aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/builtins.c184
-rw-r--r--gcc/emit-rtl.c6
-rw-r--r--gcc/tree-ssa-ccp.c3
-rw-r--r--gcc/tree.h2
5 files changed, 135 insertions, 71 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5b066a6..49a95d0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
2010-08-10 Richard Guenther <rguenther@suse.de>
+ * tree.h (get_object_alignment): Adjust prototype.
+ * builtins.c (get_object_alignment): Return unsigned int,
+ drop the align parameter. Handle MEM_REF, MISALIGNED_INDIRECT_REF
+ and TARGET_MEM_REF properly.
+ (get_pointer_alignment): Adjust.
+ * emit-rtl.c (get_mem_align_offset): Adjust comment.
+ (set_mem_attributes_minus_bitpos): Adjust.
+ * tree-ssa-ccp.c (get_value_from_alignment): Adjust.
+
+2010-08-10 Richard Guenther <rguenther@suse.de>
+
* tree-ssa-copy.c (set_copy_of_val): Use operand_equal_p.
(copy_prop_visit_assignment): Simplify.
(copy_prop_visit_stmt): Also visit assignments from
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3b9ca5a..3d5ca33 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -267,81 +267,135 @@ called_as_built_in (tree node)
}
/* 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. */
+ Don't return more than MAX_ALIGN no matter what. */
-int
-get_object_alignment (tree exp, unsigned int align, unsigned int max_align)
+unsigned int
+get_object_alignment (tree exp, 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;
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset;
+ enum machine_mode mode;
+ int unsignedp, volatilep;
+ unsigned int align, inner;
- 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;
+ /* Get the innermost object and the constant (bitpos) and possibly
+ variable (offset) offset of the access. */
+ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+ &mode, &unsignedp, &volatilep, true);
- 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;
- }
- }
+ /* Extract alignment information from the innermost object and
+ possibly adjust bitpos and offset. */
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
if (DECL_P (exp)
&& TREE_CODE (exp) != LABEL_DECL)
- align = MIN (inner, DECL_ALIGN (exp));
-#ifdef CONSTANT_ALIGNMENT
+ align = DECL_ALIGN (exp);
else if (CONSTANT_CLASS_P (exp))
- align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
+ {
+ align = TYPE_ALIGN (TREE_TYPE (exp));
+#ifdef CONSTANT_ALIGNMENT
+ align = (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 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) == MISALIGNED_INDIRECT_REF)
+ {
+ tree op1 = TREE_OPERAND (exp, 1);
+ align = integer_zerop (op1) ? BITS_PER_UNIT : TREE_INT_CST_LOW (op1);
+ }
+ else if (TREE_CODE (exp) == MEM_REF)
+ {
+ tree addr = TREE_OPERAND (exp, 0);
+ 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) == ADDR_EXPR)
+ align = MAX (align, get_object_alignment (TREE_OPERAND (addr, 0),
+ max_align));
+ bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
+ }
+ else if (TREE_CODE (exp) == TARGET_MEM_REF
+ && TMR_SYMBOL (exp))
+ {
+ align = get_object_alignment (TMR_SYMBOL (exp), max_align);
+ 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;
+ }
else
- align = MIN (align, inner);
+ align = BITS_PER_UNIT;
+
+ /* If there is a non-constant offset part extract the maximum
+ alignment that can prevail. */
+ inner = max_align;
+ 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;
+ }
+
+ /* Alignment is innermost object alignment adjusted by the constant
+ and non-constant offset parts. */
+ align = MIN (align, inner);
+ bitpos = bitpos & (align - 1);
+
+ /* 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);
}
@@ -407,7 +461,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
case ADDR_EXPR:
/* See what we are pointing at and look at its alignment. */
- return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align);
+ return get_object_alignment (TREE_OPERAND (exp, 0), max_align);
default:
return align;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 91c5d857..267d634 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1459,7 +1459,8 @@ get_mem_align_offset (rtx mem, unsigned int align)
/* This function can't use
if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
|| !CONST_INT_P (MEM_OFFSET (mem))
- || (get_object_alignment (MEM_EXPR (mem), MEM_ALIGN (mem), align)
+ || (MAX (MEM_ALIGN (mem),
+ get_object_alignment (MEM_EXPR (mem), align))
< align))
return -1;
else
@@ -1796,8 +1797,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
if (!align_computed && !INDIRECT_REF_P (t))
{
- unsigned int obj_align
- = get_object_alignment (t, align, BIGGEST_ALIGNMENT);
+ unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT);
align = MAX (align, obj_align);
}
}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a016584..622fe14 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -515,8 +515,7 @@ get_value_from_alignment (tree expr)
val = bit_value_binop (PLUS_EXPR, TREE_TYPE (expr),
TREE_OPERAND (base, 0), TREE_OPERAND (base, 1));
else if (base
- && ((align = get_object_alignment (base, BITS_PER_UNIT,
- BIGGEST_ALIGNMENT))
+ && ((align = get_object_alignment (base, BIGGEST_ALIGNMENT))
> BITS_PER_UNIT))
{
val.lattice_val = CONSTANT;
diff --git a/gcc/tree.h b/gcc/tree.h
index 271b1fb..bdf4f72 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5036,7 +5036,7 @@ extern bool can_trust_pointer_alignment (void);
extern int get_pointer_alignment (tree, unsigned int);
extern bool is_builtin_name (const char *);
extern bool is_builtin_fn (tree);
-extern int get_object_alignment (tree, unsigned int, unsigned int);
+extern unsigned int get_object_alignment (tree, unsigned int);
extern tree fold_call_stmt (gimple, bool);
extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
extern tree make_range (tree, int *, tree *, tree *, bool *);