Out of range error when building python 3.14.7 with gcc 16.2.0

Thanks, @branfosj! That -fno-math-errno is the smoking gun.

So my earlier undisclosed guess was completely wrong, so I’m not going to embarrass myself by disclosing it. Here’s a better guess:

  • all these pow cases underflow to zero
  • glibc’s pow is setting errno=ERANGE for this underflow-to-zero case (which it’s perfectly entitled to do - the C standard is very permissive when it comes to errno for math functions)
  • the -fno-math-errno flag gives gcc permission to assume that math function calls don’t set errno (and it may or may not make use of that assumption)
  • CPython has guard code that checks for errno=ERANGE in an underflow case and resets errno to 0
  • in the presence of -fno-math-errno, gcc is entitled to just assume that after the sequence here, errno is still zero (even though it isn’t), and so it skips the guard that would have reset errno to zero
  • so in the final block, errno is still ERANGE (because the guard failed), and Python goes on to raise OverflowError

Short version: CPython’s source here is incompatible with -fno-math-errno.

The weird “successful first time, fails on subsequent evaluations” behaviour appears to be due to an interaction with the PGO optimization, leading to two separate paths in the instrumented build, one of which is taken on the first call, and the other of which is taken on subsequent calls. That’s valid behaviour: given -fno-math-errno, gcc is free to either assume errno is zero or not on a whim; on the first path it actually performs the errno check; on the second it assumes (incorrectly) that errno is zero, because we told it it could.

So my assessment is: not a gcc bug, not a glibc bug, not a CPython bug. Possibly an EasyBuild bug (disclaimer: I have zero familiarity with EasyBuild). That said, I think the CPython code could potentially be hardened here to avoid the possibility of failure in the presence of -fno-math-errno. That’s easier than it used to be - back when we were supporting non-IEEE 754 platforms, we had to allow for the possibility that overflow would be indicated solely via errno. With today’s CPython assumption that we’re using IEEE 754 format, we can somewhat reasonably assume that any overflow will be accompanied by a +/-inf result, and we can do an isinf to check for that. I don’t know if there are other sites in the CPython source that would need similar hardening, though; it’s probably best to assume for now that CPython needs -fmath-errno.

@rsdmse You didn’t mention -fno-math-errno directly, but you did indicate you were using EasyBuild; I suspect that’s how -fno-math-errno is sneaking in, and it’s why you’re seeing the issue.

And it’s totally expected that -ffast-math and similar flags would cause lots of test failures; CPython does try to be well-behaved around IEEE 754 edge cases, and letting gcc play fast and loose with floating-point is incompatible with that.