aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2015-02-03 20:24:13 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2015-02-03 20:24:13 +0000
commit3548abca0218168da1bb9f8cace29282a7495fbf (patch)
treec47a87d39f9c500a700aef5ef93d27e45d2c70ec
parent0ed4f01761116587a0aac7faae8512d6e73eeed0 (diff)
downloadgcc-3548abca0218168da1bb9f8cace29282a7495fbf.zip
gcc-3548abca0218168da1bb9f8cace29282a7495fbf.tar.gz
gcc-3548abca0218168da1bb9f8cace29282a7495fbf.tar.bz2
re PR target/64660 ([SH] Convert atomic_fetch_<op> to atomic_<op>_fetch)
gcc/ PR target/64660 * config/sh/sync.md (atomic_<fetchop_name><mode>_hard, atomic_not<mode>_hard, atomic_<fetchop_name><mode>_soft_tcb, atomic_not<mode>_soft_tcb, atomic_nand<mode>_hard, atomic_nand<mode>_soft_tcb): New insns. (atomic_fetch_<fetchop_name>si_hard): Convert to insn_and_split. Split into atomic_<fetchop_name>_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_<fetchop_name><mode>_hard): Convert to insn_and_split. Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused. (atomic_fetch_not<mode>_hard): Convert to insn_and_split. Split into atomic_not<mode>_hard if operands[0] is unused. (atomic_fetch_<fetchop_name><mode>_soft_gusa): Convert to insn_and_split. Split into atomic_<fetchop_name>_fetch<mode>_soft_gusa if operands[0] is unused. (atomic_fetch_not<mode>_soft_gusa): Convert to insn_and_split. Split into atomic_not_fetch<mode>_soft_gusa if operands[0] is unused. (atomic_fetch_<fetchop_name><mode>_soft_tcb): Convert to insn_and_split. Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is unused. (atomic_fetch_not<mode>_soft_tcb): Convert to insn_and_split. Split into atomic_not<mode>_soft_tcb if operands[0] is unused. (atomic_fetch_<fetchop_name><mode>_soft_imask): Convert to insn_and_split. Split into atomic_<fetchop_name>_fetch<mode>_soft_imask if operands[0] is unused. (atomic_fetch_not<mode>_soft_imask): Convert to insn_and_split. Split into atomic_not_fetch<mode>_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<mode>_hard): Convert to insn_and_split. Split into atomic_nand<mode>_hard if operands[0] is unused. (atomic_fetch_nand<mode>_soft_gusa): Convert to insn_and_split. Split into atomic_nand_fetch<mode>_soft_gusa if operands[0] is unused. (atomic_fetch_nand<mode>_soft_tcb): Convert to insn_and_split. Split into atomic_nand<mode>_soft_tcb if operands[0] is unused. (atomic_fetch_nand<mode>_soft_imask): Convert to insn_and_split. Split into atomic_nand_fetch<mode>_soft_imask if operands[0] is unused. (atomic_<fetchop_name>_fetch<mode>_hard): Convert to insn_and_split. Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused. (atomic_not_fetch<mode>_hard): Convert to insn_and_split. Split into atomic_not<mode>_hard if operands[0] is unused. (atomic_<fetchop_name>_fetch<mode>_soft_tcb): Convert to insn_and_split. Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is unused. (atomic_not_fetch<mode>_soft_tcb): Convert to insn_and_split. Split into atomic_not<mode>_soft_tcb if operands[0] is unused. (atomic_nand_fetch<mode>_hard): Convert to insn_and_split. Split into atomic_nand<mode>_hard if operands[0] is unused. (atomic_nand_fetch<mode>_soft_tcb): Convert to insn_and_split. Split into atomic_nand<mode>_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
-rw-r--r--gcc/ChangeLog54
-rw-r--r--gcc/config/sh/sync.md333
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.target/sh/pr64660-0.h44
-rw-r--r--gcc/testsuite/gcc.target/sh/pr64660-1.c12
-rw-r--r--gcc/testsuite/gcc.target/sh/pr64660-2.c13
-rw-r--r--gcc/testsuite/gcc.target/sh/pr64660-3.c12
-rw-r--r--gcc/testsuite/gcc.target/sh/pr64660-4.c17
8 files changed, 473 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5d1f628..98c968e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,57 @@
+2015-02-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/64660
+ * config/sh/sync.md (atomic_<fetchop_name><mode>_hard,
+ atomic_not<mode>_hard, atomic_<fetchop_name><mode>_soft_tcb,
+ atomic_not<mode>_soft_tcb, atomic_nand<mode>_hard,
+ atomic_nand<mode>_soft_tcb): New insns.
+ (atomic_fetch_<fetchop_name>si_hard): Convert to insn_and_split.
+ Split into atomic_<fetchop_name>_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_<fetchop_name><mode>_hard): Convert to insn_and_split.
+ Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
+ (atomic_fetch_not<mode>_hard): Convert to insn_and_split. Split into
+ atomic_not<mode>_hard if operands[0] is unused.
+ (atomic_fetch_<fetchop_name><mode>_soft_gusa): Convert to
+ insn_and_split. Split into atomic_<fetchop_name>_fetch<mode>_soft_gusa
+ if operands[0] is unused.
+ (atomic_fetch_not<mode>_soft_gusa): Convert to insn_and_split. Split
+ into atomic_not_fetch<mode>_soft_gusa if operands[0] is unused.
+ (atomic_fetch_<fetchop_name><mode>_soft_tcb): Convert to insn_and_split.
+ Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
+ unused.
+ (atomic_fetch_not<mode>_soft_tcb): Convert to insn_and_split. Split
+ into atomic_not<mode>_soft_tcb if operands[0] is unused.
+ (atomic_fetch_<fetchop_name><mode>_soft_imask): Convert to
+ insn_and_split. Split into atomic_<fetchop_name>_fetch<mode>_soft_imask
+ if operands[0] is unused.
+ (atomic_fetch_not<mode>_soft_imask): Convert to insn_and_split. Split
+ into atomic_not_fetch<mode>_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<mode>_hard): Convert to insn_and_split. Split into
+ atomic_nand<mode>_hard if operands[0] is unused.
+ (atomic_fetch_nand<mode>_soft_gusa): Convert to insn_and_split. Split
+ into atomic_nand_fetch<mode>_soft_gusa if operands[0] is unused.
+ (atomic_fetch_nand<mode>_soft_tcb): Convert to insn_and_split. Split
+ into atomic_nand<mode>_soft_tcb if operands[0] is unused.
+ (atomic_fetch_nand<mode>_soft_imask): Convert to insn_and_split. Split
+ into atomic_nand_fetch<mode>_soft_imask if operands[0] is unused.
+ (atomic_<fetchop_name>_fetch<mode>_hard): Convert to insn_and_split.
+ Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
+ (atomic_not_fetch<mode>_hard): Convert to insn_and_split. Split into
+ atomic_not<mode>_hard if operands[0] is unused.
+ (atomic_<fetchop_name>_fetch<mode>_soft_tcb): Convert to insn_and_split.
+ Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
+ unused.
+ (atomic_not_fetch<mode>_soft_tcb): Convert to insn_and_split. Split
+ into atomic_not<mode>_soft_tcb if operands[0] is unused.
+ (atomic_nand_fetch<mode>_hard): Convert to insn_and_split. Split into
+ atomic_nand<mode>_hard if operands[0] is unused.
+ (atomic_nand_fetch<mode>_soft_tcb): Convert to insn_and_split. Split
+ into atomic_nand<mode>_soft_tcb if operands[0] is unused.
+
2015-02-03 David Malcolm <dmalcolm@redhat.com>
PR jit/64810
diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md
index 089a628..d1413c5 100644
--- a/gcc/config/sh/sync.md
+++ b/gcc/config/sh/sync.md
@@ -651,7 +651,7 @@
DONE;
})
-(define_insn "atomic_fetch_<fetchop_name>si_hard"
+(define_insn_and_split "atomic_fetch_<fetchop_name>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))
@@ -671,10 +671,17 @@
" 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_<fetchop_name>_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))
@@ -690,9 +697,15 @@
" 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_<fetchop_name><mode>_hard"
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>_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))
@@ -722,10 +735,45 @@
" 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_<fetchop_name><mode>_hard (operands[1], operands[2]));
+}
[(set_attr "length" "28")])
+(define_insn "atomic_<fetchop_name><mode>_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 "<fetchop_predicate_1>"
+ "<fetchop_constraint_1_llcs>"))]
+ 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.<bw> @%0,r0" "\n"
+ " <fetchop_name> %1,r0" "\n"
+ " mov.<bw> 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<mode>_hard"
+(define_insn_and_split "atomic_fetch_not<mode>_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))
@@ -750,9 +798,40 @@
" 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<mode>_hard (operands[1]));
+}
+ [(set_attr "length" "26")])
+
+(define_insn "atomic_not<mode>_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.<bw> @%0,r0" "\n"
+ " not r0,r0" "\n"
+ " mov.<bw> r0,@%0" "\n"
+ " mov.l @r15+,r0" "\n"
+ " movco.l r0,@%1" "\n"
+ " bf 0b";
+}
[(set_attr "length" "26")])
-(define_insn "atomic_fetch_<fetchop_name><mode>_soft_gusa"
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>_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))
@@ -777,10 +856,17 @@
" mov.<bwl> %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_<fetchop_name>_fetch<mode>_soft_gusa (
+ gen_reg_rtx (<MODE>mode), operands[1], operands[2]));
+}
[(set_attr "length" "18")])
;; Combine pattern for xor (val, -1) / nand (val, -1).
-(define_insn "atomic_fetch_not<mode>_soft_gusa"
+(define_insn_and_split "atomic_fetch_not<mode>_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))
@@ -799,9 +885,16 @@
" mov.<bwl> %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<mode>_soft_gusa (gen_reg_rtx (<MODE>mode),
+ operands[1]));
+}
[(set_attr "length" "16")])
-(define_insn "atomic_fetch_<fetchop_name><mode>_soft_tcb"
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>_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))
@@ -827,10 +920,42 @@
"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_<fetchop_name><mode>_soft_tcb (
+ operands[1], operands[2], operands[3]));
+}
[(set_attr "length" "20")])
+(define_insn "atomic_<fetchop_name><mode>_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 "<fetchop_predicate_1>"
+ "<fetchop_constraint_1_tcb>"))]
+ 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.<bwl> @%0,r0" "\n"
+ " <fetchop_name> %1,r0" "\n"
+ " mov.<bwl> 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<mode>_soft_tcb"
+(define_insn_and_split "atomic_fetch_not<mode>_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))
@@ -851,9 +976,35 @@
"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<mode>_soft_tcb (operands[1], operands[2]));
+}
[(set_attr "length" "20")])
-(define_insn "atomic_fetch_<fetchop_name><mode>_soft_imask"
+(define_insn "atomic_not<mode>_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.<bwl> @%0,r0" "\n"
+ " not r0,r0" "\n"
+ " mov.<bwl> r0,@%0" "\n"
+ "1: mov #0,r0" "\n"
+ " mov.l r0,@(%O1,gbr)";
+}
+ [(set_attr "length" "18")])
+
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>_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))
@@ -877,10 +1028,17 @@
" mov.<bwl> 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_<fetchop_name>_fetch<mode>_soft_imask (
+ gen_reg_rtx (<MODE>mode), operands[1], operands[2]));
+}
[(set_attr "length" "18")])
;; Combine pattern for xor (val, -1) / nand (val, -1).
-(define_insn "atomic_fetch_not<mode>_soft_imask"
+(define_insn_and_split "atomic_fetch_not<mode>_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))
@@ -899,6 +1057,13 @@
" mov.<bwl> 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<mode>_soft_imask (gen_reg_rtx (<MODE>mode),
+ operands[1]));
+}
[(set_attr "length" "18")])
(define_expand "atomic_fetch_nand<mode>"
@@ -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))
@@ -962,9 +1127,16 @@
" 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<mode>_hard"
+(define_insn_and_split "atomic_fetch_nand<mode>_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))
@@ -994,9 +1166,44 @@
" 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<mode>_hard (operands[1], operands[2]));
+}
[(set_attr "length" "30")])
-(define_insn "atomic_fetch_nand<mode>_soft_gusa"
+(define_insn "atomic_nand<mode>_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.<bw> @%0,r0" "\n"
+ " and %1,r0" "\n"
+ " not r0,r0" "\n"
+ " mov.<bw> 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<mode>_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))
@@ -1021,9 +1228,16 @@
" mov.<bwl> %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<mode>_soft_gusa (gen_reg_rtx (<MODE>mode),
+ operands[1], operands[2]));
+}
[(set_attr "length" "20")])
-(define_insn "atomic_fetch_nand<mode>_soft_tcb"
+(define_insn_and_split "atomic_fetch_nand<mode>_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))
@@ -1049,9 +1263,41 @@
"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<mode>_soft_tcb (operands[1], operands[2],
+ operands[3]));
+}
[(set_attr "length" "22")])
-(define_insn "atomic_fetch_nand<mode>_soft_imask"
+(define_insn "atomic_nand<mode>_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.<bwl> @%0,r0" "\n"
+ " and %1,r0" "\n"
+ " not r0,r0" "\n"
+ " mov.<bwl> r0,@%0" "\n"
+ "1: mov #0,r0" "\n"
+ " mov.l r0,@(%O2,gbr)";
+}
+ [(set_attr "length" "20")])
+
+(define_insn_and_split "atomic_fetch_nand<mode>_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))
@@ -1075,6 +1321,13 @@
" mov.<bwl> 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<mode>_soft_imask (gen_reg_rtx (<MODE>mode),
+ operands[1], operands[2]));
+}
[(set_attr "length" "20")])
;;------------------------------------------------------------------------------
@@ -1160,7 +1413,7 @@
}
[(set_attr "length" "8")])
-(define_insn "atomic_<fetchop_name>_fetch<mode>_hard"
+(define_insn_and_split "atomic_<fetchop_name>_fetch<mode>_hard"
[(set (match_operand:QIHI 0 "arith_reg_dest" "=&r")
(FETCHOP:QIHI
(mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))
@@ -1191,10 +1444,16 @@
" 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_<fetchop_name><mode>_hard (operands[1], operands[2]));
+}
[(set_attr "length" "28")])
;; Combine pattern for xor (val, -1) / nand (val, -1).
-(define_insn "atomic_not_fetch<mode>_hard"
+(define_insn_and_split "atomic_not_fetch<mode>_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))
@@ -1220,6 +1479,12 @@
" 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<mode>_hard (operands[1]));
+}
[(set_attr "length" "28")])
(define_insn "atomic_<fetchop_name>_fetch<mode>_soft_gusa"
@@ -1268,7 +1533,7 @@
}
[(set_attr "length" "16")])
-(define_insn "atomic_<fetchop_name>_fetch<mode>_soft_tcb"
+(define_insn_and_split "atomic_<fetchop_name>_fetch<mode>_soft_tcb"
[(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r")
(FETCHOP:QIHISI
(mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
@@ -1294,10 +1559,17 @@
" 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_<fetchop_name><mode>_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<mode>_soft_tcb"
+(define_insn_and_split "atomic_not_fetch<mode>_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))
@@ -1318,6 +1590,12 @@
" 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<mode>_soft_tcb (operands[1], operands[2]));
+}
[(set_attr "length" "20")])
(define_insn "atomic_<fetchop_name>_fetch<mode>_soft_imask"
@@ -1426,7 +1704,7 @@
}
[(set_attr "length" "10")])
-(define_insn "atomic_nand_fetch<mode>_hard"
+(define_insn_and_split "atomic_nand_fetch<mode>_hard"
[(set (match_operand:QIHI 0 "arith_reg_dest" "=&r")
(not:QIHI
(and:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))
@@ -1456,6 +1734,12 @@
" 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<mode>_hard (operands[1], operands[2]));
+}
[(set_attr "length" "28")])
(define_insn "atomic_nand_fetch<mode>_soft_gusa"
@@ -1483,7 +1767,7 @@
}
[(set_attr "length" "18")])
-(define_insn "atomic_nand_fetch<mode>_soft_tcb"
+(define_insn_and_split "atomic_nand_fetch<mode>_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"))
@@ -1509,6 +1793,13 @@
"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<mode>_soft_tcb (operands[1], operands[2],
+ operands[3]));
+}
[(set_attr "length" "22")])
(define_insn "atomic_nand_fetch<mode>_soft_imask"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 00c0450..98d72cb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2015-02-03 Oleg Endo <olegendo@gcc.gnu.org>
+
+ 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 <paolo.carlini@oracle.com>
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 0000000..28c1ac6
--- /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 0000000..2d5442c
--- /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 0000000..c0cef13
--- /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 0000000..fe3a83d
--- /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 0000000..4d5d7f4
--- /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"