re PR target/64660 ([SH] Convert atomic_fetch_<op> to atomic_<op>_fetch)
authorOleg Endo <olegendo@gcc.gnu.org>
Tue, 3 Feb 2015 20:24:13 +0000 (20:24 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Tue, 3 Feb 2015 20:24:13 +0000 (20:24 +0000)
gcc/
PR target/64660
* config/sh/sync.md (atomic_<fetchop_name><mode>_hard,
atomic_not<mode>_hard, atomic_<fetchop_name><mode>_soft_tcb,
atomic_not<mode>_soft_tcb, atomic_nand<mode>_hard,
atomic_nand<mode>_soft_tcb): New insns.
(atomic_fetch_<fetchop_name>si_hard): Convert to insn_and_split.
Split into atomic_<fetchop_name>_fetchsi_hard if operands[0] is unused.
(define_insn "atomic_fetch_notsi_hard): Convert to insn_and_split.
Split into atomic_not_fetchsi_hard if operands[0] is unused.
(atomic_fetch_<fetchop_name><mode>_hard): Convert to insn_and_split.
Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
(atomic_fetch_not<mode>_hard): Convert to insn_and_split.  Split into
atomic_not<mode>_hard if operands[0] is unused.
(atomic_fetch_<fetchop_name><mode>_soft_gusa): Convert to
insn_and_split.  Split into atomic_<fetchop_name>_fetch<mode>_soft_gusa
if operands[0] is unused.
(atomic_fetch_not<mode>_soft_gusa): Convert to insn_and_split.  Split
into atomic_not_fetch<mode>_soft_gusa if operands[0] is unused.
(atomic_fetch_<fetchop_name><mode>_soft_tcb): Convert to insn_and_split.
Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
unused.
(atomic_fetch_not<mode>_soft_tcb): Convert to insn_and_split.  Split
into atomic_not<mode>_soft_tcb if operands[0] is unused.
(atomic_fetch_<fetchop_name><mode>_soft_imask): Convert to
insn_and_split.  Split into atomic_<fetchop_name>_fetch<mode>_soft_imask
if operands[0] is unused.
(atomic_fetch_not<mode>_soft_imask): Convert to insn_and_split.  Split
into atomic_not_fetch<mode>_soft_imask is operands[0] is unused.
(atomic_fetch_nandsi_hard): Convert to insn_and_split.  Split into
atomic_nand_fetchsi_hard if operands[0] is unused.
(atomic_fetch_nand<mode>_hard): Convert to insn_and_split.  Split into
atomic_nand<mode>_hard if operands[0] is unused.
(atomic_fetch_nand<mode>_soft_gusa): Convert to insn_and_split.  Split
into atomic_nand_fetch<mode>_soft_gusa if operands[0] is unused.
(atomic_fetch_nand<mode>_soft_tcb): Convert to insn_and_split.  Split
into atomic_nand<mode>_soft_tcb if operands[0] is unused.
(atomic_fetch_nand<mode>_soft_imask): Convert to insn_and_split.  Split
into atomic_nand_fetch<mode>_soft_imask if operands[0] is unused.
(atomic_<fetchop_name>_fetch<mode>_hard): Convert to insn_and_split.
Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
(atomic_not_fetch<mode>_hard): Convert to insn_and_split.  Split into
atomic_not<mode>_hard if operands[0] is unused.
(atomic_<fetchop_name>_fetch<mode>_soft_tcb): Convert to insn_and_split.
Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
unused.
(atomic_not_fetch<mode>_soft_tcb): Convert to insn_and_split.  Split
into atomic_not<mode>_soft_tcb if operands[0] is unused.
(atomic_nand_fetch<mode>_hard): Convert to insn_and_split.  Split into
atomic_nand<mode>_hard if operands[0] is unused.
(atomic_nand_fetch<mode>_soft_tcb): Convert to insn_and_split.  Split
into atomic_nand<mode>_soft_tcb if operands[0] is unused.

gcc/testsuite/
PR target/64660
* gcc.target/sh/pr64660-0.h: New.
* gcc.target/sh/pr64660-1.c: New.
* gcc.target/sh/pr64660-2.c: New.
* gcc.target/sh/pr64660-3.c: New.
* gcc.target/sh/pr64660-4.c: New.

From-SVN: r220376

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

index 5d1f6280caacb0eba3ca0e13f3b61c1beed623bd..98c968ecc20cab51b210a1ee725afa87d5aa26e2 100644 (file)
@@ -1,3 +1,57 @@
+2015-02-03  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/64660
+       * config/sh/sync.md (atomic_<fetchop_name><mode>_hard,
+       atomic_not<mode>_hard, atomic_<fetchop_name><mode>_soft_tcb,
+       atomic_not<mode>_soft_tcb, atomic_nand<mode>_hard,
+       atomic_nand<mode>_soft_tcb): New insns.
+       (atomic_fetch_<fetchop_name>si_hard): Convert to insn_and_split.
+       Split into atomic_<fetchop_name>_fetchsi_hard if operands[0] is unused.
+       (define_insn "atomic_fetch_notsi_hard): Convert to insn_and_split.
+       Split into atomic_not_fetchsi_hard if operands[0] is unused.
+       (atomic_fetch_<fetchop_name><mode>_hard): Convert to insn_and_split.
+       Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
+       (atomic_fetch_not<mode>_hard): Convert to insn_and_split.  Split into
+       atomic_not<mode>_hard if operands[0] is unused.
+       (atomic_fetch_<fetchop_name><mode>_soft_gusa): Convert to
+       insn_and_split.  Split into atomic_<fetchop_name>_fetch<mode>_soft_gusa
+       if operands[0] is unused.
+       (atomic_fetch_not<mode>_soft_gusa): Convert to insn_and_split.  Split
+       into atomic_not_fetch<mode>_soft_gusa if operands[0] is unused.
+       (atomic_fetch_<fetchop_name><mode>_soft_tcb): Convert to insn_and_split.
+       Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
+       unused.
+       (atomic_fetch_not<mode>_soft_tcb): Convert to insn_and_split.  Split
+       into atomic_not<mode>_soft_tcb if operands[0] is unused.
+       (atomic_fetch_<fetchop_name><mode>_soft_imask): Convert to
+       insn_and_split.  Split into atomic_<fetchop_name>_fetch<mode>_soft_imask
+       if operands[0] is unused.
+       (atomic_fetch_not<mode>_soft_imask): Convert to insn_and_split.  Split
+       into atomic_not_fetch<mode>_soft_imask is operands[0] is unused.
+       (atomic_fetch_nandsi_hard): Convert to insn_and_split.  Split into
+       atomic_nand_fetchsi_hard if operands[0] is unused.
+       (atomic_fetch_nand<mode>_hard): Convert to insn_and_split.  Split into
+       atomic_nand<mode>_hard if operands[0] is unused.
+       (atomic_fetch_nand<mode>_soft_gusa): Convert to insn_and_split.  Split
+       into atomic_nand_fetch<mode>_soft_gusa if operands[0] is unused.
+       (atomic_fetch_nand<mode>_soft_tcb): Convert to insn_and_split.  Split
+       into atomic_nand<mode>_soft_tcb if operands[0] is unused.
+       (atomic_fetch_nand<mode>_soft_imask): Convert to insn_and_split.  Split
+       into atomic_nand_fetch<mode>_soft_imask if operands[0] is unused.
+       (atomic_<fetchop_name>_fetch<mode>_hard): Convert to insn_and_split.
+       Split into atomic_<fetchop_name><mode>_hard if operands[0] is unused.
+       (atomic_not_fetch<mode>_hard): Convert to insn_and_split.  Split into
+       atomic_not<mode>_hard if operands[0] is unused.
+       (atomic_<fetchop_name>_fetch<mode>_soft_tcb): Convert to insn_and_split.
+       Split into atomic_<fetchop_name><mode>_soft_tcb if operands[0] is
+       unused.
+       (atomic_not_fetch<mode>_soft_tcb): Convert to insn_and_split.  Split
+       into atomic_not<mode>_soft_tcb if operands[0] is unused.
+       (atomic_nand_fetch<mode>_hard): Convert to insn_and_split.  Split into
+       atomic_nand<mode>_hard if operands[0] is unused.
+       (atomic_nand_fetch<mode>_soft_tcb): Convert to insn_and_split.  Split
+       into atomic_nand<mode>_soft_tcb if operands[0] is unused.
+
 2015-02-03  David Malcolm  <dmalcolm@redhat.com>
 
        PR jit/64810
index 089a6283a47dd68fb814ae62313c0db81921ce14..d1413c595a69838db7b6aa5ccb610f51b96ca20c 100644 (file)
   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))
         "      <fetchop_name>  %2,r0"  "\n"
         "      movco.l r0,@%1"         "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_<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))
         "      not     r0,r0"          "\n"
         "      movco.l r0,@%1"         "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_not_fetchsi_hard (gen_reg_rtx (SImode), operands[1]));
 }
   [(set_attr "length" "10")])
 
