On Sun, 11 Oct 2015, Dominique d'Humières wrote: > > It seems there was regression on fatigue/fatigue2 > > http://gcc.opensuse.org/c++bench/pb11/ Fatigue > > was one of reasons to intorduce the heuristics, so it may be related to the > > patch :( > > The test in pr 64099 comment 14 now requires -fwhole-program to inline the > subroutine perdida: > > [Book15] lin/test% /opt/gcc/gcc6p-228566/bin/gfortran fatigue_v1nn2.f90 -Ofast > [Book15] lin/test% time a.out > /dev/null > 16.266u 0.003s 0:16.27 99.9% 0+0k 0+0io 36pf+0w > [Book15] lin/test% /opt/gcc/gcc6p-228566/bin/gfortran fatigue_v1nn2.f90 > -Ofast -fwhole-program > [Book15] lin/test% time a.out > /dev/null > 6.179u 0.001s 0:06.18 99.8% 0+0k 0+0io 0pf+0w
Ok, so for loops like <bb 135>: # S.255_53 = PHI <1(134), S.255_598(136)> if (S.255_53 > 3) goto <bb 137>; else goto <bb 136>; <bb 136>: _590 = S.255_53 * iftmp.446_62; _591 = _587 + _590; _592 = *back_stress_tensor.0_140[_591]; _593 = S.255_53 + _589; _594 = back_stress_rate_tensor[_593]; _595 = plastic_time_step_521 * _594; _596 = _592 + _595; *back_stress_tensor.0_140[_591] = _596; S.255_598 = S.255_53 + 1; goto <bb 135>; we analyze _591 and see that it is {iftmp.446_62, +, iftmp.446_62} (missed strength-reduction in early opts). And that is defined by a stride load from the array descriptor with the usual if (stride == 0) stride = 1 added. With strength reduction performed we'd see an IV in the loop header, without we have to do the more expensive work. I'm testing the following (solves the fatigue regression for me). Richard. 2015-10-12 Richard Biener <rguent...@suse.de> PR ipa/64099 * ipa-inline-analysis.c (estimate_function_body_sizes): Re-add code that analyzes IVs on each stmt but in a cheaper way avoiding quadratic behavior. Index: gcc/ipa-inline-analysis.c =================================================================== *** gcc/ipa-inline-analysis.c (revision 228703) --- gcc/ipa-inline-analysis.c (working copy) *************** estimate_function_body_sizes (struct cgr *** 2786,2822 **** &will_be_nonconstant); } exits.release (); ! for (gphi_iterator gsi = gsi_start_phis (loop->header); ! !gsi_end_p (gsi); gsi_next (&gsi)) { ! gphi *phi = gsi.phi (); ! tree use = gimple_phi_result (phi); ! affine_iv iv; ! predicate will_be_nonconstant; ! if (virtual_operand_p (use) ! || !simple_iv (loop, loop, use, &iv, true) ! || is_gimple_min_invariant (iv.step)) ! continue; ! will_be_nonconstant ! = will_be_nonconstant_expr_predicate (fbi.info, info, ! iv.step, ! nonconstant_names); ! if (!true_predicate_p (&will_be_nonconstant)) ! will_be_nonconstant = and_predicates (info->conds, ! &bb_predicate, ! &will_be_nonconstant); ! if (!true_predicate_p (&will_be_nonconstant) ! && !false_predicate_p (&will_be_nonconstant)) ! /* This is slightly inprecise. We may want to represent ! each loop with independent predicate. */ ! loop_stride = and_predicates (info->conds, &loop_stride, ! &will_be_nonconstant); } } set_hint_predicate (&inline_summaries->get (node)->loop_iterations, loop_iterations); ! set_hint_predicate (&inline_summaries->get (node)->loop_stride, loop_stride); scev_finalize (); } FOR_ALL_BB_FN (bb, my_function) --- 2786,2845 ---- &will_be_nonconstant); } exits.release (); + } ! /* To avoid quadratic behavior we analyze stride predicates only ! with respect to the containing loop. Thus we simply iterate ! over all defs in the outermost loop body. */ ! for (loop = loops_for_fn (cfun)->tree_root->inner; ! loop != NULL; loop = loop->next) ! { ! basic_block *body = get_loop_body (loop); ! for (unsigned i = 0; i < loop->num_nodes; i++) { ! gimple_stmt_iterator gsi; ! bb_predicate = *(struct predicate *) body[i]->aux; ! for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); ! gsi_next (&gsi)) ! { ! gimple *stmt = gsi_stmt (gsi); ! ! if (!is_gimple_assign (stmt)) ! continue; ! ! tree def = gimple_assign_lhs (stmt); ! if (TREE_CODE (def) != SSA_NAME) ! continue; ! ! affine_iv iv; ! if (!simple_iv (loop_containing_stmt (stmt), ! loop_containing_stmt (stmt), ! def, &iv, true) ! || is_gimple_min_invariant (iv.step)) ! continue; ! ! predicate will_be_nonconstant ! = will_be_nonconstant_expr_predicate (fbi.info, info, ! iv.step, ! nonconstant_names); ! if (!true_predicate_p (&will_be_nonconstant)) ! will_be_nonconstant ! = and_predicates (info->conds, &bb_predicate, ! &will_be_nonconstant); ! if (!true_predicate_p (&will_be_nonconstant) ! && !false_predicate_p (&will_be_nonconstant)) ! /* This is slightly inprecise. We may want to represent ! each loop with independent predicate. */ ! loop_stride = and_predicates (info->conds, &loop_stride, ! &will_be_nonconstant); ! } } + free (body); } set_hint_predicate (&inline_summaries->get (node)->loop_iterations, loop_iterations); ! set_hint_predicate (&inline_summaries->get (node)->loop_stride, ! loop_stride); scev_finalize (); } FOR_ALL_BB_FN (bb, my_function)