[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.