[PATCH] Make LIM able to hoist PHI nodes
Steven Bosscher
stevenb.gcc@gmail.com
Mon May 3 11:34:00 GMT 2010
On Mon, May 3, 2010 at 1:06 PM, Richard Guenther <rguenther@suse.de> wrote:
>
> Working on hoisting malloc/free pairs out of loops (coming from
> Fortran array temporaries)
Yay.
What does this mean for the unswitching pass? It'd be interesting to
know the numbers before/after your patch for how often unswitching
applies. (Unrelated note: why do we still have the RTL unswitching
pass?)
> --- 519,526 ----
> unsigned cost = 1;
>
> /* Always try to create possibilities for unswitching. */
> ! if (gimple_code (stmt) == GIMPLE_COND
> ! || gimple_code (stmt) == GIMPLE_PHI)
> return LIM_EXPENSIVE;
So hoisting a PHI is always expensive? I doubt that's true. If a PHI
controls loop invariant code, it's likely more profitable to hoist it
than to unswitch the loop on it (and discover after unswitching that
the code is invariant). Am I missing something?
> --- 736,810 ----
> level = superloop_at_depth (loop, 1);
> lim_data->max_loop = level;
>
> ! if (gimple_code (stmt) == GIMPLE_PHI)
> ! {
> ! use_operand_p use_p;
> ! unsigned min_cost = 1000;
Magic number, based on...?
> ! unsigned total_cost = 0;
> ! struct lim_aux_data *def_data;
> !
> ! /* We will end up promoting dependencies to be unconditionally
> ! evaluated. Thus the cost is slighty complicated. */
> ! FOR_EACH_PHI_ARG (use_p, stmt, iter, SSA_OP_USE)
> ! {
> ! val = USE_FROM_PTR (use_p);
> ! if (TREE_CODE (val) != SSA_NAME)
> ! continue;
> ! if (!add_dependency (val, lim_data, loop, false))
> ! return false;
> ! def_data = get_lim_data (SSA_NAME_DEF_STMT (val));
> ! if (def_data)
> ! {
> ! min_cost = MIN (min_cost, def_data->cost);
> ! total_cost += def_data->cost;
> ! }
So a data ref is never more expensive than min_cost? I don't
understand this part of the patch.
> ! }
> !
> ! lim_data->cost += min_cost;
Make it unconditionally more expensive?
Perhaps you can add comments explaining this cost model. As you say,
it's slighty complicated.
> *************** determine_invariantness_stmt (struct dom
> *** 920,925 ****
> --- 1045,1081 ----
> fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
> bb->index, bb->loop_father->num, loop_depth (bb->loop_father));
>
> + /* Look at PHI nodes, but only if there is a single one only. */
Maybe it's possible to allow only a single GIMPLE_REG PHI, but also
allow an extra PHI for a memory op? That way you could hoist invariant
loads too.
> + if (gimple_phi_num_args (stmt) == 1)
Just for my understanding: single-argument PHIs you run into are
probably PHIs for loop-closed SSA form, right? If that's the case,
then perhaps...
> + {
> + tree arg = PHI_ARG_DEF (stmt, 0);
> + new_stmt = gimple_build_assign_with_ops (TREE_CODE (arg),
> + gimple_phi_result (stmt),
> + arg, NULL_TREE);
> + SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
> + }
... you don't have to build a new PHI here if you move the invariant
out of the loop. OTOH perhaps that just complicates the logic, not
sure.
> + else
> + {
> + basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
> + gimple cond = gsi_stmt (gsi_last_bb (dom));
> + tree arg0 = NULL_TREE, arg1 = NULL_TREE, t;
> + /* Get the PHI arguments corresponding to the true and false
> + edges of COND. */
> + extract_true_false_args_from_phi (dom, stmt, &arg0, &arg1);
> + gcc_assert (arg0 && arg1);
> + t = build2 (gimple_cond_code (cond), boolean_type_node,
> + gimple_cond_lhs (cond), gimple_cond_rhs (cond));
> + t = build3 (COND_EXPR, TREE_TYPE (gimple_phi_result (stmt)),
> + t, arg0, arg1);
> + new_stmt = gimple_build_assign_with_ops (COND_EXPR,
> + gimple_phi_result (stmt),
> + t, NULL_TREE);
> + SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
> + *((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
> + }
> + gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
> + remove_phi_node (&bsi, false);
> + }
> +
Not really related to this patch: Is this COND_EXPR later expanded to
real control flow, or does it live on as a COND_EXPR all the way
through to expand? If the former -- there were reasons not to do this
in e.g. PHIOPT but I don't remember the details. But if this now
works, perhaps we can move bits of ifcvt.c to the GIMPLE level too...
Ciao!
Steven
More information about the Gcc-patches
mailing list