re PR target/64659 ([SH] Immedate values not used for atomic ops)
authorOleg Endo <olegendo@gcc.gnu.org>
Wed, 28 Jan 2015 21:11:37 +0000 (21:11 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Wed, 28 Jan 2015 21:11:37 +0000 (21:11 +0000)
gcc/
PR target/64659
* config/sh/predicates.md (atomic_arith_operand,
atomic_logical_operand): Remove.
* config/sh/sync.md (fetchop_predicate, fetchop_constraint): Remove.
(atomic_arith_operand_0): New predicate.
(atomic_compare_and_swap<mode>): Use arith_reg_dest for output values.
Use atomic_arith_operand_0 for input values.
(atomic_compare_and_swapsi_hard, atomic_compare_and_swap<mode>_hard,
atomic_compare_and_swap<mode>_soft_gusa,
atomic_compare_and_swap<mode>_soft_tcb,
atomic_compare_and_swap<mode>_soft_imask): Use arith_reg_dest and
arith_reg_operand instead of register_operand.
(atomic_exchange<mode>): Use arith_reg_dest for output value.  Use
atomic_arith_operand_0 for newval input.
(atomic_exchangesi_hard, atomic_exchange<mode>_hard,
atomic_exchange<mode>_soft_gusa, atomic_exchange<mode>_soft_tcb,
atomic_exchange<mode>_soft_imask): Use arith_reg_dest and
arith_reg_operand instead of register_operand.
(atomic_arith_operand_1, atomic_logical_operand_1): New predicates.
fetchop_predicate_1, fetchop_constraint_1_llcs,
fetchop_constraint_1_gusa, fetchop_constraint_1_tcb,
fetchop_constraint_1_imask): New code iterator attributes.
(atomic_fetch_<fetchop_name><mode>): Use arith_reg_dest instead of
register_operand.  Use fetchop_predicate_1.
(atomic_fetch_<fetchop_name>si_hard,
atomic_fetch_<fetchop_name><mode>_hard): Use arith_reg_dest instead of
register_operand.  Use fetchop_predicate_1, fetchop_constraint_1_llcs.
(atomic_fetch_<fetchop_name><mode>_soft_gusa): Use arith_reg_dest
and arith_reg_operand instead of register_operand.  Use
fetchop_predicate_1, fetchop_constraint_1_gusa.
(atomic_fetch_<fetchop_name><mode>_soft_tcb): Use arith_reg_dest
and arith_reg_operand instead of register_operand.  Use
fetchop_predicate_1, fetchop_constraint_1_tcb.  Adjust asm sequence
to allow R0 usage.
(atomic_fetch_<fetchop_name><mode>_soft_imask): Use arith_reg_dest
and arith_reg_operand instead of register_operand.  Use
fetchop_predicate_1, fetchop_constraint_1_imask.  Adjust asm sequence
to allow R0 usage.
(atomic_fetch_nand<mode>): Use arith_reg_dest instead of
register_operand.  Use atomic_logical_operand_1.
(atomic_fetch_nandsi_hard, atomic_fetch_nand<mode>_hard,
atomic_fetch_nand<mode>_soft_gusa): Use arith_reg_dest and
arith_reg_operand instead of register_operand.
(atomic_fetch_nand<mode>_soft_tcb, atomic_fetch_nand<mode>_soft_imask):
Use arith_reg_dest and arith_reg_operand instead of register_operand.
Use logical_operand and rK08.  Adjust asm sequence to allow R0 usage.
(atomic_<fetchop_name>_fetch<mode>): Use arith_reg_dest instead of
register_operand.  Use fetchop_predicate_1.
(atomic_<fetchop_name>_fetchsi_hard,
atomic_<fetchop_name>_fetch<mode>_hard): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
fetchop_constraint_1_llcs.
(atomic_<fetchop_name>_fetch<mode>_soft_gusa): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
fetchop_constraint_1_gusa.
(atomic_<fetchop_name>_fetch<mode>_soft_tcb): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
fetchop_constraint_1_tcb.  Adjust asm sequence to allow R0 usage.
(atomic_<fetchop_name>_fetch<mode>_soft_imask): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
fetchop_constraint_1_imask.  Adjust asm sequence to allow R0 usage.
(atomic_nand_fetch<mode>): Use arith_reg_dest instead of
register_operand.  Use atomic_logical_operand_1.
(atomic_nand_fetchsi_hard, atomic_nand_fetch<mode>_hard,
atomic_nand_fetch<mode>_soft_gusa): Use arith_reg_dest and
arith_reg_operand instead of register_operand.
(atomic_nand_fetch<mode>_soft_tcb): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use logical_operand
and K08.  Adjust asm sequence to allow R0 usage.
(atomic_nand_fetch<mode>_soft_imask): Use arith_reg_dest and
arith_reg_operand instead of register_operand.  Use logical_operand
and K08.

gcc/testsuite/
PR target/64659
* gcc.target/sh/sh.exp
(check_effective_target_atomic_model_soft_gusa_available,
check_effective_target_atomic_model_soft_tcb_available,
check_effective_target_atomic_model_soft_imask_available,
check_effective_target_atomic_model_hard_llcs_available): New.
* gcc.target/sh/pr64659-0.h: New.
* gcc.target/sh/pr64659-1.c: New.
* gcc.target/sh/pr64659-2.c: New.
* gcc.target/sh/pr64659-3.c: New.
* gcc.target/sh/pr64659-4.c: New.

From-SVN: r220217

