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

            Bug ID: 114341
           Summary: Optimization opportunity with {mul,div} "(x & -x)" and
                    {<<,>>} "ctz(x)"
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Explorer09 at gmail dot com
  Target Milestone: ---

This is an optimization opportunity that I'm not sure it's worth
implementing in gcc, since I only used the (x / (x & -x)) pattern on
compile time constants only.

When x and y are unsigned integers and the value of y is non-zero,
then (x / (y & -y)) and (x >> __builtin_ctz(y)) are equivalent.

Similarly, (x * (y & -y)) and (x << __builtin_ctz(y)) are equivalent.

One reason for using the (x / (y & -y)) pattern is that it's more
portable among C compilers before C23 made a standard "CTZ" API
(stdc_trailing_zeros) for everyone. Even though we have
stdc_trailing_zeros() now, the (x / (y & -y)) pattern is still useful
for constant expressions when stdc_trailing_zeros() might not be a
compiler built in.

Processors that support CTZ instructions would optimize (x / (y & -y))
to (x >> __builtin_ctz(y)); processors that do not support CTZ would
optimize the other way around. (I know RISC-V might need the latter
way of optimization.)

```c
unsigned int func1a(unsigned int x, unsigned int y) {
  if (y == 0)
    return -1; /* placeholder value to indicate error */

  return x / (y & -y);
}

unsigned int func1b(unsigned int x, unsigned int y) {
  if (y == 0)
    return -1; /* placeholder value to indicate error */

  return x >> __builtin_ctz(y);
}

unsigned int func2a(unsigned int x, unsigned int y) {
  if (y == 0)
    return -1; /* placeholder value to indicate error */

  return x * (y & -y);
}

unsigned int func2b(unsigned int x, unsigned int y) {
  if (y == 0)
    return -1; /* placeholder value to indicate error */

  return x << __builtin_ctz(y);
}
```

Reply via email to