-
Notifications
You must be signed in to change notification settings - Fork 11.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV][MC] Add support for experimental Zimop extension #75182
Conversation
This implements experimental support for the Zimop extension as specified here: https://github.com/riscv/riscv-isa-manual/blob/main/src/zimop.adoc. This change adds only assembly support.
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang @llvm/pr-subscribers-backend-risc-v Author: Jivan Hakobyan (JivanH) ChangesThis implements experimental support for the Zimop extension as specified here: https://github.com/riscv/riscv-isa-manual/blob/main/src/zimop.adoc. This change adds only assembly support. Full diff: https://github.com/llvm/llvm-project/pull/75182.diff 10 Files Affected:
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 65dd0d83448ed..bd2f81fba186d 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -208,6 +208,9 @@ The primary goal of experimental support is to assist in the process of ratifica
``experimental-zvbb``, ``experimental-zvbc``, ``experimental-zvkb``, ``experimental-zvkg``, ``experimental-zvkn``, ``experimental-zvknc``, ``experimental-zvkned``, ``experimental-zvkng``, ``experimental-zvknha``, ``experimental-zvknhb``, ``experimental-zvks``, ``experimental-zvksc``, ``experimental-zvksed``, ``experimental-zvksg``, ``experimental-zvksh``, ``experimental-zvkt``
LLVM implements the `1.0.0-rc2 specification <https://github.com/riscv/riscv-crypto/releases/download/v/riscv-crypto-spec-vector.pdf>`__. Note that current vector crypto extension version can be found in: <https://github.com/riscv/riscv-crypto>.
+``experimental-zimop``
+ LLVM implements the `v0.1 proposed specification <https://github.com/riscv/riscv-isa-manual/blob/main/src/zimop.adoc>`__.
+
To use an experimental extension from `clang`, you must add `-menable-experimental-extensions` to the command line, and specify the exact version of the experimental extension you are using. To use an experimental extension with LLVM's internal developer tools (e.g. `llc`, `llvm-objdump`, `llvm-mc`), you must prefix the extension name with `experimental-`. Note that you don't need to specify the version with internal tools, and shouldn't include the `experimental-` prefix with `clang`.
Vendor Extensions
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 20c6a525a86ba..fcb11c8c51398 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -108,6 +108,29 @@ let TargetPrefix = "riscv" in {
def int_riscv_xperm8 : BitManipGPRGPRIntrinsics;
} // TargetPrefix = "riscv"
+//===----------------------------------------------------------------------===//
+// May-Be-Operations
+
+let TargetPrefix = "riscv" in {
+
+ class MOPGPRIntrinsics
+ : DefaultAttrsIntrinsic<[llvm_any_ty],
+ [LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable]>;
+ class MOPGPRGPRIntrinsics
+ : DefaultAttrsIntrinsic<[llvm_any_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable]>;
+
+ // Zimop
+ foreach i = 0...31 in {
+ def int_riscv_mopr#i : MOPGPRIntrinsics;
+ }
+ foreach i = 0...7 in {
+ def int_riscv_moprr#i : MOPGPRGPRIntrinsics;
+ }
+} // TargetPrefix = "riscv"
+
//===----------------------------------------------------------------------===//
// Vectors
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 6322748430063..1b303ba1e9431 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -177,6 +177,8 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
{"zicfilp", RISCVExtensionVersion{0, 2}},
{"zicond", RISCVExtensionVersion{1, 0}},
+ {"zimop", RISCVExtensionVersion{0, 1}},
+
{"ztso", RISCVExtensionVersion{0, 1}},
{"zvbb", RISCVExtensionVersion{1, 0}},
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 294927aecb94b..5b642090b7b9e 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -687,6 +687,11 @@ def HasStdExtZicond : Predicate<"Subtarget->hasStdExtZicond()">,
AssemblerPredicate<(all_of FeatureStdExtZicond),
"'Zicond' (Integer Conditional Operations)">;
+def FeatureStdExtZimop : SubtargetFeature<"experimental-zimop", "HasStdExtZimop", "true",
+ "'Zimop' (May-Be-Operations)">;
+def HasStdExtZimop : Predicate<"Subtarget->hasStdExtZimop()">,
+ AssemblerPredicate<(all_of FeatureStdExtZimop),
+ "'Zimop' (May-Be-Operations)">;
def FeatureStdExtSmaia
: SubtargetFeature<"smaia", "HasStdExtSmaia", "true",
"'Smaia' (Smaia encompasses all added CSRs and all "
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index e80ba26800a13..cb68752210d54 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -401,6 +401,27 @@ class RVInstIUnary<bits<12> imm12, bits<3> funct3, RISCVOpcode opcode,
let Inst{31-20} = imm12;
}
+class RVInstIMopr<bits<7> imm7, bits<5> imm5, bits<3> funct3, RISCVOpcode opcode,
+ dag outs, dag ins, string opcodestr, string argstr>
+ : RVInstIBase<funct3, opcode, outs, ins, opcodestr, argstr> {
+ let Inst{31} = imm7{6};
+ let Inst{30} = imm5{4};
+ let Inst{29-28} = imm7{5-4};
+ let Inst{27-26} = imm5{3-2};
+ let Inst{25-22} = imm7{3-0};
+ let Inst{21-20} = imm5{1-0};
+}
+
+class RVInstRMoprr<bits<4> imm4, bits<3> imm3, bits<3> funct3, RISCVOpcode opcode,
+ dag outs, dag ins, string opcodestr, string argstr>
+ : RVInstRBase<funct3, opcode, outs, ins, opcodestr, argstr> {
+ let Inst{31} = imm4{3};
+ let Inst{30} = imm3{2};
+ let Inst{29-28} = imm4{2-1};
+ let Inst{27-26} = imm3{1-0};
+ let Inst{25} = imm4{0};
+}
+
class RVInstS<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatS> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index edc08187d8f77..bf1ed70547444 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -597,6 +597,16 @@ class Priv_rr<string opcodestr, bits<7> funct7>
let rd = 0;
}
+class RVMopr<bits<7> imm7, bits<5> imm5, bits<3> funct3,
+ RISCVOpcode opcode, string opcodestr>
+ : RVInstIMopr<imm7, imm5, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1),
+ opcodestr, "$rd, $rs1">;
+
+class RVMoprr<bits<4> imm4, bits<3> imm3, bits<3> funct3,
+ RISCVOpcode opcode, string opcodestr>
+ : RVInstRMoprr<imm4, imm3, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
+ opcodestr, "$rd, $rs1, $rs2">;
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -786,6 +796,22 @@ def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">,
} // IsSignExtendingOpW = 1
} // Predicates = [IsRV64]
+// Zimop instructions
+
+foreach i = 0...31 in {
+ let Predicates = [HasStdExtZimop] in {
+ def MOPR#i : RVMopr<0b1000111, i, 0b100, OPC_SYSTEM, "mop.r."#i>,
+ Sched<[]>;
+ } // Predicates = [HasStdExtZimop]
+}
+
+foreach i = 0...7 in {
+ let Predicates = [HasStdExtZimop] in {
+ def MOPRR#i : RVMoprr<0b1001, i, 0b100, OPC_SYSTEM, "mop.rr."#i>,
+ Sched<[]>;
+ } // Predicates = [HasStdExtZimop]
+}
+
//===----------------------------------------------------------------------===//
// Privileged instructions
//===----------------------------------------------------------------------===//
@@ -1551,6 +1577,25 @@ let Predicates = [HasStdExtC, OptForMinSize] in {
def : SelectCompressOpt<SETNE>;
}
+// Zimop instructions
+foreach i = 0...31 in {
+ defvar moprx = !cast<Instruction>("MOPR"#i);
+ defvar riscv_moprx = !cast<Intrinsic>("int_riscv_mopr"#i);
+ let Predicates = [HasStdExtZimop] in {
+ def : Pat<(XLenVT (riscv_moprx (XLenVT GPR:$rs1))),
+ (moprx GPR:$rs1)>;
+ } // Predicates = [HasStdExtZimop]
+}
+
+foreach i = 0...7 in {
+ defvar moprrx = !cast<Instruction>("MOPRR"#i);
+ defvar riscv_moprrx = !cast<Intrinsic>("int_riscv_moprr"#i);
+ let Predicates = [HasStdExtZimop] in {
+ def : Pat<(XLenVT (riscv_moprrx (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))),
+ (moprrx GPR:$rs1, GPR:$rs2)>;
+ } // Predicates = [HasStdExtZimop]
+}
+
/// Branches and jumps
// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 030ae06af6d28..0afe9b9f916d8 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -83,6 +83,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+zve32x -mattr=+experimental-zvksh %s -o - | FileCheck --check-prefix=RV32ZVKSH %s
; RUN: llc -mtriple=riscv32 -mattr=+zve32x -mattr=+experimental-zvkt %s -o - | FileCheck --check-prefix=RV32ZVKT %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicond %s -o - | FileCheck --check-prefix=RV32ZICOND %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zimop %s -o - | FileCheck --check-prefix=RV32ZIMOP %s
; RUN: llc -mtriple=riscv32 -mattr=+smaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SMAIA %s
; RUN: llc -mtriple=riscv32 -mattr=+ssaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SSAIA %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV32ZFBFMIN %s
@@ -173,6 +174,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+zve32x -mattr=+experimental-zvksh %s -o - | FileCheck --check-prefix=RV64ZVKSH %s
; RUN: llc -mtriple=riscv64 -mattr=+zve32x -mattr=+experimental-zvkt %s -o - | FileCheck --check-prefix=RV64ZVKT %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicond %s -o - | FileCheck --check-prefix=RV64ZICOND %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zimop %s -o - | FileCheck --check-prefix=RV64ZIMOP %s
; RUN: llc -mtriple=riscv64 -mattr=+smaia %s -o - | FileCheck --check-prefixes=CHECK,RV64SMAIA %s
; RUN: llc -mtriple=riscv64 -mattr=+ssaia %s -o - | FileCheck --check-prefixes=CHECK,RV64SSAIA %s
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV64ZFBFMIN %s
@@ -265,6 +267,7 @@
; RV32ZVKSH: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvksh1p0_zvl32b1p0"
; RV32ZVKT: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvkt1p0_zvl32b1p0"
; RV32ZICOND: .attribute 5, "rv32i2p1_zicond1p0"
+; RV32ZIMOP: .attribute 5, "rv32i2p1_zimop0p1"
; RV32SMAIA: .attribute 5, "rv32i2p1_smaia1p0"
; RV32SSAIA: .attribute 5, "rv32i2p1_ssaia1p0"
; RV32ZFBFMIN: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin0p8"
@@ -354,6 +357,7 @@
; RV64ZVKSH: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvksh1p0_zvl32b1p0"
; RV64ZVKT: .attribute 5, "rv64i2p1_zicsr2p0_zve32x1p0_zvkt1p0_zvl32b1p0"
; RV64ZICOND: .attribute 5, "rv64i2p1_zicond1p0"
+; RV64ZIMOP: .attribute 5, "rv64i2p1_zimop0p1"
; RV64SMAIA: .attribute 5, "rv64i2p1_smaia1p0"
; RV64SSAIA: .attribute 5, "rv64i2p1_ssaia1p0"
; RV64ZFBFMIN: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin0p8"
diff --git a/llvm/test/MC/RISCV/rv32zimop-invalid.s b/llvm/test/MC/RISCV/rv32zimop-invalid.s
new file mode 100644
index 0000000000000..e6c3adc4cd309
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zimop-invalid.s
@@ -0,0 +1,6 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-zimop < %s 2>&1 | FileCheck %s
+
+# Too few operands
+mop.r.0 t0 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
+# Too few operands
+mop.rr.0 t0, t1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
diff --git a/llvm/test/MC/RISCV/rvzimop-valid.s b/llvm/test/MC/RISCV/rvzimop-valid.s
new file mode 100644
index 0000000000000..1552936629902
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvzimop-valid.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-zimop -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+experimental-zimop -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-zimop < %s \
+# RUN: | llvm-objdump --mattr=+experimental-zimop -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-zimop < %s \
+# RUN: | llvm-objdump --mattr=+experimental-zimop -d -r - \
+# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: mop.r.0 a2, a1
+# CHECK-ASM: encoding: [0x73,0xc6,0xc5,0x81]
+mop.r.0 a2, a1
+
+# CHECK-ASM-AND-OBJ: mop.r.31 a2, a1
+# CHECK-ASM: encoding: [0x73,0xc6,0xf5,0xcd]
+mop.r.31 a2, a1
+
+# CHECK-ASM-AND-OBJ: mop.rr.0 a3, a2, a1
+# CHECK-ASM: encoding: [0xf3,0x46,0xb6,0x82]
+mop.rr.0 a3, a2, a1
+
+# CHECK-ASM-AND-OBJ: mop.rr.7 a3, a2, a1
+# CHECK-ASM: encoding: [0xf3,0x46,0xb6,0xce]
+mop.rr.7 a3, a2, a1
\ No newline at end of file
diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp
index 549964eed5551..bd41fa2338739 100644
--- a/llvm/unittests/Support/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp
@@ -738,6 +738,7 @@ R"(All available -march extensions for RISC-V
Experimental extensions
zicfilp 0.2 This is a long dummy description
zicond 1.0
+ zimop 0.1
zacas 1.0
zfbfmin 0.8
ztso 0.1
|
@dtcxzyw @wangpc-pp @topperc |
Turns out, new contrbiutor association is in fact `NONE`. Example: #75182 ``` Run echo "$AUTHOR_ASSOCIATION" NONE ```
We already have |
Right, but won't users be programming to each of the extensions that redefine them rather than some generic interface? We don't have builtins/intrinsics for all of the HINT encodings that can redefined. |
@@ -108,6 +108,29 @@ let TargetPrefix = "riscv" in { | |||
def int_riscv_xperm8 : BitManipGPRGPRIntrinsics; | |||
} // TargetPrefix = "riscv" | |||
|
|||
//===----------------------------------------------------------------------===// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't part of MC and should not be in this patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Yeah, I agree with you. |
I just read back over my original question. I'm not sure it was clear that I was asking about the need for intrinsics. I don't object to assembler support and inline assembly is always an option. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
This implements experimental support for the Zimop extension as specified here: https://github.com/riscv/riscv-isa-manual/blob/main/src/zimop.adoc.
This change adds only assembly support.