From aac69a62a1b459379367979406430cf282e347af Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Mon, 10 Apr 2017 16:51:44 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr80153.c | 48 +++++++++++ gcc/tree-affine.c | 80 +++++++------------ gcc/tree-ssa-loop-ivopts.c | 22 +++-- 5 files changed, 107 insertions(+), 60 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr80153.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6d385b3579..3bd0951bb62 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2017-04-10 Richard Biener + Bin Cheng + + 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 * tree-ssa-structalias.c (find_func_aliases): Properly handle diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f71cb1a30aa..1c5d5baba7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-04-10 Bin Cheng + + PR tree-optimization/80153 + * gcc.c-torture/execute/pr80153.c: New. + 2017-04-10 Richard Biener PR middle-end/80362 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr80153.c b/gcc/testsuite/gcc.c-torture/execute/pr80153.c new file mode 100644 index 00000000000..3eed57828be --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr80153.c @@ -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; +} diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index 30fff67b005..13c477dc7d6 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index d5bd0362f25..036e0416176 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -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); -- 2.30.2