IBM Z: Fix PR96308
authorAndreas Krebbel <krebbel@linux.ibm.com>
Wed, 12 Aug 2020 06:02:35 +0000 (08:02 +0200)
committerAndreas Krebbel <krebbel@linux.ibm.com>
Wed, 12 Aug 2020 06:11:37 +0000 (08:11 +0200)
For the testcase a symbol with a TLS reloc and an unary minus is being
generated.  The backend didn't handle this correctly.

In s390_cannot_force_const_mem an unary minus on a symbolic constant
is rejected now since gas would not allow this.

legitimize_tls_address now makes the NEG rtx the outermost operation
by pulling it out of the CONST rtx.

gcc/ChangeLog:

PR target/96308
* config/s390/s390.c (s390_cannot_force_const_mem): Reject an
unary minus for everything not being a numeric constant.
(legitimize_tls_address): Move a NEG out of the CONST rtx.

gcc/testsuite/ChangeLog:

PR target/96308
* g++.dg/pr96308.C: New test.

gcc/config/s390/s390.c
gcc/testsuite/g++.dg/pr96308.C [new file with mode: 0644]

index 22ac5e431214e23139272589eb1a212341cda878..5488a5dc5e8ae07735b6b8dbb173432423a85613 100644 (file)
@@ -4106,6 +4106,18 @@ s390_cannot_force_const_mem (machine_mode mode, rtx x)
       /* Accept all non-symbolic constants.  */
       return false;
 
+    case NEG:
+      /* Accept an unary '-' only on scalar numeric constants.  */
+      switch (GET_CODE (XEXP (x, 0)))
+       {
+       case CONST_INT:
+       case CONST_DOUBLE:
+       case CONST_WIDE_INT:
+         return false;
+       default:
+         return true;
+       }
+
     case LABEL_REF:
       /* Labels are OK iff we are non-PIC.  */
       return flag_pic != 0;
@@ -5268,6 +5280,7 @@ legitimize_tls_address (rtx addr, rtx reg)
     {
       switch (XINT (XEXP (addr, 0), 1))
        {
+       case UNSPEC_NTPOFF:
        case UNSPEC_INDNTPOFF:
          new_rtx = addr;
          break;
@@ -5290,6 +5303,18 @@ legitimize_tls_address (rtx addr, rtx reg)
       new_rtx = force_operand (new_rtx, 0);
     }
 
+  /* (const (neg (unspec (symbol_ref)))) -> (neg (const (unspec (symbol_ref)))) */
+  else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == NEG)
+    {
+      new_rtx = XEXP (XEXP (addr, 0), 0);
+      if (GET_CODE (new_rtx) != SYMBOL_REF)
+       new_rtx = gen_rtx_CONST (Pmode, new_rtx);
+
+      new_rtx = legitimize_tls_address (new_rtx, reg);
+      new_rtx = gen_rtx_NEG (Pmode, new_rtx);
+      new_rtx = force_operand (new_rtx, 0);
+    }
+
   else
     gcc_unreachable ();  /* for now ... */
 
diff --git a/gcc/testsuite/g++.dg/pr96308.C b/gcc/testsuite/g++.dg/pr96308.C
new file mode 100644 (file)
index 0000000..9009bba
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-Os -fno-move-loop-invariants -std=c++11" }
+
+struct NonTrivial3 {
+  ~NonTrivial3();
+};
+void i() { thread_local NonTrivial3 tlarr[10]; }