On Sun, Aug 23, 2026 at 8:36 PM Jeffrey Law <[email protected]> wrote: > > > > On 8/13/2026 4:03 AM, Milan Tripkovic wrote: > > This patch fixes PR123905, where the compiler generates redundant sign > > Extensions and bit masks on RISC-V when using __builtin_clz, __builtin_ctz > > and __builtin_popcount. > > > > To solve this, the patch introduces the following changes based on > > Jeff's suggestions: > > > > ext-dce.cc: Extracted the redundant sign extension check into a new helper > > function is_trivially_redundant_extension. This uses num_sign_bit_copies > > evaluated in the outer mode to check if the extension is already > > redundant, > > which allows combine to eliminate it instead of ext-dce leaving SUBREGs > > that are harder to optimize. > > > > rtlanal.cc: Improve nonzero_bits1 and num_sign_bit_copies1 so that > > they recognize that the results of CLZ, CTZ, and POPCOUNT are > > bounded by floor_log2 (bitwidth) + 1 bits, meaning that all higher > > bits are known to be zero. > > > > ASM Before: > > clzw a0,a0 > > andn t0,a0,a1 > > sext.w a0,t0 > > ret > > > > ASM After: > > clzw a0,a0 > > andn a0,a0,a1 > > ret > > > > Additionally, this patch includes a new test case > > gcc.target/riscv/pr123905.c > > which covers several scenarios: AND, ANDN, and combinations like clz & ctz > > and clz & ctz & popcount. > > > > 2026-08-13 Milan Tripkovic <[email protected]> > > > > gcc/ChangeLog: > > > > * ext-dce.cc (is_trivially_redundant_extension): New helper > > function. > > (ext_dce_try_optimize_extension): Keep trivially redundant > > SIGN_EXTENDs. > > * rtlanal.cc (nonzero_bits1): Handle POPCOUNT/CLZ/CTZ. > > (num_sign_bit_copies1): Add CLZ/CTZ/POPCOUNT handling. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/riscv/pr123905.c: New test case. > Conceptually it looks good. Since this is a generic change, it needs to > be bootstrapped and regression tested on at least one major platform. > Most folks use x86_64 or aarch64. > > I threw it into my tester to do some broader testing and it failed to > build on x86_64: > > > x86_64-linux-gnu-g++ -std=c++14 -fno-PIE -c -DIN_GCC > > -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall > > -Wno-error=narrowing -Wwrite-strings -Wcast-qual -Wno-format > > -Wmissing-format-attribute -Wconditionally-supported > > -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros > > -Wno-overlength-strings -DHAVE_CONFIG_H -fno-PIE -I. -I. > > -I../../../gcc/gcc -I../../../gcc/gcc/. -I../../../gcc/gcc/../include > > -I../../../gcc/gcc/../libcpp/include -I../../../gcc/gcc/../libcody > > -I../../../gcc/gcc/../libdecnumber > > -I../../../gcc/gcc/../libdecnumber/bid -I../libdecnumber > > -I../../../gcc/gcc/../libbacktrace -o rtlanal.o -MT rtlanal.o -MMD > > -MP -MF ./.deps/rtlanal.TPo ../../../gcc/gcc/rtlanal.cc > > In file included from ./tm.h:29, > > from ../../../gcc/gcc/backend.h:28, > > from ../../../gcc/gcc/rtlanal.cc:24: > > ../../../gcc/gcc/rtlanal.cc: In function 'long unsigned int > > nonzero_bits1(const_rtx, scalar_int_mode, const_rtx, machine_mode, > > long unsigned int)': > > ../../../gcc/gcc/config/i386/i386.h:3059:37: error: cannot convert > > 'poly_uint16' {aka 'poly_int<1, short unsigned int>'} to 'long int' in > > assignment > > 3059 | ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_LZCNT ? 2 : 0) > > | ~~~~~~~~~~~~~~~~~^~~~~~ > > | | > > | poly_uint16 {aka > > poly_int<1, short unsigned int>} > > ../../../gcc/gcc/rtlanal.cc:5238:32: note: in expansion of macro > > 'CLZ_DEFINED_VALUE_AT_ZERO' > > 5238 | if (code == CLZ && CLZ_DEFINED_VALUE_AT_ZERO > > (op_mode, val_at_zero)) > > | ^~~~~~~~~~~~~~~~~~~~~~~~~ > > ../../../gcc/gcc/config/i386/i386.h:3057:37: error: cannot convert > > 'poly_uint16' {aka 'poly_int<1, short unsigned int>'} to 'long int' in > > assignment > > 3057 | ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI ? 2 : 0) > > | ~~~~~~~~~~~~~~~~~^~~~~~ > > | | > > | poly_uint16 {aka > > poly_int<1, short unsigned int>} > > ../../../gcc/gcc/rtlanal.cc:5241:20: note: in expansion of macro > > 'CTZ_DEFINED_VALUE_AT_ZERO' > > 5241 | && CTZ_DEFINED_VALUE_AT_ZERO (op_mode, > > val_at_zero)) > > | ^~~~~~~~~~~~~~~~~~~~~~~~~ > > make: *** [Makefile:1218: rtlanal.o] Error 1 > > So there's still a bit of work to do, but it looks to be on the right > track to me.
What most other places that use CLZ_DEFINED_VALUE_AT_ZERO is just int type for the val argument rather of CLZ_DEFINED_VALUE_AT_ZERO than HOST_WIDE_INT. Why using HWI here does not work is a good question though. Because poly_int<1, short unsigned int> should be able to convert to long just fine, for `NUM_POLY_INT_COEFFS == 1` targets (x86_64 should be that), there should be an `operator short unsigned` as part of poly_int<1, short unsigned int>. Maybe there is something I am missing now. > > jeff
