From c8c9023284759150fa1ca70442d8c2c6d33ba040 Mon Sep 17 00:00:00 2001
From: Qihan Cai <qcai8733@uni.sydney.edu.au>
Date: Fri, 26 May 2023 12:46:35 +1000
Subject: [PATCH] [RISCV][CodeGen] Implement XcvMac Intrinsics

Implement XcvMac intrinsics in CodeGen.

Spec: https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md
---
 llvm/include/llvm/IR/IntrinsicsRISCV.td      |  33 +++
 llvm/lib/Support/RISCVISAInfo.cpp            |   1 +
 llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td |  31 ++-
 llvm/test/CodeGen/RISCV/corev/mac.ll         | 208 +++++++++++++++++++
 4 files changed, 272 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 5ced421c0a44..5e0b91da5661 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -1735,4 +1735,37 @@ def int_riscv_cv_bitmanip_ror : ScalarCoreVBitManipGprGprIntrinsic;
 def int_riscv_cv_bitmanip_bitrev
   : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
               [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;
+
+class ScalarCoreVMacGprGprGprIntrinsic
+  : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+              [IntrNoMem, IntrWillReturn, IntrSpeculatable]>;
+
+class ScalarCoreVMacGprGPRImmIntrinsic
+    : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+                [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<2>>]>;
+
+class ScalarCoreVMacGprGprGprImmIntrinsic
+  : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
+              [IntrNoMem, IntrWillReturn, IntrSpeculatable, ImmArg<ArgIndex<3>>]>;
+
+def int_riscv_cv_mac_mac : ScalarCoreVMacGprGprGprIntrinsic;
+def int_riscv_cv_mac_msu : ScalarCoreVMacGprGprGprIntrinsic;
+
+def int_riscv_cv_mac_mulun    : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulhhun  : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulsn    : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulhhsn  : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulurn   : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulhhurn : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulsrn   : ScalarCoreVMacGprGPRImmIntrinsic;
+def int_riscv_cv_mac_mulhhsrn : ScalarCoreVMacGprGPRImmIntrinsic;
+
+def int_riscv_cv_mac_macun    : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_machhun  : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_macsn    : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_machhsn  : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_macurn   : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_machhurn : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_macsrn   : ScalarCoreVMacGprGprGprImmIntrinsic;
+def int_riscv_cv_mac_machhsrn : ScalarCoreVMacGprGprGprImmIntrinsic;
 } // TargetPrefix = "riscv"
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 92616d467174..d30ca58acbd8 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -107,6 +107,7 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
     {"xcvsimd", RISCVExtensionVersion{1, 0}},
     {"xcvbitmanip", RISCVExtensionVersion{1, 0}},
     {"xcvbi", RISCVExtensionVersion{1, 0}},
+    {"xcvmac", RISCVExtensionVersion{1, 0}}
 };
 
 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td
