[RISCV] Add vendor-defined XTheadSync (Multi-core synchronization) extension
authorManolis Tsamis <manolis.tsamis@vrull.eu>
Wed, 22 Feb 2023 09:58:50 +0000 (10:58 +0100)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Wed, 22 Feb 2023 10:15:40 +0000 (11:15 +0100)
The vendor-defined XTheadSync (no comparable standard extension exists
at the time of writing) extension adds multi-core synchronization
instructions.

It is supported by the C9xx cores (e.g., found in the wild in the
Allwinner D1) by Alibaba T-Head.

The current (as of this commit) public documentation for this
extension is available at:
  https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf

Support for these instructions has already landed in GNU Binutils:
  https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=547c18d9bb95571261dbd17f4767194037eb82bd

Depends on D144496

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D144501

llvm/docs/RISCVUsage.rst
llvm/docs/ReleaseNotes.rst
llvm/lib/Support/RISCVISAInfo.cpp
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
llvm/lib/Target/RISCV/RISCVFeatures.td
llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
llvm/test/CodeGen/RISCV/attributes.ll
llvm/test/MC/RISCV/xtheadsync-invalid.s [new file with mode: 0644]
llvm/test/MC/RISCV/xtheadsync-valid.s [new file with mode: 0644]

index 4e17ecc..5751211 100644 (file)
@@ -195,6 +195,9 @@ The current vendor extensions supported are:
 ``XTHeadMemPair``
   LLVM implements `the THeadMemPair (two-GPR memory operations) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_  by T-HEAD of Alibaba.  Instructions are prefixed with `th.` as described in the specification.
 
+``XTHeadSync``
+  LLVM implements `the THeadSync (multi-core synchronization instructions) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_  by T-HEAD of Alibaba.  Instructions are prefixed with `th.` as described in the specification.
+
 ``XTHeadVdot``
   LLVM implements `version 1.0.0 of the THeadV-family custom instructions specification <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.0/xthead-2022-12-04-2.2.0.pdf>`_ by T-HEAD of Alibaba.  All instructions are prefixed with `th.` as described in the specification, and the riscv-toolchain-convention document linked above.
 
index 981f57e..6773424 100644 (file)
@@ -116,6 +116,7 @@ Changes to the RISC-V Backend
   extension disassembler/assembler.
 * Support for the now-ratified Zawrs extension is no longer experimental.
 * Adds support for the vendor-defined XTHeadCmo (cache management operations) extension.
+* Adds support for the vendor-defined XTHeadSync (multi-core synchronization instructions) extension.
 
 Changes to the WebAssembly Backend
 ----------------------------------
index bffd322..e051585 100644 (file)
@@ -119,6 +119,7 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
     {"xtheadcmo", RISCVExtensionVersion{1, 0}},
     {"xtheadmac", RISCVExtensionVersion{1, 0}},
     {"xtheadmempair", RISCVExtensionVersion{1, 0}},
+    {"xtheadsync", RISCVExtensionVersion{1, 0}},
     {"xtheadvdot", RISCVExtensionVersion{1, 0}},
     {"xventanacondops", RISCVExtensionVersion{1, 0}},
 };
index d7c7fcc..e278edc 100644 (file)
@@ -541,6 +541,13 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
       if (Result != MCDisassembler::Fail)
         return Result;
     }
+    if (STI.hasFeature(RISCV::FeatureVendorXTHeadSync)) {
+      LLVM_DEBUG(dbgs() << "Trying XTHeadSync custom opcode table:\n");
+      Result = decodeInstruction(DecoderTableTHeadSync32, MI, Insn, Address,
+                                 this, STI);
+      if (Result != MCDisassembler::Fail)
+        return Result;
+    }
     if (STI.hasFeature(RISCV::FeatureVendorXTHeadVdot)) {
       LLVM_DEBUG(dbgs() << "Trying XTHeadVdot custom opcode table:\n");
       Result =
index d8c52b3..5107f0d 100644 (file)
@@ -526,6 +526,13 @@ def HasVendorXTHeadMemPair : Predicate<"Subtarget->hasVendorXTHeadMemPair()">,
                                     AssemblerPredicate<(all_of FeatureVendorXTHeadMemPair),
                                     "'xtheadmempair' (T-Head two-GPR Memory Operations)">;
 
+def FeatureVendorXTHeadSync
+    : SubtargetFeature<"xtheadsync", "HasVendorXTHeadSync", "true",
+                       "'xtheadsync' (T-Head multicore synchronization instructions)">;
+def HasVendorXTHeadSync : Predicate<"Subtarget->hasVendorXTHeadSync()">,
+                                    AssemblerPredicate<(all_of FeatureVendorXTHeadSync),
+                                    "'xtheadsync' (T-Head multicore synchronization instructions)">;
+
 def FeatureVendorXTHeadVdot
     : SubtargetFeature<"xtheadvdot", "HasVendorXTHeadVdot", "true",
                        "'xtheadvdot' (T-Head Vector Extensions for Dot)",
index c191ef9..3ff9978 100644 (file)
@@ -150,6 +150,13 @@ class THCacheInst_r<bits<5> funct5, string opcodestr>
 }
 
 let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+class THCacheInst_rr<bits<7> funct7, string opcodestr>
