Hi,

When the result values of atomic ops, such as the previous value of an
atomic_fetch_add, are unused, it's possible to use shorter asm sequences
on SH.  The attached patch does that by checking the reg unused notes of
the insns in split1 and replacing them with the simpler variants, if the
result value operand is unused.
This patch introduces a problem where memory aliasing info is lost,
because the mem operands are passed to the emitted insns not as such,
but only as the register holding the address.  This will be fixed with
PR 64661.

Committed as r220376.
Tested with make -k check-gcc RUNTESTFLAGS="sh.exp --target_board=sh-sim
\{-m2/-ml,-m2/-mb,-m2a/-mb,-m2e/-ml,-m2e/-mb,-m3/-ml,-m3/-mb,-m3e/-ml,-m3e/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
to verify that the insns/splits actually work.  Will observe daily
sh4-linux test results for fallouts.

Cheers,
Oleg

gcc/ChangeLog:
        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/ChangeLog:
        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.

Index: gcc/testsuite/gcc.target/sh/pr64660-2.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64660-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64660-2.c	(revision 0)
@@ -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"
Index: gcc/testsuite/gcc.target/sh/pr64660-3.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64660-3.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64660-3.c	(revision 0)
@@ -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"
Index: gcc/testsuite/gcc.target/sh/pr64660-4.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64660-4.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64660-4.c	(revision 0)
@@ -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"
Index: gcc/testsuite/gcc.target/sh/pr64660-0.h
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64660-0.h	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64660-0.h	(revision 0)
@@ -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)
Index: gcc/testsuite/gcc.target/sh/pr64660-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64660-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64660-1.c	(revision 0)
@@ -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"
Index: gcc/config/sh/sync.md
===================================================================
--- gcc/config/sh/sync.md	(revision 220371)
+++ gcc/config/sh/sync.md	(working copy)
@@ -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_fetch_<fetchop_name><mode>_soft_gusa"
+(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_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"

Reply via email to