https://gcc.gnu.org/g:4933ad22c7293472c0bd283dce5680e6415b3819

commit r16-8087-g4933ad22c7293472c0bd283dce5680e6415b3819
Author: Andrew Pinski <[email protected]>
Date:   Thu Mar 12 15:35:30 2026 -0700

    cprop_hardreg: purge dead edges and cleanupcfg if something changes 
[PR124454]
    
    cprop_hardreg changes:
    ```
    (insn 69 62 183 6 (set (reg:SI 1 x1 [orig:107 _12 ] [107])
            (zero_extend:SI (mem:QI (reg/f:DI 1 x1 [150]) [0 MEM[(char *)_4]+0 
S1 A64]))) "/app/example.cpp":8:7 discrim 1 149 {*zero_extendqisi2_aarch64}
         (expr_list:REG_EH_REGION (const_int 2 [0x2])
            (nil)))
    ```
    
    into:
    ```
    (insn 69 62 183 6 (set (reg:SI 1 x1 [orig:107 _12 ] [107])
            (zero_extend:SI (mem:QI (plus:DI (reg/f:DI 31 sp)
                        (const_int 56 [0x38])) [0 MEM[(char *)_4]+0 S1 A64]))) 
"/app/example.cpp":8:7 discrim 1 149 {*zero_extendqisi2_aarch64}
         (expr_list:REG_EH_REGION (const_int 2 [0x2])
            (nil)))
    ```
    
    But that new instruction no longer traps as it is load from the stack. So 
later on
    purge_dead_edges removes the REG_EH_REGION note and the edge to the eh 
landing pad
    but this is during find_many_sub_basic_blocks in split3 and nothing then 
removes the
    unreachable basic blocks.
    
    To fix this, instead of depending on a later pass to clean this up, 
cprop_hardreg
    should call purge_all_dead_edges if non-call exceptions were enabled and 
then
    also call cleanup_cfg (to remove the unreachable blocks).
    
    Bootstrapped and tested on x86_64-linux-gnu and lightly tested for 
aarch64-linux-gnu.
    
            PR rtl-optimization/124454
    
    gcc/ChangeLog:
    
            * regcprop.cc (pass_cprop_hardreg::execute): If something
            changed and non-call exceptions is on, call purge_all_dead_edges
            and cleanup_cfg.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/pr124454-1.c: New test.
    
    Signed-off-by: Andrew Pinski <[email protected]>

Diff:
---
 gcc/regcprop.cc                   | 21 +++++++++++++++++++--
 gcc/testsuite/gcc.dg/pr124454-1.c | 15 +++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc
index e884cb5a9666..b1f00ca0435c 100644
--- a/gcc/regcprop.cc
+++ b/gcc/regcprop.cc
@@ -36,6 +36,7 @@
 #include "cfgrtl.h"
 #include "target.h"
 #include "function-abi.h"
+#include "cfgcleanup.h"
 
 /* The following code does forward propagation of hard register copies.
    The object is to eliminate as many dependencies as possible, so that
@@ -1443,6 +1444,7 @@ pass_cprop_hardreg::execute (function *fun)
   auto_vec<int> *curr = &worklist1;
   auto_vec<int> *next = &worklist2;
   bool any_debug_changes = false;
+  bool any_changes = false;
 
   /* We need accurate notes.  Earlier passes such as if-conversion may
      leave notes in an inconsistent state.  */
@@ -1462,7 +1464,10 @@ pass_cprop_hardreg::execute (function *fun)
   FOR_EACH_BB_FN (bb, fun)
     {
       if (cprop_hardreg_bb (bb, all_vd, visited))
-       curr->safe_push (bb->index);
+       {
+         curr->safe_push (bb->index);
+         any_changes = true;
+       }
       if (all_vd[bb->index].n_debug_insn_changes)
        any_debug_changes = true;
     }
@@ -1489,7 +1494,10 @@ pass_cprop_hardreg::execute (function *fun)
        {
          bb = BASIC_BLOCK_FOR_FN (fun, index);
           if (cprop_hardreg_bb (bb, all_vd, visited))
-           next->safe_push (bb->index);
+           {
+             next->safe_push (bb->index);
+             any_changes = true;
+           }
          if (all_vd[bb->index].n_debug_insn_changes)
            any_debug_changes = true;
        }
@@ -1501,6 +1509,15 @@ pass_cprop_hardreg::execute (function *fun)
     }
 
   free (all_vd);
+
+  /* Copy propagation of the sp register into an mem's address
+     can cause what was a trapping instruction into
+     a non-trapping one so cleanup after that in the case of non-call
+     exceptions.  */
+  if (any_changes
+      && cfun->can_throw_non_call_exceptions
+      && purge_all_dead_edges ())
+    cleanup_cfg (0);
   return 0;
 }
 
diff --git a/gcc/testsuite/gcc.dg/pr124454-1.c 
b/gcc/testsuite/gcc.dg/pr124454-1.c
new file mode 100644
index 000000000000..11c4d803d1bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr124454-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3 -fno-forward-propagate -fnon-call-exceptions 
-fno-dse -fprofile-generate -fopenmp -finstrument-functions" } */
+/* { dg-additional-options "-mno-outline-atomics" { target aarch64*-*-* } } */
+
+/* PR rtl-optimization/124454 */
+
+int a, b;
+
+void
+foo()
+{
+  long c;
+  a *= b;
+  b = *(char *)__builtin_memset(&c, 1, 4);
+}

Reply via email to