diff mbox series

[v5,1/4] Match: Add interface match_cond_with_binary_phi for true/false arg

Message ID 20240919041038.3796202-1-pan2.li@intel.com
State New
Headers show
Series [v5,1/4] Match: Add interface match_cond_with_binary_phi for true/false arg | expand

Commit Message

Li, Pan2 Sept. 19, 2024, 4:10 a.m. UTC
From: Pan Li <pan2.li@intel.com>

When matching the cond with 2 args phi node, we need to figure out
which arg of phi node comes from the true edge of cond block, as
well as the false edge.  This patch would like to add interface
to perform the action and return the true and false arg in TREE type.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.
* The x86 bootstrap test.
* The x86 fully regression test.

gcc/ChangeLog:

	* gimple-match-head.cc (match_cond_with_binary_phi): Add new func
	impl to match binary phi for true and false arg.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/gimple-match-head.cc | 120 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

Comments

Richard Biener Sept. 19, 2024, 6:21 a.m. UTC | #1
On Thu, Sep 19, 2024 at 6:11 AM <pan2.li@intel.com> wrote:
>
> From: Pan Li <pan2.li@intel.com>
>
> When matching the cond with 2 args phi node, we need to figure out
> which arg of phi node comes from the true edge of cond block, as
> well as the false edge.  This patch would like to add interface
> to perform the action and return the true and false arg in TREE type.
>
> The below test suites are passed for this patch.
> * The rv64gcv fully regression test.
> * The x86 bootstrap test.
> * The x86 fully regression test.

OK.

Thanks,
Richard.

