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 >
