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);