Bootstrapped and regtested on s390x-redhat-linux.
Consider the following RTL:
(insn (set (mem/f/c:DI (reg/f:DI 60))
(const:DI (plus:DI (symbol_ref:DI ("*.LANCHOR0"))
(const_int 8)))))
generated by cse2 pass. It is matched to movdi_64, resulting in
the following inefficient code:
larl %r5,.L6 # Load literal pool@
lg %r1,.L7-.L6(%r5) # Load .LANCHOR0+8
stgrl %r1,.LANCHOR0
br %r14
Matching it to movdi_larl improves the code, eliminating one
instruction and the literal pool entry:
larl %r1,.LANCHOR0+8
stgrl %r1,.LANCHOR0
br %r14
Taking it one step further, there is no reason to keep movdi_64 and
movdi_larl separate, since this could potentially improve code in other
ways by giving lra one more alternative to choose from.
gcc/ChangeLog:
2018-10-22 Ilya Leoshkevich <[email protected]>
* config/s390/constraints.md (ZL): New constraint.
* config/s390/s390.c (legitimate_pic_operand_p): Accept LARL
operands.
* config/s390/s390.md (movdi_larl): Remove.
(movdi_64): Add the LARL alternative.
gcc/testsuite/ChangeLog:
2018-10-25 Ilya Leoshkevich <[email protected]>
* gcc.target/s390/global-array-almost-huge-element.c: New test.
* gcc.target/s390/global-array-almost-negative-huge-element.c: New test.
* gcc.target/s390/global-array-element-pic.c: New test.
* gcc.target/s390/global-array-even-element.c: New test.
* gcc.target/s390/global-array-huge-element.c: New test.
* gcc.target/s390/global-array-negative-huge-element.c: New test.
* gcc.target/s390/global-array-odd-element.c: New test.
---
gcc/config/s390/constraints.md | 5 ++++
gcc/config/s390/s390.c | 4 +++
gcc/config/s390/s390.md | 27 +++++++------------
.../s390/global-array-almost-huge-element.c | 12 +++++++++
...lobal-array-almost-negative-huge-element.c | 12 +++++++++
.../s390/global-array-element-pic.c | 13 +++++++++
.../s390/global-array-even-element.c | 12 +++++++++
.../s390/global-array-huge-element.c | 12 +++++++++
.../s390/global-array-negative-huge-element.c | 12 +++++++++
.../s390/global-array-odd-element.c | 12 +++++++++
10 files changed, 104 insertions(+), 17 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/s390/global-array-almost-huge-element.c
create mode 100644
gcc/testsuite/gcc.target/s390/global-array-almost-negative-huge-element.c
create mode 100644 gcc/testsuite/gcc.target/s390/global-array-element-pic.c
create mode 100644 gcc/testsuite/gcc.target/s390/global-array-even-element.c
create mode 100644 gcc/testsuite/gcc.target/s390/global-array-huge-element.c
create mode 100644
gcc/testsuite/gcc.target/s390/global-array-negative-huge-element.c
create mode 100644 gcc/testsuite/gcc.target/s390/global-array-odd-element.c
diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md
index b8ba8510096..63c7fd368be 100644
--- a/gcc/config/s390/constraints.md
+++ b/gcc/config/s390/constraints.md
@@ -89,6 +89,7 @@
;; ZR -- Pointer with index register and short displacement.
;; ZS -- Pointer without index register but with long displacement.
;; ZT -- Pointer with index register and long displacement.
+;; ZL -- LARL operand when in 64-bit mode, otherwise nothing.
;;
;;
@@ -562,3 +563,7 @@
(define_address_constraint "ZT"
"Pointer with index register and long displacement."
(match_test "s390_mem_constraint (\"ZT\", op)"))
+
+(define_constraint "ZL"
+ "LARL operand when in 64-bit mode, otherwise nothing."
+ (match_test "TARGET_64BIT && larl_operand (op, VOIDmode)"))
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 6d18a034030..29a829f48ea 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3859,6 +3859,10 @@ legitimate_pic_operand_p (rtx op)
if (!SYMBOLIC_CONST (op))
return 1;
+ /* Accept addresses that can be expressed relative to (pc). */
+ if (larl_operand (op, VOIDmode))
+ return 1;
+
/* Reject everything else; must be handled
via emit_symbolic_move. */
return 0;
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 3bd18acb456..e4049c25406 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1729,21 +1729,11 @@
emit_symbolic_move (operands);
})
-(define_insn "*movdi_larl"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (match_operand:DI 1 "larl_operand" "X"))]
- "TARGET_64BIT
- && !FP_REG_P (operands[0])"
- "larl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_super_A1")])
-
(define_insn "*movdi_64"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=d, d, d, d, d, d, d,
d,f,d,d,d,d,d,T,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t,v,v,v,d,v,R")
+ "=d, d, d, d, d, d, d,
d,f,d,d,d,d,d,T,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t,v,v,v,d,v,R,d")
(match_operand:DI 1 "general_operand"
- " K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,T,d, *f, R,
T,*f,*f,d,K,t,d,t,Q,K,v,d,v,R,v"))]
+ " K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,T,d, *f, R,
T,*f,*f,d,K,t,d,t,Q,K,v,d,v,R,v,ZL"))]
"TARGET_ZARCH"
"@
lghi\t%0,%h1
@@ -1777,15 +1767,17 @@
vlvgg\t%v0,%1,0
vlgvg\t%0,%v1,0
vleg\t%v0,%1,0
- vsteg\t%v1,%0,0"
+ vsteg\t%v1,%0,0
+ larl\t%0,%1"
[(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RIL,RRE,RXY,
-
RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,VRI,VRR,VRS,VRS,VRX,VRX")
+ RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,VRI,VRR,VRS,VRS,
+ VRX,VRX,RIL")
(set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,larl,lr,load,store,
floaddf,floaddf,floaddf,fstoredf,fstoredf,larl,*,*,*,*,
- *,*,*,*,*,*,*")
+ *,*,*,*,*,*,*,larl")
(set_attr "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp,
z10,*,*,*,*,*,longdisp,*,longdisp,
- z10,z10,*,*,*,*,vx,vx,vx,vx,vx,vx")
+ z10,z10,*,*,*,*,vx,vx,vx,vx,vx,vx,*")
(set_attr "z10prop" "z10_fwd_A1,
z10_fwd_E1,
z10_fwd_E1,
@@ -1811,7 +1803,8 @@
*,
*,
*,
- *,*,*,*,*,*,*")
+ *,*,*,*,*,*,*,
+ z10_super_A1")
])
(define_split
diff --git a/gcc/testsuite/gcc.target/s390/global-array-almost-huge-element.c
b/gcc/testsuite/gcc.target/s390/global-array-almost-huge-element.c
new file mode 100644
index 00000000000..28e4ccd9bdd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-almost-huge-element.c
@@ -0,0 +1,12 @@
+/* Test the maximum possible LARL offset. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void almost_huge()
+{
+ b = a + 0x7ffffffeULL;
+ /* { dg-final { scan-assembler {(?n)\n\tlarl\t%r\d+,a\+2147483646\n} } } */
+}
diff --git
a/gcc/testsuite/gcc.target/s390/global-array-almost-negative-huge-element.c
b/gcc/testsuite/gcc.target/s390/global-array-almost-negative-huge-element.c
new file mode 100644
index 00000000000..0012ceb8d49
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-almost-negative-huge-element.c
@@ -0,0 +1,12 @@
+/* Test the minimum LARL offset. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void almost_negative_huge()
+{
+ b = a - 0x80000000ULL;
+ /* { dg-final { scan-assembler {(?n)\n\tlarl\t%r\d+,a-2147483648\n} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
b/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
new file mode 100644
index 00000000000..78721206151
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
@@ -0,0 +1,13 @@
+/* Test accesses to global array elements in PIC code. */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fPIC" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void c()
+{
+ b = a + 4;
+ /* { dg-final { scan-assembler {(?n)\n\tlarl\t%r\d+,a@GOTENT\n} } } */
+ /* { dg-final { scan-assembler-not {(?n)\n\tlarl\t%r\d+,a[^@]} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/global-array-even-element.c
b/gcc/testsuite/gcc.target/s390/global-array-even-element.c
new file mode 100644
index 00000000000..5737f7e3496
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-even-element.c
@@ -0,0 +1,12 @@
+/* Test accesses to even global array elements. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void even()
+{
+ b = a + 4;
+ /* { dg-final { scan-assembler {(?n)\n\tlarl\t%r\d+,a\+4\n} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/global-array-huge-element.c
b/gcc/testsuite/gcc.target/s390/global-array-huge-element.c
new file mode 100644
index 00000000000..d4aad5764fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-huge-element.c
@@ -0,0 +1,12 @@
+/* Test minimum invalid LARL offset. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void huge()
+{
+ b = a + 0x80000000ULL;
+ /* { dg-final { scan-assembler-not {(?n)\n\tlarl\t%r\d+,a} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/global-array-negative-huge-element.c
b/gcc/testsuite/gcc.target/s390/global-array-negative-huge-element.c
new file mode 100644
index 00000000000..bd72d01a53b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-negative-huge-element.c
@@ -0,0 +1,12 @@
+/* Test maximum invalid LARL offset. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void negative_huge()
+{
+ b = a - 0x80000004ULL;
+ /* { dg-final { scan-assembler-not {(?n)\n\tlarl\t%r\d+,a} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/global-array-odd-element.c
b/gcc/testsuite/gcc.target/s390/global-array-odd-element.c
new file mode 100644
index 00000000000..84a65e55626
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-odd-element.c
@@ -0,0 +1,12 @@
+/* Test accesses to odd global array elements. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void odd()
+{
+ b = a + 1;
+ /* { dg-final { scan-assembler-not {(?n)\n\tlarl\t%r\d+,a} } } */
+}
--
2.19.0