gcc/ChangeLog
gcc/config/sh/predicates.md
gcc/config/sh/sync.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr64659-0.h [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr64659-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr64659-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr64659-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr64659-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/sh.exp

index d1ce2aac2f892b05cef7652b4ff30d58c1fa0688..e0fef992067c7346f2b4fbd0ac039b7ed09f7ee9 100644 (file)
@@ -1,3 +1,78 @@
+2015-01-28  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/64659
+       * config/sh/predicates.md (atomic_arith_operand,
+       atomic_logical_operand): Remove.
+       * config/sh/sync.md (fetchop_predicate, fetchop_constraint): Remove.
+       (atomic_arith_operand_0): New predicate.
+       (atomic_compare_and_swap<mode>): Use arith_reg_dest for output values.
+       Use atomic_arith_operand_0 for input values.
+       (atomic_compare_and_swapsi_hard, atomic_compare_and_swap<mode>_hard,
+       atomic_compare_and_swap<mode>_soft_gusa,
+       atomic_compare_and_swap<mode>_soft_tcb,
+       atomic_compare_and_swap<mode>_soft_imask): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.
+       (atomic_exchange<mode>): Use arith_reg_dest for output value.  Use
+       atomic_arith_operand_0 for newval input.
+       (atomic_exchangesi_hard, atomic_exchange<mode>_hard,
+       atomic_exchange<mode>_soft_gusa, atomic_exchange<mode>_soft_tcb,
+       atomic_exchange<mode>_soft_imask): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.
+       (atomic_arith_operand_1, atomic_logical_operand_1): New predicates.
+       fetchop_predicate_1, fetchop_constraint_1_llcs,
+       fetchop_constraint_1_gusa, fetchop_constraint_1_tcb,
+       fetchop_constraint_1_imask): New code iterator attributes.
+       (atomic_fetch_<fetchop_name><mode>): Use arith_reg_dest instead of
+       register_operand.  Use fetchop_predicate_1.
+       (atomic_fetch_<fetchop_name>si_hard,
+       atomic_fetch_<fetchop_name><mode>_hard): Use arith_reg_dest instead of
+       register_operand.  Use fetchop_predicate_1, fetchop_constraint_1_llcs.
+       (atomic_fetch_<fetchop_name><mode>_soft_gusa): Use arith_reg_dest
+       and arith_reg_operand instead of register_operand.  Use
+       fetchop_predicate_1, fetchop_constraint_1_gusa.
+       (atomic_fetch_<fetchop_name><mode>_soft_tcb): Use arith_reg_dest
+       and arith_reg_operand instead of register_operand.  Use
+       fetchop_predicate_1, fetchop_constraint_1_tcb.  Adjust asm sequence
+       to allow R0 usage.
+       (atomic_fetch_<fetchop_name><mode>_soft_imask): Use arith_reg_dest
+       and arith_reg_operand instead of register_operand.  Use
+       fetchop_predicate_1, fetchop_constraint_1_imask.  Adjust asm sequence
+       to allow R0 usage.
+       (atomic_fetch_nand<mode>): Use arith_reg_dest instead of
+       register_operand.  Use atomic_logical_operand_1.
+       (atomic_fetch_nandsi_hard, atomic_fetch_nand<mode>_hard,
+       atomic_fetch_nand<mode>_soft_gusa): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.
+       (atomic_fetch_nand<mode>_soft_tcb, atomic_fetch_nand<mode>_soft_imask):
+       Use arith_reg_dest and arith_reg_operand instead of register_operand.
+       Use logical_operand and rK08.  Adjust asm sequence to allow R0 usage.
+       (atomic_<fetchop_name>_fetch<mode>): Use arith_reg_dest instead of
+       register_operand.  Use fetchop_predicate_1.
+       (atomic_<fetchop_name>_fetchsi_hard,
+       atomic_<fetchop_name>_fetch<mode>_hard): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
+       fetchop_constraint_1_llcs.
+       (atomic_<fetchop_name>_fetch<mode>_soft_gusa): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
+       fetchop_constraint_1_gusa.
+       (atomic_<fetchop_name>_fetch<mode>_soft_tcb): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
+       fetchop_constraint_1_tcb.  Adjust asm sequence to allow R0 usage.
+       (atomic_<fetchop_name>_fetch<mode>_soft_imask): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use fetchop_predicate_1,
+       fetchop_constraint_1_imask.  Adjust asm sequence to allow R0 usage.
+       (atomic_nand_fetch<mode>): Use arith_reg_dest instead of
+       register_operand.  Use atomic_logical_operand_1.
+       (atomic_nand_fetchsi_hard, atomic_nand_fetch<mode>_hard,
+       atomic_nand_fetch<mode>_soft_gusa): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.
+       (atomic_nand_fetch<mode>_soft_tcb): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use logical_operand
+       and K08.  Adjust asm sequence to allow R0 usage.
+       (atomic_nand_fetch<mode>_soft_imask): Use arith_reg_dest and
+       arith_reg_operand instead of register_operand.  Use logical_operand
+       and K08.
+
 2015-01-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR other/63504
index a18515a3a15a7444ead05b342ddaee72146389b9..8447524c67ff08223e2b1d9f858e627f98d29eab 100644 (file)
   return 0;
 })
 
