Commit bdb57bcb by Ilya Leoshkevich Committed by Andreas Krebbel

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
parent d7252499
2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com> 2018-09-06 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/80080 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
* config/s390/s390-passes.def: New file. * config/s390/s390-passes.def: New file.
* config/s390/s390-protos.h (class rtl_opt_pass): Add forward * config/s390/s390-protos.h (class rtl_opt_pass): Add forward
declaration. declaration.
......
...@@ -534,3 +534,15 @@ ...@@ -534,3 +534,15 @@
unsigned HOST_WIDE_INT val = INTVAL (op); unsigned HOST_WIDE_INT val = INTVAL (op);
return val <= 128 && val % 8 == 0; 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);
})
...@@ -1825,6 +1825,21 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) ...@@ -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); 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 /* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
matches CMP. matches CMP.
Return the correct condition RTL to be placed in the IF_THEN_ELSE of the 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, ...@@ -1836,6 +1851,7 @@ s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem,
{ {
rtx cc; rtx cc;
mem = s390_legitimize_cs_operand (mem);
cc = gen_rtx_REG (ccmode, CC_REGNUM); cc = gen_rtx_REG (ccmode, CC_REGNUM);
switch (GET_MODE (mem)) switch (GET_MODE (mem))
{ {
......
...@@ -10338,7 +10338,7 @@ ...@@ -10338,7 +10338,7 @@
; cdsg, csg ; cdsg, csg
(define_insn "*atomic_compare_and_swap<mode>_1" (define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:TDI 0 "register_operand" "=r") [(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) (set (match_dup 1)
(unspec_volatile:TDI (unspec_volatile:TDI
[(match_dup 1) [(match_dup 1)
...@@ -10356,7 +10356,7 @@ ...@@ -10356,7 +10356,7 @@
; cds, cdsy ; cds, cdsy
(define_insn "*atomic_compare_and_swapdi_2" (define_insn "*atomic_compare_and_swapdi_2"
[(set (match_operand:DI 0 "register_operand" "=r,r") [(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) (set (match_dup 1)
(unspec_volatile:DI (unspec_volatile:DI
[(match_dup 1) [(match_dup 1)
...@@ -10377,7 +10377,7 @@ ...@@ -10377,7 +10377,7 @@
; cs, csy ; cs, csy
(define_insn "*atomic_compare_and_swapsi_3" (define_insn "*atomic_compare_and_swapsi_3"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(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) (set (match_dup 1)
(unspec_volatile:SI (unspec_volatile:SI
[(match_dup 1) [(match_dup 1)
......
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> 2018-09-05 Marek Polacek <polacek@redhat.com>
PR c++/86982, -Wreturn-local-addr and std::move and std::forward. PR c++/86982, -Wreturn-local-addr and std::move and std::forward.
......
/* { 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" } } */
...@@ -252,5 +252,14 @@ set-torture-options $MD_TEST_OPTS ...@@ -252,5 +252,14 @@ set-torture-options $MD_TEST_OPTS
gcc-dg-runtest [lsort [glob -nocomplain $md_tests]] "" "$DEFAULT_CFLAGS" gcc-dg-runtest [lsort [glob -nocomplain $md_tests]] "" "$DEFAULT_CFLAGS"
torture-finish 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. # All done.
dg-finish dg-finish
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment