This patch utilizes the new "(mem (reg:<vectype>))" support to add vector
atomics.  These work exactly like the scalar atomic operation, but 64 times in
parallel.

gcc/ChangeLog:

        * config/gcn/gcn.md (UNSPEC_PAIR): New.
        (X): Add vector modes.
        (ATOMICMODE): New mode iterator.
        (atomic_fetch_<bare_mnemonic><mode>): Use ATOMICMODE iterator.
        (atomic_<bare_mnemonic><mode>): Likewise.
        (x2): Add vector modes.
        (size): Delete.
        (bitsize): Add vector modes.
        (createpair<mode>): New insn.
        (sync_compare_and_swap<mode>): Use ATOMICMODE iterator.
        (sync_compare_and_swap<mode>_insn): Likewise.
        (sync_compare_and_swap<mode>_lds_insn): Likewise.
        (atomic_load<mode>): Likewise.
        (atomic_store<mode>): Likewise.
        (atomic_exchange<mode>): Likewise.
---
 gcc/config/gcn/gcn.md | 114 +++++++++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 45 deletions(-)

diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index 4c56b1b5e96..75949f64dea 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -86,7 +86,8 @@ (define_c_enum "unspec" [
   UNSPEC_FLBIT_INT
   UNSPEC_FLOOR UNSPEC_CEIL UNSPEC_SIN UNSPEC_COS UNSPEC_EXP2 UNSPEC_LOG2
   UNSPEC_LDEXP UNSPEC_FREXP_EXP UNSPEC_FREXP_MANT
-  UNSPEC_DIV_SCALE UNSPEC_DIV_FMAS UNSPEC_DIV_FIXUP])
+  UNSPEC_DIV_SCALE UNSPEC_DIV_FMAS UNSPEC_DIV_FIXUP
+  UNSPEC_PAIR])
 
 ;; }}}
 ;; {{{ Attributes
@@ -1921,7 +1922,11 @@ (define_expand "<expander>ti3"
 ; the programmer to get this right.
 
 (define_code_iterator atomicops [plus minus and ior xor])
-(define_mode_attr X [(SI "") (DI "_X2")])
+(define_mode_attr X [(SI "") (V64SI "")
+                    (DI "_X2") (V64DI "_X2")])
+
+(define_mode_iterator ATOMICMODE
+                     [SI DI V64SI V64DI])
 
 ;; TODO compare_and_swap test_and_set inc dec
 ;; Hardware also supports min and max, but GCC does not.
@@ -1963,13 +1968,13 @@ (define_insn "*memory_barrier"
 ; reliably - they can cause hangs or incorrect results.
 ; TODO: flush caches according to memory model
 (define_insn "atomic_fetch_<bare_mnemonic><mode>"
-  [(set (match_operand:SIDI 0 "register_operand"     "=Sm, v, v")
-       (match_operand:SIDI 1 "memory_operand"       "+RS,RF,RM"))
+  [(set (match_operand:ATOMICMODE 0 "register_operand"     "=Sm,   v,   v")
+       (match_operand:ATOMICMODE 1 "memory_operand"       "+RS,RfRF,RmRM"))
    (set (match_dup 1)
-       (unspec_volatile:SIDI
-         [(atomicops:SIDI
+       (unspec_volatile:ATOMICMODE
+         [(atomicops:ATOMICMODE
            (match_dup 1)
-           (match_operand:SIDI 2 "register_operand" " Sm, v, v"))]
+           (match_operand:ATOMICMODE 2 "register_operand" " Sm,   v,   v"))]
           UNSPECV_ATOMIC))
    (use (match_operand 3 "const_int_operand"))]
   "0 /* Disabled.  */"
@@ -1987,11 +1992,11 @@ (define_insn "atomic_fetch_<bare_mnemonic><mode>"
 ; you might expect from a concurrent non-atomic read-modify-write.
 ; TODO: flush caches according to memory model
 (define_insn "atomic_<bare_mnemonic><mode>"
-  [(set (match_operand:SIDI 0 "memory_operand"       "+RS,RF,RM")
-       (unspec_volatile:SIDI
-         [(atomicops:SIDI
+  [(set (match_operand:ATOMICMODE 0 "memory_operand"       "+RS,RfRF,RmRM")
+       (unspec_volatile:ATOMICMODE
+         [(atomicops:ATOMICMODE
            (match_dup 0)
-           (match_operand:SIDI 1 "register_operand" " Sm, v, v"))]
+           (match_operand:ATOMICMODE 1 "register_operand" " Sm,   v,   v"))]
          UNSPECV_ATOMIC))
    (use (match_operand 2 "const_int_operand"))]
   "0 /* Disabled.  */"
@@ -2003,15 +2008,35 @@ (define_insn "atomic_<bare_mnemonic><mode>"
    (set_attr "flatmemaccess" "*,atomicwait,atomicwait")
    (set_attr "length" "12")])
 
-(define_mode_attr x2 [(SI "DI") (DI "TI")])
-(define_mode_attr size [(SI "4") (DI "8")])
-(define_mode_attr bitsize [(SI "32") (DI "64")])
+(define_mode_attr x2 [(SI "DI") (DI "TI") (V64SI "V64DI") (V64DI "V64TI")])
+(define_mode_attr bitsize [(SI "32") (DI "64") (V64SI "32") (V64DI "64")])
+
+(define_insn_and_split "createpair<mode>"
+  [(set (match_operand:<x2> 0 "register_operand"                  "=&v,&Sm")
+        (unspec:<x2> [(match_operand:ATOMICMODE 1 "register_operand" "v, Sm")
+                     (match_operand:ATOMICMODE 2 "register_operand" "v, Sm")]
+                    UNSPEC_PAIR))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  {
+    int parts = <bitsize> / 32;
+    int outpart = 0;
+    for (int inpart = 0; inpart < parts; inpart++, outpart++)
+      emit_move_insn (gcn_operand_part (<x2>mode, operands[0], outpart),
+                     gcn_operand_part (<MODE>mode, operands[1], inpart));
+    for (int inpart = 0; inpart < parts; inpart++, outpart++)
+      emit_move_insn (gcn_operand_part (<x2>mode, operands[0], outpart),
+                     gcn_operand_part (<MODE>mode, operands[2], inpart));
+    DONE;
+  })
 
 (define_expand "sync_compare_and_swap<mode>"
-  [(match_operand:SIDI 0 "register_operand")
-   (match_operand:SIDI 1 "memory_operand")
-   (match_operand:SIDI 2 "register_operand")
-   (match_operand:SIDI 3 "register_operand")]
+  [(match_operand:ATOMICMODE 0 "register_operand")
+   (match_operand:ATOMICMODE 1 "memory_operand")
+   (match_operand:ATOMICMODE 2 "register_operand")
+   (match_operand:ATOMICMODE 3 "register_operand")]
   ""
   {
     if (MEM_ADDR_SPACE (operands[1]) == ADDR_SPACE_LDS)
@@ -2024,22 +2049,21 @@ (define_expand "sync_compare_and_swap<mode>"
       }
 
     /* Operands 2 and 3 must be placed in consecutive registers, and passed
-       as a combined value.  */
+       as a combined value.  Subregs would work for the scalar case, but
+       not for the vector case.  */
     rtx src_cmp = gen_reg_rtx (<x2>mode);
-    emit_move_insn (gen_rtx_SUBREG (<MODE>mode, src_cmp, 0), operands[3]);
-    emit_move_insn (gen_rtx_SUBREG (<MODE>mode, src_cmp, <size>), operands[2]);
-    emit_insn (gen_sync_compare_and_swap<mode>_insn (operands[0],
-                                                    operands[1],
+    emit_insn (gen_createpair<mode> (src_cmp, operands[3], operands[2]));
+    emit_insn (gen_sync_compare_and_swap<mode>_insn (operands[0], operands[1],
                                                     src_cmp));
     DONE;
   })
 
 (define_insn "sync_compare_and_swap<mode>_insn"
-  [(set (match_operand:SIDI 0 "register_operand"    "=Sm, v, v")
-       (match_operand:SIDI 1 "memory_operand"      "+RS,RF,RM"))
+  [(set (match_operand:ATOMICMODE 0 "register_operand" "=Sm,   v,   v")
+       (match_operand:ATOMICMODE 1 "memory_operand"   "+RS,RfRF,RmRM"))
    (set (match_dup 1)
-       (unspec_volatile:SIDI
-         [(match_operand:<x2> 2 "register_operand" " Sm, v, v")]
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:<x2> 2 "register_operand"    " Sm,   v,   v")]
          UNSPECV_ATOMIC))]
   ""
   "@
@@ -2051,14 +2075,14 @@ (define_insn "sync_compare_and_swap<mode>_insn"
    (set_attr "flatmemaccess" "*,cmpswapx2,cmpswapx2")])
 
 (define_insn "sync_compare_and_swap<mode>_lds_insn"
-  [(set (match_operand:SIDI 0 "register_operand"    "= v")
-       (unspec_volatile:SIDI
-         [(match_operand:SIDI 1 "memory_operand"   "+RL")]
+  [(set (match_operand:ATOMICMODE 0 "register_operand"    "=   v")
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:ATOMICMODE 1 "memory_operand"   "+RLRl")]
          UNSPECV_ATOMIC))
    (set (match_dup 1)
-       (unspec_volatile:SIDI
-         [(match_operand:SIDI 2 "register_operand" "  v")
-          (match_operand:SIDI 3 "register_operand" "  v")]
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:ATOMICMODE 2 "register_operand" "    v")
+          (match_operand:ATOMICMODE 3 "register_operand" "    v")]
          UNSPECV_ATOMIC))]
   ""
   {
@@ -2071,11 +2095,11 @@ (define_insn "sync_compare_and_swap<mode>_lds_insn"
    (set_attr "length" "12")])
 
 (define_insn "atomic_load<mode>"
-  [(set (match_operand:SIDI 0 "register_operand"  "=Sm, v, v")
-       (unspec_volatile:SIDI
-         [(match_operand:SIDI 1 "memory_operand" " RS,RF,RM")]
+  [(set (match_operand:ATOMICMODE 0 "register_operand"  "=Sm,   v,   v")
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:ATOMICMODE 1 "memory_operand" " RS,RfRF,RmRM")]
          UNSPECV_ATOMIC))
-   (use (match_operand:SIDI 2 "immediate_operand" "  i, i, i"))]
+   (use (match_operand:SI 2 "immediate_operand" "  i,   i,   i"))]
   ""
   {
     /* FIXME: RDNA cache instructions may be too conservative?  */
@@ -2173,11 +2197,11 @@ (define_insn "atomic_load<mode>"
    (set_attr "rdna" "no,*,*")])
 
 (define_insn "atomic_store<mode>"
-  [(set (match_operand:SIDI 0 "memory_operand"      "=RS,RF,RM")
-       (unspec_volatile:SIDI
-         [(match_operand:SIDI 1 "register_operand" " Sm, v, v")]
+  [(set (match_operand:ATOMICMODE 0 "memory_operand"      "=RS,RfRF,RmRM")
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:ATOMICMODE 1 "register_operand" " Sm,   v,   v")]
          UNSPECV_ATOMIC))
-  (use (match_operand:SIDI 2 "immediate_operand"    "  i, i, i"))]
+  (use (match_operand:SI 2 "immediate_operand"    "  i,   i,   i"))]
   ""
   {
     switch (INTVAL (operands[2]))
@@ -2260,11 +2284,11 @@ (define_insn "atomic_store<mode>"
    (set_attr "rdna" "no,*,*")])
 
 (define_insn "atomic_exchange<mode>"
-  [(set (match_operand:SIDI 0 "register_operand"    "=Sm, v, v")
-        (match_operand:SIDI 1 "memory_operand"     "+RS,RF,RM"))
+  [(set (match_operand:ATOMICMODE 0 "register_operand"    "=Sm,   v,   v")
+        (match_operand:ATOMICMODE 1 "memory_operand"     "+RS,RfRF,RmRM"))
    (set (match_dup 1)
-       (unspec_volatile:SIDI
-         [(match_operand:SIDI 2 "register_operand" " Sm, v, v")]
+       (unspec_volatile:ATOMICMODE
+         [(match_operand:ATOMICMODE 2 "register_operand" " Sm,   v,   v")]
          UNSPECV_ATOMIC))
    (use (match_operand 3 "immediate_operand"))]
   ""
-- 
2.54.0

Reply via email to