-;; The atomic_* operand predicates are used for the atomic patterns.
-;; Depending on the particular pattern some operands can be immediate
-;; values.  Using these predicates avoids the usage of 'force_reg' in the
-;; expanders.
-(define_predicate "atomic_arith_operand"
-  (ior (match_code "subreg,reg")
-       (and (match_test "satisfies_constraint_I08 (op)")
-           (match_test "mode != QImode")
-           (match_test "mode != HImode")
-           (match_test "TARGET_SH4A"))))
-
-(define_predicate "atomic_logical_operand"
-  (ior (match_code "subreg,reg")
-       (and (match_test "satisfies_constraint_K08 (op)")
-           (match_test "mode != QImode")
-           (match_test "mode != HImode")
-           (match_test "TARGET_SH4A"))))
-
 ;; A predicate that matches any expression for which there is an
 ;; insn pattern that sets the T bit.
 (define_predicate "treg_set_expr"
index b9f23cba58b438eff1da64ecf93f916959403476..b3ff70ce171dc55ee135eba11dfc6a65967ca0e4 100644 (file)
 (define_code_attr fetchop_name
   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
 
-(define_code_attr fetchop_predicate
-  [(plus "atomic_arith_operand") (minus "register_operand")
-   (ior "atomic_logical_operand") (xor "atomic_logical_operand")
-   (and "atomic_logical_operand")])
-
-(define_code_attr fetchop_constraint
-  [(plus "rI08") (minus "r") (ior "rK08") (xor "rK08") (and "rK08")])
-
 ;;------------------------------------------------------------------------------
 ;; comapre and swap
 
+;; Only the hard_llcs SImode patterns can use an I08 for the comparison
+;; or for the new swapped in value.
+(define_predicate "atomic_arith_operand_0"
+  (and (match_code "subreg,reg,const_int")
+       (ior (match_operand 0 "arith_reg_operand")
+           (and (match_test "satisfies_constraint_I08 (op)")
+                (match_test "mode == SImode")
+                (ior (match_test "TARGET_ATOMIC_HARD_LLCS")
+                     (match_test "TARGET_ATOMIC_ANY && TARGET_SH4A
+                                  && !TARGET_ATOMIC_STRICT"))))))
+
 (define_expand "atomic_compare_and_swap<mode>"
-  [(match_operand:SI 0 "register_operand" "")          ;; bool success output
-   (match_operand:QIHISI 1 "register_operand" "")      ;; oldval output
-   (match_operand:QIHISI 2 "memory_operand" "")                ;; memory
-   (match_operand:QIHISI 3 "atomic_arith_operand" "")  ;; expected input
-   (match_operand:QIHISI 4 "atomic_arith_operand" "")  ;; newval input
-   (match_operand:SI 5 "const_int_operand" "")         ;; is_weak
-   (match_operand:SI 6 "const_int_operand" "")         ;; success model
-   (match_operand:SI 7 "const_int_operand" "")]                ;; failure model
+  [(match_operand:SI 0 "arith_reg_dest")               ;; bool success output
+   (match_operand:QIHISI 1 "arith_reg_dest")           ;; oldval output
+   (match_operand:QIHISI 2 "memory_operand")           ;; memory
+   (match_operand:QIHISI 3 "atomic_arith_operand_0")   ;; expected input
+   (match_operand:QIHISI 4 "atomic_arith_operand_0")   ;; newval input
+   (match_operand:SI 5 "const_int_operand")            ;; is_weak
+   (match_operand:SI 6 "const_int_operand")            ;; success model
+   (match_operand:SI 7 "const_int_operand")]           ;; failure model
   "TARGET_ATOMIC_ANY"
 {
   rtx addr = force_reg (Pmode, XEXP (operands[2], 0));
 })
 
 (define_insn "atomic_compare_and_swapsi_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
        (unspec_volatile:SI
-         [(mem:SI (match_operand:SI 1 "register_operand" "r"))
+         [(mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
           (match_operand:SI 2 "arith_operand" "rI08")
           (match_operand:SI 3 "arith_operand" "rI08")]
          UNSPECV_CMPXCHG_1))
   [(set_attr "length" "14")])
 
 (define_insn "atomic_compare_and_swap<mode>_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
        (unspec_volatile:SI
-         [(mem:QIHI (match_operand:SI 1 "register_operand" "r"))
-          (match_operand:QIHI 2 "register_operand" "r")
-          (match_operand:QIHI 3 "register_operand" "r")]
+         [(mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))
+          (match_operand:QIHI 2 "arith_reg_operand" "r")
+          (match_operand:QIHI 3 "arith_reg_operand" "r")]
          UNSPECV_CMPXCHG_1))
    (set (mem:QIHI (match_dup 1))
        (unspec_volatile:QIHI [(const_int 0)] UNSPECV_CMPXCHG_2))
   [(set_attr "length" "30")])
 
 (define_insn "atomic_compare_and_swap<mode>_soft_gusa"
-  [(set (match_operand:SI 0 "register_operand" "=&u")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&u")
        (unspec_volatile:SI
-         [(mem:QIHISI (match_operand:SI 1 "register_operand" "u"))
-          (match_operand:QIHISI 2 "register_operand" "u")
-          (match_operand:QIHISI 3 "register_operand" "u")]
+         [(mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))
+          (match_operand:QIHISI 2 "arith_reg_operand" "u")
+          (match_operand:QIHISI 3 "arith_reg_operand" "u")]
          UNSPECV_CMPXCHG_1))
    (set (mem:QIHISI (match_dup 1))
        (unspec_volatile:QIHISI [(const_int 0)] UNSPECV_CMPXCHG_2))
   [(set_attr "length" "20")])
 
 (define_insn "atomic_compare_and_swap<mode>_soft_tcb"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
        (unspec_volatile:SI
-         [(mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-          (match_operand:QIHISI 2 "register_operand" "r")
-          (match_operand:QIHISI 3 "register_operand" "r")]
+         [(mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+          (match_operand:QIHISI 2 "arith_reg_operand" "r")
+          (match_operand:QIHISI 3 "arith_reg_operand" "r")]
          UNSPECV_CMPXCHG_1))
    (set (mem:QIHISI (match_dup 1))
        (unspec_volatile:QIHISI [(const_int 0)] UNSPECV_CMPXCHG_2))
   [(set_attr "length" "22")])
 
 (define_insn "atomic_compare_and_swap<mode>_soft_imask"
-  [(set (match_operand:SI 0 "register_operand" "=&z")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&z")
        (unspec_volatile:SI
-         [(mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-          (match_operand:QIHISI 2 "register_operand" "r")
-          (match_operand:QIHISI 3 "register_operand" "r")]
+         [(mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+          (match_operand:QIHISI 2 "arith_reg_operand" "r")
+          (match_operand:QIHISI 3 "arith_reg_operand" "r")]
          UNSPECV_CMPXCHG_1))
    (set (mem:QIHISI (match_dup 1))
        (unspec_volatile:QIHISI [(const_int 0)] UNSPECV_CMPXCHG_2))
 ;; read - write - return old value
 
 (define_expand "atomic_exchange<mode>"
-  [(match_operand:QIHISI 0 "register_operand" "")      ;; oldval output
-   (match_operand:QIHISI 1 "memory_operand" "")                ;; memory
-   (match_operand:QIHISI 2 "atomic_arith_operand" "")  ;; newval input
-   (match_operand:SI 3 "const_int_operand" "")]                ;; memory model
+  [(match_operand:QIHISI 0 "arith_reg_dest")           ;; oldval output
+   (match_operand:QIHISI 1 "memory_operand")           ;; memory
+   (match_operand:QIHISI 2 "atomic_arith_operand_0")   ;; newval input
+   (match_operand:SI 3 "const_int_operand")]           ;; memory model
   "TARGET_ATOMIC_ANY"
 {
   rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
 })
 
 (define_insn "atomic_exchangesi_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
-       (mem:SI (match_operand:SI 1 "register_operand" "r")))
+  [(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
          [(match_operand:SI 2 "arith_operand" "rI08")] UNSPEC_ATOMIC))
   [(set_attr "length" "10")])
 
 (define_insn "atomic_exchange<mode>_hard"
-  [(set (match_operand:QIHI 0 "register_operand" "=&r")
-       (mem:QIHI (match_operand:SI 1 "register_operand" "r")))
+  [(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
-         [(match_operand:QIHI 2 "register_operand" "r")] UNSPEC_ATOMIC))
+         [(match_operand:QIHI 2 "arith_reg_operand" "r")] UNSPEC_ATOMIC))
    (set (reg:SI T_REG) (const_int 1))
    (clobber (reg:SI R0_REG))
    (clobber (match_scratch:SI 3 "=&r"))
   [(set_attr "length" "24")])
 
 (define_insn "atomic_exchange<mode>_soft_gusa"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&u")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "u")))
+  [(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
-         [(match_operand:QIHISI 2 "register_operand" "u")] UNSPEC_ATOMIC))
+         [(match_operand:QIHISI 2 "arith_reg_operand" "u")] UNSPEC_ATOMIC))
    (clobber (reg:SI R0_REG))
    (clobber (reg:SI R1_REG))]
   "TARGET_ATOMIC_SOFT_GUSA"
   [(set_attr "length" "14")])
 
 (define_insn "atomic_exchange<mode>_soft_tcb"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&r")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(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
-         [(match_operand:QIHISI 2 "register_operand" "r")] UNSPEC_ATOMIC))
+         [(match_operand:QIHISI 2 "arith_reg_operand" "r")] UNSPEC_ATOMIC))
    (clobber (reg:SI R0_REG))
    (clobber (reg:SI R1_REG))
    (use (match_operand:SI 3 "gbr_displacement"))]
   [(set_attr "length" "16")])
 
 (define_insn "atomic_exchange<mode>_soft_imask"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&z")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&z")
+       (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r")))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
-         [(match_operand:QIHISI 2 "register_operand" "r")] UNSPEC_ATOMIC))
+         [(match_operand:QIHISI 2 "arith_reg_operand" "r")] UNSPEC_ATOMIC))
    (clobber (match_scratch:SI 3 "=&r"))]
   "TARGET_ATOMIC_SOFT_IMASK"
 {
 ;;------------------------------------------------------------------------------
 ;; read - add|sub|or|and|xor|nand - write - return old value
 
+;; atomic_arith_operand_1 can be used by any atomic type for a plus op,
+;; since there's no r0 restriction.
+(define_predicate "atomic_arith_operand_1"
+  (and (match_code "subreg,reg,const_int")
+       (ior (match_operand 0 "arith_reg_operand")
+           (match_test "satisfies_constraint_I08 (op)"))))
+
+;; atomic_logic_operand_1 can be used by the hard_llcs, tcb and soft_imask
+;; patterns only due to its r0 restriction. 
+(define_predicate "atomic_logical_operand_1"
+  (and (match_code "subreg,reg,const_int")
+       (ior (match_operand 0 "arith_reg_operand")
+           (and (match_test "satisfies_constraint_K08 (op)")
+                (ior (match_test "TARGET_ATOMIC_HARD_LLCS")
+                     (match_test "TARGET_ATOMIC_SOFT_IMASK")
+                     (match_test "TARGET_ATOMIC_SOFT_TCB")
+                     (match_test "TARGET_ATOMIC_ANY && TARGET_SH4A
+                                  && mode == SImode
+                                  && !TARGET_ATOMIC_STRICT"))))))
+
+(define_code_attr fetchop_predicate_1
+  [(plus "atomic_arith_operand_1") (minus "arith_reg_operand")
+   (ior "atomic_logical_operand_1") (xor "atomic_logical_operand_1")
+   (and "atomic_logical_operand_1")])
+
+(define_code_attr fetchop_constraint_1_llcs
+  [(plus "rI08") (minus "r") (ior "rK08") (xor "rK08") (and "rK08")])
+
+(define_code_attr fetchop_constraint_1_gusa
+  [(plus "uI08") (minus "u") (ior "u") (xor "u") (and "u")])
+
+(define_code_attr fetchop_constraint_1_tcb
+  [(plus "rI08") (minus "r") (ior "rK08") (xor "rK08") (and "rK08")])
+
+(define_code_attr fetchop_constraint_1_imask
+  [(plus "rI08") (minus "r") (ior "rK08") (xor "rK08") (and "rK08")])
+
 (define_expand "atomic_fetch_<fetchop_name><mode>"
-  [(set (match_operand:QIHISI 0 "register_operand" "")
-       (match_operand:QIHISI 1 "memory_operand" ""))
+  [(set (match_operand:QIHISI 0 "arith_reg_dest")
+       (match_operand:QIHISI 1 "memory_operand"))
    (set (match_dup 1)
        (unspec:QIHISI
          [(FETCHOP:QIHISI (match_dup 1)
-            (match_operand:QIHISI 2 "<fetchop_predicate>" ""))]
+            (match_operand:QIHISI 2 "<fetchop_predicate_1>"))]
          UNSPEC_ATOMIC))
-   (match_operand:SI 3 "const_int_operand" "")]
+   (match_operand:SI 3 "const_int_operand")]
   "TARGET_ATOMIC_ANY"
 {
   rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
 })
 
 (define_insn "atomic_fetch_<fetchop_name>si_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
-       (mem:SI (match_operand:SI 1 "register_operand" "r")))
+  [(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
          [(FETCHOP:SI (mem:SI (match_dup 1))
-            (match_operand:SI 2 "<fetchop_predicate>" "<fetchop_constraint>"))]
+                      (match_operand:SI 2 "<fetchop_predicate_1>"
+                                          "<fetchop_constraint_1_llcs>"))]
          UNSPEC_ATOMIC))
    (set (reg:SI T_REG) (const_int 1))
    (clobber (reg:SI R0_REG))]
   [(set_attr "length" "10")])
 
 (define_insn "atomic_fetch_<fetchop_name><mode>_hard"
-  [(set (match_operand:QIHI 0 "register_operand" "=&r")
-       (mem:QIHI (match_operand:SI 1 "register_operand" "r")))
+  [(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
          [(FETCHOP:QIHI (mem:QIHI (match_dup 1))
-            (match_operand:QIHI 2 "<fetchop_predicate>" "<fetchop_constraint>"))]
+                        (match_operand:QIHI 2 "<fetchop_predicate_1>"
+                                              "<fetchop_constraint_1_llcs>"))]
          UNSPEC_ATOMIC))
    (set (reg:SI T_REG) (const_int 1))
    (clobber (reg:SI R0_REG))
   [(set_attr "length" "28")])
 
 (define_insn "atomic_fetch_<fetchop_name><mode>_soft_gusa"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&u")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "u")))
+  [(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
-         [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "u"))]
+         [(FETCHOP:QIHISI
+               (mem:QIHISI (match_dup 1))
+               (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                       "<fetchop_constraint_1_gusa>"))]
          UNSPEC_ATOMIC))
    (clobber (match_scratch:QIHISI 3 "=&u"))
    (clobber (reg:SI R0_REG))
   [(set_attr "length" "18")])
 
 (define_insn "atomic_fetch_<fetchop_name><mode>_soft_tcb"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&r")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(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
-         [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "r"))]
+         [(FETCHOP:QIHISI
+               (mem:QIHISI (match_dup 1))
+               (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                       "<fetchop_constraint_1_tcb>"))]
          UNSPEC_ATOMIC))
    (use (match_operand:SI 3 "gbr_displacement"))