-(define_insn "atomic_fetch_<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))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%3"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_<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))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%2"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_not<mode>_hard (operands[1]));
+}
+  [(set_attr "length" "26")])
+
+(define_insn "atomic_not<mode>_hard"
+  [(set (mem:QIHI (match_operand:SI 0 "arith_reg_operand" "r"))
+       (unspec:QIHI [(not:QIHI (mem:QIHI (match_dup 0)))] UNSPEC_ATOMIC))
+   (set (reg:SI T_REG) (const_int 1))
+   (clobber (reg:SI R0_REG))
+   (clobber (match_scratch:SI 1 "=&r"))
+   (clobber (match_scratch:SI 2 "=0"))]
+  "TARGET_ATOMIC_HARD_LLCS"
+{
+  return "\r   mov     #-4,%1"                 "\n"
+        "      and     %0,%1"                  "\n"
+        "      xor     %1,%0"                  "\n"
+        "      add     r15,%0"                 "\n"
+        "      add     #-4,%0"                 "\n"
+        "0:    movli.l @%1,r0"                 "\n"
+        "      mov.l   r0,@-r15"               "\n"
+        "      mov.<bw>        @%0,r0"         "\n"
+        "      not     r0,r0"                  "\n"
+        "      mov.<bw>        r0,@%0"         "\n"
+        "      mov.l   @r15+,r0"               "\n"
+        "      movco.l r0,@%1"                 "\n"
+        "      bf      0b";
 }
   [(set_attr "length" "26")])
 
