diff mbox

[SH,committed] Add atomic not insns

Message ID 1422789503.25265.19.camel@yam-132-YW-E178-FTW
State New
Headers show

Commit Message

Oleg Endo Feb. 1, 2015, 11:18 a.m. UTC
Hi,

This adds atomic not insns for SH.  Although not directly supported by
the atomic builtins, for things like atomic xor (-1) or atomic nand (-1)
combine will happily try to simplify the insns into a unary not.

Committed as r220317.
Tested with make -k check-gcc RUNTESTFLAGS="sh.exp=pr64851*
--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 actually work.  Will observe daily sh4-linux
test results for fallouts.

Cheers,
Oleg

gcc/ChangeLog:
	PR target/64851
	* config/sh/sync.md (atomic_fetch_notsi_hard,
	atomic_fetch_not<mode>_hard, atomic_fetch_not<mode>_soft_gusa,
	atomic_fetch_not<mode>_soft_tcb, atomic_fetch_not<mode>_soft_imask,
	atomic_not_fetchsi_hard, atomic_not_fetch<mode>_hard,
	atomic_not_fetch<mode>_soft_gusa, atomic_not_fetch<mode>_soft_tcb,
	atomic_not_fetch<mode>_soft_imask): New insns.

gcc/testsuite/ChangeLog:
	PR target/64851
	* gcc.target/sh/pr64851-0.h: New
	* gcc.target/sh/pr64851-1.c: New
	* gcc.target/sh/pr64851-2.c: New
	* gcc.target/sh/pr64851-3.c: New
	* gcc.target/sh/pr64851-4.c: New
diff mbox

Patch

Index: gcc/config/sh/sync.md
===================================================================
--- gcc/config/sh/sync.md	(revision 220260)
+++ gcc/config/sh/sync.md	(working copy)
@@ -673,6 +673,25 @@ 
 }
   [(set_attr "length" "10")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:SI [(not:SI (mem:SI (match_dup 1)))] UNSPEC_ATOMIC))
+   (set (reg:SI T_REG) (const_int 1))
+   (clobber (reg:SI R0_REG))]
+  "TARGET_ATOMIC_HARD_LLCS
+   || (TARGET_SH4A && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)"
+{
+  return "\r0:	movli.l	@%1,r0"		"\n"
+	 "	mov	r0,%0"		"\n"
+	 "	not	r0,r0"		"\n"
+	 "	movco.l	r0,@%1"		"\n"
+	 "	bf	0b";
+}
+  [(set_attr "length" "10")])
+
 (define_insn "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")))
@@ -705,6 +724,34 @@ 
 }
   [(set_attr "length" "28")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHI [(not:QIHI (mem:QIHI (match_dup 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 "=1"))]
+  "TARGET_ATOMIC_HARD_LLCS"
+{
+  return "\r	mov	#-4,%2"			"\n"
+	 "	and	%1,%2"			"\n"
+	 "	xor	%2,%1"			"\n"
+	 "	add	r15,%1"			"\n"
+	 "	add	#-4,%1"			"\n"
+	 "0:	movli.l	@%2,r0"			"\n"
+	 "	mov.l	r0,@-r15"		"\n"
+	 "	mov.<bw>	@%1,%0"		"\n"
+	 "	not	%0,r0"			"\n"
+	 "	mov.<bw>	r0,@%1"		"\n"
+	 "	mov.l	@r15+,r0"		"\n"
+	 "	movco.l	r0,@%2"			"\n"
+	 "	bf	0b";
+}
+  [(set_attr "length" "26")])
+
 (define_insn "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")))
@@ -732,6 +779,28 @@ 
 }
   [(set_attr "length" "18")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 1)))] UNSPEC_ATOMIC))
+   (clobber (match_scratch:QIHISI 2 "=&u"))
+   (clobber (reg:SI R0_REG))
+   (clobber (reg:SI R1_REG))]
+  "TARGET_ATOMIC_SOFT_GUSA"
+{
+  return "\r	mova	1f,r0"			"\n"
+	 "	mov	r15,r1"			"\n"
+	 "	.align 2"			"\n"
+	 "	mov	#(0f-1f),r15"		"\n"
+	 "0:	mov.<bwl>	@%1,%0"		"\n"
+	 "	not	%0,%2"			"\n"
+	 "	mov.<bwl>	%2,@%1"		"\n"
+	 "1:	mov	r1,r15";
+}
+  [(set_attr "length" "16")])
+
 (define_insn "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")))