-   (clobber (match_scratch:QIHISI 4 "=&r"))
    (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     #(0f-1f),r1"            "\n"
         "      mov.l   r0,@(%O3,gbr)"          "\n"
-        "0:    mov.<bwl>       @%1,%0"         "\n"
-        "      mov     #0,r0"                  "\n"
-        "      mov     %0,%4"                  "\n"
-        "      <fetchop_name>  %2,%4"          "\n"
-        "      mov.<bwl>       %4,@%1"         "\n"
-        "1:    mov.l   r0,@(%O3,gbr)";
+        "0:    mov.<bwl>       @%1,r0"         "\n"
+        "      mov     r0,%0"                  "\n"
+        "      <fetchop_name>  %2,r0"          "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "1:    mov     #0,r0"                  "\n"
+        "      mov.l   r0,@(%O3,gbr)";
 }
   [(set_attr "length" "20")])
 
 (define_insn "atomic_fetch_<fetchop_name><mode>_soft_imask"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&z")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(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
-         [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "r"))]
+         [(FETCHOP:QIHISI
+               (mem:QIHISI (match_dup 1))
+               (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                       "<fetchop_constraint_1_imask>"))]
          UNSPEC_ATOMIC))
-   (clobber (match_scratch:QIHISI 3 "=&r"))
-   (clobber (match_scratch:SI 4 "=&r"))]
+   (clobber (reg:SI R0_REG))
+   (clobber (match_scratch:QIHISI 3 "=&r"))]
   "TARGET_ATOMIC_SOFT_IMASK"
 {
-  return "\r   stc     sr,%0"                  "\n"
-        "      mov     %0,%4"                  "\n"
-        "      or      #0xF0,%0"               "\n"
-        "      ldc     %0,sr"                  "\n"
-        "      mov.<bwl>       @%1,%0"         "\n"
-        "      mov     %0,%3"                  "\n"
-        "      <fetchop_name>  %2,%3"          "\n"
-        "      mov.<bwl>       %3,@%1"         "\n"
-        "      ldc     %4,sr";
+  return "\r   stc     sr,r0"                  "\n"
+        "      mov     r0,%3"                  "\n"
+        "      or      #0xF0,r0"               "\n"
+        "      ldc     r0,sr"                  "\n"
+        "      mov.<bwl>       @%1,r0"         "\n"
+        "      mov     r0,%0"                  "\n"
+        "      <fetchop_name>  %2,r0"          "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "      ldc     %3,sr";
 }
   [(set_attr "length" "18")])
 
 (define_expand "atomic_fetch_nand<mode>"
-  [(set (match_operand:QIHISI 0 "register_operand" "")
-       (match_operand:QIHISI 1 "memory_operand" ""))
+  [(set (match_operand:QIHISI 0 "arith_reg_dest")
+       (match_operand:QIHISI 1 "memory_operand"))
    (set (match_dup 1)
        (unspec:QIHISI
          [(not:QIHISI (and:QIHISI (match_dup 1)
-                      (match_operand:QIHISI 2 "atomic_logical_operand" "")))]
+                      (match_operand:QIHISI 2 "atomic_logical_operand_1")))]
          UNSPEC_ATOMIC))
