+
+ /* Now the regular final value replacement. */
+ FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
+ {
+ edge exit;
+ tree def, rslt, niter;
+ gimple_stmt_iterator bsi;
+
+ /* If we do not know exact number of iterations of the loop, we cannot
+ replace the final value. */
+ exit = single_exit (loop);
+ if (!exit)
+ continue;
+
+ niter = number_of_latch_executions (loop);
+ if (niter == chrec_dont_know)
+ continue;
+
+ /* Ensure that it is possible to insert new statements somewhere. */
+ if (!single_pred_p (exit->dest))
+ split_loop_exit_edge (exit);
+ bsi = gsi_after_labels (exit->dest);
+
+ ex_loop = superloop_at_depth (loop,
+ loop_depth (exit->dest->loop_father) + 1);
+
+ for (psi = gsi_start_phis (exit->dest); !gsi_end_p (psi); )
+ {
+ phi = gsi_stmt (psi);
+ rslt = PHI_RESULT (phi);
+ def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
+ if (!is_gimple_reg (def))
+ {
+ gsi_next (&psi);
+ continue;
+ }
+
+ if (!POINTER_TYPE_P (TREE_TYPE (def))
+ && !INTEGRAL_TYPE_P (TREE_TYPE (def)))
+ {
+ gsi_next (&psi);
+ continue;
+ }
+
+ def = analyze_scalar_evolution_in_loop (ex_loop, loop, def, NULL);
+ def = compute_overall_effect_of_inner_loop (ex_loop, def);
+ if (!tree_does_not_contain_chrecs (def)
+ || chrec_contains_symbols_defined_in_loop (def, ex_loop->num)
+ /* Moving the computation from the loop may prolong life range
+ of some ssa names, which may cause problems if they appear
+ on abnormal edges. */
+ || contains_abnormal_ssa_name_p (def)
+ /* Do not emit expensive expressions. The rationale is that
+ when someone writes a code like
+
+ while (n > 45) n -= 45;
+
+ he probably knows that n is not large, and does not want it
+ to be turned into n %= 45. */
+ || expression_expensive_p (def))
+ {
+ gsi_next (&psi);
+ continue;
+ }
+
+ /* Eliminate the PHI node and replace it by a computation outside
+ the loop. */
+ def = unshare_expr (def);
+ remove_phi_node (&psi, false);
+
+ def = force_gimple_operand_gsi (&bsi, def, false, NULL_TREE,
+ true, GSI_SAME_STMT);
+ ass = gimple_build_assign (rslt, def);
+ gsi_insert_before (&bsi, ass, GSI_SAME_STMT);
+ }
+ }
+ return 0;