diff options
author | Richard Biener <rguenther@suse.de> | 2012-12-18 13:12:34 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2012-12-18 13:12:34 +0000 |
commit | 8b679c9b242fe694269439e3e8be166a5e2d7dc9 (patch) | |
tree | 4097eac3f8bd34e5c316b801522cc85d298958a3 /gcc | |
parent | 898be2f38dd5832034f726feab95661f589ec007 (diff) | |
download | gcc-8b679c9b242fe694269439e3e8be166a5e2d7dc9.zip gcc-8b679c9b242fe694269439e3e8be166a5e2d7dc9.tar.gz gcc-8b679c9b242fe694269439e3e8be166a5e2d7dc9.tar.bz2 |
re PR middle-end/55555 (miscompilation at -O2 (number_of_iterations))
2012-12-18 Richard Biener <rguenther@suse.de>
PR tree-optimization/55555
* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
analyze evolution of the index for the loop it is used in.
* tree-scalar-evolution.c (instantiate_scev_name): Take
inner loop we will be creating a chrec for. Generalize
fix for PR40281 and prune invalid SCEVs.
(instantiate_scev_poly): Likewise - pass down inner loop
we will be creating a chrec for.
(instantiate_scev_binary): Take and pass through inner loop.
(instantiate_array_ref): Likewise.
(instantiate_scev_convert): Likewise.
(instantiate_scev_not): Likewise.
(instantiate_scev_3): Likewise.
(instantiate_scev_2): Likewise.
(instantiate_scev_1): Likewise.
(instantiate_scev_r): Likewise.
(resolve_mixers): Adjust.
(instantiate_scev): Likewise.
* gcc.dg/torture/pr55555.c: New testcase.
* gcc.dg/vect/vect-iv-11.c: Adjust.
From-SVN: r194578
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr55555.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-iv-11.c | 3 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.c | 124 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 7 |
6 files changed, 142 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 104fc9e..b032c96 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2012-12-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/55555 + * tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly + analyze evolution of the index for the loop it is used in. + * tree-scalar-evolution.c (instantiate_scev_name): Take + inner loop we will be creating a chrec for. Generalize + fix for PR40281 and prune invalid SCEVs. + (instantiate_scev_poly): Likewise - pass down inner loop + we will be creating a chrec for. + (instantiate_scev_binary): Take and pass through inner loop. + (instantiate_array_ref): Likewise. + (instantiate_scev_convert): Likewise. + (instantiate_scev_not): Likewise. + (instantiate_scev_3): Likewise. + (instantiate_scev_2): Likewise. + (instantiate_scev_1): Likewise. + (instantiate_scev_r): Likewise. + (resolve_mixers): Adjust. + (instantiate_scev): Likewise. + 2012-12-18 Jakub Jelinek <jakub@redhat.com> PR debug/55717 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2360147..551236c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-12-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/55555 + * gcc.dg/torture/pr55555.c: New testcase. + * gcc.dg/vect/vect-iv-11.c: Adjust. + 2012-12-18 Jakub Jelinek <jakub@redhat.com> PR debug/55717 diff --git a/gcc/testsuite/gcc.dg/torture/pr55555.c b/gcc/testsuite/gcc.dg/torture/pr55555.c new file mode 100644 index 0000000..9e42266 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr55555.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ + +double s[4] = { 1.0, 2.0, 3.0, 4.0 }, pol_x[2] = { 5.0, 6.0 }; + +__attribute__((noinline)) int +foo (void) +{ + double coef_x[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int lxp = 0; + if (lxp <= 1) + do + { + double t = pol_x[lxp]; + long S; + long l = lxp * 4L - 1; + for (S = 1; S <= 4; S++) + coef_x[S + l] = coef_x[S + l] + s[S - 1] * t; + } + while (lxp++ != 1); + asm volatile ("" : : "r" (coef_x) : "memory"); + for (lxp = 0; lxp < 8; lxp++) + if (coef_x[lxp] != ((lxp & 3) + 1) * (5.0 + (lxp >= 4))) + __builtin_abort (); + return 1; +} + +int +main () +{ + asm volatile ("" : : : "memory"); + if (!foo ()) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-iv-11.c b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c index ef1c577..632b97c 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-iv-11.c +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c @@ -3,7 +3,8 @@ #include <stdarg.h> #include "tree-vect.h" -int main1 (int len) +int __attribute__((noinline,noclone)) +main1 (int len) { int s = 0; int i = len; diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index d191542..9fc2f79 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -2147,8 +2147,8 @@ loop_closed_phi_def (tree var) return NULL_TREE; } -static tree instantiate_scev_r (basic_block, struct loop *, tree, bool, - htab_t, int); +static tree instantiate_scev_r (basic_block, struct loop *, struct loop *, + tree, bool, htab_t, int); /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form. @@ -2166,7 +2166,8 @@ static tree instantiate_scev_r (basic_block, struct loop *, tree, bool, static tree instantiate_scev_name (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree res; @@ -2225,7 +2226,8 @@ instantiate_scev_name (basic_block instantiate_below, loop_p loop = loop_containing_stmt (SSA_NAME_DEF_STMT (chrec)); res = analyze_scalar_evolution (loop, chrec); res = compute_overall_effect_of_inner_loop (loop, res); - res = instantiate_scev_r (instantiate_below, evolution_loop, res, + res = instantiate_scev_r (instantiate_below, evolution_loop, + inner_loop, res, fold_conversions, cache, size_expr); } else if (!dominated_by_p (CDI_DOMINATORS, instantiate_below, @@ -2234,8 +2236,16 @@ instantiate_scev_name (basic_block instantiate_below, } else if (res != chrec_dont_know) - res = instantiate_scev_r (instantiate_below, evolution_loop, res, - fold_conversions, cache, size_expr); + { + if (inner_loop + && !flow_loop_nested_p (def_bb->loop_father, inner_loop)) + /* ??? We could try to compute the overall effect of the loop here. */ + res = chrec_dont_know; + else + res = instantiate_scev_r (instantiate_below, evolution_loop, + inner_loop, res, + fold_conversions, cache, size_expr); + } /* Store the correct value to the cache. */ set_instantiated_value (cache, instantiate_below, chrec, res); @@ -2258,17 +2268,20 @@ instantiate_scev_name (basic_block instantiate_below, static tree instantiate_scev_poly (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree op1; tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, + get_chrec_loop (chrec), CHREC_LEFT (chrec), fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) return chrec_dont_know; op1 = instantiate_scev_r (instantiate_below, evolution_loop, + get_chrec_loop (chrec), CHREC_RIGHT (chrec), fold_conversions, cache, size_expr); if (op1 == chrec_dont_know) @@ -2277,19 +2290,8 @@ instantiate_scev_poly (basic_block instantiate_below, if (CHREC_LEFT (chrec) != op0 || CHREC_RIGHT (chrec) != op1) { - unsigned var = CHREC_VARIABLE (chrec); - - /* When the instantiated stride or base has an evolution in an - innermost loop, return chrec_dont_know, as this is not a - valid SCEV representation. In the reduced testcase for - PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no - meaning. */ - if ((tree_is_chrec (op0) && CHREC_VARIABLE (op0) > var) - || (tree_is_chrec (op1) && CHREC_VARIABLE (op1) > var)) - return chrec_dont_know; - op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL); - chrec = build_polynomial_chrec (var, op0, op1); + chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1); } return chrec; @@ -2311,18 +2313,19 @@ instantiate_scev_poly (basic_block instantiate_below, static tree instantiate_scev_binary (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, enum tree_code code, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, enum tree_code code, tree type, tree c0, tree c1, bool fold_conversions, htab_t cache, int size_expr) { tree op1; - tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, + tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop, c0, fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) return chrec_dont_know; - op1 = instantiate_scev_r (instantiate_below, evolution_loop, + op1 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop, c1, fold_conversions, cache, size_expr); if (op1 == chrec_dont_know) @@ -2370,12 +2373,14 @@ instantiate_scev_binary (basic_block instantiate_below, static tree instantiate_array_ref (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree res; tree index = TREE_OPERAND (chrec, 1); - tree op1 = instantiate_scev_r (instantiate_below, evolution_loop, index, + tree op1 = instantiate_scev_r (instantiate_below, evolution_loop, + inner_loop, index, fold_conversions, cache, size_expr); if (op1 == chrec_dont_know) @@ -2406,11 +2411,13 @@ instantiate_array_ref (basic_block instantiate_below, static tree instantiate_scev_convert (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, tree type, tree op, bool fold_conversions, htab_t cache, int size_expr) { - tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op, + tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, + inner_loop, op, fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) @@ -2453,11 +2460,13 @@ instantiate_scev_convert (basic_block instantiate_below, static tree instantiate_scev_not (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, enum tree_code code, tree type, tree op, bool fold_conversions, htab_t cache, int size_expr) { - tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op, + tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, + inner_loop, op, fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) @@ -2501,24 +2510,25 @@ instantiate_scev_not (basic_block instantiate_below, static tree instantiate_scev_3 (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree op1, op2; tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 0), + inner_loop, TREE_OPERAND (chrec, 0), fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) return chrec_dont_know; op1 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 1), + inner_loop, TREE_OPERAND (chrec, 1), fold_conversions, cache, size_expr); if (op1 == chrec_dont_know) return chrec_dont_know; op2 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 2), + inner_loop, TREE_OPERAND (chrec, 2), fold_conversions, cache, size_expr); if (op2 == chrec_dont_know) return chrec_dont_know; @@ -2548,18 +2558,19 @@ instantiate_scev_3 (basic_block instantiate_below, static tree instantiate_scev_2 (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree op1; tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 0), + inner_loop, TREE_OPERAND (chrec, 0), fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) return chrec_dont_know; op1 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 1), + inner_loop, TREE_OPERAND (chrec, 1), fold_conversions, cache, size_expr); if (op1 == chrec_dont_know) return chrec_dont_know; @@ -2587,11 +2598,12 @@ instantiate_scev_2 (basic_block instantiate_below, static tree instantiate_scev_1 (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, - TREE_OPERAND (chrec, 0), + inner_loop, TREE_OPERAND (chrec, 0), fold_conversions, cache, size_expr); if (op0 == chrec_dont_know) @@ -2619,7 +2631,8 @@ instantiate_scev_1 (basic_block instantiate_below, static tree instantiate_scev_r (basic_block instantiate_below, - struct loop *evolution_loop, tree chrec, + struct loop *evolution_loop, struct loop *inner_loop, + tree chrec, bool fold_conversions, htab_t cache, int size_expr) { /* Give up if the expression is larger than the MAX that we allow. */ @@ -2634,31 +2647,36 @@ instantiate_scev_r (basic_block instantiate_below, switch (TREE_CODE (chrec)) { case SSA_NAME: - return instantiate_scev_name (instantiate_below, evolution_loop, chrec, + return instantiate_scev_name (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); case POLYNOMIAL_CHREC: - return instantiate_scev_poly (instantiate_below, evolution_loop, chrec, + return instantiate_scev_poly (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); case POINTER_PLUS_EXPR: case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: - return instantiate_scev_binary (instantiate_below, evolution_loop, chrec, + return instantiate_scev_binary (instantiate_below, evolution_loop, + inner_loop, chrec, TREE_CODE (chrec), chrec_type (chrec), TREE_OPERAND (chrec, 0), TREE_OPERAND (chrec, 1), fold_conversions, cache, size_expr); CASE_CONVERT: - return instantiate_scev_convert (instantiate_below, evolution_loop, chrec, + return instantiate_scev_convert (instantiate_below, evolution_loop, + inner_loop, chrec, TREE_TYPE (chrec), TREE_OPERAND (chrec, 0), fold_conversions, cache, size_expr); case NEGATE_EXPR: case BIT_NOT_EXPR: - return instantiate_scev_not (instantiate_below, evolution_loop, chrec, + return instantiate_scev_not (instantiate_below, evolution_loop, + inner_loop, chrec, TREE_CODE (chrec), TREE_TYPE (chrec), TREE_OPERAND (chrec, 0), fold_conversions, cache, size_expr); @@ -2671,7 +2689,8 @@ instantiate_scev_r (basic_block instantiate_below, return chrec_known; case ARRAY_REF: - return instantiate_array_ref (instantiate_below, evolution_loop, chrec, + return instantiate_array_ref (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); default: @@ -2684,15 +2703,18 @@ instantiate_scev_r (basic_block instantiate_below, switch (TREE_CODE_LENGTH (TREE_CODE (chrec))) { case 3: - return instantiate_scev_3 (instantiate_below, evolution_loop, chrec, + return instantiate_scev_3 (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); case 2: - return instantiate_scev_2 (instantiate_below, evolution_loop, chrec, + return instantiate_scev_2 (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); case 1: - return instantiate_scev_1 (instantiate_below, evolution_loop, chrec, + return instantiate_scev_1 (instantiate_below, evolution_loop, + inner_loop, chrec, fold_conversions, cache, size_expr); case 0: @@ -2729,8 +2751,8 @@ instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop, fprintf (dump_file, ")\n"); } - res = instantiate_scev_r (instantiate_below, evolution_loop, chrec, false, - cache, 0); + res = instantiate_scev_r (instantiate_below, evolution_loop, + NULL, chrec, false, cache, 0); if (dump_file && (dump_flags & TDF_SCEV)) { @@ -2753,8 +2775,8 @@ tree resolve_mixers (struct loop *loop, tree chrec) { htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info); - tree ret = instantiate_scev_r (block_before_loop (loop), loop, chrec, true, - cache, 0); + tree ret = instantiate_scev_r (block_before_loop (loop), loop, NULL, + chrec, true, cache, 0); htab_delete (cache); return ret; } diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index a9b7077..4a09999 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -2671,7 +2671,12 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) upper = false; } - ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx)); + struct loop *dloop = loop_containing_stmt (data->stmt); + if (!dloop) + return true; + + ev = analyze_scalar_evolution (dloop, *idx); + ev = instantiate_parameters (loop, ev); init = initial_condition (ev); step = evolution_part_in_loop_num (ev, loop->num); |