Thanks Jeff and Richard for suggestion and reviewing.
Have another try in phiopt to do the convert from PHI to stmt = cond ? a : b.
It can perform the convert from PHI to stmt = cond ? a : b successfully, and
then
the widen-mul is able to do the recog to .SAT_ADD.
For now, to limit the risck, the above convert from PHI to stmt = cond ? a : b
only be performed when matched,
as well as the backend support the usadd standard name. Unfortunately, I am
stuck in the case that when the lhs
is not matched, we need to clean up something like created stmt in previous, or
we will have ICE for missing definition.
sat_add.c: In function ‘sat_add_u_3_uint8_t’:
sat_add.c:69:1: error: missing definition
69 | SAT_ADD_U_3(uint8_t);
| ^~~~~~~~~~~
for SSA_NAME: _6 in statement:
# VUSE <.MEM_14(D)>
return _6;
during GIMPLE pass: phiopt
dump file: sat_add.c.046t.phiopt1
sat_add.c:69:1: internal compiler error: verify_ssa failed
0x1db41ba verify_ssa(bool, bool
/home/pli/gcc/555/riscv-gnu-toolchain/gcc/__RISCV_BUILD__/../gcc/tree-ssa.cc:1203
0x18e3075 execute_function_todo
/home/pli/gcc/555/riscv-gnu-toolchain/gcc/__RISCV_BUILD__/../gcc/passes.cc:2096
0x18e1c52 do_per_function
/home/pli/gcc/555/riscv-gnu-toolchain/gcc/__RISCV_BUILD__/../gcc/passes.cc:1688
0x18e3222 execute_todo
I bet the reason is that we created new stmt like stmt_cond and stmt_val but we
don't insert it.
Thus, there will be orphan nodes somewhere and we need something like rollback
to recover the
gimple up to a point. I tried sorts of release_xx or likewise but seems not
working.
So is there any suggest to take care of such gimple rollback or another
solution for this? Below are
The function to perform the convert from PHI to stmt = cond ? a : b for
reference, thanks a lot.
Pan
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 918cf50b589..7982b65bac4 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -486,6 +486,88 @@ phiopt_early_allow (gimple_seq &seq, gimple_match_op &op)
}
}
+extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree));
+
+/* Try to match the phi expr to the gimple cond. Return true if we can
+ perform the convert or return false. There will be some restrictions
+ or such kind of conversion, aka:
+
+ 1. Only selected pattern will try this convert.
+ 2. The generated gassign matched the selected IFN pattern.
+ 3. The backend has implement the standard name.
+
+ From:
+ <bb 2> :
+ _1 = x_3(D) + y_4(D);
+ if (_1 >= x_3(D))
+ goto <bb 3>; [INV]
+ else
+ goto <bb 4>; [INV]
+
+ <bb 3> :
+
+ <bb 4> :
+ # _2 = PHI <255(2), _1(3)>
+
+ To:
+ <bb 2> :
+ _1 = x_3(D) + y_4(D);
+ phi_cond_6 = _1 >= x_3(D);
+ _2 = phi_cond_6 ? _1 : 255; */
+
+static bool
+match_phi_to_gimple_cond (basic_block cond_bb, gphi *phi, tree arg0, tree arg1)
+{
+ gcond *cond = as_a <gcond *> (*gsi_last_bb (cond_bb));
+
+ if (!cond)
+ return false;
+
+ enum tree_code code = gimple_cond_code (cond);
+ tree phi_result = gimple_phi_result (phi);
+ tree cond_tree = make_temp_ssa_name (boolean_type_node, NULL, "phi_cond");
+ tree cmp_tree = build2 (code, boolean_type_node, gimple_cond_lhs (cond),
+ gimple_cond_rhs (cond));
+ tree rhs = build3 (COND_EXPR, TREE_TYPE (phi_result), cond_tree, arg0, arg1);
+
+ gassign *stmt_cond = gimple_build_assign (cond_tree, cmp_tree);
+ gassign *stmt_val = gimple_build_assign (phi_result, rhs);
+
+ tree ops[2];
+ tree lhs = gimple_assign_lhs (stmt_val);
+ bool matched_p = (gimple_unsigned_integer_sat_add (lhs, ops, NULL)
+ && direct_internal_fn_supported_p (IFN_SAT_ADD, TREE_TYPE (lhs),
+ OPTIMIZE_FOR_BOTH));
+
+ if (matched_p)
+ {
+ gimple_stmt_iterator gsi = gsi_last_bb (cond_bb);
+ gimple_stmt_iterator psi = gsi_for_stmt (phi);
+
+ gsi_insert_before (&gsi, stmt_cond, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt_val, GSI_SAME_STMT);
+ remove_phi_node (&psi, false);
+ }
+ else
+ {
+ // Clean up the stmt created, but non of blow works well.
+ // gsi = gsi_for_stmt (stmt_val);
+ // gsi_remove (&gsi, true);
+ // release_defs (stmt_val);
+ // ggc_free (stmt_val);
+
+ // gsi = gsi_for_stmt (stmt_cond);
+ // gsi_remove (&gsi, true);
+ // release_defs (stmt_cond);
+ // ggc_free (stmt_cond);
+
+ // release_defs (stmt_cond);
+ // release_defs (stmt_val);
+ release_ssa_name (cond_tree);
+ }
+
+ return matched_p;
+}
+
/* gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT.
Return NULL if nothing can be simplified or the resulting simplified value
with parts pushed if EARLY_P was true. Also rejects non allowed tree code
@@ -826,6 +908,9 @@ match_simplify_replacement (basic_block cond_bb,
basic_block middle_bb,
So, given the condition COND, and the two PHI arguments, match and
simplify
can happen on (COND) ? arg0 : arg1. */
+ if (match_phi_to_gimple_cond (cond_bb, phi, arg0, arg1))
+ return true;
+
stmt = last_nondebug_stmt (cond_bb);
/* We need to know which is the true edge and which is the false
-----Original Message-----
From: Jeff Law <[email protected]>
Sent: Thursday, May 23, 2024 10:59 PM
To: Richard Biener <[email protected]>; Li, Pan2 <[email protected]>
Cc: [email protected]; [email protected]; [email protected];
[email protected]; [email protected]
Subject: Re: [PATCH v2] Match: Support __builtin_add_overflow branch form for
unsigned SAT_ADD
On 5/23/24 6:14 AM, Richard Biener wrote:
> On Thu, May 23, 2024 at 1:08 PM Li, Pan2 <[email protected]> wrote:
>>
>> I have a try to convert the PHI from Part-A to Part-B, aka PHI to _2 =
>> phi_cond ? _1 : 255.
>> And then we can do the matching on COND_EXPR in the underlying widen-mul
>> pass.
>>
>> Unfortunately, meet some ICE when verify_gimple_phi in sccopy1 pass =>
>> sat_add.c:66:1: internal compiler error: tree check: expected class ‘type’,
>> have ‘exceptional’ (error_mark) in useless_type_conversion_p, at
>> gimple-expr.cc:86
>
> Likely you have released _2, more comments below on your previous mail.
You can be sure by calling debug_tree () on the SSA_NAME node in
question. If it reports "in-free-list", then that's definitive that the
SSA_NAME was released back to the SSA_NAME manager. If that SSA_NAME is
still in the IL, then that's very bad.
jeff