From cbe5f6859a73b2acf203bd7d13f9fb245d63cbd4 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 18 Jul 2023 10:02:52 +0200 Subject: [PATCH] middle-end/105715 - missed RTL if-conversion with COND_EXPR expansion When the COND_EXPR condition operand was split out to a separate stmt it became subject to CSE with other condition evaluations. This unfortunately leads to TER no longer applying and in turn RTL expansion of COND_EXPRs no longer seeing the condition and thus failing to try conditional move expansion. This can be seen with gcc.target/i386/pr45685.c when built with -march=cascadelake which then FAILs to produce the expected number of cmovs. It can also be seen when we create more COND_EXPRs early like for instruction selection of MIN/MAX operations that map to IEEE a > b ? a : b expression semantics. PR middle-end/105715 * gimple-isel.cc (gimple_expand_vec_exprs): Merge into... (pass_gimple_isel::execute): ... this. Duplicate comparison defs of COND_EXPRs. --- gcc/gimple-isel.cc | 127 +++++++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 44 deletions(-) diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc index e5670645d76..8deb3719c35 100644 --- a/gcc/gimple-isel.cc +++ b/gcc/gimple-isel.cc @@ -336,47 +336,6 @@ gimple_expand_vec_cond_expr (struct function *fun, gimple_stmt_iterator *gsi, -/* Iterate all gimple statements and try to expand - VEC_COND_EXPR assignments. */ - -static unsigned int -gimple_expand_vec_exprs (struct function *fun) -{ - gimple_stmt_iterator gsi; - basic_block bb; - hash_map vec_cond_ssa_name_uses; - auto_bitmap dce_ssa_names; - bool cfg_changed = false; - - FOR_EACH_BB_FN (bb, fun) - { - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple *g = gimple_expand_vec_cond_expr (fun, &gsi, - &vec_cond_ssa_name_uses); - if (g != NULL) - { - tree lhs = gimple_assign_lhs (gsi_stmt (gsi)); - gimple_set_lhs (g, lhs); - gsi_replace (&gsi, g, false); - } - - cfg_changed |= gimple_expand_vec_set_extract_expr (fun, &gsi); - - if (gsi_end_p (gsi)) - break; - } - } - - for (hash_map::iterator it = vec_cond_ssa_name_uses.begin (); - it != vec_cond_ssa_name_uses.end (); ++it) - bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION ((*it).first)); - - simple_dce_from_worklist (dce_ssa_names); - - return cfg_changed ? TODO_cleanup_cfg : 0; -} - namespace { const pass_data pass_data_gimple_isel = @@ -405,12 +364,92 @@ public: return true; } - unsigned int execute (function *fun) final override + unsigned int execute (function *fun) final override; +}; // class pass_gimple_isel + + +/* Iterate all gimple statements and perform pre RTL expansion + GIMPLE massaging to improve instruction selection. */ + +unsigned int +pass_gimple_isel::execute (struct function *fun) +{ + gimple_stmt_iterator gsi; + basic_block bb; + hash_map vec_cond_ssa_name_uses; + auto_bitmap dce_ssa_names; + bool cfg_changed = false; + + FOR_EACH_BB_FN (bb, fun) { - return gimple_expand_vec_exprs (fun); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function + calls mapping to supported optabs. */ + gimple *g = gimple_expand_vec_cond_expr (fun, &gsi, + &vec_cond_ssa_name_uses); + if (g != NULL) + { + tree lhs = gimple_assign_lhs (gsi_stmt (gsi)); + gimple_set_lhs (g, lhs); + gsi_replace (&gsi, g, false); + } + + /* Recognize .VEC_SET and .VEC_EXTRACT patterns. */ + cfg_changed |= gimple_expand_vec_set_extract_expr (fun, &gsi); + if (gsi_end_p (gsi)) + break; + + gassign *stmt = dyn_cast (*gsi); + if (!stmt) + continue; + + tree_code code = gimple_assign_rhs_code (stmt); + tree lhs = gimple_assign_lhs (stmt); + if (TREE_CODE_CLASS (code) == tcc_comparison + && !has_single_use (lhs)) + { + /* Duplicate COND_EXPR condition defs when they are + comparisons so RTL expansion with the help of TER + can perform better if conversion. */ + imm_use_iterator imm_iter; + use_operand_p use_p; + auto_vec cond_exprs; + unsigned cnt = 0; + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs) + { + if (is_gimple_debug (USE_STMT (use_p))) + continue; + cnt++; + if (gimple_bb (USE_STMT (use_p)) == bb + && is_gimple_assign (USE_STMT (use_p)) + && gimple_assign_rhs1_ptr (USE_STMT (use_p)) == use_p->use + && gimple_assign_rhs_code (USE_STMT (use_p)) == COND_EXPR) + cond_exprs.safe_push (as_a (USE_STMT (use_p))); + } + for (unsigned i = cond_exprs.length () == cnt ? 1 : 0; + i < cond_exprs.length (); ++i) + { + gassign *copy = as_a (gimple_copy (stmt)); + tree new_def = duplicate_ssa_name (lhs, copy); + gimple_assign_set_lhs (copy, new_def); + auto gsi2 = gsi_for_stmt (cond_exprs[i]); + gsi_insert_before (&gsi2, copy, GSI_SAME_STMT); + gimple_assign_set_rhs1 (cond_exprs[i], new_def); + update_stmt (cond_exprs[i]); + } + } + } } -}; // class pass_gimple_isel + for (auto it = vec_cond_ssa_name_uses.begin (); + it != vec_cond_ssa_name_uses.end (); ++it) + bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION ((*it).first)); + + simple_dce_from_worklist (dce_ssa_names); + + return cfg_changed ? TODO_cleanup_cfg : 0; +} } // anon namespace