Following testcase fails on ARM (from https://bugs.linaro.org/show_bug.cgi?id=1900).
__attribute__ ((noinline)) double direct(int x, ...) { return x*x; } __attribute__ ((noinline)) double broken(double (*indirect)(int x, ...), int v) { return indirect(v); } int main () { double d1, d2; int i = 2; d1 = broken (direct, i); if (d1 != i*i) { __builtin_abort (); } return 0; } Please note that we have a sibcall from "broken" to "indirect". "direct" is variadic function so it is conforming to AAPCS base standard. "broken" is a non-variadic function and will return the value in floating point register for TARGET_HARD_FLOAT. Thus we should not be doing sibcall here. Attached patch fixes this. Bootstrap and regression testing is ongoing. Is this OK if no issues with the testing? Thanks, Kugan gcc/ChangeLog: 2015-11-17 Kugan Vivekanandarajah <kug...@linaro.org> * config/arm/arm.c (arm_function_ok_for_sibcall): Disable sibcall to indirect function when TARGET_HARD_FLOAT. gcc/testsuite/ChangeLog: 2015-11-17 Kugan Vivekanandarajah <kug...@linaro.org> * gcc.target/arm/variadic_sibcall.c: New test.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index a379121..8b560bc 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -6681,6 +6681,12 @@ arm_function_ok_for_sibcall (tree decl, tree exp) register. */ rtx a, b; + /* When it is an indirect call (i.e, decl == NULL), it could be + returning its result in a VFP or could be a variadic function. + Thus return false. */ + if (!decl && TARGET_HARD_FLOAT) + return false; + a = arm_function_value (TREE_TYPE (exp), decl, false); b = arm_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)), cfun->decl, false); diff --git a/gcc/testsuite/gcc.target/arm/variadic_sibcall.c b/gcc/testsuite/gcc.target/arm/variadic_sibcall.c index e69de29..86f07fe 100644 --- a/gcc/testsuite/gcc.target/arm/variadic_sibcall.c +++ b/gcc/testsuite/gcc.target/arm/variadic_sibcall.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +__attribute__ ((noinline)) +double direct(int x, ...) +{ + return x*x; +} + +__attribute__ ((noinline)) +double broken(double (*indirect)(int x, ...), int v) +{ + return indirect(v); +} + +int main () +{ + double d1, d2; + int i = 2; + d1 = broken (direct, i); + if (d1 != i*i) + { + __builtin_abort (); + } + return 0; +} +