diff options
author | chrbr <chrbr@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-02-19 07:48:12 +0000 |
---|---|---|
committer | chrbr <chrbr@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-02-19 07:48:12 +0000 |
commit | 90bd1b58d324856ce720b850bb9ca15ff7a4b392 (patch) | |
tree | 95c5f542910b0d62fc039d0340cee3d8e1f9e5f7 /gcc/tree-ssa-loop-ivopts.c | |
parent | 906d19a32ba4382b03d1667dc0bdfb87aa6a1506 (diff) | |
download | gcc-90bd1b58d324856ce720b850bb9ca15ff7a4b392.tar.gz |
fix alignment bug in packed structs for STRICT_ALIGNMENT targets
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@132416 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-ivopts.c')
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 153 |
1 files changed, 81 insertions, 72 deletions
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 6ff690dfaa9..25f6b51ab3c 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1391,10 +1391,75 @@ idx_record_use (tree base, tree *idx, return true; } -/* Returns true if memory reference REF may be unaligned. */ +/* If we can prove that TOP = cst * BOT for some constant cst, + store cst to MUL and return true. Otherwise return false. + The returned value is always sign-extended, regardless of the + signedness of TOP and BOT. */ static bool -may_be_unaligned_p (tree ref) +constant_multiple_of (tree top, tree bot, double_int *mul) +{ + tree mby; + enum tree_code code; + double_int res, p0, p1; + unsigned precision = TYPE_PRECISION (TREE_TYPE (top)); + + STRIP_NOPS (top); + STRIP_NOPS (bot); + + if (operand_equal_p (top, bot, 0)) + { + *mul = double_int_one; + return true; + } + + code = TREE_CODE (top); + switch (code) + { + case MULT_EXPR: + mby = TREE_OPERAND (top, 1); + if (TREE_CODE (mby) != INTEGER_CST) + return false; + + if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res)) + return false; + + *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)), + precision); + return true; + + case PLUS_EXPR: + case MINUS_EXPR: + if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0) + || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1)) + return false; + + if (code == MINUS_EXPR) + p1 = double_int_neg (p1); + *mul = double_int_sext (double_int_add (p0, p1), precision); + return true; + + case INTEGER_CST: + if (TREE_CODE (bot) != INTEGER_CST) + return false; + + p0 = double_int_sext (tree_to_double_int (top), precision); + p1 = double_int_sext (tree_to_double_int (bot), precision); + if (double_int_zero_p (p1)) + return false; + *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res), + precision); + return double_int_zero_p (res); + + default: + return false; + } +} + +/* Returns true if memory reference REF with step STEP may be unaligned. */ + +static bool +may_be_unaligned_p (tree ref, tree step) { tree base; tree base_type; @@ -1418,11 +1483,20 @@ may_be_unaligned_p (tree ref) base_type = TREE_TYPE (base); base_align = TYPE_ALIGN (base_type); - if (mode != BLKmode - && (base_align < GET_MODE_ALIGNMENT (mode) + if (mode != BLKmode) + { + double_int mul; + tree al = build_int_cst (TREE_TYPE (step), + GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT); + + if (base_align < GET_MODE_ALIGNMENT (mode) || bitpos % GET_MODE_ALIGNMENT (mode) != 0 - || bitpos % BITS_PER_UNIT != 0)) - return true; + || bitpos % BITS_PER_UNIT != 0) + return true; + + if (! constant_multiple_of (step, al, &mul)) + return true; + } return false; } @@ -1549,7 +1623,7 @@ find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p) /* Moreover, on strict alignment platforms, check that it is sufficiently aligned. */ - if (STRICT_ALIGNMENT && may_be_unaligned_p (base)) + if (STRICT_ALIGNMENT && may_be_unaligned_p (base, step)) goto fail; base = build_fold_addr_expr (base); @@ -2585,71 +2659,6 @@ tree_int_cst_sign_bit (const_tree t) return (w >> bitno) & 1; } -/* If we can prove that TOP = cst * BOT for some constant cst, - store cst to MUL and return true. Otherwise return false. - The returned value is always sign-extended, regardless of the - signedness of TOP and BOT. */ - -static bool -constant_multiple_of (tree top, tree bot, double_int *mul) -{ - tree mby; - enum tree_code code; - double_int res, p0, p1; - unsigned precision = TYPE_PRECISION (TREE_TYPE (top)); - - STRIP_NOPS (top); - STRIP_NOPS (bot); - - if (operand_equal_p (top, bot, 0)) - { - *mul = double_int_one; - return true; - } - - code = TREE_CODE (top); - switch (code) - { - case MULT_EXPR: - mby = TREE_OPERAND (top, 1); - if (TREE_CODE (mby) != INTEGER_CST) - return false; - - if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res)) - return false; - - *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)), - precision); - return true; - - case PLUS_EXPR: - case MINUS_EXPR: - if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0) - || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1)) - return false; - - if (code == MINUS_EXPR) - p1 = double_int_neg (p1); - *mul = double_int_sext (double_int_add (p0, p1), precision); - return true; - - case INTEGER_CST: - if (TREE_CODE (bot) != INTEGER_CST) - return false; - - p0 = double_int_sext (tree_to_double_int (top), precision); - p1 = double_int_sext (tree_to_double_int (bot), precision); - if (double_int_zero_p (p1)) - return false; - *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res), - precision); - return double_int_zero_p (res); - - default: - return false; - } -} - /* If A is (TYPE) BA and B is (TYPE) BB, and the types of BA and BB have the same precision that is at least as wide as the precision of TYPE, stores BA to A and BB to B, and returns the type of BA. Otherwise, returns the |