https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97445
--- Comment #43 from Christophe Leroy <christophe.leroy at csgroup dot eu> --- (In reply to Christophe Leroy from comment #42) > (In reply to Jakub Jelinek from comment #41) > > It is documented to be undefined: > > -- Built-in Function: int __builtin_clz (unsigned int x) > > Returns the number of leading 0-bits in X, starting at the most > > significant bit position. If X is 0, the result is undefined. > > Especially GCC 11 (but e.g. clang too) will e.g. during value range > > propagation assume that e.g. the builtin return value will be only 0 to 31, > > not to 32, etc. > > The portable way how to write this is x ? __builtin_clz (x) : > > whatever_value_you_want_for_clz_0; > > and the compiler should recognize that and if the instruction is well > > defined for 0 and matches your choice, use optimal sequence. > > int f(int x) > { > return x ? __builtin_clz(x) : 32; > } > > Is compiled into (with -O2): > > 00000000 <f>: > 0: 2c 03 00 00 cmpwi r3,0 > 4: 40 82 00 0c bne 10 <f+0x10> > 8: 38 60 00 20 li r3,32 > c: 4e 80 00 20 blr > 10: 7c 63 00 34 cntlzw r3,r3 > 14: 4e 80 00 20 blr > > > > Allthough > > int g(void) > { int g(int x) { return __builtin_clz(0); } Gives 00000018 <g>: 18: 38 60 00 20 li r3,32 1c: 4e 80 00 20 blr