S/390: Prohibit SYMBOL_REF in UNSPECV_CAS

Inhibit constant propagation inlining SYMBOL_REF loads into
UNSPECV_CAS.  Even though reload can later undo it, the resulting
code will be less efficient.

gcc/ChangeLog:

2018-09-06  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/80080
	* config/s390/predicates.md: Add nonsym_memory_operand.
	* config/s390/s390.c (s390_legitimize_cs_operand): If operand
	contains a SYMBOL_REF, load it into an intermediate pseudo.
	(s390_emit_compare_and_swap): Legitimize operand.
	* config/s390/s390.md: Use the new nonsym_memory_operand
	with UNSPECV_CAS patterns.

gcc/testsuite/ChangeLog:

2018-09-06  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/80080
	* gcc.target/s390/pr80080-3.c: New test.
	* gcc.target/s390/s390.exp: Make sure the new test passes
	on all optimization levels.

From-SVN: r264143
This commit is contained in:
Ilya Leoshkevich 2018-09-06 07:38:42 +00:00 committed by Andreas Krebbel
parent d725249946
commit bdb57bcb54
7 changed files with 67 additions and 3 deletions

View File

@ -1,3 +1,13 @@
2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/80080
* config/s390/predicates.md: Add nonsym_memory_operand.
* config/s390/s390.c (s390_legitimize_cs_operand): If operand
contains a SYMBOL_REF, load it into an intermediate pseudo.
(s390_emit_compare_and_swap): Legitimize operand.
* config/s390/s390.md: Use the new nonsym_memory_operand
with UNSPECV_CAS patterns.
2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/80080

View File

@ -534,3 +534,15 @@
unsigned HOST_WIDE_INT val = INTVAL (op);
return val <= 128 && val % 8 == 0;
})
;; Certain operations (e.g. CS) cannot access SYMBOL_REF directly, it needs to
;; be loaded into some register first. In theory, if we put a SYMBOL_REF into
;; a corresponding insn anyway, reload will generate a load for it, but, when
;; coupled with constant propagation, this will lead to an inefficient code
;; (see PR 80080).
(define_predicate "nonsym_memory_operand"
(match_code "mem")
{
return memory_operand (op, mode) && !contains_symbol_ref_p (op);
})

View File

@ -1825,6 +1825,21 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
}
/* If MEM is not a legitimate compare-and-swap memory operand, return a new
MEM, whose address is a pseudo containing the original MEM's address. */
static rtx
s390_legitimize_cs_operand (rtx mem)
{
rtx tmp;
if (!contains_symbol_ref_p (mem))
return mem;
tmp = gen_reg_rtx (Pmode);
emit_move_insn (tmp, copy_rtx (XEXP (mem, 0)));
return change_address (mem, VOIDmode, tmp);
}
/* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
matches CMP.
Return the correct condition RTL to be placed in the IF_THEN_ELSE of the
@ -1836,6 +1851,7 @@ s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem,
{
rtx cc;
mem = s390_legitimize_cs_operand (mem);
cc = gen_rtx_REG (ccmode, CC_REGNUM);
switch (GET_MODE (mem))
{

View File

@ -10338,7 +10338,7 @@
; cdsg, csg
(define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:TDI 0 "register_operand" "=r")
(match_operand:TDI 1 "memory_operand" "+S"))
(match_operand:TDI 1 "nonsym_memory_operand" "+S"))
(set (match_dup 1)
(unspec_volatile:TDI
[(match_dup 1)
@ -10356,7 +10356,7 @@
; cds, cdsy
(define_insn "*atomic_compare_and_swapdi_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(match_operand:DI 1 "memory_operand" "+Q,S"))
(match_operand:DI 1 "nonsym_memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_dup 1)
@ -10377,7 +10377,7 @@
; cs, csy
(define_insn "*atomic_compare_and_swapsi_3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operand:SI 1 "memory_operand" "+Q,S"))
(match_operand:SI 1 "nonsym_memory_operand" "+Q,S"))
(set (match_dup 1)
(unspec_volatile:SI
[(match_dup 1)

View File

@ -1,3 +1,10 @@
2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/80080
* gcc.target/s390/pr80080-3.c: New test.
* gcc.target/s390/s390.exp: Make sure the new test passes
on all optimization levels.
2018-09-05 Marek Polacek <polacek@redhat.com>
PR c++/86982, -Wreturn-local-addr and std::move and std::forward.

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-march=z10" } */
extern int foo3_mem;
int foo3 (void)
{
return __atomic_exchange_n (&foo3_mem, 5, __ATOMIC_ACQUIRE);
}
/* { dg-final { scan-assembler "\n\(\\.L\\d+):\n\tcs\t.*\n\tjne\t\\1\n" } } */

View File

@ -252,5 +252,14 @@ set-torture-options $MD_TEST_OPTS
gcc-dg-runtest [lsort [glob -nocomplain $md_tests]] "" "$DEFAULT_CFLAGS"
torture-finish
# Tests that should pass on all optimization levels.
foreach t [list $srcdir/$subdir/pr80080-3.c] {
torture-init
set-torture-options [list -O1 -O2 -O3 -O0 -Os -Ofast -Og]
gcc-dg-runtest [list $t] \
"" $DEFAULT_CFLAGS
torture-finish
}
# All done.
dg-finish