aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/s390/s390.c25
-rw-r--r--gcc/testsuite/g++.dg/pr96308.C7
2 files changed, 32 insertions, 0 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 22ac5e4..5488a5d 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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
index 0000000..9009bba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr96308.C
@@ -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]; }