On 9/19/26 1:17 PM, Robert Guthrie wrote:
Hello again, I think maybe something like this is more reasonable than my last attempt? It passes the same tests as master, bootstraps, etc. except i386/memset-pr120683-23.c, which is just a verbatim asm diff, and it deleted one ret instruction from that output, so I think that is OK.
Does this make sense at a glance?

I still wasn't sure how to correctly handle CFG RTL mode here, but this seems to do a decent job.

diff --git a/gcc/cfgcleanup.cc b/gcc/cfgcleanup.cc
index 1d9ec908dab..7db2a25fc97 100644
--- a/gcc/cfgcleanup.cc
+++ b/gcc/cfgcleanup.cc
@@ -2835,6 +2835,49 @@ try_optimize_cfg (int mode)
            }
        }

+         /* If we have two consecutive return-only basic blocks,
+            delete the second one, redirecting all of its predecessors
+            to the first one.  */
+         if (!(mode & CLEANUP_NO_INSN_DEL)
+             && (mode & CLEANUP_CFGLAYOUT)
+             && bb_is_just_return (b, &ret, &use))
+           {
+             basic_block target = nullptr;
+             edge e;
+             edge_iterator ei;
+             FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+               {
+                 if (b != e->src
+                     && bb_is_just_return (e->src, &ret, &use)
+                     && EDGE_COUNT (e->src->preds) > EDGE_COUNT (b->preds)
+                     && BB_PARTITION (b) == BB_PARTITION (e->src))
+                   {
+                     target = e->src;
+                     break;
+                   }
+               }
+
+             if (target)
+               {
+                 edge e;
+                 for (edge_iterator ei = ei_start (b->preds);
+                       (e = ei_safe_edge (ei));)
+                   redirect_edge_and_branch_force (e, target);
+
+                 if (dump_file)
+                   fprintf (dump_file,
+                     "deleted unnecessary ret-only block %d by "
+                     "re-targeting to %d\n",
+                     b->index, target->index);
+
+                 c = b->next_bb;
+                 delete_basic_block (b);
+                 changed = true;
+                 b = c;
+                 continue;
+               }
+            }
That would be the right track if this case were exposed prior to the end of basic block layout.  I'm not sure it'll work at the point where you need it.  Though maybe I'm missing something.

jeff

Reply via email to