Hi Jeff,

> On 20 Sep 2026, at 19:14, Jeff Law <[email protected]> wrote:
> 
> 
> 
> On 9/4/26 6:35 AM, [email protected] wrote:
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> The conditional-compare expander accepts a plain boolean as a comparison
>> against zero. This is useful when a chain also contains an explicit
>> comparison. It is harmful when every leaf is a boolean. For example:
>> 
>> _Bool
>> f (_Bool x, _Bool y)
>> {
>> return x || y;
>> }
>> 
>> AArch64 emitted:
>> 
>> and w1, w1, 255
>> tst w0, 255
>> ccmp w1, 0, 0, eq
>> cset w0, ne
>> 
>> Make candidate recognition report whether it found an explicit comparison.
>> It already validates every statement before it follows the next definition.
>> Reject a candidate without an explicit comparison.
>> 
>> TER fallback starts a new conditional-compare recognition call for each
>> forwarded suffix. Cache accepted all-boolean subchains in the existing
>> per-function ssaexpand state so that these calls inspect a linear chain in
>> linear time. The state is shared by cfgexpand and expression expansion and
>> is released when RTL expansion finishes.
>> 
>> The example then emits:
>> 
>> orr w0, w0, w1
>> 
>> Tests cover all-boolean and mixed chains, a non-binary boolean definition,
>> and a long rejected chain.
>> 
>> Changes since v1:
>> - Report explicit comparisons during candidate recognition.
>> - Cache all-boolean subchains so TER fallback stays linear.
>> - Add non-binary definition and long-chain tests.
>> 
>> gcc/
>> 
>> PR middle-end/109832
>> * ccmp.cc (ccmp_tree_comparison_p): Report whether an accepted leaf
>> is a comparison.
>> (ccmp_candidate_p): Propagate the result and cache all-boolean
>> candidates.
>> (expand_ccmp_expr): Reject an all-boolean candidate.
>> * tree-outof-ssa.h (ssaexpand::ccmp_no_comparison): New member.
>> * tree-outof-ssa.cc (finish_out_of_ssa): Free it.
>> 
>> gcc/testsuite/
>> 
>> PR middle-end/109832
>> * gcc.target/aarch64/ccmp_7.c: New test.
>> * gcc.target/aarch64/ccmp_9.c: Likewise.
>> * gcc.target/aarch64/ccmp_11.c: Likewise.
>> * gcc.target/aarch64/ccmp_13.c: Likewise.
>> 
>> Signed-off-by: Kyrylo Tkachov <[email protected]>
> I must be missing something here.  On both RISC-V and AArch64 we get this 
> coming out of gimple:
> 
>> bool f (bool x, bool y) 
>> { 
>>  bool _3; 
>> 
>> ;;   basic block 2, loop depth 0 
>> ;;    pred:       ENTRY 
>>  _3 = x_1(D) | y_2(D); 
>>  return _3; 
>> ;;    succ:       EXIT  
>> 
>> }
>> 
> So that's sensible.  On RISC-V that then expands into:
> 
>> (insn 7 4 8 2 (set (reg:DI 138) 
>>        (ior:DI (reg/v:DI 135 [ x ]) 
>>            (reg/v:DI 136 [ y ]))) "j.c":4:14 -1 
>>     (nil))  
>> (insn 8 7 9 2 (set (reg:DI 139) 
>>        (zero_extend:DI (subreg:QI (reg:DI 138) 0))) "j.c":4:14 discrim 1 -1 
>>     (nil))
>> 
> 
> We later are able to track the nonzero bits in r135 and r136 and compute 
> nonzero bits for r138.  That in turn allows removal of the zero extension 
> resulting in:
> 
>> : 
>>        or      a0,a0,a1        # 13    [c=4 l=4]  *iordi3/0 
>>        ret             # 27    [c=0 l=4]  simple_return
>> 
> 
> aarch64 on the other hand generates this:
> 
>> (insn 7 4 8 2 (set (reg:CC 66 cc) 
>>        (compare:CC (reg/v:SI 103 [ x ]) 
>>            (const_int 0 [0]))) "j.c":4:14 -1 
>>     (nil)) 
>> (insn 8 7 11 2 (set (reg:CC 66 cc) 
>>        (if_then_else:CC (eq (reg:CC 66 cc) 
>>                (const_int 0 [0])) 
>>            (compare:CC (reg/v:SI 104 [ y ]) 
>>                (const_int 0 [0])) 
>>            (unspec:CC [ 
>>                    (const_int 0 [0]) 
>>                ] UNSPEC_NZCV))) "j.c":4:14 -1 
>>     (nil)) 
>> (insn 11 8 12 2 (set (reg:SI 107) 
>>        (ne:SI (reg:CC 66 cc) 
>>            (const_int 0 [0]))) "j.c":4:14 -1 
>>     (nil))
>> 
> Which is in the WTH space.    I suspect sensible initial code generation 
> would really help here.
> 
> Not objecting to the patchkit right now as there may be a good reason for the 
> initial RTL in the AArch port, but it's also the case that if we can arrange 
> for clean code early, it's often better to do so.
> 

This is what this patch 1 is intended to address:
The RTL in your message is the pre-patch result. On targets with conditional 
compares, expand_expr_real_gassign tries the generic conditional-compare 
expander before normal binary expansion. Without this patch, it treats each 
plain boolean as != 0, which sends the expression through the AArch64 CMP/CCMP 
hooks.
This patch rejects the all-boolean candidate before that expander emits any 
RTL. Expansion then falls through to the normal BIT_IOR_EXPR path. The initial 
RTL after the patch contains an ior:SI, which produces orr w0, w0, w1. It 
therefore starts with the same ordinary IOR form as the RISC-V expansion. Mixed 
chains still use conditional compares.

> jeff
> 

Reply via email to