-   (match_operand:SI 3 "const_int_operand" "")]
+   (match_operand:SI 3 "const_int_operand")]
   "TARGET_ATOMIC_ANY"
 {
   rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
 })
 
 (define_insn "atomic_fetch_nandsi_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&r")
-       (mem:SI (match_operand:SI 1 "register_operand" "r")))
+  [(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 (and:SI (mem:SI (match_dup 1))
   [(set_attr "length" "12")])
 
 (define_insn "atomic_fetch_nand<mode>_hard"
-  [(set (match_operand:QIHI 0 "register_operand" "=&r")
-       (mem:QIHI (match_operand:SI 1 "register_operand" "r")))
+  [(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 (and:QIHI (mem:QIHI (match_dup 1))
   [(set_attr "length" "30")])
 
 (define_insn "atomic_fetch_nand<mode>_soft_gusa"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&u")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "u")))
+  [(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 (and:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "u")))]
+         [(not:QIHISI
+            (and:QIHISI (mem:QIHISI (match_dup 1))
+                        (match_operand:QIHISI 2 "arith_reg_operand" "u")))]
          UNSPEC_ATOMIC))
    (clobber (match_scratch:QIHISI 3 "=&u"))
    (clobber (reg:SI R0_REG))
   [(set_attr "length" "20")])
 
 (define_insn "atomic_fetch_nand<mode>_soft_tcb"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&r")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(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 (and:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "r")))]
+         [(not:QIHISI
+            (and:QIHISI (mem:QIHISI (match_dup 1))
+                        (match_operand:QIHISI 2 "logical_operand" "rK08")))]
          UNSPEC_ATOMIC))
    (use (match_operand:SI 3 "gbr_displacement"))
-   (clobber (match_scratch:QIHISI 4 "=&r"))
    (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"
+        "      .align 2"                       "\n"
         "      mov.l   r0,@(%O3,gbr)"          "\n"
-        "0:    mov.<bwl>       @%1,%0"         "\n"
-        "      mov     #0,r0"                  "\n"
-        "      mov     %2,%4"                  "\n"
-        "      and     %0,%4"                  "\n"
-        "      not     %4,%4"                  "\n"
-        "      mov.<bwl>       %4,@%1"         "\n"
-        "1:    mov.l   r0,@(%O3,gbr)";
+        "0:    mov.<bwl>       @%1,r0"         "\n"
+        "      mov     r0,%0"                  "\n"
+        "      and     %2,r0"                  "\n"
+        "      not     r0,r0"                  "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "1:    mov     #0,r0"                  "\n"
+        "      mov.l   r0,@(%O3,gbr)";
 }
   [(set_attr "length" "22")])
 
 (define_insn "atomic_fetch_nand<mode>_soft_imask"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&z")
-       (mem:QIHISI (match_operand:SI 1 "register_operand" "r")))
+  [(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 (and:QIHISI (mem:QIHISI (match_dup 1))
-            (match_operand:QIHISI 2 "register_operand" "r")))]
+         [(not:QIHISI
+            (and:QIHISI (mem:QIHISI (match_dup 1))
+                        (match_operand:QIHISI 2 "logical_operand" "rK08")))]
          UNSPEC_ATOMIC))
