https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127853
--- Comment #3 from Vineet Gupta <vineetg at gcc dot gnu.org> ---
You're right, I described it wrongly: with the macro returning 0, VALUE is
meaningless, and the BUILT_IN_C?Z folds you quote correctly check == 2.
The bug is in simplify_count_zeroes (tree-ssa-forwprop.cc). It recognises the
table-based clz/ctz idiom and always builds the two-argument .CLZ (x, VALUE) /
.CTZ (x, VALUE), using VALUE even when C?Z_DEFINED_VALUE_AT_ZERO returned 0.
That breaks the convention fold_builtin_bit_query documents ("Only keep second
argument to IFN_CLZ/IFN_CTZ if it is the value defined at zero during GIMPLE").
The IFN rules right after the ones you quoted,
(cond (ne @0 integer_zerop@1) (IFN_CLZ (convert?@3 @0) INTEGER_CST@2) @2)
and its IFN_CTZ twin, trust that argument and remove the caller's guard.
Testcase attached (clz-table-zero-1.c), x86_64 -O2, no -mlzcnt. For f, after
einline:
_6 = .CLZ (v_3(D), 32); under if (v_3(D) != 0)
phiopt2 (-fdump-tree-phiopt2-details-folding):
Applying pattern match.pd:11800, gimple-match-1.cc:7293
COND_EXPR in block 2 and PHI in block 4 converted to straightline code.
leaving just _6 = .CLZ (v_3(D), 32):
f:
bsrl %edi, %eax
xorl $31, %eax
ret
so f (0) returns garbage and the test aborts, on any CPU. The ctz variant is
the same, but only shows up where rep bsf doesn't execute as tzcnt.
Fix: in simplify_count_zeroes,pass the second argument only when the macro
returns 2; the COND_EXPR it already emits handles zero. Patch to follow.