-(define_insn "atomic_fetch_<fetchop_name><mode>_soft_gusa"
+(define_insn_and_split "atomic_fetch_<fetchop_name><mode>_soft_gusa"
   [(set (match_operand:QIHISI 0 "arith_reg_dest" "=&u")
        (mem:QIHISI (match_operand:SI 1 "arith_reg_operand" "u")))
    (set (mem:QIHISI (match_dup 1))
         "      <fetchop_name>  %2,%3"          "\n"
         "      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))
         "      not     %0,%2"                  "\n"
         "      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))
         "      mov.<bwl>       r0,@%1"         "\n"
         "1:    mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O3,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_<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))
         "      mov.<bwl>       r0,@%1"         "\n"
         "1:    mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O2,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_not<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))
         "      <fetchop_name>  %2,r0"          "\n"
         "      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))
         "      not     r0,r0"                  "\n"
         "      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")])
 
   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))
         "      not     r0,r0"          "\n"
         "      movco.l r0,@%1"         "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_nand_fetchsi_hard (gen_reg_rtx (SImode), operands[1],
+                                          operands[2]));
 }
   [(set_attr "length" "12")])
 
-(define_insn "atomic_fetch_nand<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))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%3"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_nand<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))
         "      not     %3,%3"                  "\n"
         "      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))
         "      mov.<bwl>       r0,@%1"         "\n"
         "1:    mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O3,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_nand<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))
         "      not     r0,r0"                  "\n"
         "      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")])
 
 }
   [(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"))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%3"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_<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))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%2"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_not<mode>_hard (operands[1]));
 }
   [(set_attr "length" "28")])
 
 }
   [(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"))
         "1:    mov     r0,%0"                  "\n"
         "      mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O3,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_<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))
         "1:    mov     r0,%0"                  "\n"
         "      mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O2,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_not<mode>_soft_tcb (operands[1], operands[2]));
 }
   [(set_attr "length" "20")])
 
 }
   [(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"))
         "      mov.l   @r15+,r0"               "\n"
         "      movco.l r0,@%3"                 "\n"
         "      bf      0b";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_nand<mode>_hard (operands[1], operands[2]));
 }
   [(set_attr "length" "28")])
 
 }
   [(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"))
         "      mov.<bwl>       r0,@%1"         "\n"
         "1:    mov     #0,r0"                  "\n"
         "      mov.l   r0,@(%O3,gbr)";
+}
+  "&& can_create_pseudo_p () && optimize
+   && sh_reg_dead_or_unused_after_insn (insn, REGNO (operands[0]))"
+  [(const_int 0)]
+{
+  emit_insn (gen_atomic_nand<mode>_soft_tcb (operands[1], operands[2],
+                                            operands[3]));
 }
   [(set_attr "length" "22")])
 
index 00c0450dbb597aac433f7b8f5b6edbbc514b6490..98d72cbc38a3ae23802d83428e5ca8e560223bd3 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-03  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/64660
+       * gcc.target/sh/pr64660-0.h: New.
+       * gcc.target/sh/pr64660-1.c: New.
+       * gcc.target/sh/pr64660-2.c: New.
+       * gcc.target/sh/pr64660-3.c: New.
+       * gcc.target/sh/pr64660-4.c: New.
+
 2015-02-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/64877
