https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127853

--- Comment #6 from Vineet Gupta <vineetg at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #4)
> I think we need
> --- a/gcc/tree-ssa-forwprop.cc        2026-10-02 22:28:59.195109574 +0200
> +++ b/gcc/tree-ssa-forwprop.cc        2026-10-12 14:47:37.704649342 +0200
> @@ -3530,7 +3530,7 @@ simplify_count_zeroes (gimple_stmt_itera
>                                          ctz_val) == 2;
>        zero_val = input_bits - 1 - zero_val;
>      }
> -  int nargs = 2;
> +  int nargs = 1 + zero_ok;

My version has slightly different code but equivalent code.

+  int nargs = zero_ok ? 2 : 1;

> @@ -3543,7 +3543,6 @@ simplify_count_zeroes (gimple_stmt_itera
>        zero_ok = true;
>        zero_val = 0;
>        ctz_val = 0;
> -      nargs = 1;
>      }

I think this needs to stay:

that branch resets ctz_val to 0, so with BMI/LZCNT (zero_ok from the macro) the
call becomes .CTZ (x, 0), claiming ctz (0) == 0 while the insn gives 32.

Consider the test below at  -O2 -mbmi:

```
static const unsigned char T[32] = {
  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};

__attribute__((noipa)) unsigned h (unsigned v)
{
  if (v)
    return T[((v & -v) * 0x077CB531U) >> 27];
  return 0;
}
```

With the "nargs = 1;" removed, forwprop1 gives

  if (v_7(D) != 0) ... _8 = .CTZ (v_7(D), 0);

phiopt2: Applying pattern match.pd:11839, then just .CTZ (v_3(D), 0):

h:
      xorl    %eax, %eax
      tzcntl  %edi, %eax
      ret

so h (0) returns 32 instead of 0.

Keeping "nargs = 1;" there .CTZ (v_7(D)), the guard survives, h (0) == 0.

Reply via email to