gcc.dg/torture/stackalign/builtin-apply-4.c was failing for MIPS16
hard-float with -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects.
We created a specialised out-of-line version of bar() that was
called by (rather than inlined into) main().  So we had the
equivalent of:

  static double __attribute__((noinline)) bar (void) { return 1.0; }
  double foo (void) { return bar (); }

Compiled without -fpic this worked fine, but compiled with -fpic it hit:

      /* If this is a locally-defined and locally-binding function,
         avoid the stub by calling the local alias directly.  */
      if (mips16_local_function_p (fn))
        {
          *fn_ptr = mips16_local_alias (fn);
          return NULL_RTX;
        }

The problem is that these local aliases are only defined (and only
needed) for functions that take arguments in floating-point registers,
so we got a link error trying to call bar()'s local alias.

Tested on mips64-linux-gnu and applied.

Richard


gcc/
        * config/mips/mips.c (mips16_build_call_stub): Don't use a stub
        for calls to locally-binding MIPS16 functions if only the return
        type uses float regs.

Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      2012-01-15 18:22:47.000000000 +0000
+++ gcc/config/mips/mips.c      2012-01-15 18:31:58.000000000 +0000
@@ -6172,6 +6172,13 @@ mips16_build_call_stub (rtx retval, rtx
   if (mips16_stub_function_p (fn))
     return NULL_RTX;
 
+  /* If we're calling a locally-defined MIPS16 function, we know that
+     it will return values in both the "soft-float" and "hard-float"
+     registers.  There is no need to use a stub to move the latter
+     to the former.  */
+  if (fp_code == 0 && mips16_local_function_p (fn))
+    return NULL_RTX;
+
   /* This code will only work for o32 and o64 abis.  The other ABI's
      require more sophisticated support.  */
   gcc_assert (TARGET_OLDABI);

Reply via email to