]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
phiopt: allow store placement of `= {}` [PR122153]
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Fri, 3 Oct 2025 21:09:57 +0000 (14:09 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Sat, 4 Oct 2025 16:25:57 +0000 (09:25 -0700)
Currently cselim and cselim-limited are able to
handle stores which have a rhs of a ssa name or a constant.
This extends that support to also allow `= {}`.
The sink pass will also commonalize the store but in some
cases this is too late in the pipeline. Doing it in phiopt1
allows for better inlining estimates too.

This is also the first step in improving/fixing PR 122083
such that we do an early inlining which is now not happening
for GCC 15+.

Bootstrapped and tested on x86_64-linux-gnu.

PR tree-optimization/122153

gcc/ChangeLog:

* tree-ssa-phiopt.cc (cond_if_else_store_replacement_1): Handle
stores of empty constructors too.

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/pr122153-1.c: New test.

Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c [new file with mode: 0644]
gcc/tree-ssa-phiopt.cc

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr122153-1.c
new file mode 100644 (file)
index 0000000..d6e7527
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-phiopt1" } */
+/* PR tree-optimization/122153 */
+struct s1
+{
+  int t;
+};
+void g(struct s1*);
+struct s1 f(int *a, int c, int d)
+{
+  struct s1 r;
+  int t1;
+  if (c < d)
+  {
+    r = (struct s1){};
+    t1 = c;
+  }
+  else
+  {
+    r = (struct s1){};
+    t1 = d;
+  }
+  g(&r);
+  r.t = t1;
+  return r;
+}
+/* the `r = {};` store should be commonialized out of the conditional
+   and produce a MIN_EXPR in phiopt1. */
+
+/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt1" } } */
index e1c9e1296c0ef2e9117e3d3c63133bcf73ed707c..bdd1f7396da22476c7d1f21381240aca5ed306eb 100644 (file)
@@ -3645,6 +3645,7 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
   gimple_stmt_iterator gsi;
   gphi *newphi;
   gassign *new_stmt;
+  bool empty_constructor = false;
 
   if (then_assign == NULL
       || !gimple_assign_single_p (then_assign)
@@ -3659,8 +3660,7 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
     return false;
 
   lhs = gimple_assign_lhs (then_assign);
-  if (!is_gimple_reg_type (TREE_TYPE (lhs))
-      || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
+  if (!operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
     return false;
 
   lhs_base = get_base_address (lhs);
@@ -3673,6 +3673,16 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
   then_locus = gimple_location (then_assign);
   else_locus = gimple_location (else_assign);
 
+  if (!is_gimple_reg_type (TREE_TYPE (lhs)))
+    {
+      if (!operand_equal_p (then_rhs, else_rhs))
+       return false;
+      /* Currently only handle commoning of `= {}`.   */
+      if (TREE_CODE (then_rhs) != CONSTRUCTOR)
+       return false;
+      empty_constructor = true;
+    }
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf(dump_file, "factoring out stores:\n\tthen:\n");
@@ -3699,12 +3709,17 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
   /* 2) Create a PHI node at the join block, with one argument
        holding the old RHS, and the other holding the temporary
        where we stored the old memory contents.  */
-  name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
-  newphi = create_phi_node (name, join_bb);
-  add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus);
-  add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus);
+  if (empty_constructor)
+    name = unshare_expr (then_rhs);
+  else
+    {
+      name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
+      newphi = create_phi_node (name, join_bb);
+      add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus);
+      add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus);
+    }
 
-  new_stmt = gimple_build_assign (lhs, gimple_phi_result (newphi));
+  new_stmt = gimple_build_assign (lhs, name);
   /* Update the vdef for the new store statement. */
   tree newvphilhs = make_ssa_name (gimple_vop (cfun));
   tree vdef = gimple_phi_result (vphi);
@@ -3715,16 +3730,21 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
   update_stmt (vphi);
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf(dump_file, "to use phi:\n");
-      print_gimple_stmt (dump_file, newphi, 0,
-                        TDF_VOPS|TDF_MEMSYMS);
-      fprintf(dump_file, "\n");
+      if (!empty_constructor)
+       {
+        fprintf(dump_file, "to use phi:\n");
+         print_gimple_stmt (dump_file, newphi, 0,
+                            TDF_VOPS|TDF_MEMSYMS);
+          fprintf(dump_file, "\n");
+       }
+      else
+       fprintf(dump_file, "to:\n");
       print_gimple_stmt (dump_file, new_stmt, 0,
                         TDF_VOPS|TDF_MEMSYMS);
       fprintf(dump_file, "\n\n");
     }
 
-  /* 3) Insert that PHI node.  */
+  /* 3) Insert that new store.  */
   gsi = gsi_after_labels (join_bb);
   if (gsi_end_p (gsi))
     {