This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH, m68k] Fix PR target/41302


Maxim Kuvyrkov wrote:
Jeff Law wrote:
On 10/30/09 04:14, Maxim Kuvyrkov wrote:
The attached patch fixes <gcc.gnu.org/PR41302>.

As described in the PR, the problem is in m68k_ok_for_sibcall_p() allowing sibcalls of functions that return the result in a different location (register A0) from what the current function expects (register D0).

This patch ports similar code from the arm backend, and also handles a specific to m68k case when the result is returned in both D0 and A0 registers.

Tested on coldfire-elf with no regressions on gcc, g++ and libstdc++ testsuites. OK for trunk?

Thanks,

The way you've written the condition below is somewhat odd and it's bloody hard to see the empty statement semi-colon in the if-clause.

Noted.
...
While making the changes I've spotted a couple of quirks in the patch, and now I'm testing an updated version. Will follow up once the tests are finished.

Here is an updated version. Turned out that testing on coldfire-elf was of little relevance as ABI of cf-elf is different from cf-linux (cf-elf always returns result in D0). So I've fixed the patch to handle different ABIs correctly and updated the testcase.


Tested on coldfire-linux, ok to check in?

--
Maxim Kuvyrkov
CodeSourcery
maxim@codesourcery.com
(650) 331-3385 x724
2009-11-03  Maxim Kuvyrkov  <maxim@codesourcery.com>

	PR target/41302
	* config/m68k/m68k.c (m68k_reg_present_p): New static function.
	(m68k_ok_for_sibcall_p): Handle different result return locations.

2009-11-03  Maxim Kuvyrkov  <maxim@codesourcery.com>

	PR target/41302
	* gcc.target/m68k/pr41302.c: New test.
Index: testsuite/gcc.target/m68k/pr41302.c
===================================================================
--- testsuite/gcc.target/m68k/pr41302.c	(revision 0)
+++ testsuite/gcc.target/m68k/pr41302.c	(revision 0)
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "move.l \%d0,\%a0" { target *linux* } } } */
+
+struct pts {
+  int c;
+};
+
+unsigned int bar (struct pts *a, int b);
+
+struct pts * foo (struct pts *a, int b)
+{
+  return (struct pts *) bar (a, b);
+}
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "move.l \%d0,\%a0" { target *linux* } } } */
+
+struct pts {
+  int c;
+};
+
+unsigned int bar (struct pts *a, int b);
+
+struct pts * foo (struct pts *a, int b)
+{
+  return (struct pts *) bar (a, b);
+}
Index: config/m68k/m68k.c
===================================================================
--- config/m68k/m68k.c	(revision 153734)
+++ config/m68k/m68k.c	(working copy)
@@ -1399,6 +1399,30 @@ flags_in_68881 (void)
   return cc_status.flags & CC_IN_68881;
 }
 
+/* Return true if PARALLEL contains register REGNO.  */
+static bool
+m68k_reg_present_p (const_rtx parallel, unsigned int regno)
+{
+  int i;
+
+  if (REG_P (parallel) && REGNO (parallel) == regno)
+    return true;
+
+  if (GET_CODE (parallel) != PARALLEL)
+    return false;
+
+  for (i = 0; i < XVECLEN (parallel, 0); ++i)
+    {
+      const_rtx x;
+
+      x = XEXP (XVECEXP (parallel, 0, i), 0);
+      if (REG_P (x) && REGNO (x) == regno)
+	return true;
+    }
+
+  return false;
+}
+
 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL_P.  */
 
 static bool
@@ -1411,6 +1435,26 @@ m68k_ok_for_sibcall_p (tree decl, tree e
   if (CALL_EXPR_STATIC_CHAIN (exp))
     return false;
 
+  if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl))))
+    {
+      /* Check that the return value locations are the same.  For
+	 example that we aren't returning a value from the sibling in
+	 a D0 register but then need to transfer it to a A0 register.  */
+      rtx cfun_value;
+      rtx call_value;
+
+      cfun_value = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (cfun->decl)),
+				   cfun->decl);
+      call_value = FUNCTION_VALUE (TREE_TYPE (exp), decl);
+
+      /* Check that the values are equal or that the result the callee
+	 function returns is superset of what the current function returns.  */
+      if (!(rtx_equal_p (cfun_value, call_value)
+	    || (REG_P (cfun_value)
+		&& m68k_reg_present_p (call_value, REGNO (cfun_value)))))
+	return false;
+    }
+
   kind = m68k_get_function_kind (current_function_decl);
   if (kind == m68k_fk_normal_function)
     /* We can always sibcall from a normal function, because it's
@@ -5188,6 +5232,9 @@ m68k_libcall_value (enum machine_mode mo
   return gen_rtx_REG (mode, m68k_libcall_value_in_a0_p ? A0_REG : D0_REG);
 }
 
+/* Location in which function value is returned.
+   NOTE: Due to differences in ABIs, don't call this function directly,
+   use FUNCTION_VALUE instead.  */
 rtx
 m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
 {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]