S/390: Make legitimate_address_p accept UNSPEC_LTREF

Message ID 20190211121145.5055-1-iii@linux.ibm.com
State New
Headers show
Series
  • S/390: Make legitimate_address_p accept UNSPEC_LTREF
Related show

Commit Message

Ilya Leoshkevich Feb. 11, 2019, 12:11 p.m.
Bootstrapped and regtested on s390x-redhat-linux.

After r265371 (S/390: Make "b" constraint match literal pool references),
satisfies_constraint_b () started accepting memory references, whose
addresses do not pass legitimate_address_p ().  Specifically, literal
pool accesses past the end of the entry they are based on are explicitly
rejected by s390_decompose_address ().  This leads to ICE in early_mach
pass when trying to perform UNSPEC_LTREF substitution on such addresses.

s390_decompose_address () check does not apply to relative addresses.
The reason it is even made is that larl_operand () does not accept
literal pool references transformed into UNSPEC_LTREF.  This patch
makes larl_operand () treat plain and transformed literal pool
references identically.

gcc/ChangeLog:

2019-02-08  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/89233
	* config/s390/predicates.md (larl_operand): Allow UNSPEC_LTREF.
	* config/s390/s390.c (s390_decompose_address): Update comment.
	(s390_loadrelative_operand_p): Allow UNSPEC_LTREF.

gcc/testsuite/ChangeLog:

2019-02-08  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/89233
	* gcc.target/s390/pr89233.c: New test.
---
 gcc/config/s390/predicates.md           | 21 +++++++--------------
 gcc/config/s390/s390.c                  |  8 ++++++--
 gcc/testsuite/gcc.target/s390/pr89233.c | 11 +++++++++++
 3 files changed, 24 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/pr89233.c

-- 
2.20.1

Patch

diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 9a3d99e7897..1af505d156d 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -145,20 +145,11 @@ 
 ;;  Return true if OP a valid operand for the LARL instruction.
 
 (define_predicate "larl_operand"
-  (match_code "label_ref, symbol_ref, const")
+  (match_code "label_ref, symbol_ref, const, plus, unspec")
 {
-  /* Allow labels and local symbols.  */
-  if (GET_CODE (op) == LABEL_REF)
-    return true;
-  if (SYMBOL_REF_P (op))
-    return (!SYMBOL_FLAG_NOTALIGN2_P (op)
-	    && SYMBOL_REF_TLS_MODEL (op) == 0
-	    && s390_rel_address_ok_p (op));
-
-  /* Everything else must have a CONST, so strip it.  */
-  if (GET_CODE (op) != CONST)
-    return false;
-  op = XEXP (op, 0);
+  /* Strip CONST to unify SYMBOL_REF and UNSPEC_LTREF handling.  */
+  if (GET_CODE (op) == CONST)
+    op = XEXP (op, 0);
 
   /* Allow adding *even* in-range constants.  */
   if (GET_CODE (op) == PLUS)
@@ -172,9 +163,11 @@ 
       op = XEXP (op, 0);
     }
 
-  /* Labels and local symbols allowed here as well.  */
+  /* Allow labels and local symbols.  */
   if (GET_CODE (op) == LABEL_REF)
     return true;
+  if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_LTREF)
+    op = XVECEXP (op, 0, 0);
   if (SYMBOL_REF_P (op))
     return (!SYMBOL_FLAG_NOTALIGN2_P (op)
 	    && SYMBOL_REF_TLS_MODEL (op) == 0
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 6a571a3e054..8755f613d43 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3019,8 +3019,9 @@  s390_decompose_address (rtx addr, struct s390_address *out)
 	  orig_disp = gen_rtx_CONST (Pmode, disp);
 	  if (offset)
 	    {
-	      /* If we have an offset, make sure it does not
-		 exceed the size of the constant pool entry.  */
+	      /* If we have an offset, make sure it does not exceed the size of
+		 the constant pool entry.  Otherwise we might generate an
+		 out-of-range displacement for the base register form.  */
 	      rtx sym = XVECEXP (disp, 0, 0);
 	      if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
 		return false;
@@ -3140,6 +3141,9 @@  s390_loadrelative_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
       addr = XEXP (addr, 0);
     }
 
+  if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_LTREF)
+    addr = XVECEXP (addr, 0, 0);
+
   if (GET_CODE (addr) == SYMBOL_REF
       || (GET_CODE (addr) == UNSPEC
 	  && (XINT (addr, 1) == UNSPEC_GOTENT
diff --git a/gcc/testsuite/gcc.target/s390/pr89233.c b/gcc/testsuite/gcc.target/s390/pr89233.c
new file mode 100644
index 00000000000..f572bfa08d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr89233.c
@@ -0,0 +1,11 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=z13 -O1" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+int
+f ()
+{
+  v4si x = {0, 1, 2, 3};
+  return x[4];
+}