https://gcc.gnu.org/g:0fe35e9b93a286de78dd5b80d8d58e9ef0591f03

commit r15-7067-g0fe35e9b93a286de78dd5b80d8d58e9ef0591f03
Author: Andrew Pinski <quic_apin...@quicinc.com>
Date:   Sun Jan 19 16:07:10 2025 -0800

    inline: Purge the abnormal edges as needed in fold_marked_statements 
[PR118077]
    
    While fixing PR target/117665, I had noticed that fold_marked_statements
    would not purge the abnormal edges which could not be taken any more due
    to folding a call (devirtualization or simplification of a [target] 
builtin).
    Devirutalization could also cause a call that used to be able to have an
    abornal edge become one not needing one too so this was needed for GCC 15.
    
    Bootstrapped and tested on x86_64-linux-gnu
    
            PR tree-optimization/118077
            PR tree-optimization/117668
    
    gcc/ChangeLog:
    
            * tree-inline.cc (fold_marked_statements): Purge abnormal edges
            as needed.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/opt/devirt6.C: New test.
    
    Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>

Diff:
---
 gcc/testsuite/g++.dg/opt/devirt6.C | 23 +++++++++++++++++++++++
 gcc/tree-inline.cc                 | 22 ++++++++++++++++++++--
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/g++.dg/opt/devirt6.C 
b/gcc/testsuite/g++.dg/opt/devirt6.C
new file mode 100644
index 000000000000..5caf9da78910
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/devirt6.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O3" }
+
+// PR tree-optimization/118077
+
+// This used to ICE because the devirtualization call
+// of bb inside f1 (which was inlined into f2) became
+// a direct call to c1::bb but the abnormal edge
+// was not removed even though bb was const.
+
+int f() __attribute__((returns_twice));
+struct c1 {
+  virtual int bb(void) const { return 0; }
+  bool f1(int a)
+  {
+    return a && !bb();
+  }
+};
+struct c2 final : c1 { void f2(int); };
+void c2::f2(int a) {
+  if (!f1(a))
+    f();
+}
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index 11278e5c4832..5b3539009a38 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -5430,6 +5430,7 @@ static void
 fold_marked_statements (int first, hash_set<gimple *> *statements)
 {
   auto_bitmap to_purge;
+  auto_bitmap to_purge_abnormal;
 
   auto_vec<edge, 20> stack (n_basic_blocks_for_fn (cfun) + 2);
   auto_sbitmap visited (last_basic_block_for_fn (cfun));
@@ -5456,8 +5457,16 @@ fold_marked_statements (int first, hash_set<gimple *> 
*statements)
              continue;
 
            gimple *old_stmt = gsi_stmt (gsi);
-           tree old_decl = (is_gimple_call (old_stmt)
-                            ? gimple_call_fndecl (old_stmt) : 0);
+           bool can_make_abnormal_goto = false;
+           tree old_decl = NULL_TREE;
+
+           if (is_gimple_call (old_stmt))
+             {
+               old_decl = gimple_call_fndecl (old_stmt);
+               if (stmt_can_make_abnormal_goto (old_stmt))
+                 can_make_abnormal_goto = true;
+             }
+
            if (old_decl && fndecl_built_in_p (old_decl))
              {
                /* Folding builtins can create multiple instructions,
@@ -5473,6 +5482,8 @@ fold_marked_statements (int first, hash_set<gimple *> 
*statements)
                      {
                        cgraph_update_edges_for_call_stmt (old_stmt,
                                                           old_decl, NULL);
+                       if (can_make_abnormal_goto)
+                         bitmap_set_bit (to_purge_abnormal, dest->index);
                        break;
                      }
                    if (gsi_end_p (i2))
@@ -5501,6 +5512,9 @@ fold_marked_statements (int first, hash_set<gimple *> 
*statements)
                            if (maybe_clean_or_replace_eh_stmt (old_stmt,
                                                                new_stmt))
                              bitmap_set_bit (to_purge, dest->index);
+                           if (can_make_abnormal_goto
+                               && !stmt_can_make_abnormal_goto (new_stmt))
+                             bitmap_set_bit (to_purge_abnormal, dest->index);
                            break;
                          }
                        gsi_next (&i2);
@@ -5521,6 +5535,9 @@ fold_marked_statements (int first, hash_set<gimple *> 
*statements)
 
                if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
                  bitmap_set_bit (to_purge, dest->index);
+               if (can_make_abnormal_goto
+                   && !stmt_can_make_abnormal_goto (new_stmt))
+                 bitmap_set_bit (to_purge_abnormal, dest->index);
              }
          }
 
@@ -5542,6 +5559,7 @@ fold_marked_statements (int first, hash_set<gimple *> 
*statements)
     }
 
   gimple_purge_all_dead_eh_edges (to_purge);
+  gimple_purge_all_dead_abnormal_call_edges (to_purge_abnormal);
 }
 
 /* Expand calls to inline functions in the body of FN.  */

Reply via email to