From 3548abca0218168da1bb9f8cace29282a7495fbf Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Tue, 3 Feb 2015 20:24:13 +0000 Subject: [PATCH] re PR target/64660 ([SH] Convert atomic_fetch_ to atomic__fetch) gcc/ PR target/64660 * config/sh/sync.md (atomic__hard, atomic_not_hard, atomic__soft_tcb, atomic_not_soft_tcb, atomic_nand_hard, atomic_nand_soft_tcb): New insns. (atomic_fetch_si_hard): Convert to insn_and_split. Split into atomic__fetchsi_hard if operands[0] is unused. (define_insn "atomic_fetch_notsi_hard): Convert to insn_and_split. Split into atomic_not_fetchsi_hard if operands[0] is unused. (atomic_fetch__hard): Convert to insn_and_split. Split into atomic__hard if operands[0] is unused. (atomic_fetch_not_hard): Convert to insn_and_split. Split into atomic_not_hard if operands[0] is unused. (atomic_fetch__soft_gusa): Convert to insn_and_split. Split into atomic__fetch_soft_gusa if operands[0] is unused. (atomic_fetch_not_soft_gusa): Convert to insn_and_split. Split into atomic_not_fetch_soft_gusa if operands[0] is unused. (atomic_fetch__soft_tcb): Convert to insn_and_split. Split into atomic__soft_tcb if operands[0] is unused. (atomic_fetch_not_soft_tcb): Convert to insn_and_split. Split into atomic_not_soft_tcb if operands[0] is unused. (atomic_fetch__soft_imask): Convert to insn_and_split. Split into atomic__fetch_soft_imask if operands[0] is unused. (atomic_fetch_not_soft_imask): Convert to insn_and_split. Split into atomic_not_fetch_soft_imask is operands[0] is unused. (atomic_fetch_nandsi_hard): Convert to insn_and_split. Split into atomic_nand_fetchsi_hard if operands[0] is unused. (atomic_fetch_nand_hard): Convert to insn_and_split. Split into atomic_nand_hard if operands[0] is unused. (atomic_fetch_nand_soft_gusa): Convert to insn_and_split. Split into atomic_nand_fetch_soft_gusa if operands[0] is unused. (atomic_fetch_nand_soft_tcb): Convert to insn_and_split. Split into atomic_nand_soft_tcb if operands[0] is unused. (atomic_fetch_nand_soft_imask): Convert to insn_and_split. Split into atomic_nand_fetch_soft_imask if operands[0] is unused. (atomic__fetch_hard): Convert to insn_and_split. Split into atomic__hard if operands[0] is unused. (atomic_not_fetch_hard): Convert to insn_and_split. Split into atomic_not_hard if operands[0] is unused. (atomic__fetch_soft_tcb): Convert to insn_and_split. Split into atomic__soft_tcb if operands[0] is unused. (atomic_not_fetch_soft_tcb): Convert to insn_and_split. Split into atomic_not_soft_tcb if operands[0] is unused. (atomic_nand_fetch_hard): Convert to insn_and_split. Split into atomic_nand_hard if operands[0] is unused. (atomic_nand_fetch_soft_tcb): Convert to insn_and_split. Split into atomic_nand_soft_tcb if operands[0] is unused. gcc/testsuite/ PR target/64660 * gcc.target/sh/pr64660-0.h: New. * gcc.target/sh/pr64660-1.c: New. * gcc.target/sh/pr64660-2.c: New. * gcc.target/sh/pr64660-3.c: New. * gcc.target/sh/pr64660-4.c: New. From-SVN: r220376 --- gcc/ChangeLog | 54 ++++ gcc/config/sh/sync.md | 333 ++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 9 + gcc/testsuite/gcc.target/sh/pr64660-0.h | 44 ++++ gcc/testsuite/gcc.target/sh/pr64660-1.c | 12 + gcc/testsuite/gcc.target/sh/pr64660-2.c | 13 + gcc/testsuite/gcc.target/sh/pr64660-3.c | 12 + gcc/testsuite/gcc.target/sh/pr64660-4.c | 17 ++ 8 files changed, 473 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.target/sh/pr64660-0.h create mode 100644 gcc/testsuite/gcc.target/sh/pr64660-1.c create mode 100644 gcc/testsuite/gcc.target/sh/pr64660-2.c create mode 100644 gcc/testsuite/gcc.target/sh/pr64660-3.c create mode 100644 gcc/testsuite/gcc.target/sh/pr64660-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d1f6280caa..98c968ecc20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,57 @@ +2015-02-03 Oleg Endo + + PR target/64660 + * config/sh/sync.md (atomic__hard, + atomic_not_hard, atomic__soft_tcb, + atomic_not_soft_tcb, atomic_nand_hard, + atomic_nand_soft_tcb): New insns. + (atomic_fetch_si_hard): Convert to insn_and_split. + Split into atomic__fetchsi_hard if operands[0] is unused. + (define_insn "atomic_fetch_notsi_hard): Convert to insn_and_split. + Split into atomic_not_fetchsi_hard if operands[0] is unused. + (atomic_fetch__hard): Convert to insn_and_split. + Split into atomic__hard if operands[0] is unused. + (atomic_fetch_not_hard): Convert to insn_and_split. Split into + atomic_not_hard if operands[0] is unused. + (atomic_fetch__soft_gusa): Convert to + insn_and_split. Split into atomic__fetch_soft_gusa + if operands[0] is unused. + (atomic_fetch_not_soft_gusa): Convert to insn_and_split. Split + into atomic_not_fetch_soft_gusa if operands[0] is unused. + (atomic_fetch__soft_tcb): Convert to insn_and_split. + Split into atomic__soft_tcb if operands[0] is + unused. + (atomic_fetch_not_soft_tcb): Convert to insn_and_split. Split + into atomic_not_soft_tcb if operands[0] is unused. + (atomic_fetch__soft_imask): Convert to + insn_and_split. Split into atomic__fetch_soft_imask + if operands[0] is unused. + (atomic_fetch_not_soft_imask): Convert to insn_and_split. Split + into atomic_not_fetch_soft_imask is operands[0] is unused. + (atomic_fetch_nandsi_hard): Convert to insn_and_split. Split into + atomic_nand_fetchsi_hard if operands[0] is unused. + (atomic_fetch_nand_hard): Convert to insn_and_split. Split into + atomic_nand_hard if operands[0] is unused. + (atomic_fetch_nand_soft_gusa): Convert to insn_and_split. Split + into atomic_nand_fetch_soft_gusa if operands[0] is unused. + (atomic_fetch_nand_soft_tcb): Convert to insn_and_split. Split + into atomic_nand_soft_tcb if operands[0] is unused. + (atomic_fetch_nand_soft_imask): Convert to insn_and_split. Split + into atomic_nand_fetch_soft_imask if operands[0] is unused. + (atomic__fetch_hard): Convert to insn_and_split. + Split into atomic__hard if operands[0] is unused. + (atomic_not_fetch_hard): Convert to insn_and_split. Split into + atomic_not_hard if operands[0] is unused. + (atomic__fetch_soft_tcb): Convert to insn_and_split. + Split into atomic__soft_tcb if operands[0] is + unused. + (atomic_not_fetch_soft_tcb): Convert to insn_and_split. Split + into atomic_not_soft_tcb if operands[0] is unused. + (atomic_nand_fetch_hard): Convert to insn_and_split. Split into + atomic_nand_hard if operands[0] is unused. + (atomic_nand_fetch_soft_tcb): Convert to insn_and_split. Split + into atomic_nand_soft_tcb if operands[0] is unused. + 2015-02-03 David Malcolm PR jit/64810 diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md index 089a6283a47..d1413c595a6 100644 --- a/gcc/config/sh/sync.md +++ b/gcc/config/sh/sync.md @@ -651,7 +651,7 @@ DONE; }) -(define_insn "atomic_fetch_si_hard" +(define_insn_and_split "atomic_fetch_si_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -670,11 +670,18 @@ " %2,r0" "\n" " movco.l r0,@%1" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetchsi_hard (gen_reg_rtx (SImode), + operands[1], operands[2])); } [(set_attr "length" "10")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_notsi_hard" +(define_insn_and_split "atomic_fetch_notsi_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -689,10 +696,16 @@ " not r0,r0" "\n" " movco.l r0,@%1" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetchsi_hard (gen_reg_rtx (SImode), operands[1])); } [(set_attr "length" "10")]) -(define_insn "atomic_fetch__hard" +(define_insn_and_split "atomic_fetch__hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -721,11 +734,46 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%3" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__hard (operands[1], operands[2])); } [(set_attr "length" "28")]) +(define_insn "atomic__hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI + [(FETCHOP:QIHI (mem:QIHI (match_dup 0)) + (match_operand:QIHI 1 "" + ""))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (match_scratch:SI 3 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%2" "\n" + " and %0,%2" "\n" + " xor %2,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%2,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " %1,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%2" "\n" + " bf 0b"; +} + [(set_attr "length" "26")]) + ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_hard" +(define_insn_and_split "atomic_fetch_not_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -749,10 +797,41 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%2" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_hard (operands[1])); } [(set_attr "length" "26")]) -(define_insn "atomic_fetch__soft_gusa" +(define_insn "atomic_not_hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI [(not:QIHI (mem:QIHI (match_dup 0)))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 1 "=&r")) + (clobber (match_scratch:SI 2 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%1" "\n" + " and %0,%1" "\n" + " xor %1,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%1,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%1" "\n" + " bf 0b"; +} + [(set_attr "length" "26")]) + +(define_insn_and_split "atomic_fetch__soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -776,11 +855,18 @@ " %2,%3" "\n" " mov. %3,@%1" "\n" "1: mov r1,r15"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetch_soft_gusa ( + gen_reg_rtx (mode), operands[1], operands[2])); } [(set_attr "length" "18")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_gusa" +(define_insn_and_split "atomic_fetch_not_soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -798,10 +884,17 @@ " not %0,%2" "\n" " mov. %2,@%1" "\n" "1: mov r1,r15"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetch_soft_gusa (gen_reg_rtx (mode), + operands[1])); } [(set_attr "length" "16")]) -(define_insn "atomic_fetch__soft_tcb" +(define_insn_and_split "atomic_fetch__soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -826,11 +919,43 @@ " mov. r0,@%1" "\n" "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__soft_tcb ( + operands[1], operands[2], operands[3])); } [(set_attr "length" "20")]) +(define_insn "atomic__soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI + [(FETCHOP:QIHISI + (mem:QIHISI (match_dup 0)) + (match_operand:QIHISI 1 "" + ""))] + UNSPEC_ATOMIC)) + (use (match_operand:SI 2 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " mov #(0f-1f),r1" "\n" + " .align 2" "\n" + " mov.l r0,@(%O2,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " %1,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O2,gbr)"; +} + [(set_attr "length" "18")]) + ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_tcb" +(define_insn_and_split "atomic_fetch_not_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -850,10 +975,36 @@ " mov. r0,@%1" "\n" "1: mov #0,r0" "\n" " mov.l r0,@(%O2,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_soft_tcb (operands[1], operands[2])); } [(set_attr "length" "20")]) -(define_insn "atomic_fetch__soft_imask" +(define_insn "atomic_not_soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 0)))] UNSPEC_ATOMIC)) + (use (match_operand:SI 1 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " mov #(0f-1f),r1" "\n" + " .align 2" "\n" + " mov.l r0,@(%O1,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O1,gbr)"; +} + [(set_attr "length" "18")]) + +(define_insn_and_split "atomic_fetch__soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -876,11 +1027,18 @@ " %2,r0" "\n" " mov. r0,@%1" "\n" " ldc %3,sr"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__fetch_soft_imask ( + gen_reg_rtx (mode), operands[1], operands[2])); } [(set_attr "length" "18")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_fetch_not_soft_imask" +(define_insn_and_split "atomic_fetch_not_soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -898,6 +1056,13 @@ " not r0,r0" "\n" " mov. r0,@%1" "\n" " ldc %2,sr"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_fetch_soft_imask (gen_reg_rtx (mode), + operands[1])); } [(set_attr "length" "18")]) @@ -942,7 +1107,7 @@ DONE; }) -(define_insn "atomic_fetch_nandsi_hard" +(define_insn_and_split "atomic_fetch_nandsi_hard" [(set (match_operand:SI 0 "arith_reg_dest" "=&r") (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:SI (match_dup 1)) @@ -961,10 +1126,17 @@ " not r0,r0" "\n" " movco.l r0,@%1" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetchsi_hard (gen_reg_rtx (SImode), operands[1], + operands[2])); } [(set_attr "length" "12")]) -(define_insn "atomic_fetch_nand_hard" +(define_insn_and_split "atomic_fetch_nand_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHI (match_dup 1)) @@ -993,10 +1165,45 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%3" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_hard (operands[1], operands[2])); } [(set_attr "length" "30")]) -(define_insn "atomic_fetch_nand_soft_gusa" +(define_insn "atomic_nand_hard" + [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHI + [(not:QIHI (and:QIHI (mem:QIHI (match_dup 0)) + (match_operand:QIHI 1 "logical_operand" "rK08")))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) + (clobber (reg:SI R0_REG)) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (match_scratch:SI 3 "=0"))] + "TARGET_ATOMIC_HARD_LLCS" +{ + return "\r mov #-4,%2" "\n" + " and %0,%2" "\n" + " xor %2,%0" "\n" + " add r15,%0" "\n" + " add #-4,%0" "\n" + "0: movli.l @%2,r0" "\n" + " mov.l r0,@-r15" "\n" + " mov. @%0,r0" "\n" + " and %1,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + " mov.l @r15+,r0" "\n" + " movco.l r0,@%2" "\n" + " bf 0b"; +} + [(set_attr "length" "28")]) + +(define_insn_and_split "atomic_fetch_nand_soft_gusa" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))) (set (mem:QIHISI (match_dup 1)) @@ -1020,10 +1227,17 @@ " not %3,%3" "\n" " mov. %3,@%1" "\n" "1: mov r1,r15"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetch_soft_gusa (gen_reg_rtx (mode), + operands[1], operands[2])); } [(set_attr "length" "20")]) -(define_insn "atomic_fetch_nand_soft_tcb" +(define_insn_and_split "atomic_fetch_nand_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -1048,10 +1262,42 @@ " mov. r0,@%1" "\n" "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_soft_tcb (operands[1], operands[2], + operands[3])); } [(set_attr "length" "22")]) -(define_insn "atomic_fetch_nand_soft_imask" +(define_insn "atomic_nand_soft_tcb" + [(set (mem:QIHISI (match_operand:SI 0 "arith_reg_operand" "r")) + (unspec:QIHISI + [(not:QIHISI + (and:QIHISI (mem:QIHISI (match_dup 0)) + (match_operand:QIHISI 1 "logical_operand" "rK08")))] + UNSPEC_ATOMIC)) + (use (match_operand:SI 2 "gbr_displacement")) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG))] + "TARGET_ATOMIC_SOFT_TCB" +{ + return "\r mova 1f,r0" "\n" + " .align 2" "\n" + " mov #(0f-1f),r1" "\n" + " mov.l r0,@(%O2,gbr)" "\n" + "0: mov. @%0,r0" "\n" + " and %1,r0" "\n" + " not r0,r0" "\n" + " mov. r0,@%0" "\n" + "1: mov #0,r0" "\n" + " mov.l r0,@(%O2,gbr)"; +} + [(set_attr "length" "20")]) + +(define_insn_and_split "atomic_fetch_nand_soft_imask" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))) (set (mem:QIHISI (match_dup 1)) @@ -1074,6 +1320,13 @@ " not r0,r0" "\n" " mov. r0,@%1" "\n" " ldc %3,sr"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_fetch_soft_imask (gen_reg_rtx (mode), + operands[1], operands[2])); } [(set_attr "length" "20")]) @@ -1160,7 +1413,7 @@ } [(set_attr "length" "8")]) -(define_insn "atomic__fetch_hard" +(define_insn_and_split "atomic__fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (FETCHOP:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1190,11 +1443,17 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%3" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__hard (operands[1], operands[2])); } [(set_attr "length" "28")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_not_fetch_hard" +(define_insn_and_split "atomic_not_fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (not:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")))) (set (mem:QIHI (match_dup 1)) @@ -1219,6 +1478,12 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%2" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_hard (operands[1])); } [(set_attr "length" "28")]) @@ -1268,7 +1533,7 @@ } [(set_attr "length" "16")]) -(define_insn "atomic__fetch_soft_tcb" +(define_insn_and_split "atomic__fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (FETCHOP:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1293,11 +1558,18 @@ "1: mov r0,%0" "\n" " mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic__soft_tcb ( + operands[1], operands[2], operands[3])); } [(set_attr "length" "20")]) ;; Combine pattern for xor (val, -1) / nand (val, -1). -(define_insn "atomic_not_fetch_soft_tcb" +(define_insn_and_split "atomic_not_fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (not:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")))) (set (mem:QIHISI (match_dup 1)) @@ -1317,6 +1589,12 @@ "1: mov r0,%0" "\n" " mov #0,r0" "\n" " mov.l r0,@(%O2,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_not_soft_tcb (operands[1], operands[2])); } [(set_attr "length" "20")]) @@ -1426,7 +1704,7 @@ } [(set_attr "length" "10")]) -(define_insn "atomic_nand_fetch_hard" +(define_insn_and_split "atomic_nand_fetch_hard" [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r") (not:QIHI (and:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1455,6 +1733,12 @@ " mov.l @r15+,r0" "\n" " movco.l r0,@%3" "\n" " bf 0b"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_hard (operands[1], operands[2])); } [(set_attr "length" "28")]) @@ -1483,7 +1767,7 @@ } [(set_attr "length" "18")]) -(define_insn "atomic_nand_fetch_soft_tcb" +(define_insn_and_split "atomic_nand_fetch_soft_tcb" [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r") (not:QIHISI (and:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")) @@ -1508,6 +1792,13 @@ " mov. r0,@%1" "\n" "1: mov #0,r0" "\n" " mov.l r0,@(%O3,gbr)"; +} + "&& can_create_pseudo_p () && optimize + && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))" + [(const_int 0)] +{ + emit_insn (gen_atomic_nand_soft_tcb (operands[1], operands[2], + operands[3])); } [(set_attr "length" "22")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00c0450dbb5..98d72cbc38a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-02-03 Oleg Endo + + PR target/64660 + * gcc.target/sh/pr64660-0.h: New. + * gcc.target/sh/pr64660-1.c: New. + * gcc.target/sh/pr64660-2.c: New. + * gcc.target/sh/pr64660-3.c: New. + * gcc.target/sh/pr64660-4.c: New. + 2015-02-03 Paolo Carlini PR c++/64877 diff --git a/gcc/testsuite/gcc.target/sh/pr64660-0.h b/gcc/testsuite/gcc.target/sh/pr64660-0.h new file mode 100644 index 00000000000..28c1ac61aae --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr64660-0.h @@ -0,0 +1,44 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ + +#define concat_1(x, y) x ## y +#define concat(x, y) concat_1 (x, y) +#define makefuncname(name) concat (concat (test_, __LINE__), name) + +#define emitfuncs(name,val)\ + void makefuncname (_0) (char* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + void makefuncname (_1) (short* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + void makefuncname (_2) (int* mem)\ + {\ + name (mem, val, __ATOMIC_ACQ_REL);\ + }\ + +emitfuncs (__atomic_add_fetch, 1) +emitfuncs (__atomic_fetch_add, 1) + +emitfuncs (__atomic_sub_fetch, 1) +emitfuncs (__atomic_fetch_sub, 1) + +emitfuncs (__atomic_and_fetch, 1) +emitfuncs (__atomic_fetch_and, 1) + +emitfuncs (__atomic_or_fetch, 1) +emitfuncs (__atomic_fetch_or, 1) + +emitfuncs (__atomic_xor_fetch, 1) +emitfuncs (__atomic_fetch_xor, 1) + +emitfuncs (__atomic_nand_fetch, 1) +emitfuncs (__atomic_fetch_nand, 1) + +emitfuncs (__atomic_xor_fetch, -1) +emitfuncs (__atomic_fetch_xor, -1) + +emitfuncs (__atomic_nand_fetch, -1) +emitfuncs (__atomic_fetch_nand, -1) diff --git a/gcc/testsuite/gcc.target/sh/pr64660-1.c b/gcc/testsuite/gcc.target/sh/pr64660-1.c new file mode 100644 index 00000000000..2d5442c427c --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr64660-1.c @@ -0,0 +1,12 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_gusa_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-gusa,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } } */ + +#include "pr64660-0.h" diff --git a/gcc/testsuite/gcc.target/sh/pr64660-2.c b/gcc/testsuite/gcc.target/sh/pr64660-2.c new file mode 100644 index 00000000000..c0cef13d164 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr64660-2.c @@ -0,0 +1,13 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_tcb_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-tcb,gbr-offset=0,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not" 12 } } */ +/* { dg-final { scan-assembler-not "fetch" } } */ + +#include "pr64660-0.h" diff --git a/gcc/testsuite/gcc.target/sh/pr64660-3.c b/gcc/testsuite/gcc.target/sh/pr64660-3.c new file mode 100644 index 00000000000..fe3a83daf95 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr64660-3.c @@ -0,0 +1,12 @@ +/* Check that the appropriate atomic insns are used if the result values + are unused. */ +/* { dg-do compile { target { atomic_model_soft_imask_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=soft-imask,strict -mno-usermode" } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } } */ + +#include "pr64660-0.h" diff --git a/gcc/testsuite/gcc.target/sh/pr64660-4.c b/gcc/testsuite/gcc.target/sh/pr64660-4.c new file mode 100644 index 00000000000..4d5d7f45392 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr64660-4.c @@ -0,0 +1,17 @@ +/* Check that atomic not ops are generated. */ +/* { dg-do compile { target { atomic_model_hard_llcs_available } } } */ +/* { dg-options "-dp -O2 -matomic-model=hard-llcs,strict" } */ +/* { dg-final { scan-assembler-times "atomic_add" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_add_fetch" 4 } } */ +/* { dg-final { scan-assembler-times "atomic_and" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_and_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_or" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_or_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_xor" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_xor_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_nand" 6 } } */ +/* { dg-final { scan-assembler-times "atomic_nand_fetch" 2 } } */ +/* { dg-final { scan-assembler-times "atomic_not" 12 } } */ +/* { dg-final { scan-assembler-times "atomic_not_fetch" 4 } } */ + +#include "pr64660-0.h"