Re: [PATCH v3 2/3] x86: Add a pass to fold tail call
"H.J. Lu" <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAMe9rOoJHqAaA+hdzgwEagE2S_fap5QhAgJWrLaVB8UjJodGXQ@mail.gmail.com> |
On Tue, Aug 11, 2026 at 8:18 PM Uros Bizjak <[email protected]> wrote: > > On Wed, Jul 29, 2026 at 9:49 AM H.J. Lu <[email protected]> wrote: > > > > x86 conditional branch (jcc) target can be either a label or a symbol. > > Add a pass to fold tail call with jcc by turning: > > > > jcc .L6 > > ... > > .L6: > > jmp tailcall > > > > into: > > > > jcc tailcall > > > > Immediately before the pass which turning REG_EH_REGION notes back into > > NOTE_INSN_EH_REGION notes, conditional branches look like > > > > (jump_insn 7 6 14 2 (set (pc) > > (if_then_else (eq (reg:CCZ 17 flags) > > (const_int 0 [0])) > > (label_ref:DI 23) > > (pc))) "x.c":8:5 1458 {jcc} > > (expr_list:REG_DEAD (reg:CCZ 17 flags) > > (int_list:REG_BR_PROB 217325348 (nil))) > > ... > > (code_label 23 20 8 4 4 (nil) [1 uses]) > > (note 8 23 9 4 [bb 4] NOTE_INSN_BASIC_BLOCK) > > (call_insn/j 9 8 10 4 (call (mem:QI (symbol_ref:DI ("bar") [flags 0x41] <functi > > on_decl 0x7f4cff3c0b00 bar>) [0 bar S1 A8]) > > (const_int 0 [0])) "x.c":8:14 discrim 1 1469 {sibcall_di} > > (expr_list:REG_CALL_DECL (symbol_ref:DI ("bar") [flags 0x41] <function_dec > > l 0x7f4cff3c0b00 bar>) > > (nil)) > > (nil)) > > > > Searching backward from exit basic blocks with only sibcalls, check the > > last instruction in each predecessor. If the last instruction is a > > conditional jump and its target is the exit block, change the conditional > > jump target to the sibcall target, decrement the destination basic block > > entry label use count, redirect the edge to the exit basic block and call > > delete_unreachable_blocks to delete the unreachable basic blocks. Repeat > > it until there is no conditional jump to update. > > I think this should use cond_exec infrastructure, where ifcvt rewrites > conditional jump + sibcall to a RTX like: > > (cond_exec > (match_operator 0 "ix86_comparison_operator" [(reg:CC FLAGS_REG) > (const_int 0)]) > (call (mem:QI (match_operand:W 1 "constant_call_address_operand")) > (match_operand 2))) > > It looks that ifcvt is able to do this transformation, since > ifcvt.cc's cond_exec_process_insns, the core loop that wraps an insn's > pattern in COND_EXEC, explicitly asserts NONJUMP_INSN_P (insn) || > CALL_P (insn). It doesn't work for sibcall since the sibcall edge is marked with e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_ABNORMAL | EDGE_SIBCALL); and cond_exec_find_if_block doesn't support edges marked with EDGE_COMPLEX which is defined as /* The following four flags all indicate something special about an edge. Test the edge flags on EDGE_COMPLEX to detect all forms of "strange" control flow transfers. */ #define EDGE_COMPLEX \ (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE) > Looking at arm.md, its call instructions use %? predicate, but they > don't set "predicated" attribute for some reason. > > Please see chapter 18.21 Conditional Execution in GCC internals. > > Uros. -- H.J.