- cond = *use->op_p;
- op_p = &TREE_OPERAND (cond, 0);
- if (TREE_CODE (*op_p) != SSA_NAME
- || zero_p (get_iv (data, *op_p)->step))
- op_p = &TREE_OPERAND (cond, 1);
-
- op = force_gimple_operand (comp, &stmts, true, SSA_NAME_VAR (*op_p));
- if (stmts)
- bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
-
- *op_p = op;
-}
-
-/* Ensure that operand *OP_P may be used at the end of EXIT without
- violating loop closed ssa form. */
-
-static void
-protect_loop_closed_ssa_form_use (edge exit, use_operand_p op_p)
-{
- basic_block def_bb;
- struct loop *def_loop;
- tree phi, use;
-
- use = USE_FROM_PTR (op_p);
- if (TREE_CODE (use) != SSA_NAME)
- return;
-
- def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (use));
- if (!def_bb)
- return;
-
- def_loop = def_bb->loop_father;
- if (flow_bb_inside_loop_p (def_loop, exit->dest))
- return;
-
- /* Try finding a phi node that copies the value out of the loop. */
- for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
- if (PHI_ARG_DEF_FROM_EDGE (phi, exit) == use)
- break;
-
- if (!phi)
- {
- /* Create such a phi node. */
- tree new_name = duplicate_ssa_name (use, NULL);
-
- phi = create_phi_node (new_name, exit->dest);
- SSA_NAME_DEF_STMT (new_name) = phi;
- add_phi_arg (phi, use, exit);
- }
-
- SET_USE (op_p, PHI_RESULT (phi));
-}
-
-/* Ensure that operands of STMT may be used at the end of EXIT without
- violating loop closed ssa form. */
-
-static void
-protect_loop_closed_ssa_form (edge exit, tree stmt)
-{
- ssa_op_iter iter;
- use_operand_p use_p;
-
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
- protect_loop_closed_ssa_form_use (exit, use_p);
-}
-
-/* STMTS compute a value of a phi argument OP on EXIT of a loop. Arrange things
- so that they are emitted on the correct place, and so that the loop closed
- ssa form is preserved. */
-
-void
-compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
-{
- tree_stmt_iterator tsi;
- block_stmt_iterator bsi;
- tree phi, stmt, def, next;
-
- if (!single_pred_p (exit->dest))
- split_loop_exit_edge (exit);
-
- /* Ensure there is label in exit->dest, so that we can
- insert after it. */
- tree_block_label (exit->dest);
- bsi = bsi_after_labels (exit->dest);
-
- if (TREE_CODE (stmts) == STATEMENT_LIST)
- {
- for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
- {
- bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_NEW_STMT);
- protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
- }
- }
- else
- {
- bsi_insert_after (&bsi, stmts, BSI_NEW_STMT);
- protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
- }
-
- if (!op)
- return;
-
- for (phi = phi_nodes (exit->dest); phi; phi = next)
- {
- next = PHI_CHAIN (phi);
-
- if (PHI_ARG_DEF_FROM_EDGE (phi, exit) == op)
- {
- def = PHI_RESULT (phi);
- remove_statement (phi, false);
- stmt = build2 (MODIFY_EXPR, TREE_TYPE (op),
- def, op);
- SSA_NAME_DEF_STMT (def) = stmt;
- bsi_insert_after (&bsi, stmt, BSI_CONTINUE_LINKING);
- }
- }
-}
-
-/* Rewrites the final value of USE (that is only needed outside of the loop)
- using candidate CAND. */
-
-static void
-rewrite_use_outer (struct ivopts_data *data,
- struct iv_use *use, struct iv_cand *cand)
-{
- edge exit;
- tree value, op, stmts, tgt;
- tree phi;
-
- switch (TREE_CODE (use->stmt))
- {
- case PHI_NODE:
- tgt = PHI_RESULT (use->stmt);
- break;
- case MODIFY_EXPR:
- tgt = TREE_OPERAND (use->stmt, 0);
- break;
- default:
- gcc_unreachable ();
- }
-
- exit = single_dom_exit (data->current_loop);
-
- if (exit)
- {
- if (!cand->iv)
- {
- struct cost_pair *cp = get_use_iv_cost (data, use, cand);
- value = unshare_expr (cp->value);
- }
- else
- value = get_computation_at (data->current_loop,
- use, cand, last_stmt (exit->src));
-
- op = force_gimple_operand (value, &stmts, true, SSA_NAME_VAR (tgt));
-
- /* If we will preserve the iv anyway and we would need to perform
- some computation to replace the final value, do nothing. */
- if (stmts && name_info (data, tgt)->preserve_biv)
- return;
-
- for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
- {
- use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, exit);
-
- if (USE_FROM_PTR (use_p) == tgt)
- SET_USE (use_p, op);
- }
-
- if (stmts)
- compute_phi_arg_on_exit (exit, stmts, op);
-
- /* Enable removal of the statement. We cannot remove it directly,
- since we may still need the aliasing information attached to the
- ssa name defined by it. */
- name_info (data, tgt)->iv->have_use_for = false;
- return;
- }
-
- /* If the variable is going to be preserved anyway, there is nothing to
- do. */
- if (name_info (data, tgt)->preserve_biv)
- return;