[Bug middle-end/78103] Failure to optimize with __builtin_clzl
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sat Jul 24 12:28:42 GMT 2021
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78103
--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I actually think this should be doable with combiner splitters.
For the
unsigned int findLastSet3(unsigned long x) {
return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0;
}
or
unsigned int findLastSet4(unsigned int x) {
return x ? 8 * sizeof(unsigned int) - __builtin_clz(x) : 0;
}
the combiner sees everything together, in the first case
(parallel [
(set (reg:SI 84 [ <retval> ])
(minus:SI (const_int 64 [0x40])
(xor:SI (minus:SI (const_int 63 [0x3f])
(subreg:SI (clz:DI (reg/v:DI 85 [ x ])) 0))
(const_int 63 [0x3f]))))
(clobber (reg:CC 17 flags))
])
and in the latter case
(parallel [
(set (reg/v:SI 85 [ x ])
(minus:SI (const_int 32 [0x20])
(xor:SI (minus:SI (const_int 31 [0x1f])
(clz:SI (reg/v:SI 85 [ x ])))
(const_int 31 [0x1f]))))
(clobber (reg:CC 17 flags))
])
so we just need to split it - into bsr and add 1 (of course only if
!TARGET_LZCNT, otherwise it is defined even for 0 and we don't know that it
will be UB on zero).
For the #c0 findLastSet we don't know that, but again we should know that it is
UB at zero when !TARGET_LZCNT and so we could first split
(set (reg:DI 87 [ _1 ])
(xor:DI (sign_extend:DI (minus:SI (const_int 63 [0x3f])
(subreg:SI (clz:DI (reg/v:DI 85 [ x ])) 0)))
(const_int 63 [0x3f])))
into bsr and xor (i.e. get rid of the sign extension, if it is UB at zero, then
we know clz will be in range 0 to 63 and sign extension or zero extension are
the same and performed already when using the bs{q,l} instruction.
More information about the Gcc-bugs
mailing list