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.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

I'll push this after confirming it fixes all the fallout of
early MIN/MAX if conversion.

        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 | 121 ++++++++++++++++++++++++++++++---------------
 1 file changed, 80 insertions(+), 41 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,11 +336,43 @@ gimple_expand_vec_cond_expr (struct function *fun, 
gimple_stmt_iterator *gsi,
 
 
 
-/* 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;
@@ -352,6 +384,8 @@ gimple_expand_vec_exprs (struct function *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)
@@ -361,14 +395,54 @@ gimple_expand_vec_exprs (struct function *fun)
              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));
 
@@ -377,41 +451,6 @@ gimple_expand_vec_exprs (struct function *fun)
   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 *
-- 
2.35.3

Reply via email to