re PR tree-optimization/80153 (ivopt generate wrong code)
PR tree-optimization/80153 * tree-affine.c (aff_combination_to_tree): Get base pointer from the first element of pointer type aff_tree. Build result expr in aff_tree's type. (add_elt_to_tree): Convert to type unconditionally. Remove other fold_convert calls. * tree-ssa-loop-ivopts.c (alloc_iv): Pass in consistent types. (rewrite_use_nonlinear_expr): Check invariant using iv information. gcc/testsuite PR tree-optimization/80153 * gcc.c-torture/execute/pr80153.c: New. From-SVN: r246810
This commit is contained in:
parent
78a9876f98
commit
aac69a62a1
|
@ -1,3 +1,15 @@
|
|||
2017-04-10 Richard Biener <rguenther@suse.de>
|
||||
Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
PR tree-optimization/80153
|
||||
* tree-affine.c (aff_combination_to_tree): Get base pointer from
|
||||
the first element of pointer type aff_tree. Build result expr in
|
||||
aff_tree's type.
|
||||
(add_elt_to_tree): Convert to type unconditionally. Remove other
|
||||
fold_convert calls.
|
||||
* tree-ssa-loop-ivopts.c (alloc_iv): Pass in consistent types.
|
||||
(rewrite_use_nonlinear_expr): Check invariant using iv information.
|
||||
|
||||
2017-04-10 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* tree-ssa-structalias.c (find_func_aliases): Properly handle
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2017-04-10 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
PR tree-optimization/80153
|
||||
* gcc.c-torture/execute/pr80153.c: New.
|
||||
|
||||
2017-04-10 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/80362
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* PR tree-optimization/80153 */
|
||||
|
||||
void check (int, int, int) __attribute__((noinline));
|
||||
void check (int c, int c2, int val)
|
||||
{
|
||||
if (!val) {
|
||||
__builtin_abort();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *buf;
|
||||
static int l, i;
|
||||
|
||||
void _fputs(const char *str) __attribute__((noinline));
|
||||
void _fputs(const char *str)
|
||||
{
|
||||
buf = str;
|
||||
i = 0;
|
||||
l = __builtin_strlen(buf);
|
||||
}
|
||||
|
||||
char _fgetc() __attribute__((noinline));
|
||||
char _fgetc()
|
||||
{
|
||||
char val = buf[i];
|
||||
i++;
|
||||
if (i > l)
|
||||
return -1;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
static const char *string = "oops!\n";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
_fputs(string);
|
||||
|
||||
for (i = 0; i < __builtin_strlen(string); i++) {
|
||||
c = _fgetc();
|
||||
check(c, string[i], c == string[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -377,58 +377,28 @@ static tree
|
|||
add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
|
||||
{
|
||||
enum tree_code code;
|
||||
tree type1 = type;
|
||||
if (POINTER_TYPE_P (type))
|
||||
type1 = sizetype;
|
||||
|
||||
widest_int scale = wide_int_ext_for_comb (scale_in, type);
|
||||
|
||||
if (scale == -1
|
||||
&& POINTER_TYPE_P (TREE_TYPE (elt)))
|
||||
{
|
||||
elt = convert_to_ptrofftype (elt);
|
||||
elt = fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt);
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
elt = fold_convert (type, elt);
|
||||
if (scale == 1)
|
||||
{
|
||||
if (!expr)
|
||||
{
|
||||
if (POINTER_TYPE_P (TREE_TYPE (elt)))
|
||||
return elt;
|
||||
else
|
||||
return fold_convert (type1, elt);
|
||||
}
|
||||
return elt;
|
||||
|
||||
if (POINTER_TYPE_P (TREE_TYPE (expr)))
|
||||
return fold_build_pointer_plus (expr, elt);
|
||||
if (POINTER_TYPE_P (TREE_TYPE (elt)))
|
||||
return fold_build_pointer_plus (elt, expr);
|
||||
return fold_build2 (PLUS_EXPR, type1,
|
||||
expr, fold_convert (type1, elt));
|
||||
return fold_build2 (PLUS_EXPR, type, expr, elt);
|
||||
}
|
||||
|
||||
if (scale == -1)
|
||||
{
|
||||
if (!expr)
|
||||
return fold_build1 (NEGATE_EXPR, type1,
|
||||
fold_convert (type1, elt));
|
||||
return fold_build1 (NEGATE_EXPR, type, elt);
|
||||
|
||||
if (POINTER_TYPE_P (TREE_TYPE (expr)))
|
||||
{
|
||||
elt = convert_to_ptrofftype (elt);
|
||||
elt = fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt);
|
||||
return fold_build_pointer_plus (expr, elt);
|
||||
}
|
||||
return fold_build2 (MINUS_EXPR, type1,
|
||||
expr, fold_convert (type1, elt));
|
||||
return fold_build2 (MINUS_EXPR, type, expr, elt);
|
||||
}
|
||||
|
||||
elt = fold_convert (type1, elt);
|
||||
if (!expr)
|
||||
return fold_build2 (MULT_EXPR, type1, elt,
|
||||
wide_int_to_tree (type1, scale));
|
||||
return fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
|
||||
|
||||
if (wi::neg_p (scale))
|
||||
{
|
||||
|
@ -438,15 +408,8 @@ add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
|
|||
else
|
||||
code = PLUS_EXPR;
|
||||
|
||||
elt = fold_build2 (MULT_EXPR, type1, elt,
|
||||
wide_int_to_tree (type1, scale));
|
||||
if (POINTER_TYPE_P (TREE_TYPE (expr)))
|
||||
{
|
||||
if (code == MINUS_EXPR)
|
||||
elt = fold_build1 (NEGATE_EXPR, type1, elt);
|
||||
return fold_build_pointer_plus (expr, elt);
|
||||
}
|
||||
return fold_build2 (code, type1, expr, elt);
|
||||
elt = fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
|
||||
return fold_build2 (code, type, expr, elt);
|
||||
}
|
||||
|
||||
/* Makes tree from the affine combination COMB. */
|
||||
|
@ -454,17 +417,25 @@ add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
|
|||
tree
|
||||
aff_combination_to_tree (aff_tree *comb)
|
||||
{
|
||||
tree type = comb->type;
|
||||
tree expr = NULL_TREE;
|
||||
tree type = comb->type, base = NULL_TREE, expr = NULL_TREE;
|
||||
unsigned i;
|
||||
widest_int off, sgn;
|
||||
tree type1 = type;
|
||||
if (POINTER_TYPE_P (type))
|
||||
type1 = sizetype;
|
||||
|
||||
gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
|
||||
|
||||
for (i = 0; i < comb->n; i++)
|
||||
i = 0;
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
type = sizetype;
|
||||
if (comb->n > 0 && comb->elts[0].coef == 1
|
||||
&& POINTER_TYPE_P (TREE_TYPE (comb->elts[0].val)))
|
||||
{
|
||||
base = comb->elts[0].val;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < comb->n; i++)
|
||||
expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef);
|
||||
|
||||
if (comb->rest)
|
||||
|
@ -482,7 +453,12 @@ aff_combination_to_tree (aff_tree *comb)
|
|||
off = comb->offset;
|
||||
sgn = 1;
|
||||
}
|
||||
return add_elt_to_tree (expr, type, wide_int_to_tree (type1, off), sgn);
|
||||
expr = add_elt_to_tree (expr, type, wide_int_to_tree (type, off), sgn);
|
||||
|
||||
if (base)
|
||||
return fold_build_pointer_plus (base, expr);
|
||||
else
|
||||
return fold_convert (comb->type, expr);
|
||||
}
|
||||
|
||||
/* Copies the tree elements of COMB to ensure that they are not shared. */
|
||||
|
|
|
@ -1171,7 +1171,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
|
|||
|| contain_complex_addr_expr (expr))
|
||||
{
|
||||
aff_tree comb;
|
||||
tree_to_aff_combination (expr, TREE_TYPE (base), &comb);
|
||||
tree_to_aff_combination (expr, TREE_TYPE (expr), &comb);
|
||||
base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
|
||||
}
|
||||
|
||||
|
@ -7183,7 +7183,7 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
|
|||
struct iv_use *use, struct iv_cand *cand)
|
||||
{
|
||||
tree comp;
|
||||
tree op, tgt;
|
||||
tree tgt;
|
||||
gassign *ass;
|
||||
gimple_stmt_iterator bsi;
|
||||
|
||||
|
@ -7194,6 +7194,7 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
|
|||
if (cand->pos == IP_ORIGINAL
|
||||
&& cand->incremented_at == use->stmt)
|
||||
{
|
||||
tree op = NULL_TREE;
|
||||
enum tree_code stmt_code;
|
||||
|
||||
gcc_assert (is_gimple_assign (use->stmt));
|
||||
|
@ -7213,14 +7214,19 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
|
|||
op = gimple_assign_rhs2 (use->stmt);
|
||||
else if (gimple_assign_rhs2 (use->stmt) == cand->var_before)
|
||||
op = gimple_assign_rhs1 (use->stmt);
|
||||
else
|
||||
op = NULL_TREE;
|
||||
}
|
||||
else
|
||||
op = NULL_TREE;
|
||||
|
||||
if (op && expr_invariant_in_loop_p (data->current_loop, op))
|
||||
return;
|
||||
if (op != NULL_TREE)
|
||||
{
|
||||
if (expr_invariant_in_loop_p (data->current_loop, op))
|
||||
return;
|
||||
if (TREE_CODE (op) == SSA_NAME)
|
||||
{
|
||||
struct iv *iv = get_iv (data, op);
|
||||
if (iv != NULL && integer_zerop (iv->step))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comp = get_computation (data->current_loop, use, cand);
|
||||
|
|
Loading…
Reference in New Issue