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).

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.

Reply via email to