PR target/83862 pointed out a problem I put into the 128-bit floating point type signbit optimization. The issue is we want to avoid doing a load to a floating point/vector register and then a direct move to do signbit, so we change the load to load the upper 64-bits of the floating point value to get the sign bit. Unfortunately, if the type is IEEE 128-bit and memory is addressed with an indexed address on a little endian system, it generates an illegal address and generates an internal compiler error.
I have tested this on a little endian power8 system, with bootstrap compilers. There was not regression, and the new test passes. Can I install this into the trunk? The same code is also in GCC 6 and 7. While, -mabi=ieeelongdouble is not supported in those releases, you can get a failure if you use an explicit _Float128 type instead of long double. Assuming that the bug shows up, can I apply these patches to those branches as well? [gcc] 2018-01-16 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/83862 * config/rs6000/rs6000.c (rs6000_split_signbit): Do not create an illegal address on little endian systems if the source value is in memory addressed with indexed addressing. * config/rs6000/rs6000.md (signbit<mode>2_dm): Likewise. (signbit<mode>2_dm_<su>ext): Likewise. [gcc/testsuite] 2018-01-16 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/83862 * gcc.target/powerpc/pr83862.c: New test. -- 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 256753) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -23341,9 +23341,27 @@ rs6000_split_signbit (rtx dest, rtx src) if (MEM_P (src)) { - rtx mem = (WORDS_BIG_ENDIAN - ? adjust_address (src, DImode, 0) - : adjust_address (src, DImode, 8)); + rtx addr = XEXP (src, 0); + rtx mem; + + if (!WORDS_BIG_ENDIAN) + { + /* Do not create an illegal address for indexed addressing when we + add in the 8 to address the second word where the sign bit is. + Instead use the desitnation register as a base register. */ + if (GET_CODE (addr) == PLUS + && !rs6000_legitimate_offset_address_p (DImode, addr, true, true)) + { + emit_insn (gen_rtx_SET (dest, addr)); + mem = change_address (src, DImode, + gen_rtx_PLUS (Pmode, dest, GEN_INT (8))); + } + else + mem = adjust_address (src, DImode, 8); + } + else + mem = adjust_address (src, DImode, 0); + emit_insn (gen_rtx_SET (dest_di, mem)); } Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 256753) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -4835,9 +4835,11 @@ (define_expand "copysign<mode>3" }) ;; Optimize signbit on 64-bit systems with direct move to avoid doing the store -;; and load. +;; and load. We restrict signbit coming from a load to use a base register for +;; the destination, in case we need to use the base register as a tempoary +;; address register. (define_insn_and_split "signbit<mode>2_dm" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") + [(set (match_operand:SI 0 "gpc_reg_operand" "=r,&b,r") (unspec:SI [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")] UNSPEC_SIGNBIT))] @@ -4853,7 +4855,7 @@ (define_insn_and_split "signbit<mode>2_d (set_attr "type" "mftgpr,load,integer")]) (define_insn_and_split "*signbit<mode>2_dm_<su>ext" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,&b,r") (any_extend:DI (unspec:SI [(match_operand:SIGNBIT 1 "input_operand" "wa,m,r")] Index: gcc/testsuite/gcc.target/powerpc/pr83862.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr83862.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/pr83862.c (working copy) @@ -0,0 +1,21 @@ +/* PR target/83862.c */ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-require-effective-target ppc_float128_sw } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mpower8-vector -O2 -mabi=ieeelongdouble -Wno-psabi" } */ + +/* On little endian systems, optimizing signbit of IEEE 128-bit values from + memory could abort if the memory address was indexed (reg+reg). The + optimization is only on 64-bit machines with direct move. + + Compile with -g -O2 -mabi=ieeelongdouble -Wno-psabi. */ + +#ifndef TYPE +#define TYPE long double +#endif + +int sbr (TYPE a) { return __builtin_signbit (a); } +int sbm (TYPE *a) { return __builtin_signbit (*a); } +int sbo (TYPE *a) { return __builtin_signbit (a[4]); } +int sbi (TYPE *a, unsigned long n) { return __builtin_signbit (a[n]); } +void sbs (int *p, TYPE a) { *p = __builtin_signbit (a); }