diff --git a/gcc/testsuite/gfortran.dg/graphite/pr90240.f b/gcc/testsuite/gfortran.dg/graphite/pr90240.f new file mode 100644 index 00000000000..0873f2124c2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/graphite/pr90240.f @@ -0,0 +1,18 @@ +! { dg-do compile } +! { dg-options "-O1 -floop-nest-optimize" } + + PARAMETER (n=1335, N2=1335) + COMMON a(n,N2), b(n,N2), c(n,N2), + * d(n,N2), + 2 e(n,N2), f(n,N2), + * g(n,N2), h(n,N2) + DO 200 j=1,i + DO 300 k=1,l + a(k,j) = c(k,j)*g(k,j)*f(k+1,m)+f(k,m)+f(k,j) + 2 +f(k+1,j)*h(k+1,j) + b(k,j+1) = d(k,j+1)*g(k,m)+g(k,j+1) + 1 *e(k,m)+e(k,j+1)+e(k,j)+e(k+1,j) + 2 *h(k,j+1)-h(k,j) + 300 ENDDO + 200 ENDDO + END diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index a2b6b2b2312..534e1463807 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -4557,22 +4557,25 @@ get_address_cost (struct ivopts_data *data, struct iv_use *use, static comp_cost get_scaled_computation_cost_at (ivopts_data *data, gimple *at, comp_cost cost) { - int loop_freq = data->current_loop->header->count.to_frequency (cfun); - int bb_freq = gimple_bb (at)->count.to_frequency (cfun); - if (loop_freq != 0) - { - gcc_assert (cost.scratch <= cost.cost); - int scaled_cost - = cost.scratch + (cost.cost - cost.scratch) * bb_freq / loop_freq; + if (data->speed + && data->current_loop->header->count.to_frequency (cfun) > 0) + { + basic_block bb = gimple_bb (at); + gcc_assert (cost.scratch <= cost.cost); + int scale_factor = (int)(intptr_t) bb->aux; + if (scale_factor == 1) + return cost; - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Scaling cost based on bb prob " - "by %2.2f: %d (scratch: %d) -> %d (%d/%d)\n", - 1.0f * bb_freq / loop_freq, cost.cost, - cost.scratch, scaled_cost, bb_freq, loop_freq); + int scaled_cost + = cost.scratch + (cost.cost - cost.scratch) * scale_factor; - cost.cost = scaled_cost; - } + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Scaling cost based on bb prob " + "by %2.2f: %d (scratch: %d) -> %d\n", + 1.0f * scale_factor, cost.cost, cost.scratch, scaled_cost); + + cost.cost = scaled_cost; + } return cost; } @@ -6678,9 +6681,8 @@ try_improve_iv_set (struct ivopts_data *data, } iv_ca_delta_commit (data, ivs, best_delta, true); - gcc_assert (best_cost == iv_ca_cost (ivs)); iv_ca_delta_free (&best_delta); - return true; + return best_cost == iv_ca_cost (ivs); } /* Attempts to find the optimal set of induction variables. We do simple @@ -6717,6 +6719,14 @@ find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp) } } + /* If the set has infinite_cost, it can't be optimal. */ + if (iv_ca_cost (set).infinite_cost_p ()) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + "Overflow to infinite cost in try_improve_iv_set.\n"); + iv_ca_free (&set); + } return set; } @@ -7522,6 +7532,49 @@ loop_body_includes_call (basic_block *body, unsigned num_nodes) return false; } +/* Determine cost scaling factor for basic blocks in loop. */ +#define COST_SCALING_FACTOR_BOUND (20) + +static void +determine_scaling_factor (struct ivopts_data *data, basic_block *body) +{ + int lfreq = data->current_loop->header->count.to_frequency (cfun); + if (!data->speed || lfreq <= 0) + return; + + int max_freq = lfreq; + for (unsigned i = 0; i < data->current_loop->num_nodes; i++) + { + body[i]->aux = (void *)(intptr_t) 1; + if (max_freq < body[i]->count.to_frequency (cfun)) + max_freq = body[i]->count.to_frequency (cfun); + } + if (max_freq > lfreq) + { + int divisor, factor; + /* Check if scaling factor itself needs to be scaled by the bound. This + is to avoid overflow when scaling cost according to profile info. */ + if (max_freq / lfreq > COST_SCALING_FACTOR_BOUND) + { + divisor = max_freq; + factor = COST_SCALING_FACTOR_BOUND; + } + else + { + divisor = lfreq; + factor = 1; + } + for (unsigned i = 0; i < data->current_loop->num_nodes; i++) + { + int bfreq = body[i]->count.to_frequency (cfun); + if (bfreq <= lfreq) + continue; + + body[i]->aux = (void*)(intptr_t) (factor * bfreq / divisor); + } + } +} + /* Optimizes the LOOP. Returns true if anything changed. */ static bool @@ -7560,7 +7613,6 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop, body = get_loop_body (loop); data->body_includes_call = loop_body_includes_call (body, loop->num_nodes); renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes); - free (body); data->loop_single_exit_p = exit != NULL && loop_only_exit_p (loop, exit); @@ -7574,6 +7626,9 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop, if (data->vgroups.length () > MAX_CONSIDERED_GROUPS) goto finish; + /* Determine cost scaling factor for basic blocks in loop. */ + determine_scaling_factor (data, body); + /* Finds candidates for the induction variables (item 2). */ find_iv_candidates (data); @@ -7584,6 +7639,9 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop, /* Find the optimal set of induction variables (item 3, part 2). */ iv_ca = find_optimal_iv_set (data); + /* Cleanup basic block aux field. */ + for (unsigned i = 0; i < data->current_loop->num_nodes; i++) + body[i]->aux = NULL; if (!iv_ca) goto finish; changed = true; @@ -7599,6 +7657,7 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop, remove_unused_ivs (data, toremove); finish: + free (body); free_loop_data (data); return changed;