aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.ibm.com>2020-08-12 08:02:35 +0200
committerAndreas Krebbel <krebbel@linux.ibm.com>2020-08-12 08:11:37 +0200
commit220ffae474db36ba20487427be699f0987a00b0c (patch)
tree11453d3b3153b6c1ed6b153881d8443bfd13be5f /gcc
parent1d17c38ac1d1d916abbce14e6b2e0d61517c6e9b (diff)
downloadgcc-220ffae474db36ba20487427be699f0987a00b0c.zip
gcc-220ffae474db36ba20487427be699f0987a00b0c.tar.gz
gcc-220ffae474db36ba20487427be699f0987a00b0c.tar.bz2
IBM Z: Fix PR96308
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.
Diffstat (limited to 'gcc')
-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]; }