Hello,
On 26.10.2011 21:49, Alexander Monakov wrote:
2011-10-26 Alexander Monakov<amona...@ispras.ru>
* common.opt: Add -fsel-sched-predication option.
* config/ia64/ia64.c (get_mode_no_for_insn): Support conditional loads.
* rtl.h (COND_SET_SRC_PTR, COND_SET_SRC_PTR): New macros.
* sched-deps.c (conditions_mutex_with_rev_p): Rename from
conditions_mutex_p. Adjust the caller.
(conditions_mutex_p, conditions_same_p,
conditions_same_or_mutex_p): New functions.
(sched_analyze_insn): Extract LHS/RHS for conditional assignments.
* sched-int.h (conditions_mutex_p, conditions_same_p,
conditions_same_or_mutex_p): Declare.
* sel-sched-ir.c (vinsn_equal_p): Support conditional insns.
(vinsn_equal_skip_cond_p): New function.
(init_expr): Add new argument (was_predicated). Update all callers.
(merge_expr_data): Assert equality of merged predicates.
(av_set_add_nocopy, join_distinct_sets): Export.
(av_set_tail, av_set_concat): New functions.
(av_set_union_and_live): Add parameter to_fallthru_p, generate
predicated insns.
(setup_id_lhs_rhs): Support conditional insns.
(setup_id_cond): New function.
(init_id_from_df, deps_init_id): Use it.
(get_dest_and_mode): Support conditional insns.
* sel-sched-ir.h (enum local_trans_type): Add TRANS_PREDICATION.
(struct _expr): Add new member (was_predicated).
(EXPR_COND, EXPR_WAS_PREDICATED): New accessor macros.
(struct idata_def): Add new member (cond).
(IDATA_COND, VINSN_COND, INSN_COND): New accessor macros.
(vinsn_equal_skip_cond_p, maybe_predicate_expr_into,
av_set_add_nocopy, av_set_intersect, join_distinct_sets,
av_set_concat): Declare.
(av_set_union_and_live): Change prototype.
* sel-sched.c is lost somewhere here.
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 1a73308..85e469a 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -1607,6 +1614,39 @@ vinsn_equal_p (vinsn_t x, vinsn_t y)
return rtx_equal_p_cb (VINSN_PATTERN (x), VINSN_PATTERN (y), repcf);
}
+/* Compare two vinsns as rhses if possible and as vinsns otherwise.
+ Ignore potential differences in conditions. */
+bool
+vinsn_equal_skip_cond_p (vinsn_t x, vinsn_t y)
+{
As we discussed offline, this functionality can be integrated in
vinsn_equal_p, so we don't need extra predicate for that.
@@ -2221,22 +2287,41 @@ av_set_union_and_clear (av_set_t *top, av_set_t *fromp,
insn_t insn)
}
/* Same as above, but also update availability of target register in
- TOP judging by TO_LV_SET and FROM_LV_SET. */
+ TOP judging by TO_LV_SET and FROM_LV_SET. INSN is the conditional branch,
+ and TO_FALLTHRU_P indicates whether TOP is from the fallthrough arm. */
void
av_set_union_and_live (av_set_t *top, av_set_t *fromp, regset to_lv_set,
from the fallthru edge
@@ -3567,6 +3685,10 @@ get_dest_and_mode (rtx insn, rtx *dst_loc, enum
machine_mode *mode)
rtx pat = PATTERN (insn);
gcc_assert (dst_loc);
+
+ if (GET_CODE (pat) == COND_EXEC)
+ pat = COND_EXEC_CODE (pat);
+
Do we need to conditionalize this on flag_sel_sched_predication?
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 91fb0fe..f5c6f8b 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -2712,6 +2716,181 @@ is_ineligible_successor (insn_t insn, ilist_t p)
return false;
}
+/* An entry in the predication cache. */
+struct predication_cache
+{
+ /* A predicate that would be added. */
+ rtx cond;
+ /* Original vinsn. */
+ vinsn_t vinsn_old;
+ /* The vinsn resulting from applying predicate COND to vinsn VINSN_OLD. */
+ vinsn_t vinsn_new;
+};
+
+static htab_t predication_cache;
No comment before this variable. Also, this section is worth a comment
describing why we need a separate cache for predicated insns.
+/* Try to construct NEW_EXPR as the result of applying predicate COND to
+ EXPR, using uid of INSN to record the transformation in the history vector.
+ Return value indicates whether transformation is valid. */
+static bool
+predicate_expr (expr_t new_expr, expr_t expr, insn_t insn, rtx cond)
+{
+ struct predication_cache *entry;
+ vinsn_t vi = EXPR_VINSN (expr), new_vi;
+ rtx pat = PATTERN (EXPR_INSN_RTX (expr));
+
+ if (VINSN_UNIQUE_P (vi)
+ || modified_in_p (cond, EXPR_INSN_RTX (expr)))
+ return false;
+
+ entry = find_in_predication_cache (cond, vi);
+
+ if (entry)
+ {
+ new_vi = entry->vinsn_new;
+ if (!new_vi)
+ return false;
+ if (INSN_IN_STREAM_P (VINSN_INSN_RTX (new_vi)))
+ new_vi = vinsn_copy (new_vi, false);
+ }
+ else
+ {
+ entry = XNEW (struct predication_cache);
+ entry->cond = cond;
+ entry->vinsn_old = vi;
+ vinsn_attach (vi);
+
+ pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond), copy_rtx (pat));
+ if (insn_invalid_p (make_insn_raw (pat)))
We are throwing away this insn when it is valid and making it again below
with create_insn_rtx_from_pattern, please avoid doing that.
+ {
+ entry->vinsn_new = NULL;
+ *(struct predication_cache **) htab_find_slot (predication_cache,
+ entry,
+ INSERT) = entry;
+ return false;
+ }
+ pat = create_insn_rtx_from_pattern (pat, NULL_RTX);
+ new_vi = entry->vinsn_new = create_vinsn_from_insn_rtx (pat, false);
+ vinsn_attach (new_vi);
+ *(struct predication_cache **) htab_find_slot (predication_cache, entry,
+ INSERT) = entry;
+ }
+
+ if (sched_verbose>= 6)
+ {
+ sel_print (" new from pred: ");
+ dump_vinsn (new_vi);
+ sel_print ("\n");
+ }
We don't have similar debug output with speculation/substitution, do we
want it here because of the different place where the transformation is
happening? In this case, please expand the debug message, otherwise it is
better to remove it.
@@ -2784,12 +2969,13 @@ compute_av_set_at_bb_end (insn_t insn, ilist_t p, int
ws)
{
basic_block bb0 = BLOCK_FOR_INSN (zero_succ);
basic_block bb1 = BLOCK_FOR_INSN (succ);
+ bool to_fallthru_p = in_fallthru_bb_p (insn, zero_succ, true);
Why do we need to skip nop blocks here?
/* If we're scheduling separate expr, in order to generate correct code
we need to stop the search at bookkeeping code generated with the
same destination register or memory. */
- if (lhs_of_insn_equals_to_dest_p (insn, sparams->dest))
+ if (!mutexed&& lhs_of_insn_equals_to_dest_p (insn, sparams->dest))
Comment needs an update.
@@ -6409,6 +6626,17 @@ code_motion_process_successors (insn_t insn, av_set_t
orig_ops,
{
int b;
+ if (cond
+&& conditions_same_or_mutex_p (cond, INSN_COND (insn))
+&& !(single_succ_p (succ_i.e1->src))
+ && (((succ_i.e1->flags& EDGE_FALLTHRU) != 0)
+ == conditions_mutex_p (cond, INSN_COND (insn))))
+ {
+ if (sched_verbose>= 6)
+ sel_print ("Not following predicated-off path from %d\n",
+ INSN_UID (succ));
+ continue;
+ }
Also worth a comment before if.
@@ -6659,6 +6911,12 @@ code_motion_path_driver (insn_t insn, av_set_t orig_ops,
ilist_t path,
gcc_assert (insn == sel_bb_end (bb));
+ if (orig_cond&& av_set_common_cond (orig_ops))
+ orig_cond = NULL;
Why this? Also needs a comment, and there is no ChangeLog entry for
code_motion_path_driver changes.
Andrey