From 98ab9e8ffc983b1dbb880dd31516474bd93d2969 Mon Sep 17 00:00:00 2001 From: rguenth Date: Tue, 10 Aug 2010 09:16:22 +0000 Subject: [PATCH] 2010-08-10 Richard Guenther * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163051 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 ++++ gcc/builtins.c | 184 ++++++++++++++++++++++++++++++++++------------------- gcc/emit-rtl.c | 6 +- gcc/tree-ssa-ccp.c | 3 +- gcc/tree.h | 2 +- 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 + * 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 + * 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 *); -- 2.7.4