https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121787
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Component|target |rtl-optimization
See Also| |https://gcc.gnu.org/bugzill
| |a/show_bug.cgi?id=121829
CC| |ebotcazou at gcc dot gnu.org,
| |jakub at gcc dot gnu.org,
| |rguenth at gcc dot gnu.org
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Robin Dapp from comment #2)
> Happens in vsetvl but during the initialization phase when we call
> loop_optimizer_init which does checking_verify_loop_structure. Maybe the
> loop structure has been broken for several passes already and we only notice
> in vsetvl?
The pass manager verifies loop structure after each pass.
> ;; basic block 3, loop depth 1, count 1073741824 (estimated locally, freq
> 9.0909), maybe hot
> ;; prev block 6, next block 4, flags: (REACHABLE, RTL, MODIFIED)
> ;; pred: 6 [always] count:955630224 (estimated locally, freq 8.0909)
> (FALLTHRU,DFS_BACK)
> ;; 2 [50.0% (adjusted)] count:59055800 (estimated locally,
> freq 0.5000)
> ;; 5 [always] count:59055800 (estimated locally, freq 0.5000)
>
> The loop is being changed by apply_loop_flags before verifying it.
Unlikely but not impossible that this wrecks it. I see:
t.c:10:1: error: loop 1’s header does not have exactly 2 entries
10 | }
| ^
during RTL pass: vsetvl
t.c:10:1: internal compiler error: in verify_loop_structure, at cfgloop.cc:1741
and indeed there's a missing preheader. Before loop_optimizer_init ()
we have
(code_label 10 8 11 3 4 ("j") [2 uses])
(note 11 10 12 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
(jump_insn 12 11 13 3 (asm_operands/v ("#asm2") ("") 0 []
[]
[
(label_ref:DI 10)
] t.c:15) "t.c":15:3 -1
(nil)
-> 10)
as loop (single block, but with asm goto). We then split the entry
edge to create a preheader but that messes up the asm goto in BB 2.
This looks very similar to the situation in PR121829. We do _not_
create a forwarder block on RTL.
But the problematic transform is force_single_succ_latches (), which does
simply split_edge () on the latch edge and that in turn messes up the
preheader because of:
/* We are going to place the new block in front of edge destination.
Avoid existence of fallthru predecessors. */
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{
edge e = find_fallthru_edge (edge_in->dest->preds);
if (e)
force_nonfallthru (e);
}
and force_nonfallthru_and_redirect does not seem to handle asm goto
correctly and we end up with a diamond.
I'm not very familiar with cfgrtl.cc, but clearly what force_nonfallthru
above does looks weird (if not wrong). Seems like a latent issue though,
possibly to avoid in the risc backend if you avoid LOOPS_NORMAL but
use AVOID_CFG_MANIPULATION - unsure if you need any of the things
LOOPS_NORMAL gets you.
diff --git a/gcc/cfgloopmanip.cc b/gcc/cfgloopmanip.cc
index 81b64f7d063..0455c901c45 100644
--- a/gcc/cfgloopmanip.cc
+++ b/gcc/cfgloopmanip.cc
@@ -1623,9 +1623,11 @@ create_preheader (class loop *loop, int flags)
should not end with a control instruction. */
/* ??? This, and below JUMP_P check needs to be a new
CFG hook. */
- || (cfun->curr_properties & PROP_gimple
- && !gsi_end_p (gsi_last_bb (single_entry->src))
- && stmt_ends_bb_p (*gsi_last_bb (single_entry->src)))))
+ || ((cfun->curr_properties & PROP_gimple
+ && !gsi_end_p (gsi_last_bb (single_entry->src))
+ && stmt_ends_bb_p (*gsi_last_bb (single_entry->src))
+ || (cfun->curr_properties & PROP_rtl
+ && JUMP_P (BB_END (single_entry->src)))))))
need_forwarder_block = true;
/* If we want fallthru preheaders, also create forwarder block when
avoids the issue (extending the PR121829 fix to RTL).