-   (clobber (match_scratch:QIHISI 3 "=&r"))
-   (clobber (match_scratch:SI 4 "=&r"))]
+   (clobber (reg:SI R0_REG))
+   (clobber (match_scratch:SI 3 "=&r"))]
   "TARGET_ATOMIC_SOFT_IMASK"
 {
-  return "\r   stc     sr,%0"                  "\n"
-        "      mov     %0,%4"                  "\n"
-        "      or      #0xF0,%0"               "\n"
-        "      ldc     %0,sr"                  "\n"
-        "      mov.<bwl>       @%1,%0"         "\n"
-        "      mov     %2,%3"                  "\n"
-        "      and     %0,%3"                  "\n"
-        "      not     %3,%3"                  "\n"
-        "      mov.<bwl>       %3,@%1"         "\n"
-        "      ldc     %4,sr";
+  return "\r   stc     sr,r0"                  "\n"
+        "      mov     r0,%3"                  "\n"
+        "      or      #0xF0,r0"               "\n"
+        "      ldc     r0,sr"                  "\n"
+        "      mov.<bwl>       @%1,r0"         "\n"
+        "      mov     r0,%0"                  "\n"
+        "      and     %2,r0"                  "\n"
+        "      not     r0,r0"                  "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "      ldc     %3,sr";
 }
   [(set_attr "length" "20")])
 
 ;; read - add|sub|or|and|xor|nand - write - return new value
 
 (define_expand "atomic_<fetchop_name>_fetch<mode>"
-  [(set (match_operand:QIHISI 0 "register_operand" "")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest")
        (FETCHOP:QIHISI
-         (match_operand:QIHISI 1 "memory_operand" "")
-         (match_operand:QIHISI 2 "<fetchop_predicate>" "")))
+         (match_operand:QIHISI 1 "memory_operand")
+         (match_operand:QIHISI 2 "<fetchop_predicate_1>")))
    (set (match_dup 1)
        (unspec:QIHISI
          [(FETCHOP:QIHISI (match_dup 1) (match_dup 2))]
 })
 
 (define_insn "atomic_<fetchop_name>_fetchsi_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&z")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&z")
        (FETCHOP:SI
-         (mem:SI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:SI 2 "<fetchop_predicate>" "<fetchop_constraint>")))
+         (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:SI 2 "<fetchop_predicate_1>"
+                             "<fetchop_constraint_1_llcs>")))
    (set (mem:SI (match_dup 1))
        (unspec:SI
          [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2))]
   [(set_attr "length" "8")])
 
 (define_insn "atomic_<fetchop_name>_fetch<mode>_hard"
-  [(set (match_operand:QIHI 0 "register_operand" "=&r")
+  [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r")
        (FETCHOP:QIHI
-         (mem:QIHI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:QIHI 2 "<fetchop_predicate>" "<fetchop_constraint>")))
+         (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:QIHI 2 "<fetchop_predicate_1>"
+                               "<fetchop_constraint_1_llcs>")))
    (set (mem:QIHI (match_dup 1))
        (unspec:QIHI
          [(FETCHOP:QIHI (mem:QIHI (match_dup 1)) (match_dup 2))]
   [(set_attr "length" "28")])
 
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_gusa"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&u")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u")
        (FETCHOP:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "u"))
-         (match_operand:QIHISI 2 "register_operand" "u")))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))
+         (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                 "<fetchop_constraint_1_gusa>")))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2))]
   [(set_attr "length" "16")])
 
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_tcb"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&r")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r")
        (FETCHOP:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:QIHISI 2 "register_operand" "r")))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                 "<fetchop_constraint_1_tcb>")))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2))]
   "TARGET_ATOMIC_SOFT_TCB"
 {
   return "\r   mova    1f,r0"                  "\n"
-        "      .align 2"                       "\n"
         "      mov     #(0f-1f),r1"            "\n"
+        "      .align 2"                       "\n"
         "      mov.l   r0,@(%O3,gbr)"          "\n"
-        "0:    mov.<bwl>       @%1,%0"         "\n"
+        "0:    mov.<bwl>       @%1,r0"         "\n"
+        "      <fetchop_name>  %2,r0"          "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "1:    mov     r0,%0"                  "\n"
         "      mov     #0,r0"                  "\n"
-        "      <fetchop_name>  %2,%0"          "\n"
-        "      mov.<bwl>       %0,@%1"         "\n"
-        "1:    mov.l   r0,@(%O3,gbr)";
+        "      mov.l   r0,@(%O3,gbr)";
 }
