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.

jeff

Reply via email to