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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.