On Mon, May 24, 2021 at 11:52 AM Hongtao Liu <crazy...@gmail.com> 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