https://gcc.gnu.org/g:a1de16a8e523de2ba928f7b5251059329eef0dc6
commit r16-5084-ga1de16a8e523de2ba928f7b5251059329eef0dc6 Author: Andrew Pinski <[email protected]> Date: Thu Nov 6 12:04:30 2025 -0800 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 <[email protected]> Diff: --- gcc/testsuite/gcc.c-torture/compile/pr122588-1.c | 25 ++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c | 30 ++++++++++++++++++++++++ gcc/tree-ssa-forwprop.cc | 7 +++++- 3 files changed, 61 insertions(+), 1 deletion(-) 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 000000000000..43ec621512c5 --- /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 000000000000..2c214c905765 --- /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 ae7f0e770ba2..9f8d4ad3b443 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);