-  [(set_attr "length" "18")])
+  [(set_attr "length" "20")])
 
 (define_insn "atomic_<fetchop_name>_fetch<mode>_soft_imask"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&z")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&z")
        (FETCHOP:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:QIHISI 2 "register_operand" "r")))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:QIHISI 2 "<fetchop_predicate_1>"
+                                 "<fetchop_constraint_1_imask>")))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(FETCHOP:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2))]
   [(set_attr "length" "16")])
 
 (define_expand "atomic_nand_fetch<mode>"
-  [(set (match_operand:QIHISI 0 "register_operand" "")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest")
        (not:QIHISI (and:QIHISI
-         (match_operand:QIHISI 1 "memory_operand" "")
-         (match_operand:QIHISI 2 "atomic_logical_operand" ""))))
+         (match_operand:QIHISI 1 "memory_operand")
+         (match_operand:QIHISI 2 "atomic_logical_operand_1"))))
    (set (match_dup 1)
        (unspec:QIHISI
          [(not:QIHISI (and:QIHISI (match_dup 1) (match_dup 2)))]
          UNSPEC_ATOMIC))
-   (match_operand:SI 3 "const_int_operand" "")]
+   (match_operand:SI 3 "const_int_operand")]
   "TARGET_ATOMIC_ANY"
 {
   rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
 })
 
 (define_insn "atomic_nand_fetchsi_hard"
-  [(set (match_operand:SI 0 "register_operand" "=&z")
-       (not:SI (and:SI (mem:SI (match_operand:SI 1 "register_operand" "r"))
+  [(set (match_operand:SI 0 "arith_reg_dest" "=&z")
+       (not:SI (and:SI (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
                        (match_operand:SI 2 "logical_operand" "rK08"))))
    (set (mem:SI (match_dup 1))
        (unspec:SI
   [(set_attr "length" "10")])
 
 (define_insn "atomic_nand_fetch<mode>_hard"
-  [(set (match_operand:QIHI 0 "register_operand" "=&r")
+  [(set (match_operand:QIHI 0 "arith_reg_dest" "=&r")
        (not:QIHI
-         (and:QIHI (mem:QIHI (match_operand:SI 1 "register_operand" "r"))
+         (and:QIHI (mem:QIHI (match_operand:SI 1 "arith_reg_operand" "r"))
                    (match_operand:QIHI 2 "logical_operand" "rK08"))))
    (set (mem:QIHI (match_dup 1))
        (unspec:QIHI
   [(set_attr "length" "28")])
 
 (define_insn "atomic_nand_fetch<mode>_soft_gusa"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&u")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u")
        (not:QIHISI (and:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "u"))
-         (match_operand:QIHISI 2 "register_operand" "u"))))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u"))
+         (match_operand:QIHISI 2 "arith_reg_operand" "u"))))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(not:QIHISI (and:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2)))]
   [(set_attr "length" "18")])
 
 (define_insn "atomic_nand_fetch<mode>_soft_tcb"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&r")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&r")
        (not:QIHISI (and:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:QIHISI 2 "register_operand" "r"))))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:QIHISI 2 "logical_operand" "rK08"))))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(not:QIHISI (and:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2)))]
         "      mov     #(0f-1f),r1"            "\n"
         "      .align 2"                       "\n"
         "      mov.l   r0,@(%O3,gbr)"          "\n"
-        "0:    mov.<bwl>       @%1,%0"         "\n"
-        "      mov     #0,r0"                  "\n"
-        "      and     %2,%0"                  "\n"
-        "      not     %0,%0"                  "\n"
-        "      mov.<bwl>       %0,@%1"         "\n"
-        "1:    mov.l   r0,@(%O3,gbr)";
+        "0:    mov.<bwl>       @%1,r0"         "\n"
+        "      and     %2,r0"                  "\n"
+        "      not     r0,r0"                  "\n"
+        "      mov     r0,%0"                  "\n"
+        "      mov.<bwl>       r0,@%1"         "\n"
+        "1:    mov     #0,r0"                  "\n"
+        "      mov.l   r0,@(%O3,gbr)";
 }
