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