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:
parent
d725249946
commit
bdb57bcb54
@ -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
|
||||
|
@ -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);
|
||||
})
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
10
gcc/testsuite/gcc.target/s390/pr80080-3.c
Normal file
10
gcc/testsuite/gcc.target/s390/pr80080-3.c
Normal 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" } } */
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user