This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Make s390 use an UNSPEC instead of (const (minus ...))


This patch makes the s390 port use UNSPECs instead of (const (minus ...)).
It's part of my ongoing quest to enforce a grammar for CONSTs.  See:

    http://gcc.gnu.org/ml/gcc-patches/2008-10/msg00339.html

for details.

The port only uses (const (minus ...)) to represent the difference
between two pool labels.  It originally allowed:

    (const (minus (label_ref ...) (label_ref ...)))

at all times, but this caused PR 26018 (which is similiar to the
CRIS problem I'm trying to fix).  It was therefore necessary to
add a state variable to say whether the address routines are
being called after the start of md_reorg.

I think using an UNSPEC is a little cleaner than a state variable.
Not all label differences are valid even when the variable is true;
we really only want to allow specific differences that have already
been "blessed" by the pool-layout code.  UNSPECs give exactly the
kind of target-specific control we need.

Tested by comparing the before and after assembly output for
gcc.c-torture, gcc.dg and g++.dg on s390x-linux-gnu, using the
options:

  {-O0,-O2} x {-fno-pic,-fpic} x {-m31,-m64}

There were no differences.  OK to install?

Richard


gcc/
	* config/s390/s390.md (UNSPEC_POOL_OFFSET): New constant.
	* config/s390/s390.c (machine_function): Remove
	decomposed_literal_pool_addresses_ok_p.
	(s390_decompose_address): Check for UNSPEC_POOL_OFFSET instead of
	the difference of two labels.
	(s390_output_addr_const_extra): Handle UNSPEC_POOL_OFFSET.
	(s390_pool_offset): New function.
	(s390_find_constant, s390_find_execute, s390_dump_pool): Use it.
	(s390_reorg): Don't set decomposed_literal_pool_addresses_ok_p.

Index: gcc/config/s390/s390.md
===================================================================
--- gcc/config/s390/s390.md	2008-10-10 10:33:42.000000000 +0100
+++ gcc/config/s390/s390.md	2008-10-10 10:33:48.000000000 +0100
@@ -68,6 +68,7 @@ (define_constants
    ; GOT/PLT and lt-relative accesses
    (UNSPEC_LTREL_OFFSET		100)
    (UNSPEC_LTREL_BASE		101)
+   (UNSPEC_POOL_OFFSET		102)
    (UNSPEC_GOTENT		110)
    (UNSPEC_GOT			111)
    (UNSPEC_GOTOFF		112)
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2008-08-31 11:45:07.000000000 +0100
+++ gcc/config/s390/s390.c	2008-10-10 10:33:21.000000000 +0100
@@ -316,9 +316,6 @@ struct machine_function GTY(())
   /* True if we may need to perform branch splitting.  */
   bool split_branches_pending_p;
 
-  /* True during final stage of literal pool processing.  */
-  bool decomposed_literal_pool_addresses_ok_p;
-
   /* Some local-dynamic TLS symbol name.  */
   const char *some_ld_name;
 
@@ -1955,15 +1952,10 @@ s390_decompose_address (rtx addr, struct
 	  ;
         }
 
-      /* Accept chunkified literal pool symbol references.  */
-      else if (cfun && cfun->machine
-	       && cfun->machine->decomposed_literal_pool_addresses_ok_p
-	       && GET_CODE (disp) == MINUS
-               && GET_CODE (XEXP (disp, 0)) == LABEL_REF
-               && GET_CODE (XEXP (disp, 1)) == LABEL_REF)
-        {
-	  ;
-        }
+      /* Accept pool label offsets.  */
+      else if (GET_CODE (disp) == UNSPEC
+	       && XINT (disp, 1) == UNSPEC_POOL_OFFSET)
+	;
 
       /* Accept literal pool references.  */
       else if (GET_CODE (disp) == UNSPEC
@@ -4909,6 +4901,14 @@ s390_output_addr_const_extra (FILE *file
 	return true;
       }
 
+  if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 2)
+    switch (XINT (x, 1))
+      {
+      case UNSPEC_POOL_OFFSET:
+	x = gen_rtx_MINUS (GET_MODE (x), XVECEXP (x, 0, 0), XVECEXP (x, 0, 1));
+	output_addr_const (file, x);
+	return true;
+      }
   return false;
 }
 
@@ -5823,6 +5823,20 @@ s390_add_constant (struct constant_pool 
     }
 }
 
