When LSX is not available but sc.q is (for example on LA664 where the
SIMD unit is not enabled), we can use a LL-SC loop for 16-byte atomic
store.

gcc/ChangeLog:

        * config/loongarch/loongarch.cc (loongarch_print_operand_reloc):
        Accept "%t" for printing the number of the 64-bit machine
        register holding the upper half of a TImode.
        * config/loongarch/sync.md (atomic_storeti_scq): New
        define_insn.
        (atomic_storeti): expand to atomic_storeti_scq if !ISA_HAS_LSX.
---
 gcc/config/loongarch/loongarch.cc | 11 +++++++++++
 gcc/config/loongarch/sync.md      | 18 +++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 469aa3eb1b5..eb3baac7019 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -6208,6 +6208,7 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool 
hi64_part,
    'r'  Print address 12-31bit relocation associated with OP.
    'R'  Print address 32-51bit relocation associated with OP.
    'T' Print a comment marker if %G outputs nothing.
+   't' Print the register containing the higher 64 bits of a TImode.
    'u' Print a LASX register.
    'v' Print the insn size suffix b, h, w or d for vector modes V16QI, V8HI,
          V4SI, V2SI, and w, d for vector modes V4SF, V2DF respectively.
@@ -6478,6 +6479,16 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
        }
       break;
 
+    case 't':
+      if (GET_MODE (op) != TImode
+         || (op != CONST0_RTX (TImode) && code != REG))
+       {
+         output_operand_lossage ("invalid use of '%%%c'", letter);
+         break;
+       }
+      op = loongarch_subword (op, 1);
+      letter = 'z';
+      /* fall through */
     default:
       switch (code)
        {
diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md
index a0129b62a45..b3f9efc79f5 100644
--- a/gcc/config/loongarch/sync.md
+++ b/gcc/config/loongarch/sync.md
@@ -236,12 +236,28 @@ (define_insn "atomic_storeti_lsx"
 }
   [(set (attr "length") (const_int 12))])
 
+(define_insn "atomic_storeti_scq"
+  [(set (match_operand:TI 0 "memory_operand" "=m")
+       (unspec_volatile:TI
+         [(match_operand:TI 1 "register_operand" "r")]
+         UNSPEC_ATOMIC_STORE))
+   (clobber (match_scratch:DI 2 "=&r"))]
+  "TARGET_64BIT && ISA_HAS_SCQ"
+  "1:\\n\\tll.d\t$r0,%0\n\tmove\t%2,%1\n\tsc.q\t%2,%t1,%0\n\tbeqz\t%2,1b"
+  [(set (attr "length") (const_int 16))])
+
 (define_expand "atomic_storeti"
   [(match_operand:TI 0 "memory_operand"   "=m")
    (match_operand:TI 1 "reg_or_0_operand" "rJ")
    (match_operand:SI 2 "const_int_operand")]
-  "ISA_HAS_LSX && TARGET_64BIT"
+  "TARGET_64BIT && (ISA_HAS_LSX || ISA_HAS_SCQ)"
 {
+  if (!ISA_HAS_LSX)
+    {
+      emit_insn (gen_atomic_storeti_scq (operands[0], operands[1]));
+      DONE;
+    }
+
   rtx vr = gen_reg_rtx (V2DImode), op1 = operands[1];
   rtvec v = rtvec_alloc (2);
 
-- 
2.48.1

Reply via email to