From: Andreas Krebbel Date: Wed, 12 Aug 2020 06:02:35 +0000 (+0200) Subject: IBM Z: Fix PR96308 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=220ffae474db36ba20487427be699f0987a00b0c;p=gcc.git 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. --- diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 22ac5e43121..5488a5dc5e8 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 00000000000..9009bba5e82 --- /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]; }