+/* Return an rtx that represents the offset of X from the start of
+   pool POOL.  */
+
+static rtx
+s390_pool_offset (struct constant_pool *pool, rtx x)
+{
+  rtx label;
+
+  label = gen_rtx_LABEL_REF (GET_MODE (x), pool->label);
+  x = gen_rtx_UNSPEC (GET_MODE (x), gen_rtvec (2, x, label),
+		      UNSPEC_POOL_OFFSET);
+  return gen_rtx_CONST (GET_MODE (x), x);
+}
+
 /* Find constant VAL of mode MODE in the constant pool POOL.
    Return an RTX describing the distance from the start of
    the pool to the location of the new constant.  */
@@ -5832,7 +5846,6 @@ s390_find_constant (struct constant_pool
 		    enum machine_mode mode)
 {
   struct constant *c;
-  rtx offset;
   int i;
 
   for (i = 0; i < NR_C_MODES; i++)
@@ -5846,10 +5859,7 @@ s390_find_constant (struct constant_pool
 
   gcc_assert (c);
 
-  offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
-                                 gen_rtx_LABEL_REF (Pmode, pool->label));
-  offset = gen_rtx_CONST (Pmode, offset);
-  return offset;
+  return s390_pool_offset (pool, gen_rtx_LABEL_REF (Pmode, c->label));
 }
 
 /* Check whether INSN is an execute.  Return the label_ref to its
@@ -5897,7 +5907,6 @@ s390_add_execute (struct constant_pool *
 s390_find_execute (struct constant_pool *pool, rtx insn)
 {
   struct constant *c;
-  rtx offset;
 
   for (c = pool->execute; c != NULL; c = c->next)
     if (INSN_UID (insn) == INSN_UID (c->value))
@@ -5905,10 +5914,7 @@ s390_find_execute (struct constant_pool 
 
   gcc_assert (c);
 
-  offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
-				 gen_rtx_LABEL_REF (Pmode, pool->label));
-  offset = gen_rtx_CONST (Pmode, offset);
-  return offset;
+  return s390_pool_offset (pool, gen_rtx_LABEL_REF (Pmode, c->label));
 }
 
 /* For an execute INSN, extract the execute target template.  */
@@ -5989,11 +5995,7 @@ s390_dump_pool (struct constant_pool *po
 	    && GET_CODE (XEXP (value, 0)) == UNSPEC
 	    && XINT (XEXP (value, 0), 1) == UNSPEC_LTREL_OFFSET
 	    && XVECLEN (XEXP (value, 0), 0) == 1)
-	  {
-	    value = gen_rtx_MINUS (Pmode, XVECEXP (XEXP (value, 0), 0, 0),
-				   gen_rtx_LABEL_REF (VOIDmode, pool->label));
-	    value = gen_rtx_CONST (VOIDmode, value);
-	  }
+	  value = s390_pool_offset (pool, XVECEXP (XEXP (value, 0), 0, 0));
 
 	insn = emit_label_after (c->label, insn);
 	INSN_ADDRESSES_NEW (insn, -1);
@@ -9598,9 +9600,6 @@ s390_reorg (void)
      machine_dependent_reorg might confuse insn length counts.  */
   split_all_insns_noflow ();
 
-  /* From here on decomposed literal pool addresses must be accepted.  */
-  cfun->machine->decomposed_literal_pool_addresses_ok_p = true;
-
   /* Install the main literal pool and the associated base
      register load insns.
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]