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;
+               }
+            }

Thank you
Robert

Reply via email to