https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119778
--- Comment #14 from Richard Biener <rguenth at gcc dot gnu.org> --- In this case speculative call expansion is wrecking abnormal edges. Instead of distributing an abnormal edge to both calls we leave it on the merge block of the if (). The actual issue seems to be that when early inlining void S::foo (struct S * const this) { int (*) () * _1; int (*) () _2; ;; basic block 2, loop depth 0 ;; pred: ENTRY _1 = this_4(D)->_vptr.S; _2 = *_1; OBJ_TYPE_REF(_2;(struct S)this_4(D)->0B) (this_4(D)); return; into qux at ;; basic block 6, loop depth 0 ;; pred: 2 ;; 4 # a.1_4(ab) = PHI <a.1_9(D)(2), a.1_2(ab)(4)> S::foo (y_13(D)); ;; succ: 7 ;; 5 while S::foo (y_13(D)) is marked as ctrl-altering due to the abnormal edge the inlined OBJ_TYPE_REF(_2;(struct S)this_4(D)->0B) (this_4(D)) call is not. We're set up to purge edges, but the indirect call expansion done fails to mark inlined calls it adds abnormal edges from as control-altering.