https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120231
Bug ID: 120231 Summary: GCC fails to notice that (double)u64 is non-negative Product: gcc Version: 16.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: acoplan at gcc dot gnu.org Target Milestone: --- For the following function: _Bool f(unsigned long u64) { return (double)u64 >= 0.0; } at -O3 on AArch64, GCC generates: f: ucvtf d31, x0 fcmpe d31, #0.0 cset w0, ge ret whereas LLVM gives: f: mov w0, #1 ret i.e. it folds the comparison to constant true. GCC should do the same. This would be useful in the context of code like the following: unsigned long sqrtint(unsigned long a) { return __builtin_sqrt(a); } for which GCC currently generates: sqrtint: ucvtf d0, x0 fcmp d0, #0.0 bpl .L5 stp x29, x30, [sp, -16]! mov x29, sp bl sqrt ldp x29, x30, [sp], 16 fcvtzu x0, d0 ret .L5: fsqrt d0, d0 fcvtzu x0, d0 ret i.e. it tests if the input is non-negative so that errno can be set correctly, but the test is redundant since the input is necessarily non-negative. Indeed LLVM generates: sqrtint: ucvtf d0, x0 fsqrt d0, d0 fcvtzu x0, d0 ret for this case.