index d3edf15729a0..2f65ca68aea2 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td
@@ -707,6 +707,15 @@ def trailing1sPlus1 : SDNodeXForm<imm, [{
 // Patterns for MAC operations
 //===----------------------------------------------------------------------===//
 
+class PatCoreVMacGprGprGpr <string intr, string asm>
+  : Pat<(!cast<Intrinsic>("int_riscv_cv_mac_" # intr) GPR:$rs1, GPR:$rs2, GPR:$rd),
+        (!cast<RVInst>("CV_" # asm) GPR:$rd, GPR:$rs1, GPR:$rs2)>;
+class PatCoreVMacGprGprGprUimm5 <string intr, string asm>
+  : Pat<(!cast<Intrinsic>("int_riscv_cv_mac_" # intr) GPR:$rs1, GPR:$rs2, GPR:$rd, cv_tuimm5:$imm5),
+        (!cast<RVInst>("CV_" # asm) GPR:$rd, GPR:$rs1, GPR:$rs2, cv_tuimm5:$imm5)>;
+class PatCoreVMacGprGprUimm5 <string intr, string asm>
+  : Pat<(!cast<Intrinsic>("int_riscv_cv_mac_" # intr) GPR:$rs1, GPR:$rs2, cv_tuimm5:$imm5),
+        (!cast<RVInst>("CV_" # asm) GPR:$rs1, GPR:$rs2, cv_tuimm5:$imm5)>;
 
 let Predicates = [HasExtXcvmac] in {
 
@@ -759,6 +768,26 @@ let Predicates = [HasExtXcvmac] in {
   def : Pat<(ushiftRound (machhu GPR:$rd, GPR:$rs1, GPR:$rs2), uimm5:$imm5),
             (CV_MACHHURN GPR:$rd, GPR:$rs1, GPR:$rs2, uimm5:$imm5)>;
 
+  def : PatCoreVMacGprGprGpr<"mac", "MAC">;
+  def : PatCoreVMacGprGprGpr<"msu", "MSU">;
+
+  def : PatCoreVMacGprGprUimm5<"mulun", "MULUN">;
+  def : PatCoreVMacGprGprUimm5<"mulhhun", "MULHHUN">;
+  def : PatCoreVMacGprGprUimm5<"mulsn", "MULSN">;
+  def : PatCoreVMacGprGprUimm5<"mulhhsn", "MULHHSN">;
+  def : PatCoreVMacGprGprUimm5<"mulurn", "MULURN">;
+  def : PatCoreVMacGprGprUimm5<"mulhhurn", "MULHHURN">;
+  def : PatCoreVMacGprGprUimm5<"mulsrn", "MULSRN">;
+  def : PatCoreVMacGprGprUimm5<"mulhhsrn", "MULHHSRN">;
+
+  def : PatCoreVMacGprGprGprUimm5<"macun", "MACUN">;
+  def : PatCoreVMacGprGprGprUimm5<"machhun", "MACHHUN">;
+  def : PatCoreVMacGprGprGprUimm5<"macsn", "MACSN">;
+  def : PatCoreVMacGprGprGprUimm5<"machhsn", "MACHHSN">;
+  def : PatCoreVMacGprGprGprUimm5<"macurn", "MACURN">;
+  def : PatCoreVMacGprGprGprUimm5<"machhurn", "MACHHURN">;
+  def : PatCoreVMacGprGprGprUimm5<"macsrn", "MACSRN">;
+  def : PatCoreVMacGprGprGprUimm5<"machhsrn", "MACHHSRN">;
 }
 
 //===----------------------------------------------------------------------===//
@@ -887,7 +916,7 @@ let Predicates = [HasExtXcvmem] in {
 //===----------------------------------------------------------------------===//
 
 class PatCorevGprGpr <string intr, string asm> :
-  PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # intr), 
+  PatGprGpr<!cast<Intrinsic>("int_riscv_cv_simd_" # intr),
             !cast<RVInst>("CV_" # asm)>;
 
 // Note that rd is the last argument
diff --git a/llvm/test/CodeGen/RISCV/corev/mac.ll b/llvm/test/CodeGen/RISCV/corev/mac.ll
index 334e8ad0e1ef..430437f00780 100644
--- a/llvm/test/CodeGen/RISCV/corev/mac.ll
+++ b/llvm/test/CodeGen/RISCV/corev/mac.ll
@@ -306,3 +306,211 @@ define i32 @machhuRN(i32 %a, i32 %b, i32 %c) {
   %6 = lshr i32 %5, 5
   ret i32 %6
 }
+
+declare i32 @llvm.riscv.cv.mac.mac(i32, i32, i32)
+
+define i32 @test.mac(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.mac:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mac a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mac(i32 %a, i32 %b, i32 %c)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.msu(i32, i32, i32)
+
+define i32 @test.msu(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.msu:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.msu a2, a0, a1
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.msu(i32 %a, i32 %b, i32 %c)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulun(i32, i32, i32)
+
+define i32 @test.mulun(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulun:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulun a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulun(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulhhun(i32, i32, i32)
+
+define i32 @test.mulhhun(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulhhun:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulhhun a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulhhun(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulsn(i32, i32, i32)
+
+define i32 @test.mulsn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulsn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulsn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulsn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulhhsn(i32, i32, i32)
+
+define i32 @test.mulhhsn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulhhsn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulhhsn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulhhsn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulurn(i32, i32, i32)
+
+define i32 @test.mulurn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulurn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulurn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulurn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulhhurn(i32, i32, i32)
+
+define i32 @test.mulhhurn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulhhurn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulhhurn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulhhurn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulsrn(i32, i32, i32)
+
+define i32 @test.mulsrn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulsrn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulsrn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulsrn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.mulhhsrn(i32, i32, i32)
+
+define i32 @test.mulhhsrn(i32 %a, i32 %b) {
+; CHECK-LABEL: test.mulhhsrn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.mulhhsrn a0, a0, a1, 5
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.mulhhsrn(i32 %a, i32 %b, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.macun(i32, i32, i32, i32)
+
+define i32 @test.macun(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.macun:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.macun a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.macun(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.machhun(i32, i32, i32, i32)
+
+define i32 @test.machhun(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.machhun:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.machhun a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.machhun(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.macsn(i32, i32, i32, i32)
+
+define i32 @test.macsn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.macsn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.macsn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.macsn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.machhsn(i32, i32, i32, i32)
+
+define i32 @test.machhsn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.machhsn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.machhsn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.machhsn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.macurn(i32, i32, i32, i32)
+
+define i32 @test.macurn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.macurn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.macurn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.macurn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.machhurn(i32, i32, i32, i32)
+
+define i32 @test.machhurn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.machhurn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.machhurn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.machhurn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.macsrn(i32, i32, i32, i32)
+
+define i32 @test.macsrn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.macsrn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.macsrn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.macsrn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
+
+declare i32 @llvm.riscv.cv.mac.machhsrn(i32, i32, i32, i32)
+
+define i32 @test.machhsrn(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: test.machhsrn:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    cv.machhsrn a2, a0, a1, 5
+; CHECK-NEXT:    mv a0, a2
+; CHECK-NEXT:    ret
+  %1 = call i32 @llvm.riscv.cv.mac.machhsrn(i32 %a, i32 %b, i32 %c, i32 5)
+  ret i32 %1
+}
-- 
GitLab