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

Reply via email to