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 <[email protected]>
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 <[email protected]>
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: [email protected], 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); }