fix alignment bug in packed structs for STRICT_ALIGNMENT targets

Co-Authored-By: Zdenek Dvorak <ook@ucw.cz>

From-SVN: r132416
This commit is contained in:
Christian Bruel 2008-02-19 08:48:12 +01:00 committed by Christian Bruel
parent d9484c5ba9
commit 32159434b6
2 changed files with 86 additions and 72 deletions

View File

@ -1,3 +1,8 @@
2008-02-19 Christian Bruel <christian.bruel@st.com>
Zdenek Dvorak <ook@ucw.cz>
* tree-ssa-loop-ivopts.c (may_be_unaligned_p): Check step alignment.
2008-02-19 Uros Bizjak <ubizjak@gmail.com>
PR target/33555

View File

@ -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