When I added the support for __float128 last year, I accidentally broke returning structures containing a single float or double item using the System V 32-bit calling sequence.
This patch goes back to using SCALAR_FLOAT_TYPE_P (which looks at the tree node) instead of SCALAR_FLOAT_MODE_NOT_VECTOR_P (which only looks at the mode). I have tested this patch on the trunk on a big endian power7 system, and there were no regressions. The same patch applies to the GCC-6 branch, and I am testing it now. Assuming there are no regresions on the GCC-6 branch, can I check this patch into both the trunk and gcc-6-branch? [gcc] 2016-07-18 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/71493 * config/rs6000/rs6000.c (rs6000_function_value): Fix unintentional System V.4 structure return breakage for structures with a single floating point element. [gcc/testsuite] 2016-07-18 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/71493 * gcc.target/powerpc/pr71493-1.c: New test. * gcc.target/powerpc/pr71493-2.c: Likewise. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 238438) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -35467,7 +35467,8 @@ rs6000_function_value (const_tree valtyp if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) /* _Decimal128 must use an even/odd register pair. */ regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN; - else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS + else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS + && !FLOAT128_VECTOR_P (mode) && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT)) regno = FP_ARG_RETURN; else if (TREE_CODE (valtype) == COMPLEX_TYPE Index: gcc/testsuite/gcc.target/powerpc/pr71493-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr71493-2.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr71493-2.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile { target { powerpc*-*-linux* && ilp32 } } } */ +/* { dg-options "-O2 -m32 -msvr4-struct-return" } */ + +struct S2 { double d; }; + +struct S2 foo2 (void) +{ + struct S2 s = { 1.0 }; + return s; +} + +/* { dg-final { scan-assembler "lwz" } } */ +/* { dg-final { scan-assembler-not "lfd" } } */ Index: gcc/testsuite/gcc.target/powerpc/pr71493-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr71493-1.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr71493-1.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile { target { powerpc*-*-linux* && ilp32 } } } */ +/* { dg-options "-O2 -m32 -msvr4-struct-return" } */ + +struct S1 { float f; }; + +struct S1 foo1 (void) +{ + struct S1 s = { 1.0f }; + return s; +} + +/* { dg-final { scan-assembler "lwz" } } */ +/* { dg-final { scan-assembler-not "lfs" } } */ -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 238438) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -35467,7 +35467,8 @@ rs6000_function_value (const_tree valtyp if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) /* _Decimal128 must use an even/odd register pair. */ regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN; - else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS + else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS + && !FLOAT128_VECTOR_P (mode) && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT)) regno = FP_ARG_RETURN; else if (TREE_CODE (valtype) == COMPLEX_TYPE Index: gcc/testsuite/gcc.target/powerpc/pr71493-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr71493-2.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr71493-2.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile { target { powerpc*-*-linux* && ilp32 } } } */ +/* { dg-options "-O2 -m32 -msvr4-struct-return" } */ + +struct S2 { double d; }; + +struct S2 foo2 (void) +{ + struct S2 s = { 1.0 }; + return s; +} + +/* { dg-final { scan-assembler "lwz" } } */ +/* { dg-final { scan-assembler-not "lfd" } } */ Index: gcc/testsuite/gcc.target/powerpc/pr71493-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr71493-1.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr71493-1.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile { target { powerpc*-*-linux* && ilp32 } } } */ +/* { dg-options "-O2 -m32 -msvr4-struct-return" } */ + +struct S1 { float f; }; + +struct S1 foo1 (void) +{ + struct S1 s = { 1.0f }; + return s; +} + +/* { dg-final { scan-assembler "lwz" } } */ +/* { dg-final { scan-assembler-not "lfs" } } */