https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84301
--- Comment #4 from Alexander Monakov <amonakov at gcc dot gnu.org> --- Moreover, without --param selsched-max-lookahead=2 sel-sched moves both the assignment and <retval> use into middle of BB 2, breaking the assumption in mode-switching that retval use is the last insn: 249 /* If this function returns a value at the end, we have to 250 insert the final mode switch before the return value copy 251 to its hard register. */ 252 if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1 253 && NONJUMP_INSN_P ((last_insn = BB_END (src_bb))) 254 && GET_CODE (PATTERN (last_insn)) == USE 255 && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG) (independently of max-pending-list-length being 0 or not). It seems a bit surprising that mode-switching needs to treat return value specially, but more importantly, are the restrictions on return value register set/use placement written down somewhere? I don't see any explicit dependencies or barriers either, so isn't this like a repeat of cc0 situation? What are other (dozens of) RTL passes doing to avoid disturbing the required order? Looking via gdb, apparently what pins those uses/clobbers to BB end for haifa-sched is: 2728 /* Selective scheduling handles control dependencies by itself. */ 2729 if (!sel_sched_p ()) 2730 add_branch_dependences (head, tail); but the function doesn't do what it says on the tin: 2432 /* Add dependences so that branches are scheduled to run last in their 2433 block. */ 2434 static void 2435 add_branch_dependences (rtx_insn *head, rtx_insn *tail) 2436 { 2437 rtx_insn *insn, *last; 2438 2439 /* For all branches, calls, uses, clobbers, cc0 setters, and instructions 2440 that can throw exceptions, force them to remain in order at the end of 2441 the block by adding dependencies and giving the last a high priority. 2442 There may be notes present, and prev_head may also be a note.