I noticed this while working on std::optional, the full blown cselim with data
references
hanldes the case where there are a few stores on either side of the branch that
don't
interfer with the other stores. We could just support clobbers but that would
have
a similar code except for an extra check for clobbers. So let's just add
support
for skipping on store on either side of the conditional too.
The change to trailing_store_in_bb simplifies some things as already the other
side would check on the store being a simple assign, this does not change
anything.
Note cselim-1.c was reduced from a draft version of this patch which was
miscompiling isl.
In the whole testsuite the only regressions were in graphite. So I thought it
would
be a good idea to have a testcase to be added for the miscompiling case. I had
forgot
some stores could also be loads so another check was needed in that case.
This was found by looking into std::optional::reset code gen.
Changes since v1:
* v2: skip stores and not just clobbers
Bootstrapped and tested on x86_64-linux-gnu.
PR tree-optimization/127053
gcc/ChangeLog:
* tree-ssa-phiopt.cc (trailing_store_in_bb): Rename vphi to
vuse_only.
(cond_if_else_store_replacement_limited): Add case if
cond_if_else_store_replacement_1 failed, allowing
for skipping one store on each side.
(trailing_store_in_bb): Require the store stmt
to be a gimple simple assign.
gcc/testsuite/ChangeLog:
* g++.dg/tree-ssa/cselim-2.C: New test.
* gcc.dg/torture/cselim-1.c: New test.
Signed-off-by: Andrea Pinski <[email protected]>
---
gcc/testsuite/g++.dg/tree-ssa/cselim-2.C | 23 ++++++++++
gcc/testsuite/gcc.dg/torture/cselim-1.c | 34 ++++++++++++++
gcc/tree-ssa-phiopt.cc | 56 +++++++++++++++++++++---
3 files changed, 107 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/tree-ssa/cselim-2.C
create mode 100644 gcc/testsuite/gcc.dg/torture/cselim-1.c
diff --git a/gcc/testsuite/g++.dg/tree-ssa/cselim-2.C
b/gcc/testsuite/g++.dg/tree-ssa/cselim-2.C
new file mode 100644
index 00000000000..9c040f9d183
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/cselim-2.C
@@ -0,0 +1,23 @@
+// PR tree-optimization/127053
+// { dg-do compile }
+// { dg-options "-O2 -ftree-cselim -fdump-tree-phiopt1-details" }
+// testcase reduced from std::optional::reset.
+
+void sink(int*);
+typedef int T;
+
+int f(int b, T *c)
+{
+ int a;
+ sink(&a);
+ if (b)
+ {
+ a = 0;
+ c->~T();
+ }
+ else
+ a = 0;
+ return a;
+}
+
+// { dg-final { scan-tree-dump "factoring out stores" "phiopt1" } }
diff --git a/gcc/testsuite/gcc.dg/torture/cselim-1.c
b/gcc/testsuite/gcc.dg/torture/cselim-1.c
new file mode 100644
index 00000000000..4133f627b26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/cselim-1.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+
+/* CS-ELIM was miscompiling this
+ by moving the store of v1.t across
+ the load of v1 in `v2 = v1`. */
+
+/* This was reduced from isl manually. */
+
+struct s1 {
+ int t;
+};
+
+struct s1 v1, v2;
+
+[[gnu::noipa]]
+void f(int a) {
+ if (a) {
+ v1.t = 1;
+ v2 = v1;
+ } else {
+ v1.t = 2;
+ v2 = v1;
+ }
+}
+
+int main()
+{
+ f(1);
+ if (v2.t != 1)
+ __builtin_abort ();
+ f(0);
+ if (v2.t != 2)
+ __builtin_abort ();
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 343cd159118..c1a32106a00 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -3503,12 +3503,12 @@ cond_if_else_store_replacement_1 (basic_block then_bb,
basic_block else_bb,
}
/* Return the last store in BB with VDEF or NULL if there are
- loads following the store. VPHI is where the only use of the
+ loads following the store. VUSE_ONLY is where the only use of the
vdef should be. If ONLYONESTORE is true, then the store is
the only store in the BB. */
static gimple *
-trailing_store_in_bb (basic_block bb, tree vdef, gphi *vphi, bool onlyonestore)
+trailing_store_in_bb (basic_block bb, tree vdef, gimple *vuse_only, bool
onlyonestore)
{
if (SSA_NAME_IS_DEFAULT_DEF (vdef))
return NULL;
@@ -3524,14 +3524,17 @@ trailing_store_in_bb (basic_block bb, tree vdef, gphi
*vphi, bool onlyonestore)
&& gimple_code (SSA_NAME_DEF_STMT (gimple_vuse (store))) != GIMPLE_PHI)
return NULL;
+ // Needs to be an simple store and not a call.
+ if (!gimple_assign_single_p (store))
+ return NULL;
/* Verify there is no load or store after the store, the vdef of the store
- should only be used by the vphi joining the 2 bbs. */
+ should only be used by the vuse_only. */
use_operand_p use_p;
gimple *use_stmt;
if (!single_imm_use (gimple_vdef (store), &use_p, &use_stmt))
return NULL;
- if (use_stmt != vphi)
+ if (use_stmt != vuse_only)
return NULL;
return store;
@@ -3854,8 +3857,49 @@ cond_if_else_store_replacement_limited (basic_block
then_bb, basic_block else_bb
if (!else_assign)
return false;
- return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
- then_assign, else_assign, vphi);
+ if (!cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
+ then_assign, else_assign, vphi))
+ {
+ gimple *then_n, *else_n;
+
+ // Try to see if one "store" can be skipped on either side.
+ if (!flag_expensive_optimizations)
+ return false;
+ then_n = trailing_store_in_bb (then_bb, gimple_vuse (then_assign),
+ then_assign, true);
+ if (then_n)
+ {
+ ao_ref then_ref_n;
+ ao_ref_init (&then_ref_n, gimple_assign_lhs (then_n));
+ if (stmt_may_clobber_ref_p_1 (then_assign, &then_ref_n, false)
+ || ref_maybe_used_by_stmt_p (then_assign, &then_ref_n, false))
+ then_n = nullptr;
+ }
+ else_n = trailing_store_in_bb (else_bb, gimple_vuse (else_assign),
+ else_assign, true);
+ if (else_n)
+ {
+ ao_ref else_ref_n;
+ ao_ref_init (&else_ref_n, gimple_assign_lhs (else_n));
+ if (stmt_may_clobber_ref_p_1 (else_assign, &else_ref_n, false)
+ || ref_maybe_used_by_stmt_p (else_assign, &else_ref_n, false))
+ else_n = nullptr;
+ }
+ if (then_n
+ && cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
+ then_n, else_assign, vphi))
+ return true;
+ if (else_n
+ && cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
+ then_assign, else_n, vphi))
+ return true;
+ if (else_n && then_n
+ && cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
+ then_n, else_n, vphi))
+ return true;
+ return false;
+ }
+ return true;
}
/* Conditional store replacement. We already know
--
2.43.0