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.