@@ -760,6 +829,30 @@ 
 }
   [(set_attr "length" "20")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 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"
+	 "	.align 2"			"\n"
+	 "	mov	#(0f-1f),r1"		"\n"
+	 "	mov.l	r0,@(%O2,gbr)"		"\n"
+	 "0:	mov.<bwl>	@%1,r0"		"\n"
+	 "	mov	r0,%0"			"\n"
+	 "	not	r0,r0"			"\n"
+	 "	mov.<bwl>	r0,@%1"		"\n"
+	 "1:	mov	#0,r0"			"\n"
+	 "	mov.l	r0,@(%O2,gbr)";
+}
+  [(set_attr "length" "20")])
+
 (define_insn "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")))
@@ -786,6 +879,28 @@ 
 }
   [(set_attr "length" "18")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 1)))] UNSPEC_ATOMIC))
+   (clobber (reg:SI R0_REG))
+   (clobber (match_scratch:QIHISI 2 "=&r"))]
+  "TARGET_ATOMIC_SOFT_IMASK"
+{
+  return "\r	stc	sr,r0"			"\n"
+	 "	mov	r0,%2"			"\n"
+	 "	or	#0xF0,r0"		"\n"
+	 "	ldc	r0,sr"			"\n"
+	 "	mov.<bwl>	@%1,r0"		"\n"
+	 "	mov	r0,%0"			"\n"
+	 "	not	r0,r0"			"\n"
+	 "	mov.<bwl>	r0,@%1"		"\n"
+	 "	ldc	%2,sr";
+}
+  [(set_attr "length" "18")])
+
 (define_expand "atomic_fetch_nand<mode>"
   [(set (match_operand:QIHISI 0 "arith_reg_dest")
 	(match_operand:QIHISI 1 "memory_operand"))
@@ -1028,6 +1143,23 @@ 
 }
   [(set_attr "length" "8")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "atomic_not_fetchsi_hard"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&z")
+	(not:SI (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))))
+   (set (mem:SI (match_dup 1))
+	(unspec:SI [(not:SI (mem:SI (match_dup 1)))] UNSPEC_ATOMIC))
+   (set (reg:SI T_REG) (const_int 1))]
+  "TARGET_ATOMIC_HARD_LLCS
+   || (TARGET_SH4A && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)"
+{
+  return "\r0:	movli.l	@%1,%0"		"\n"
+	 "	not	%0,%0"		"\n"
+	 "	movco.l	%0,@%1"		"\n"
+	 "	bf	0b";
+}
+  [(set_attr "length" "8")])
+
 (define_insn "atomic_<fetchop_name>_fetch<mode>_hard"
   [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r")
 	(FETCHOP:QIHI
@@ -1061,6 +1193,35 @@ 
 }
   [(set_attr "length" "28")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHI [(not:QIHI (mem:QIHI (match_dup 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 "=1"))]
+  "TARGET_ATOMIC_HARD_LLCS"
+{
+  return "\r	mov	#-4,%2"			"\n"
+	 "	and	%1,%2"			"\n"
+	 "	xor	%2,%1"			"\n"
+	 "	add	r15,%1"			"\n"
+	 "	add	#-4,%1"			"\n"
+	 "0:	movli.l	@%2,r0"			"\n"
+	 "	mov.l	r0,@-r15"		"\n"
+	 "	mov.<bw>	@%1,r0"		"\n"
+	 "	not	r0,r0"			"\n"
+	 "	mov.<bw>	r0,@%1"		"\n"
+	 "	mov	r0,%0"			"\n"
+	 "	mov.l	@r15+,r0"		"\n"
+	 "	movco.l	r0,@%2"			"\n"
+	 "	bf	0b";
+}
+  [(set_attr "length" "28")])
+
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_gusa"
   [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u")
 	(FETCHOP:QIHISI
@@ -1086,6 +1247,27 @@ 
 }
   [(set_attr "length" "16")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "atomic_not_fetch<mode>_soft_gusa"
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u")
+	(not:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))))
+   (set (mem:QIHISI (match_dup 1))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 1)))] UNSPEC_ATOMIC))
+   (clobber (reg:SI R0_REG))
+   (clobber (reg:SI R1_REG))]
+  "TARGET_ATOMIC_SOFT_GUSA"
+{
+  return "\r	mova	1f,r0"			"\n"
+	 "	mov	r15,r1"			"\n"
+	 "	.align 2"			"\n"
+	 "	mov	#(0f-1f),r15"		"\n"
+	 "0:	mov.<bwl>	@%1,%0"		"\n"
+	 "	not	%0,%0"		"\n"
+	 "	mov.<bwl>	%0,@%1"		"\n"
+	 "1:	mov	r1,r15";
+}
+  [(set_attr "length" "16")])
+
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_tcb"
   [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r")
 	(FETCHOP:QIHISI
@@ -1114,6 +1296,30 @@ 
 }
   [(set_attr "length" "20")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "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))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 1)))] UNSPEC_ATOMIC))
+   (clobber (reg:SI R0_REG))
+   (clobber (reg:SI R1_REG))
+   (use (match_operand:SI 2 "gbr_displacement"))]
+  "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>	@%1,r0"		"\n"
+	 "	not	r0,r0"		"\n"
+	 "	mov.<bwl>	r0,@%1"		"\n"
+	 "1:	mov	r0,%0"			"\n"
+	 "	mov	#0,r0"			"\n"
+	 "	mov.l	r0,@(%O2,gbr)";
+}
+  [(set_attr "length" "20")])
+
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_imask"
   [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&z")
 	(FETCHOP:QIHISI
@@ -1138,6 +1344,26 @@ 
 }
   [(set_attr "length" "16")])
 
