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.

Reply via email to