https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119873
Bug ID: 119873 Summary: s390x musttail call failure on s390x Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long long uint64_t; struct TcFieldData { constexpr TcFieldData() : data(0) {} constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint8_t aux_idx, uint16_t offset) : data(uint64_t{offset} << 48 | uint64_t{aux_idx} << 24 | uint64_t{hasbit_idx} << 16 | uint64_t{coded_tag}) {} uint64_t data; }; const char *foo (void *, void *, void *, void *, uint64_t, TcFieldData); [[gnu::noinline]] const char *bar (void *, void *, void *, void *, uint64_t, TcFieldData) { return nullptr; } const char * baz (void *a, void *b, void *c, void *d, uint64_t e, TcFieldData f) { [[clang::musttail]] return bar (a, b, c, d, e, f); } const char * qux (void *a, void *b, void *c, void *d, uint64_t e, TcFieldData f) { [[clang::musttail]] return foo (a, b, c, d, e, f); } from protobuf fails to compile on s390x-linux e.g. at -O2, with /tmp/0.C: In function ‘const char* qux(void*, void*, void*, void*, uint64_t, TcFieldData)’: /tmp/0.C:24:34: error: cannot tail-call: target is not able to optimize the call into a sibling call 24 | [[clang::musttail]] return foo (a, b, c, d, e, f); | ~~~~^~~~~~~~~~~~~~~~~~ If I understand it right, this is because /* Register 6 on s390 is available as an argument register but unfortunately "caller saved". This makes functions needing this register for arguments not suitable for sibcalls. */ return !s390_call_saved_register_used (exp); I wonder if it couldn't be allowed if the argument passed in %r6 register is passed through from the caller to the callee unmodified, i.e. if in exp the argument in %r6 register is SSA_NAME which is SSA_NAME_IS_DEFAULT_DEF with PARM_DECL which has %r6 as DECL_INCOMING_RTL. Of course, if one passes something else, I can understand why it can't be tail called. Note, looking at what clang does, it silently ignores the musttail attribute, calls the function normally, without diagnosing it. I think the gcc behavior is better, at least the user is told that it can't be tail called. clang does the same for many reasons, but not in this case.