-  [(set_attr "length" "20")])
+  [(set_attr "length" "22")])
 
 (define_insn "atomic_nand_fetch<mode>_soft_imask"
-  [(set (match_operand:QIHISI 0 "register_operand" "=&z")
+  [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&z")
        (not:QIHISI (and:QIHISI
-         (mem:QIHISI (match_operand:SI 1 "register_operand" "r"))
-         (match_operand:QIHISI 2 "register_operand" "r"))))
+         (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "r"))
+         (match_operand:QIHISI 2 "logical_operand" "rK08"))))
    (set (mem:QIHISI (match_dup 1))
        (unspec:QIHISI
          [(not:QIHISI (and:QIHISI (mem:QIHISI (match_dup 1)) (match_dup 2)))]
index fb86e8c9fbf41e59f26611e7cd9be2204d267266..9dc18d731780fe14329b48d296787846b3777573 100644 (file)
@@ -1,3 +1,17 @@
+2015-01-28  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/64659
+       * gcc.target/sh/sh.exp
+       (check_effective_target_atomic_model_soft_gusa_available,
+       check_effective_target_atomic_model_soft_tcb_available,
+       check_effective_target_atomic_model_soft_imask_available,
+       check_effective_target_atomic_model_hard_llcs_available): New.
+       * gcc.target/sh/pr64659-0.h: New.
+       * gcc.target/sh/pr64659-1.c: New.
+       * gcc.target/sh/pr64659-2.c: New.
+       * gcc.target/sh/pr64659-3.c: New.
+       * gcc.target/sh/pr64659-4.c: New.
+
 2015-01-28  Alex Velenko  <Alex.Velenko@arm.com>
 
        * gcc.target/arm/atomic-op-consume.c (scan-assember-times): Adjust
diff --git a/gcc/testsuite/gcc.target/sh/pr64659-0.h b/gcc/testsuite/gcc.target/sh/pr64659-0.h
new file mode 100644 (file)
index 0000000..a63df2b
--- /dev/null
@@ -0,0 +1,60 @@
+/* Check that atomic ops utilize insns with immediate values.  */
+
+#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_add_fetch)
+emitfuncs (__atomic_fetch_add)
+
+emitfuncs (__atomic_sub_fetch)
+emitfuncs (__atomic_fetch_sub)
+
+emitfuncs (__atomic_and_fetch)
+emitfuncs (__atomic_fetch_and)
+
+emitfuncs (__atomic_or_fetch)
+emitfuncs (__atomic_fetch_or)
+
+emitfuncs (__atomic_xor_fetch)
+emitfuncs (__atomic_fetch_xor)
+
+emitfuncs (__atomic_nand_fetch)
+emitfuncs (__atomic_fetch_nand)
+
+void
+test___atomic_compare_exchange_0 (char* mem)
+{
+  char expected = 1;
+  char desired = 5;
+  __atomic_compare_exchange (mem, &expected, &desired, 0, __ATOMIC_ACQ_REL,
+                            __ATOMIC_RELAXED);
+}
+
+void
+test___atomic_compare_exchange_1 (short* mem)
+{
+  short expected = 1;
+  short desired = 5;
+  __atomic_compare_exchange (mem, &expected, &desired, 0, __ATOMIC_ACQ_REL,
+                            __ATOMIC_RELAXED);
+}
+
+void
+test___atomic_compare_exchange_2 (int* mem)
+{
+  int expected = 1;
+  int desired = 5;
+  __atomic_compare_exchange (mem, &expected, &desired, 0, __ATOMIC_ACQ_REL,
+                            __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr64659-1.c b/gcc/testsuite/gcc.target/sh/pr64659-1.c
new file mode 100644 (file)
index 0000000..e86c0bb
--- /dev/null
@@ -0,0 +1,7 @@
+/* Check that atomic ops utilize insns with immediate values.  */
+/* { dg-do compile { target { atomic_model_soft_gusa_available } } }  */
+/* { dg-options "-O2 -matomic-model=soft-gusa,strict" }  */
+/* { dg-final { scan-assembler-times "add\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "add\t#-1" 6 } }  */
+
+#include "pr64659-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64659-2.c b/gcc/testsuite/gcc.target/sh/pr64659-2.c
new file mode 100644 (file)
index 0000000..e9c069c
--- /dev/null
@@ -0,0 +1,10 @@
+/* Check that atomic ops utilize insns with immediate values.  */
+/* { 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 "add\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "add\t#-1" 6 } }  */
+/* { dg-final { scan-assembler-times "and\t#1" 12 } }  */
+/* { dg-final { scan-assembler-times "\tor\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "xor\t#1" 6 } }  */
+
+#include "pr64659-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64659-3.c b/gcc/testsuite/gcc.target/sh/pr64659-3.c
new file mode 100644 (file)
index 0000000..b5a7f41
--- /dev/null
@@ -0,0 +1,10 @@
+/* Check that atomic ops utilize insns with immediate values.  */
+/* { dg-do compile { target { atomic_model_soft_imask_available } } }  */
+/* { dg-options "-O2 -matomic-model=soft-imask,strict -mno-usermode" }  */
+/* { dg-final { scan-assembler-times "add\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "add\t#-1" 6 } }  */
+/* { dg-final { scan-assembler-times "and\t#1" 12 } }  */
+/* { dg-final { scan-assembler-times "\tor\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "xor\t#1" 6 } }  */
+
+#include "pr64659-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64659-4.c b/gcc/testsuite/gcc.target/sh/pr64659-4.c
new file mode 100644 (file)
index 0000000..acf1cde
--- /dev/null
@@ -0,0 +1,11 @@
+/* Check that atomic ops utilize insns with immediate values.  */
+/* { dg-do compile { target { atomic_model_hard_llcs_available } } }  */
+/* { dg-options "-O2 -matomic-model=hard-llcs,strict" }  */
+/* { dg-final { scan-assembler-times "add\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "add\t#-1" 6 } }  */
+/* { dg-final { scan-assembler-times "and\t#1" 12 } }  */
+/* { dg-final { scan-assembler-times "\tor\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "xor\t#1" 6 } }  */
+/* { dg-final { scan-assembler-times "cmp/eq\t#1" 1 } }  */
+
+#include "pr64659-0.h"
index ff3048fa4e9402b26c6101ccdc8c2476eeec334a..6f9c97e34e7037a709e2d1794091165aa3b6ce11 100644 (file)
@@ -33,6 +33,34 @@ proc check_effective_target_sh2a { } {
     } ""]
 }
 
+# Return 1 if target supports atomic-model=soft-gusa
+proc check_effective_target_atomic_model_soft_gusa_available { } {
+    return [check_no_compiler_messages atomic_model_soft_gusa_available object {
+            int x = 0;
+    } "-matomic-model=soft-gusa"]
+}
+
+# Return 1 if target supports atomic-model=soft-tcb
+proc check_effective_target_atomic_model_soft_tcb_available { } {
+    return [check_no_compiler_messages atomic_model_soft_tcb_available object {
+            int x = 0;
+    } "-matomic-model=soft-tcb,gbr-offset=0"]
+}
+
+# Return 1 if target supports atomic-model=soft-imask
+proc check_effective_target_atomic_model_soft_imask_available { } {
+    return [check_no_compiler_messages atomic_model_soft_imask_available object {
+            int x = 0;
+    } "-matomic-model=soft-imask -mno-usermode"]
+}
+
+# Return 1 if target supports atomic-model=hard-llcs
+proc check_effective_target_atomic_model_hard_llcs_available { } {
+    return [check_no_compiler_messages atomic_model_hard_llcs_available object {
+            int x = 0;
+    } "-matomic-model=hard-llcs"]
+}
+
 # If a testcase doesn't have special options, use these.
 global DEFAULT_CFLAGS
 if ![info exists DEFAULT_CFLAGS] then {