https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94083
The original bug report was apparently lost in the sourceware/gcc migration back in the spring and I didn't notice until now. This testcase int foo(void) { volatile float f, g; int n; f = __builtin_huge_valf(); g = __builtin_huge_valf(); n += 1 - (f != __builtin_huge_valf()); return n; } compiled for soft-float with -O2, and looking at the original tree dump I see f = Inf; g = Inf; SAVE_EXPR <!(f u<= 3.4028234663852885981170418348451692544e+38)>;, n = SAVE_EX PR <!(f u<= 3.4028234663852885981170418348451692544e+38)> + n;; So the C front end converted the f != Inf compare to a f u<= <max-representable-float> compare, but the problem here is that the != operation is a single libcall, but u<= is two libcalls. So code that should have a single soft-float libcall ends up with two. First a call to __unordsf2, then a compare and branch, and then a call to __lesf2. This is a de-optimization. Perhaps we can convert the f u<= <max-representable-float> back to f != Inf in the optimization to get a single libcall. Or maybe we can add unordered soft-float libcalls like ulesf2.