-/* Iterate all gimple statements and try to expand
- VEC_COND_EXPR assignments. */
+namespace {
+
+const pass_data pass_data_gimple_isel =
+{
+ GIMPLE_PASS, /* type */
+ "isel", /* name */
+ OPTGROUP_VEC, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_update_ssa, /* todo_flags_finish */
+};
-static unsigned int
-gimple_expand_vec_exprs (struct function *fun)
+class pass_gimple_isel : public gimple_opt_pass
+{
+public:
+ pass_gimple_isel (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_gimple_isel, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate (function *) final override
+ {
+ return true;
+ }
+
+ 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;
{
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)
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 <gassign *> (*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<gassign *, 4> 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 <gassign *> (USE_STMT (use_p)));
+ }
+ for (unsigned i = cond_exprs.length () == cnt ? 1 : 0;
+ i < cond_exprs.length (); ++i)
+ {
+ gassign *copy = as_a <gassign *> (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]);
+ }
+ }
}
}
- for (hash_map<tree, unsigned int>::iterator it = vec_cond_ssa_name_uses.begin ();
+ 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));
return cfg_changed ? TODO_cleanup_cfg : 0;
}
-namespace {
-
-const pass_data pass_data_gimple_isel =
-{
- GIMPLE_PASS, /* type */
- "isel", /* name */
- OPTGROUP_VEC, /* optinfo_flags */
- TV_NONE, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
-};
-
-class pass_gimple_isel : public gimple_opt_pass
-{
-public:
- pass_gimple_isel (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_gimple_isel, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate (function *) final override
- {
- return true;
- }
-
- unsigned int execute (function *fun) final override
- {
- return gimple_expand_vec_exprs (fun);
- }
-
-}; // class pass_gimple_isel
-
} // anon namespace
gimple_opt_pass *