+    : RVInstR<funct7, 0, OPC_CUSTOM_0, (outs), (ins GPR:$rs1, GPR:$rs2),
+      opcodestr, "$rs1, $rs2"> {
+  let rd = 0;
+}
+
+let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
 class THCacheInst_void<bits<5> funct5, string opcodestr>
     : RVInstR<0b0000000, 0, OPC_CUSTOM_0, (outs), (ins), opcodestr, ""> {
   let rd = 0;
@@ -523,3 +530,11 @@ def TH_L2CACHE_CALL  : THCacheInst_void<0b10101, "th.l2cache.call">;
 def TH_L2CACHE_IALL  : THCacheInst_void<0b10110, "th.l2cache.iall">;
 def TH_L2CACHE_CIALL : THCacheInst_void<0b10111, "th.l2cache.ciall">;
 }
+
+let Predicates = [HasVendorXTHeadSync], DecoderNamespace = "THeadSync" in {
+def TH_SFENCE_VMAS : THCacheInst_rr<0b0000010, "th.sfence.vmas">;
+def TH_SYNC        : THCacheInst_void<0b11000, "th.sync">;
+def TH_SYNC_S      : THCacheInst_void<0b11001, "th.sync.s">;
+def TH_SYNC_I      : THCacheInst_void<0b11010, "th.sync.i">;
+def TH_SYNC_IS     : THCacheInst_void<0b11011, "th.sync.is">;
+}
index bd1467e..352b73f 100644 (file)
@@ -44,6 +44,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadcmo %s -o - | FileCheck --check-prefix=RV32XTHEADCMO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV32XTHEADMAC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV32XTHEADMEMPAIR %s
+; RUN: llc -mtriple=riscv32 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV32XTHEADSYNC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zca %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCA %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcb %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCB %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zcd %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCD %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadcmo %s -o - | FileCheck --check-prefix=RV64XTHEADCMO %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADMAC %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV64XTHEADMEMPAIR %s
+; RUN: llc -mtriple=riscv64 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV64XTHEADSYNC %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadvdot %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADVDOT %s
 ; RUN: llc -mtriple=riscv64 -mattr=+zawrs %s -o - | FileCheck --check-prefixes=CHECK,RV64ZAWRS %s
 ; RUN: llc -mtriple=riscv64 -mattr=+experimental-ztso %s -o - | FileCheck --check-prefixes=CHECK,RV64ZTSO %s
 ; RV32XTHEADCMO: .attribute 5, "rv32i2p0_xtheadcmo1p0"
 ; RV32XTHEADMAC: .attribute 5, "rv32i2p0_xtheadmac1p0"
 ; RV32XTHEADMEMPAIR: .attribute 5, "rv32i2p0_xtheadmempair1p0"
+; RV32XTHEADSYNC: .attribute 5, "rv32i2p0_xtheadsync1p0"
 ; RV32ZCA: .attribute 5, "rv32i2p0_zca1p0"
 ; RV32ZCB: .attribute 5, "rv32i2p0_zca1p0_zcb1p0"
 ; RV32ZCD: .attribute 5, "rv32i2p0_zcd1p0"
 ; RV64XTHEADCMO: .attribute 5, "rv64i2p0_xtheadcmo1p0"
 ; RV64XTHEADMAC: .attribute 5, "rv64i2p0_xtheadmac1p0"
 ; RV64XTHEADMEMPAIR: .attribute 5, "rv64i2p0_xtheadmempair1p0"
+; RV64XTHEADSYNC: .attribute 5, "rv64i2p0_xtheadsync1p0"
 ; RV64XTHEADVDOT: .attribute 5, "rv64i2p0_f2p0_d2p0_v1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xtheadvdot1p0"
 ; RV64ZTSO: .attribute 5, "rv64i2p0_ztso0p1"
 ; RV64ZCA: .attribute 5, "rv64i2p0_zca1p0"
diff --git a/llvm/test/MC/RISCV/xtheadsync-invalid.s b/llvm/test/MC/RISCV/xtheadsync-invalid.s
new file mode 100644 (file)
index 0000000..cb54da0
--- /dev/null
@@ -0,0 +1,8 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+xtheadsync < %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple riscv64 -mattr=+xtheadsync < %s 2>&1 | FileCheck %s
+
+th.sfence.vmas t0 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+th.sync t0 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+th.sync.s t0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+th.sync.i t0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
+th.sync.is t0 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/xtheadsync-valid.s b/llvm/test/MC/RISCV/xtheadsync-valid.s
new file mode 100644 (file)
index 0000000..da2ee8a
--- /dev/null
@@ -0,0 +1,30 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+xtheadsync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+xtheadsync < %s \
+# RUN:     | llvm-objdump --mattr=+xtheadsync -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+xtheadsync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+xtheadsync < %s \
+# RUN:     | llvm-objdump --mattr=+xtheadsync -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: th.sfence.vmas a0, a1
+# CHECK-ASM: encoding: [0x0b,0x00,0xb5,0x04]
+th.sfence.vmas a0, a1
+
+# CHECK-ASM-AND-OBJ: th.sync
+# CHECK-ASM: encoding: [0x0b,0x00,0x80,0x01]
+th.sync
+
+# CHECK-ASM-AND-OBJ: th.sync.i
+# CHECK-ASM: encoding: [0x0b,0x00,0xa0,0x01]
+th.sync.i
+
+# CHECK-ASM-AND-OBJ: th.sync.is
+# CHECK-ASM: encoding: [0x0b,0x00,0xb0,0x01]
+th.sync.is
+
+# CHECK-ASM-AND-OBJ: th.sync.s
+# CHECK-ASM: encoding: [0x0b,0x00,0x90,0x01]
+th.sync.s