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.