https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119086
Bug ID: 119086 Summary: __builtin_constant_p is missing opportunities Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: gjl at gcc dot gnu.org Target Milestone: --- Created attachment 60634 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60634&action=edit bic.c: C test case In the attached test case bic.c, there is this function: static inline __attribute__((always_inline)) unsigned root2 (unsigned x) { if (__builtin_constant_p ((unsigned) __builtin_sqrtf ((float) x))) return (unsigned) __builtin_sqrtf ((float) x); X = __builtin_constant_p ((unsigned) __builtin_sqrtf ((float) x)); return expensive_root2 (x); } int main (void) { X = root2 (15); return 0; } It tries to use constant folding when a compile-time constant is passed to root2. $ gcc -O2 bic.c -S -dp Even though constant 15 is passed to root2, __builtin_constant_p ((unsigned) __builtin_sqrtf ((float) x)) evaluates to false, AND that exact same argument expression IS folded to a constant. main.s: main: .LFB2: .cfi_startproc subq $8, %rsp # 20 [c=4 l=4] pro_epilogue_adjust_stack_add_di/0 .cfi_def_cfa_offset 16 # __builtin_constant_p(...) is false, so GCC takes the expensive path. movl $15, %edi # 6 [c=4 l=5] *movsi_internal/0 # Even though __builtin_constant_p(...) is false, the compiler CAN fold the expression # to a compile-time constant: It sets X = 3 = (unsigned) sqrtf (15). movl $3, X(%rip) # 5 [c=4 l=10] *movsi_internal/1 call expensive_root2 # 7 [c=9 l=5] *call_value movl %eax, X(%rip) # 10 [c=4 l=6] *movsi_internal/1 xorl %eax, %eax # 28 [c=4 l=2] *movdi_xor addq $8, %rsp # 23 [c=4 l=4] pro_epilogue_adjust_stack_add_di/0 .cfi_def_cfa_offset 8 ret # 24 [c=0 l=1] simple_return_internal So it would be great if __builtin_constant would return true in such cases. I see this with v13.3 on x86_64 and also on current trunk for other targets (and where sqrtf doesn't throw). Notice that the behaviour is the same with extern float sqrtf (float) __attribute__((nothrow)); and with sqrtf instead of __builtin_sqrtf.