[PATCH] gcc: Keep TImode libcalls on the direct-return convention [PR78799]
Oleg Tolmatcev <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Libgcc helper libcalls such as __udivti3 still use the historical TImode direct-return convention. Preserve that convention when TARGET_RETURN_IN_MEMORY is queried for a libcall so the caller's expectation continues to match libgcc on x86_64-w64-mingw32. gcc/ChangeLog: PR target/78799 * config/i386/i386.cc (ix86_return_in_memory): Keep TImode libcalls on the direct-return convention. * testsuite/gcc.target/i386/pr78799-2.c: New test. Signed-off-by: Oleg Tolmatcev <[email protected]> --- gcc/config/i386/i386.cc | 8 ++++++- gcc/testsuite/gcc.target/i386/pr78799-2.c | 28 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr78799-2.c diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index e83402f2c4..2156e50e49 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -4446,13 +4446,19 @@ ix86_libcall_value (machine_mode mode) /* Return true iff type is returned in memory. */ static bool -ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) +ix86_return_in_memory (const_tree type, const_tree fntype) { const machine_mode mode = type_natural_mode (type, NULL, true); HOST_WIDE_INT size; if (TARGET_64BIT) { + /* Libcalls use TARGET_LIBCALL_VALUE for their return ABI. Keep + TImode helpers such as __udivti3 on the historical direct-return + convention so they continue to match libgcc. */ + if (fntype == NULL_TREE && mode == TImode) + return false; + if (ix86_function_type_abi (fntype) == MS_ABI) { size = int_size_in_bytes (type); diff --git a/gcc/testsuite/gcc.target/i386/pr78799-2.c b/gcc/testsuite/gcc.target/i386/pr78799-2.c new file mode 100644 index 0000000000..f223f6de94 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr78799-2.c @@ -0,0 +1,28 @@ +/* { dg-do run { target { int128 && x86_64-*-mingw* } } } */ +/* { dg-options "-O2" } */ + +typedef unsigned long long u64; +typedef unsigned __int128 u128; + +__attribute__((noinline, noclone)) +static u64 +div128_high_by (u64 high, u64 divisor) +{ + u128 n = (u128) high << 64; + return (u64) (n / (u128) divisor); +} + +int +main (void) +{ + if (div128_high_by (1ull, 3ull) != 0x5555555555555555ull) + __builtin_abort (); + + if (div128_high_by (1ull << 62, 1ull << 63) != (1ull << 63)) + __builtin_abort (); + + if (div128_high_by (1ull, ~0ull) != 1ull) + __builtin_abort (); + + return 0; +} -- 2.55.0.windows.3