+;; Combine pattern for xor (val, -1) / nand (val, -1).
+(define_insn "atomic_not_fetch<mode>_soft_imask"
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&z")
+	(not:QIHISI (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))))
+   (set (mem:QIHISI (match_dup 1))
+	(unspec:QIHISI [(not:QIHISI (mem:QIHISI (match_dup 1)))] UNSPEC_ATOMIC))
+   (clobber (match_scratch:SI 2 "=&r"))]
+  "TARGET_ATOMIC_SOFT_IMASK"
+{
+  return "\r	stc	sr,%0"			"\n"
+	 "	mov	%0,%2"			"\n"
+	 "	or	#0xF0,%0"		"\n"
+	 "	ldc	%0,sr"			"\n"
+	 "	mov.<bwl>	@%1,%0"		"\n"
+	 "	not	%0,%0"		"\n"
+	 "	mov.<bwl>	%0,@%1"		"\n"
+	 "	ldc	%2,sr";
+}
+  [(set_attr "length" "16")])
+
 (define_expand "atomic_nand_fetch<mode>"
   [(set (match_operand:QIHISI 0 "arith_reg_dest")
 	(not:QIHISI (and:QIHISI
Index: gcc/testsuite/gcc.target/sh/pr64851-2.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64851-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64851-2.c	(revision 0)
@@ -0,0 +1,6 @@ 
+/* Check that atomic not ops are generated.  */
+/* { dg-do compile { target { atomic_model_soft_tcb_available } } }  */
+/* { dg-options "-O2 -matomic-model=soft-tcb,gbr-offset=0,strict" }  */
+/* { dg-final { scan-assembler-times "not\t" 12 } }  */
+
+#include "pr64851-0.h"
Index: gcc/testsuite/gcc.target/sh/pr64851-3.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64851-3.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64851-3.c	(revision 0)
@@ -0,0 +1,6 @@ 
+/* Check that atomic not ops are generated.  */
+/* { dg-do compile { target { atomic_model_soft_imask_available } } }  */
+/* { dg-options "-O2 -matomic-model=soft-imask,strict -mno-usermode" }  */
+/* { dg-final { scan-assembler-times "not\t" 12 } }  */
+
+#include "pr64851-0.h"
Index: gcc/testsuite/gcc.target/sh/pr64851-4.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64851-4.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64851-4.c	(revision 0)
@@ -0,0 +1,6 @@ 
+/* Check that atomic not ops are generated.  */
+/* { dg-do compile { target { atomic_model_hard_llcs_available } } }  */
+/* { dg-options "-O2 -matomic-model=hard-llcs,strict" }  */
+/* { dg-final { scan-assembler-times "not\t" 12 } }  */
+
+#include "pr64851-0.h"
Index: gcc/testsuite/gcc.target/sh/pr64851-0.h
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64851-0.h	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64851-0.h	(revision 0)
@@ -0,0 +1,21 @@ 
+/* Check that atomic not ops are generated.  */
+
+#define emitfuncs(name)\
+  void test_ ## name ## _0 (char* mem)\
+  {\
+    name (mem, -1, __ATOMIC_ACQ_REL);\
+  }\
+  void test_ ## name ## _1 (short* mem)\
+  {\
+    name (mem, -1, __ATOMIC_ACQ_REL);\
+  }\
+  void test_ ## name ##_2 (int* mem)\
+  {\
+    name (mem, -1, __ATOMIC_ACQ_REL);\
+  }\
+
+emitfuncs (__atomic_xor_fetch)
+emitfuncs (__atomic_fetch_xor)
+
+emitfuncs (__atomic_nand_fetch)
+emitfuncs (__atomic_fetch_nand)
Index: gcc/testsuite/gcc.target/sh/pr64851-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr64851-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/sh/pr64851-1.c	(revision 0)
@@ -0,0 +1,6 @@ 
+/* Check that atomic not ops are generated.  */
+/* { dg-do compile { target { atomic_model_soft_gusa_available } } }  */
+/* { dg-options "-O2 -matomic-model=soft-gusa,strict" }  */
+/* { dg-final { scan-assembler-times "not\t" 12 } }  */
+
+#include "pr64851-0.h"