This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: Make s390 use an UNSPEC instead of (const (minus ...))
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: hpenner at de dot ibm dot com, uweigand at de dot ibm dot com, Andreas dot Krebbel at de dot ibm dot com
- Date: Fri, 10 Oct 2008 19:22:01 +0100
- Subject: 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.