On Mon, May 24, 2021 at 11:52 AM Hongtao Liu <[email protected]> wrote:
>
> Hi:
> Details described in PR.
> Bootstrapped and regtest on
> x86_64-linux-gnu{-m32,}/x86_64-linux-gnu{-m32\
> -march=cascadelake,-march=cascadelake}
> Ok for trunk?
+static tree
+strip_nop_cond_scalar_reduction (bool has_nop, tree op)
+{
+ if (!has_nop)
+ return op;
+
+ if (TREE_CODE (op) != SSA_NAME)
+ return NULL_TREE;
+
+ gimple* stmt = SSA_NAME_DEF_STMT (op);
+ if (!stmt
+ || gimple_code (stmt) != GIMPLE_ASSIGN
+ || gimple_has_volatile_ops (stmt)
+ || gimple_assign_rhs_code (stmt) != NOP_EXPR)
+ return NULL_TREE;
+
+ return gimple_assign_rhs1 (stmt);
this allows arbitrary conversions where the comment suggests you
only want to allow conversions to the same precision but different sign.
Sth like
gassign *stmt = safe_dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op));
if (!stmt
|| !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
|| !tree_nop_conversion_p (TREE_TYPE (op), TREE_TYPE
(gimple_assign_rhs1 (stmt))))
return NULL_TREE;
+ if (gimple_bb (stmt) != gimple_bb (*nop_reduc)
+ || gimple_code (stmt) != GIMPLE_ASSIGN
+ || gimple_has_volatile_ops (stmt))
+ return false;
!is_gimple_assign (stmt) instead of gimple_code (stmt) != GIMPLE_ASSIGN
the gimple_has_volatile_ops check is superfluous given you restrict
the assign code.
+ /* Check that R_NOP1 is used in nop_stmt or in PHI only. */
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_nop1)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (use_stmt == SSA_NAME_DEF_STMT (r_op1))
+ continue;
+ if (gimple_code (use_stmt) != GIMPLE_PHI)
+ return false;
can the last check be use_stmt == phi since we should have the
PHI readily available?
@@ -1735,6 +1822,23 @@ convert_scalar_cond_reduction (gimple *reduc,
gimple_stmt_iterator *gsi,
rhs = fold_build2 (gimple_assign_rhs_code (reduc),
TREE_TYPE (rhs1), op0, tmp);
+ if (has_nop)
+ {
+ /* Create assignment nop_rhs = op0 +/- _ifc_. */
+ tree nop_rhs = make_temp_ssa_name (TREE_TYPE (rhs1), NULL, "_nop_");
+ gimple* new_assign2 = gimple_build_assign (nop_rhs, rhs);
+ gsi_insert_before (gsi, new_assign2, GSI_SAME_STMT);
+ /* Rebuild rhs for nop_expr. */
+ rhs = fold_build1 (NOP_EXPR,
+ TREE_TYPE (gimple_assign_lhs (nop_reduc)),
+ nop_rhs);
+
+ /* Delete nop_reduc. */
+ stmt_it = gsi_for_stmt (nop_reduc);
+ gsi_remove (&stmt_it, true);
+ release_defs (nop_reduc);
+ }
+
hmm, the whole function could be cleaned up with sth like
/* Build rhs for unconditional increment/decrement. */
gimple_seq stmts = NULL;
rhs = gimple_build (&stmts, gimple_assing_rhs_code (reduc),
TREE_TYPE (rhs1), op0, tmp);
if (has_nop)
rhs = gimple_convert (&stmts, TREE_TYPE (gimple_assign_lhs
(nop_reduc)), rhs);
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
plus in the caller moving the
new_stmt = gimple_build_assign (res, rhs);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
to the else branch as well as the folding done on new_stmt (maybe return
new_stmt instead of rhs from convert_scalar_cond_reduction.
Richard.
> gcc/ChangeLog:
>
> PR tree-optimization/pr98365
> * tree-if-conv.c (strip_nop_cond_scalar_reduction): New function.
> (is_cond_scalar_reduction): Handle nop_expr in cond scalar reduction.
> (convert_scalar_cond_reduction): Ditto.
> (predicate_scalar_phi): Ditto.
>
> gcc/testsuite/ChangeLog:
>
> PR tree-optimization/pr98365
> * gcc.target/i386/pr98365.c: New test.
>
> --
> BR,
> Hongtao