aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-11-06 12:04:30 -0800
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>2025-11-07 12:06:32 -0800
commita1de16a8e523de2ba928f7b5251059329eef0dc6 (patch)
treebcf74387b146b6ef244284cae2f613a21f4cfc07
parent0c0b0e727995cee804d5f72d243ca2112a0005c2 (diff)
downloadgcc-a1de16a8e523de2ba928f7b5251059329eef0dc6.zip
gcc-a1de16a8e523de2ba928f7b5251059329eef0dc6.tar.gz
gcc-a1de16a8e523de2ba928f7b5251059329eef0dc6.tar.bz2
forwprop: Handle already true/false branchs in optimize_unreachable [PR122588]
When optimize_unreachable was moved from fab to forwprop, I missed that due to the integrated copy prop, we might end up with an already true branch leading to a __builtin_unreachable block. optimize_unreachable would switch around the if and things go down hill from there since the other edge was already marked as non-executable, forwprop didn't process those blocks and didn't do copy prop into that block and the original assignment statement was removed. This fixes the problem by having optimize_unreachable not touch the if statement was already changed to true/false. Note I placed the testcase in gcc.c-torture/compile as gcc.dg/torture is NOT currently testing -Og (see PR 122450 for that). Changes since v1: * v2: Add gimple testcase. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/122588 gcc/ChangeLog: * tree-ssa-forwprop.cc (optimize_unreachable): Don't touch if the condition was already true or false. gcc/testsuite/ChangeLog: * gcc.c-torture/compile/pr122588-1.c: New test. * gcc.dg/tree-ssa/pr122588-1.c: New test. Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr122588-1.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c30
-rw-r--r--gcc/tree-ssa-forwprop.cc7
3 files changed, 61 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c
new file mode 100644
index 0000000..43ec621
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c
@@ -0,0 +1,25 @@
+/* Disable warnings about __sync_nand_and_fetch. */
+/* { dg-options "-w" } */
+/* PR tree-optimization/122588 */
+
+int i;
+char c;
+
+static inline __attribute__((__always_inline__))
+void foo0 (int a)
+{
+l5:
+ __sync_nand_and_fetch (&i, 0);
+ int x = __builtin_memcmp_eq (&a, 0, 4);
+ if (__builtin_iseqsig (x, 0.))
+ goto l5;
+ if (a)
+ __builtin_unreachable ();
+ c = a;
+}
+
+int
+main ()
+{
+ foo0 (1);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c
new file mode 100644
index 0000000..2c214c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fgimple" } */
+/* PR tree-optimization/122588 */
+
+/* The removal of unreachable blocks should not
+ change blocks which have already become true/false.
+ The function below was is an example of that. And
+ forwprop does not go into non-executable blocks
+ so the statement `t = _1;` was still holding the
+ old reference. */
+
+int t;
+
+__GIMPLE(ssa,startwith("forwprop4")) void g(void)
+{
+ int _1;
+ __BB(2):
+ _1 = 1;
+ if (_1 != 0)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ __BB(3):
+ __builtin_unreachable ();
+
+ __BB(4):
+ t = _1;
+ return;
+}
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index ae7f0e7..9f8d4ad 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -5080,7 +5080,12 @@ optimize_unreachable (basic_block bb)
stmt = gsi_stmt (gsi);
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
- if (e->flags & EDGE_TRUE_VALUE)
+ /* If the condition is already true/false
+ ignore it. This can happen during copy prop of forwprop. */
+ if (gimple_cond_true_p (cond_stmt)
+ || gimple_cond_false_p (cond_stmt))
+ continue;
+ else if (e->flags & EDGE_TRUE_VALUE)
gimple_cond_make_false (cond_stmt);
else if (e->flags & EDGE_FALSE_VALUE)
gimple_cond_make_true (cond_stmt);