diff --git a/gcc/testsuite/gcc.target/sh/pr64660-0.h b/gcc/testsuite/gcc.target/sh/pr64660-0.h
new file mode 100644 (file)
index 0000000..28c1ac6
--- /dev/null
@@ -0,0 +1,44 @@
+/* Check that the appropriate atomic insns are used if the result values
+   are unused.  */
+
+#define concat_1(x, y) x ## y
+#define concat(x, y) concat_1 (x, y)
+#define makefuncname(name) concat (concat (test_, __LINE__), name)
+
+#define emitfuncs(name,val)\
+  void makefuncname (_0) (char* mem)\
+  {\
+    name (mem, val, __ATOMIC_ACQ_REL);\
+  }\
+  void makefuncname (_1) (short* mem)\
+  {\
+    name (mem, val, __ATOMIC_ACQ_REL);\
+  }\
+  void makefuncname (_2) (int* mem)\
+  {\
+    name (mem, val, __ATOMIC_ACQ_REL);\
+  }\
+
+emitfuncs (__atomic_add_fetch, 1)
+emitfuncs (__atomic_fetch_add, 1)
+
+emitfuncs (__atomic_sub_fetch, 1)
+emitfuncs (__atomic_fetch_sub, 1)
+
+emitfuncs (__atomic_and_fetch, 1)
+emitfuncs (__atomic_fetch_and, 1)
+
+emitfuncs (__atomic_or_fetch, 1)
+emitfuncs (__atomic_fetch_or, 1)
+
+emitfuncs (__atomic_xor_fetch, 1)
+emitfuncs (__atomic_fetch_xor, 1)
+
+emitfuncs (__atomic_nand_fetch, 1)
+emitfuncs (__atomic_fetch_nand, 1)
+
+emitfuncs (__atomic_xor_fetch, -1)
+emitfuncs (__atomic_fetch_xor, -1)
+
+emitfuncs (__atomic_nand_fetch, -1)
+emitfuncs (__atomic_fetch_nand, -1)
diff --git a/gcc/testsuite/gcc.target/sh/pr64660-1.c b/gcc/testsuite/gcc.target/sh/pr64660-1.c
new file mode 100644 (file)
index 0000000..2d5442c
--- /dev/null
@@ -0,0 +1,12 @@
+/* Check that the appropriate atomic insns are used if the result values
+   are unused.  */
+/* { dg-do compile { target { atomic_model_soft_gusa_available } } }  */
+/* { dg-options "-dp -O2 -matomic-model=soft-gusa,strict" }  */
+/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } }  */
+/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } }  */
+
+#include "pr64660-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64660-2.c b/gcc/testsuite/gcc.target/sh/pr64660-2.c
new file mode 100644 (file)
index 0000000..c0cef13
--- /dev/null
@@ -0,0 +1,13 @@
+/* Check that the appropriate atomic insns are used if the result values
+   are unused.  */
+/* { dg-do compile { target { atomic_model_soft_tcb_available } } }  */
+/* { dg-options "-dp -O2 -matomic-model=soft-tcb,gbr-offset=0,strict" }  */
+/* { dg-final { scan-assembler-times "atomic_add" 12 } }  */
+/* { dg-final { scan-assembler-times "atomic_and" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_or" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_xor" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_nand" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_not" 12 } }  */
+/* { dg-final { scan-assembler-not "fetch" } }  */
+
+#include "pr64660-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64660-3.c b/gcc/testsuite/gcc.target/sh/pr64660-3.c
new file mode 100644 (file)
index 0000000..fe3a83d
--- /dev/null
@@ -0,0 +1,12 @@
+/* Check that the appropriate atomic insns are used if the result values
+   are unused.  */
+/* { dg-do compile { target { atomic_model_soft_imask_available } } }  */
+/* { dg-options "-dp -O2 -matomic-model=soft-imask,strict -mno-usermode" }  */
+/* { dg-final { scan-assembler-times "atomic_add_fetch" 12 } }  */
+/* { dg-final { scan-assembler-times "atomic_and_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_or_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_xor_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_nand_fetch" 6 } }  */
+/* { dg-final { scan-assembler-times "atomic_not_fetch" 12 } }  */
+
+#include "pr64660-0.h"
diff --git a/gcc/testsuite/gcc.target/sh/pr64660-4.c b/gcc/testsuite/gcc.target/sh/pr64660-4.c
new file mode 100644 (file)
index 0000000..4d5d7f4
--- /dev/null
@@ -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"