These checks were added to the original test by:
https://github.com/gcc-mirror/gcc/commit/0f149d5215a22a03406a82ec1669bf65b329a4df
Since 6b545db83c5a4e2c79e0b289e840be2c5fbbf327, clang has learned
to see through this tail call prevention.
First seen by us on our SVE bot which runs the test suite at -O3:
https://lab.llvm.org/buildbot/#/builders/197/builds/4192
Clang is correct here, this is why:
int check_fa_work (const char *c, const char *f) { const char d = 0; if (c >= &d) return c >= f && f >= &d; else return c <= f && f <= &d; }
This function only ever returns 0 or 1 due to the &&.
int check_fa_mid (const char *c) { const char *f = __builtin_frame_address (0); /* Prevent a tail call to check_fa_work, eliding the current stack frame. */ return check_fa_work (c, f) != 0; }
This function returns whether the result of check_fa_work is not equal to 0.
Clang has realised that if check_fa_work returns 0, check_fa_mid does also.
Same for 1. Meaning you can tail call check_fa_work.
check_fa_work returns 0, 0 != 0 is False, so check_fa_mid returns 0
check_fa_work returns 1, 1 != 0 is True, so check_fa_mid returns 1
Giving you asm like:
check_fa_mid: // @check_fa_mid stp x29, x30, [sp, #-16]! // 16-byte Folded Spill mov x29, sp mov x1, x29 ldp x29, x30, [sp], #16 // 16-byte Folded Reload b check_fa_work
Which means we have one less frame and the test fails.
A correct way to do it would be "==" which would have to invert the result.
However we cannot modify the test files, so disable the test instead.
I have filed a bug with gcc:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109146