> gcc/ChangeLog:
>
>         * gimple-match-head.cc (match_cond_with_binary_phi): Add new func
>         impl to match binary phi for true and false arg.
>
> Signed-off-by: Pan Li <pan2.li@intel.com>
> ---
>  gcc/gimple-match-head.cc | 120 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 120 insertions(+)
>
> diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc
> index 924d3f1e710..b63b66e9485 100644
> --- a/gcc/gimple-match-head.cc
> +++ b/gcc/gimple-match-head.cc
> @@ -375,3 +375,123 @@ gimple_bitwise_inverted_equal_p (tree expr1, tree expr2, bool &wascmp, tree (*va
>      return true;
>    return false;
>  }
> +
> +/*
> + * Return the relevant gcond * of the given phi, as well as the true
> + * and false TREE args of the phi.  Or return nullptr.
> + *
> + * If matched the gcond *, the output argument TREE true_arg and false_arg
> + * will be updated to the relevant args of phi.
> + *
> + * If failed to match, nullptr gcond * will be returned, as well as the output
> + * arguments will be set to NULL_TREE.
> + */
> +
> +static inline gcond *
> +match_cond_with_binary_phi (gphi *phi, tree *true_arg, tree *false_arg)
> +{
> +  *true_arg = *false_arg = NULL_TREE;
> +
> +  if (gimple_phi_num_args (phi) != 2)
> +    return nullptr;
> +
> +  basic_block pred_b0 = EDGE_PRED (gimple_bb (phi), 0)->src;
> +  basic_block pred_b1 = EDGE_PRED (gimple_bb (phi), 1)->src;
> +  edge edge_for_pred_0 = nullptr;
> +
> +  if (EDGE_COUNT (pred_b0->succs) == 2
> +      && EDGE_COUNT (pred_b1->succs) == 1
> +      && EDGE_COUNT (pred_b1->preds) == 1
> +      && pred_b0 == EDGE_PRED (gimple_bb (phi), 0)->src)
> +    /*
> +     * +------+
> +     * | b0:  |
> +     * | def  |       +-----+
> +     * | ...  |       | b1: |
> +     * | cond |------>| def |
> +     * +------+       | ... |
> +     *    |           +-----+
> +     *    #              |
> +     *    |              |
> +     *    v              |
> +     * +-----+           |
> +     * | b2: |           |
> +     * | def |<----------+
> +     * +-----+
> +     * #: edge_for_pred_0.
> +     */
> +    edge_for_pred_0 = EDGE_PRED (gimple_bb (phi), 0);
> +  else if (EDGE_COUNT (pred_b1->succs) == 2
> +          && EDGE_COUNT (pred_b0->succs) == 1
> +          && EDGE_COUNT (pred_b0->preds) == 1
> +          && pred_b1 == EDGE_PRED (pred_b0, 0)->src)
> +    /*
> +     *                +------+
> +     *                | b1:  |
> +     * +-----+        | def  |
> +     * | b0: |        | ...  |
> +     * | def |<---#---| cond |
> +     * | ... |        +------+
> +     * +-----+           |
> +     *    |              |
> +     *    |              |
> +     *    |              |
> +     *    v              |
> +     * +-----+           |
> +     * | b2: |           |
> +     * | def |<----------+
> +     * +-----+
> +     * #: edge_for_pred_0.
> +     */
> +    edge_for_pred_0 = EDGE_PRED (pred_b0, 0);
> +  else if (EDGE_COUNT (pred_b0->succs) == 1
> +          && EDGE_COUNT (pred_b1->succs) == 1
> +          && EDGE_COUNT (pred_b0->preds) == 1
> +          && EDGE_COUNT (pred_b1->preds) == 1
> +          && EDGE_COUNT (EDGE_PRED (pred_b0, 0)->src->succs) == 2
> +          && EDGE_PRED (pred_b0, 0)->src == EDGE_PRED (pred_b1, 0)->src)
> +    /* +------+
> +     * | b0:  |
> +     * | ...  |       +-----+
> +     * | cond |------>| b2: |
> +     * +------+       | ... |
> +     *    |           +-----+
> +     *    #              |
> +     *    |              |
> +     *    v              |
> +     * +-----+           |
> +     * | b1: |           |
> +     * | ... |           |
> +     * +-----+           |
> +     *    |              |
> +     *    |              |
> +     *    v              |
> +     * +-----+           |
> +     * | b3: |<----------+
> +     * | ... |
> +     * +-----+
> +     * #: edge_for_pred_0.
> +     */
> +    edge_for_pred_0 = EDGE_PRED (pred_b0, 0);
> +
> +  if (!edge_for_pred_0)
> +    return nullptr;
> +
> +  gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (edge_for_pred_0->src));
> +
> +  if (!cond)
> +    return nullptr;
> +
> +  if (edge_for_pred_0->flags & EDGE_TRUE_VALUE)
> +    {
> +      *true_arg = gimple_phi_arg_def (phi, 0);
> +      *false_arg = gimple_phi_arg_def (phi, 1);
> +    }
> +  else /* Aka edge_for_pred_0->flags & EDGE_FALSE_VALUE  */
> +    {
> +      *false_arg = gimple_phi_arg_def (phi, 0);
> +      *true_arg = gimple_phi_arg_def (phi, 1);
> +    }
> +
> +  return cond;
> +}
> --
> 2.43.0
>
diff mbox series

Patch

diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc
index 924d3f1e710..b63b66e9485 100644
--- a/gcc/gimple-match-head.cc
+++ b/gcc/gimple-match-head.cc
@@ -375,3 +375,123 @@  gimple_bitwise_inverted_equal_p (tree expr1, tree expr2, bool &wascmp, tree (*va
     return true;
   return false;
 }
+
+/*
+ * Return the relevant gcond * of the given phi, as well as the true
+ * and false TREE args of the phi.  Or return nullptr.
+ *
+ * If matched the gcond *, the output argument TREE true_arg and false_arg
+ * will be updated to the relevant args of phi.
+ *
+ * If failed to match, nullptr gcond * will be returned, as well as the output
+ * arguments will be set to NULL_TREE.
+ */
+
+static inline gcond *
+match_cond_with_binary_phi (gphi *phi, tree *true_arg, tree *false_arg)
+{
+  *true_arg = *false_arg = NULL_TREE;
+
+  if (gimple_phi_num_args (phi) != 2)
+    return nullptr;
+
+  basic_block pred_b0 = EDGE_PRED (gimple_bb (phi), 0)->src;
+  basic_block pred_b1 = EDGE_PRED (gimple_bb (phi), 1)->src;
+  edge edge_for_pred_0 = nullptr;
+
+  if (EDGE_COUNT (pred_b0->succs) == 2
+      && EDGE_COUNT (pred_b1->succs) == 1
+      && EDGE_COUNT (pred_b1->preds) == 1
+      && pred_b0 == EDGE_PRED (gimple_bb (phi), 0)->src)
+    /*
+     * +------+
+     * | b0:  |
+     * | def  |       +-----+
+     * | ...  |       | b1: |
+     * | cond |------>| def |
+     * +------+       | ... |
+     *    |           +-----+
+     *    #              |
+     *    |              |
+     *    v              |
+     * +-----+           |
+     * | b2: |           |
+     * | def |<----------+
+     * +-----+
+     * #: edge_for_pred_0.
+     */
+    edge_for_pred_0 = EDGE_PRED (gimple_bb (phi), 0);
+  else if (EDGE_COUNT (pred_b1->succs) == 2
+	   && EDGE_COUNT (pred_b0->succs) == 1
+	   && EDGE_COUNT (pred_b0->preds) == 1
+	   && pred_b1 == EDGE_PRED (pred_b0, 0)->src)
+    /*
+     *                +------+
+     *                | b1:  |
+     * +-----+        | def  |
+     * | b0: |        | ...  |
+     * | def |<---#---| cond |
+     * | ... |        +------+
+     * +-----+           |
+     *    |              |
+     *    |              |
+     *    |              |
+     *    v              |
+     * +-----+           |
+     * | b2: |           |
+     * | def |<----------+
+     * +-----+
+     * #: edge_for_pred_0.
+     */
+    edge_for_pred_0 = EDGE_PRED (pred_b0, 0);
+  else if (EDGE_COUNT (pred_b0->succs) == 1
+	   && EDGE_COUNT (pred_b1->succs) == 1
+	   && EDGE_COUNT (pred_b0->preds) == 1
+	   && EDGE_COUNT (pred_b1->preds) == 1
+	   && EDGE_COUNT (EDGE_PRED (pred_b0, 0)->src->succs) == 2
+	   && EDGE_PRED (pred_b0, 0)->src == EDGE_PRED (pred_b1, 0)->src)
+    /* +------+
+     * | b0:  |
+     * | ...  |       +-----+
+     * | cond |------>| b2: |
+     * +------+       | ... |
+     *    |           +-----+
+     *    #              |
+     *    |              |
+     *    v              |
+     * +-----+           |
+     * | b1: |           |
+     * | ... |           |
+     * +-----+           |
+     *    |              |
+     *    |              |
+     *    v              |
+     * +-----+           |
+     * | b3: |<----------+
+     * | ... |
+     * +-----+
+     * #: edge_for_pred_0.
+     */
+    edge_for_pred_0 = EDGE_PRED (pred_b0, 0);
+
+  if (!edge_for_pred_0)
+    return nullptr;
+
+  gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (edge_for_pred_0->src));
+
+  if (!cond)
+    return nullptr;
+
+  if (edge_for_pred_0->flags & EDGE_TRUE_VALUE)
+    {
+      *true_arg = gimple_phi_arg_def (phi, 0);
+      *false_arg = gimple_phi_arg_def (phi, 1);
+    }
+  else /* Aka edge_for_pred_0->flags & EDGE_FALSE_VALUE  */
+    {
+      *false_arg = gimple_phi_arg_def (phi, 0);
+      *true_arg = gimple_phi_arg_def (phi, 1);
+    }
+
+  return cond;
+}