aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/builtins.c50
-rw-r--r--gcc/tree.h1
3 files changed, 43 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd5acdb..d252a5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2012-01-25 Richard Guenther <rguenther@suse.de>
+
+ * 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 <ramana.radhakrishnan@linaro.org>
PR rtl-optimization/48308
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 44b8551..d62b419 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -477,37 +477,59 @@ get_object_or_type_alignment (tree exp)
return align;
}
-/* 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.
+/* 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)
+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));
+ 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 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.
+ 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 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 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.
diff --git a/gcc/tree.h b/gcc/tree.h
index 5719b8f..140f23e 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);