Skip to content
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

[MLIR][VCIX] Support VCIX intrinsics in LLVMIR dialect #75875

Merged
merged 5 commits into from
Feb 7, 2024

Conversation

nikolaypanchenko
Copy link
Contributor

The changeset extends LLVMIR intrinsics with VCIX intrinsics.
The VCIX intrinsics allow MLIR users to interact with RISC-V co-processors that are compatible with XSfvcp extension

Source: https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software

@llvmbot
Copy link
Collaborator

llvmbot commented Dec 18, 2023

@llvm/pr-subscribers-mlir-core

@llvm/pr-subscribers-mlir

Author: Kolya Panchenko (nikolaypanchenko)

Changes

The changeset extends LLVMIR intrinsics with VCIX intrinsics.
The VCIX intrinsics allow MLIR users to interact with RISC-V co-processors that are compatible with XSfvcp extension

Source: https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software


Patch is 26.93 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/75875.diff

13 Files Affected:

  • (modified) mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt (+8)
  • (added) mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h (+40)
  • (added) mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td (+112)
  • (modified) mlir/include/mlir/Target/LLVMIR/Dialect/All.h (+2)
  • (added) mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h (+31)
  • (modified) mlir/lib/Dialect/LLVMIR/CMakeLists.txt (+22)
  • (added) mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp (+55)
  • (modified) mlir/lib/Target/LLVMIR/CMakeLists.txt (+1)
  • (modified) mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt (+1)
  • (added) mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt (+16)
  • (added) mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp (+89)
  • (added) mlir/test/Target/LLVMIR/vcix-rv32.mlir (+73)
  • (added) mlir/test/Target/LLVMIR/vcix-rv64.mlir (+74)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 8e41fcc05a161e..4c8078c545c735 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -71,3 +71,11 @@ mlir_tablegen(ROCDLConversions.inc -gen-llvmir-conversions)
 mlir_tablegen(ROCDLOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=rocdl)
 mlir_tablegen(ROCDLOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=rocdl)
 add_public_tablegen_target(MLIRROCDLConversionsIncGen)
+
+add_mlir_dialect(VCIXOps vcix)
+add_mlir_doc(VCIXOps RVCIXDialect Dialects/ -gen-dialect-doc -dialect=rocdl)
+set(LLVM_TARGET_DEFINITIONS VCIXOps.td)
+mlir_tablegen(VCIXConversions.inc -gen-llvmir-conversions)
+mlir_tablegen(VCIXOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=rocdl)
+mlir_tablegen(VCIXOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=rocdl)
+add_public_tablegen_target(MLIRVCIXConversionsIncGen)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h b/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h
new file mode 100644
index 00000000000000..3c911d6bc8677b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h
@@ -0,0 +1,40 @@
+//===- VCIXDialect.h - MLIR VCIX IR dialect -------------------*- C++ ---*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The file defines the basic operations for the VCIX dialect.
+//
+// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+// to extend application processors with custom coprocessors and
+// variable-latency arithmetic units. The interface offers throughput comparable
+// to that of standard RISC-V vector instructions. To accelerate performance,
+// system designers may use VCIX as a low-latency, high-throughput interface to
+// a coprocessor
+//
+// https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_
+#define MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_
+
+#include "mlir/Bytecode/BytecodeOpInterface.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+///// Ops /////
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOps.h.inc"
+
+#include "mlir/Dialect/LLVMIR/VCIXOpsDialect.h.inc"
+
+#endif /* MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_ */
diff --git a/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td b/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td
new file mode 100644
index 00000000000000..3f1fa37988c199
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td
@@ -0,0 +1,112 @@
+//===-- VCIX.td - VCIX dialect operation definitions *- tablegen -*--------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// The file defines the basic operations for the VCIX dialect.
+//
+// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+// to extend application processors with custom coprocessors and
+// variable-latency arithmetic units. The interface offers throughput comparable
+// to that of standard RISC-V vector instructions. To accelerate performance,
+// system designers may use VCIX as a low-latency, high-throughput interface to
+// a coprocessor
+//
+// https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef VCIXIR_OPS
+
+include "mlir/IR/OpBase.td"
+include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+
+//===----------------------------------------------------------------------===//
+// VCIX dialect definition.
+//===----------------------------------------------------------------------===//
+
+def VCIX_Dialect : Dialect {
+  let name = "vcix";
+  let cppNamespace = "::mlir::vcix";
+  let dependentDialects = ["LLVM::LLVMDialect"];
+  let description = [{
+     The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+     to extend application processors with custom coprocessors and
+     variable-latency arithmetic units. The interface offers throughput comparable
+     to that of standard RISC-V vector instructions. To accelerate performance,
+     system designers may use VCIX as a low-latency, high-throughput interface to
+     a coprocessor
+
+     https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+  }];
+}
+
+// Special version for intrinsic version where int attr is zext to i32 or i64
+// depending on xlen of the target
+def VCIX_VectorOrScalar
+    : AnyTypeOf<[LLVM_AnyVector, I<64>, I<32>, F<16>, F<32>, F<64>]>;
+def VCIX_OpcodeAttr : AnyAttrOf<[I32Attr, I64Attr]>;
+def VCIX_Register : AnyTypeOf<[I32, I64]>;
+def VCIX_ImmAttr : AnyAttrOf<[I32Attr, I64Attr]>;
+def VCIX_VL : AnyTypeOf<[I<64>, I<32>]>;
+
+class VCIX_Op<string mnemonic, list<Trait> traits = []>
+    : LLVM_OpBase<VCIX_Dialect, mnemonic, traits> {
+}
+
+def VCIX_BinaryImmOp
+    : VCIX_Op<"v.iv">,
+    Results<(outs LLVM_AnyVector: $res)>,
+    Arguments<(ins VCIX_OpcodeAttr: $opcode,
+                   LLVM_AnyVector: $vs2,
+                   VCIX_ImmAttr: $imm,
+                   VCIX_Register: $rd,
+                   Optional<VCIX_VL>: $vl)> {
+  string llvmBuilder = [{
+      llvm::Type *xlen =getXlenType($opcode, moduleTranslation);
+      llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $opcode, $_location, moduleTranslation);
+      llvm::Value *immConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $imm, $_location, moduleTranslation);
+      VectorType vt = op.getResult().getType().cast<VectorType>();
+      llvm::Value *vl =
+          createVL(builder, $vl, vt, xlen, $_location, moduleTranslation);
+      $res = createIntrinsicCall(
+          builder, llvm::Intrinsic::riscv_sf_vc_v_iv_se,
+          {opcodeConst, $vs2, immConst, vl},
+          {$_resultType, xlen, $vs2->getType(), xlen, xlen});
+  }];
+}
+
+def VCIX_BinaryOp
+    : VCIX_Op<"v.sv">,
+    Results<(outs LLVM_AnyVector: $res)>,
+    Arguments<(ins VCIX_OpcodeAttr: $opcode,
+                   LLVM_AnyVector: $vs2,
+                   VCIX_VectorOrScalar: $op,
+                   Optional<VCIX_VL>: $vl)> {
+  string llvmBuilder = [{
+      llvm::Type *xlen = getXlenType($opcode, moduleTranslation);
+      llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $opcode, $_location, moduleTranslation);
+      llvm::Intrinsic::ID id;
+      llvm::Type *opType = $op->getType();
+      if (opType->isVectorTy()) {
+        id = llvm::Intrinsic::riscv_sf_vc_v_vv_se;
+      } else if (opType->isIntegerTy()) {
+        id = llvm::Intrinsic::riscv_sf_vc_v_xv_se;
+      } else {
+        id = llvm::Intrinsic::riscv_sf_vc_v_fv_se;
+      }
+      VectorType vt = op.getResult().getType().cast<VectorType>();
+      llvm::Value *vl =
+          createVL(builder, $vl, vt, xlen, $_location, moduleTranslation);
+      $res = createIntrinsicCall(
+          builder, id, {opcodeConst, $vs2, $op, vl},
+          {$_resultType, xlen, $vs2->getType(), $op->getType(), xlen});
+  }];
+}
+
+#endif // VCIXIR_OPS
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
index 0b37e23e45118b..de9d5872cc4546 100644
--- a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
@@ -28,6 +28,7 @@
 #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/SPIRV/SPIRVToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/X86Vector/X86VectorToLLVMIRTranslation.h"
 
 namespace mlir {
@@ -48,6 +49,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry &registry) {
   registerOpenMPDialectTranslation(registry);
   registerROCDLDialectTranslation(registry);
   registerSPIRVDialectTranslation(registry);
+  registerVCIXDialectTranslation(registry);
   registerX86VectorDialectTranslation(registry);
 
   // Extension required for translating GPU offloading Ops.
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h b/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h
new file mode 100644
index 00000000000000..d84d03a2257928
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h
@@ -0,0 +1,31 @@
+//===- VCIXToLLVMIRTranslation.h - VCIX to LLVM IR ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides registration calls for VCIX dialect to LLVM IR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
+#define MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
+
+namespace mlir {
+
+class DialectRegistry;
+class MLIRContext;
+
+/// Register the VCIX dialect and the translation from it to the LLVM IR in the
+/// given registry;
+void registerVCIXDialectTranslation(DialectRegistry &registry);
+
+/// Register the VCIX dialect and the translation from it in the registry
+/// associated with the given context.
+void registerVCIXDialectTranslation(MLIRContext &context);
+
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index b00259677697a5..392065b859ee54 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -85,3 +85,25 @@ add_mlir_dialect_library(MLIRROCDLDialect
   MLIRLLVMDialect
   MLIRSideEffectInterfaces
   )
+
+add_mlir_dialect_library(MLIRVCIXDialect
+  IR/VCIXDialect.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
+
+  DEPENDS
+  MLIRGPUCompilationAttrInterfacesIncGen
+  MLIRVCIXOpsIncGen
+  MLIRVCIXConversionsIncGen
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  AsmParser
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRSideEffectInterfaces
+  )
diff --git a/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp
new file mode 100644
index 00000000000000..30ad5bfed1c0b2
--- /dev/null
+++ b/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp
@@ -0,0 +1,55 @@
+//===- VCIXDialect.cpp - MLIR VCIX ops implementation ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VCIX dialect and its operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/LLVMIR/VCIXDialect.h"
+
+#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Operation.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/SourceMgr.h"
+
+using namespace mlir;
+using namespace vcix;
+
+#include "mlir/Dialect/LLVMIR/VCIXOpsDialect.cpp.inc"
+
+//===----------------------------------------------------------------------===//
+// VCIXDialect initialization, type parsing, and registration.
+//===----------------------------------------------------------------------===//
+
+// TODO: This should be the llvm.rocdl dialect once this is supported.
+void VCIXDialect::initialize() {
+  addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/LLVMIR/VCIXOps.cpp.inc"
+      >();
+
+  addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.cpp.inc"
+      >();
+}
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOps.cpp.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.cpp.inc"
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index 94280a2ec9012b..08e10fc3d965bb 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -58,6 +58,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
   MLIROpenACCToLLVMIRTranslation
   MLIROpenMPToLLVMIRTranslation
   MLIRROCDLToLLVMIRTranslation
+  MLIRVCIXToLLVMIRTranslation
   MLIRSPIRVToLLVMIRTranslation
   )
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
index c9d916d8a5d82d..87bed032d2e2da 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
@@ -9,5 +9,6 @@ add_subdirectory(NVVM)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenMP)
 add_subdirectory(ROCDL)
+add_subdirectory(VCIX)
 add_subdirectory(SPIRV)
 add_subdirectory(X86Vector)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt
new file mode 100644
index 00000000000000..d2622af16d9383
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_mlir_translation_library(MLIRVCIXToLLVMIRTranslation
+  VCIXToLLVMIRTranslation.cpp
+
+  DEPENDS
+  MLIRVCIXConversionsIncGen
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRVCIXDialect
+  MLIRSupport
+  MLIRTargetLLVMIRExport
+  )
diff --git a/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp
new file mode 100644
index 00000000000000..40aec7eb406782
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp
@@ -0,0 +1,89 @@
+//===- VCIXToLLVMIRTranslation.cpp - Translate VCIX to LLVM IR ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a translation between the MLIR VCIX dialect and
+// LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
+#include "mlir/Dialect/LLVMIR/VCIXDialect.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace mlir;
+using namespace mlir::LLVM;
+using mlir::LLVM::detail::createIntrinsicCall;
+
+/// Infer XLen type from opcode's type. This is done to avoid passing target
+/// option around
+static llvm::Type *getXlenType(Attribute opcodeAttr,
+                               LLVM::ModuleTranslation &moduleTranslation) {
+  auto intAttr = opcodeAttr.cast<IntegerAttr>();
+  unsigned xlenWidth = intAttr.getType().cast<IntegerType>().getWidth();
+  return llvm::Type::getIntNTy(moduleTranslation.getLLVMContext(), xlenWidth);
+}
+
+/// Return VL for VCIX intrinsic. If vl was previously set, return it,
+/// otherwise construct a constant using fixed vector type
+static llvm::Value *createVL(llvm::IRBuilderBase &builder, llvm::Value *vl,
+                             VectorType vtype, llvm::Type *xlen, Location loc,
+                             LLVM::ModuleTranslation &moduleTranslation) {
+  if (vl) {
+    assert(vtype.isScalable() &&
+           "vl parameter must be set for scalable vectors");
+    return builder.CreateZExtOrTrunc(vl, xlen);
+  }
+
+  assert(vtype.getRank() == 1 && "Only 1-d fixed vectors are supported");
+  return mlir::LLVM::detail::getLLVMConstant(
+      xlen,
+      IntegerAttr::get(IntegerType::get(&moduleTranslation.getContext(), 64),
+                       vtype.getShape()[0]),
+      loc, moduleTranslation);
+}
+
+namespace {
+/// Implementation of the dialect interface that converts operations belonging
+/// to the VCIX dialect to LLVM IR.
+class VCIXDialectLLVMIRTranslationInterface
+    : public LLVMTranslationDialectInterface {
+public:
+  using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
+
+  /// Translates the given operation to LLVM IR using the provided IR builder
+  /// and saving the state in `moduleTranslation`.
+  LogicalResult
+  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
+                   LLVM::ModuleTranslation &moduleTranslation) const final {
+    Operation &opInst = *op;
+#include "mlir/Dialect/LLVMIR/VCIXConversions.inc"
+
+    return failure();
+  }
+};
+} // namespace
+
+void mlir::registerVCIXDialectTranslation(DialectRegistry &registry) {
+  registry.insert<vcix::VCIXDialect>();
+  registry.addExtension(+[](MLIRContext *ctx, vcix::VCIXDialect *dialect) {
+    dialect->addInterfaces<VCIXDialectLLVMIRTranslationInterface>();
+  });
+}
+
+void mlir::registerVCIXDialectTranslation(MLIRContext &context) {
+  DialectRegistry registry;
+  registerVCIXDialectTranslation(registry);
+  context.appendDialectRegistry(registry);
+}
+
diff --git a/mlir/test/Target/LLVMIR/vcix-rv32.mlir b/mlir/test/Target/LLVMIR/vcix-rv32.mlir
new file mode 100644
index 00000000000000..d9aaf390b462ea
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/vcix-rv32.mlir
@@ -0,0 +1,73 @@
+// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_fv(<vscale x 4 x float> %0, float %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.fv.se.nxv4f32.i32.nxv4f32.f32.i32(i32 1, <vscale x 4 x float> %0, float %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_fv(%arg0: vector<[4]xf32>, %arg1: f32, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 1 : i32}> : (vector<[4]xf32>, f32, i32) -> vector<[4]xf32>
+  llvm.return %0 : vector<[4]xf32>
+}
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_xv(<vscale x 4 x float> %0, i32 %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.xv.se.nxv4f32.i32.nxv4f32.i32.i32(i32 3, <vscale x 4 x float> %0, i32 %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_xv(%arg0: vector<[4]xf32>, %arg1: i32, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 3 : i32}> : (vector<[4]xf32>, i32, i32) -> vector<[4]xf32>
+  llvm.return %0 : vector<[4]xf32>
+}
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_vv(<vscale x 4 x float> %0, <vscale x 4 x float> %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.vv.se.nxv4f32.i32.nxv4f32.nxv4f32.i32(i32 3, <vscale x 4 x float> %0, <vscale x 4 x float> %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_vv(%arg0: vector<[4]xf32>, %arg1: vector<[4]xf32>, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 3 : i32}> : (vector<[4]xf32>, vector<[4]xf32>, i32) -> vector<...
[truncated]

@llvmbot
Copy link
Collaborator

llvmbot commented Dec 18, 2023

@llvm/pr-subscribers-mlir-llvm

Author: Kolya Panchenko (nikolaypanchenko)

Changes

The changeset extends LLVMIR intrinsics with VCIX intrinsics.
The VCIX intrinsics allow MLIR users to interact with RISC-V co-processors that are compatible with XSfvcp extension

Source: https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software


Patch is 26.93 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/75875.diff

13 Files Affected:

  • (modified) mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt (+8)
  • (added) mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h (+40)
  • (added) mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td (+112)
  • (modified) mlir/include/mlir/Target/LLVMIR/Dialect/All.h (+2)
  • (added) mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h (+31)
  • (modified) mlir/lib/Dialect/LLVMIR/CMakeLists.txt (+22)
  • (added) mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp (+55)
  • (modified) mlir/lib/Target/LLVMIR/CMakeLists.txt (+1)
  • (modified) mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt (+1)
  • (added) mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt (+16)
  • (added) mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp (+89)
  • (added) mlir/test/Target/LLVMIR/vcix-rv32.mlir (+73)
  • (added) mlir/test/Target/LLVMIR/vcix-rv64.mlir (+74)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 8e41fcc05a161e..4c8078c545c735 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -71,3 +71,11 @@ mlir_tablegen(ROCDLConversions.inc -gen-llvmir-conversions)
 mlir_tablegen(ROCDLOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=rocdl)
 mlir_tablegen(ROCDLOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=rocdl)
 add_public_tablegen_target(MLIRROCDLConversionsIncGen)
+
+add_mlir_dialect(VCIXOps vcix)
+add_mlir_doc(VCIXOps RVCIXDialect Dialects/ -gen-dialect-doc -dialect=rocdl)
+set(LLVM_TARGET_DEFINITIONS VCIXOps.td)
+mlir_tablegen(VCIXConversions.inc -gen-llvmir-conversions)
+mlir_tablegen(VCIXOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=rocdl)
+mlir_tablegen(VCIXOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=rocdl)
+add_public_tablegen_target(MLIRVCIXConversionsIncGen)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h b/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h
new file mode 100644
index 00000000000000..3c911d6bc8677b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/VCIXDialect.h
@@ -0,0 +1,40 @@
+//===- VCIXDialect.h - MLIR VCIX IR dialect -------------------*- C++ ---*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The file defines the basic operations for the VCIX dialect.
+//
+// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+// to extend application processors with custom coprocessors and
+// variable-latency arithmetic units. The interface offers throughput comparable
+// to that of standard RISC-V vector instructions. To accelerate performance,
+// system designers may use VCIX as a low-latency, high-throughput interface to
+// a coprocessor
+//
+// https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_
+#define MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_
+
+#include "mlir/Bytecode/BytecodeOpInterface.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+///// Ops /////
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOps.h.inc"
+
+#include "mlir/Dialect/LLVMIR/VCIXOpsDialect.h.inc"
+
+#endif /* MLIR_DIALECT_LLVMIR_VCIXDIALECT_H_ */
diff --git a/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td b/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td
new file mode 100644
index 00000000000000..3f1fa37988c199
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td
@@ -0,0 +1,112 @@
+//===-- VCIX.td - VCIX dialect operation definitions *- tablegen -*--------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// The file defines the basic operations for the VCIX dialect.
+//
+// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+// to extend application processors with custom coprocessors and
+// variable-latency arithmetic units. The interface offers throughput comparable
+// to that of standard RISC-V vector instructions. To accelerate performance,
+// system designers may use VCIX as a low-latency, high-throughput interface to
+// a coprocessor
+//
+// https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef VCIXIR_OPS
+
+include "mlir/IR/OpBase.td"
+include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+
+//===----------------------------------------------------------------------===//
+// VCIX dialect definition.
+//===----------------------------------------------------------------------===//
+
+def VCIX_Dialect : Dialect {
+  let name = "vcix";
+  let cppNamespace = "::mlir::vcix";
+  let dependentDialects = ["LLVM::LLVMDialect"];
+  let description = [{
+     The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
+     to extend application processors with custom coprocessors and
+     variable-latency arithmetic units. The interface offers throughput comparable
+     to that of standard RISC-V vector instructions. To accelerate performance,
+     system designers may use VCIX as a low-latency, high-throughput interface to
+     a coprocessor
+
+     https://www.sifive.com/document-file/sifive-vector-coprocessor-interface-vcix-software
+  }];
+}
+
+// Special version for intrinsic version where int attr is zext to i32 or i64
+// depending on xlen of the target
+def VCIX_VectorOrScalar
+    : AnyTypeOf<[LLVM_AnyVector, I<64>, I<32>, F<16>, F<32>, F<64>]>;
+def VCIX_OpcodeAttr : AnyAttrOf<[I32Attr, I64Attr]>;
+def VCIX_Register : AnyTypeOf<[I32, I64]>;
+def VCIX_ImmAttr : AnyAttrOf<[I32Attr, I64Attr]>;
+def VCIX_VL : AnyTypeOf<[I<64>, I<32>]>;
+
+class VCIX_Op<string mnemonic, list<Trait> traits = []>
+    : LLVM_OpBase<VCIX_Dialect, mnemonic, traits> {
+}
+
+def VCIX_BinaryImmOp
+    : VCIX_Op<"v.iv">,
+    Results<(outs LLVM_AnyVector: $res)>,
+    Arguments<(ins VCIX_OpcodeAttr: $opcode,
+                   LLVM_AnyVector: $vs2,
+                   VCIX_ImmAttr: $imm,
+                   VCIX_Register: $rd,
+                   Optional<VCIX_VL>: $vl)> {
+  string llvmBuilder = [{
+      llvm::Type *xlen =getXlenType($opcode, moduleTranslation);
+      llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $opcode, $_location, moduleTranslation);
+      llvm::Value *immConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $imm, $_location, moduleTranslation);
+      VectorType vt = op.getResult().getType().cast<VectorType>();
+      llvm::Value *vl =
+          createVL(builder, $vl, vt, xlen, $_location, moduleTranslation);
+      $res = createIntrinsicCall(
+          builder, llvm::Intrinsic::riscv_sf_vc_v_iv_se,
+          {opcodeConst, $vs2, immConst, vl},
+          {$_resultType, xlen, $vs2->getType(), xlen, xlen});
+  }];
+}
+
+def VCIX_BinaryOp
+    : VCIX_Op<"v.sv">,
+    Results<(outs LLVM_AnyVector: $res)>,
+    Arguments<(ins VCIX_OpcodeAttr: $opcode,
+                   LLVM_AnyVector: $vs2,
+                   VCIX_VectorOrScalar: $op,
+                   Optional<VCIX_VL>: $vl)> {
+  string llvmBuilder = [{
+      llvm::Type *xlen = getXlenType($opcode, moduleTranslation);
+      llvm::Value *opcodeConst = mlir::LLVM::detail::getLLVMConstant(
+          xlen, $opcode, $_location, moduleTranslation);
+      llvm::Intrinsic::ID id;
+      llvm::Type *opType = $op->getType();
+      if (opType->isVectorTy()) {
+        id = llvm::Intrinsic::riscv_sf_vc_v_vv_se;
+      } else if (opType->isIntegerTy()) {
+        id = llvm::Intrinsic::riscv_sf_vc_v_xv_se;
+      } else {
+        id = llvm::Intrinsic::riscv_sf_vc_v_fv_se;
+      }
+      VectorType vt = op.getResult().getType().cast<VectorType>();
+      llvm::Value *vl =
+          createVL(builder, $vl, vt, xlen, $_location, moduleTranslation);
+      $res = createIntrinsicCall(
+          builder, id, {opcodeConst, $vs2, $op, vl},
+          {$_resultType, xlen, $vs2->getType(), $op->getType(), xlen});
+  }];
+}
+
+#endif // VCIXIR_OPS
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
index 0b37e23e45118b..de9d5872cc4546 100644
--- a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
@@ -28,6 +28,7 @@
 #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/SPIRV/SPIRVToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/X86Vector/X86VectorToLLVMIRTranslation.h"
 
 namespace mlir {
@@ -48,6 +49,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry &registry) {
   registerOpenMPDialectTranslation(registry);
   registerROCDLDialectTranslation(registry);
   registerSPIRVDialectTranslation(registry);
+  registerVCIXDialectTranslation(registry);
   registerX86VectorDialectTranslation(registry);
 
   // Extension required for translating GPU offloading Ops.
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h b/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h
new file mode 100644
index 00000000000000..d84d03a2257928
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h
@@ -0,0 +1,31 @@
+//===- VCIXToLLVMIRTranslation.h - VCIX to LLVM IR ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides registration calls for VCIX dialect to LLVM IR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
+#define MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
+
+namespace mlir {
+
+class DialectRegistry;
+class MLIRContext;
+
+/// Register the VCIX dialect and the translation from it to the LLVM IR in the
+/// given registry;
+void registerVCIXDialectTranslation(DialectRegistry &registry);
+
+/// Register the VCIX dialect and the translation from it in the registry
+/// associated with the given context.
+void registerVCIXDialectTranslation(MLIRContext &context);
+
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_DIALECT_VCIX_VCIXTOLLVMIRTRANSLATION_H
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index b00259677697a5..392065b859ee54 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -85,3 +85,25 @@ add_mlir_dialect_library(MLIRROCDLDialect
   MLIRLLVMDialect
   MLIRSideEffectInterfaces
   )
+
+add_mlir_dialect_library(MLIRVCIXDialect
+  IR/VCIXDialect.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
+
+  DEPENDS
+  MLIRGPUCompilationAttrInterfacesIncGen
+  MLIRVCIXOpsIncGen
+  MLIRVCIXConversionsIncGen
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  AsmParser
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRSideEffectInterfaces
+  )
diff --git a/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp
new file mode 100644
index 00000000000000..30ad5bfed1c0b2
--- /dev/null
+++ b/mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp
@@ -0,0 +1,55 @@
+//===- VCIXDialect.cpp - MLIR VCIX ops implementation ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VCIX dialect and its operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/LLVMIR/VCIXDialect.h"
+
+#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Operation.h"
+#include "llvm/ADT/TypeSwitch.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/SourceMgr.h"
+
+using namespace mlir;
+using namespace vcix;
+
+#include "mlir/Dialect/LLVMIR/VCIXOpsDialect.cpp.inc"
+
+//===----------------------------------------------------------------------===//
+// VCIXDialect initialization, type parsing, and registration.
+//===----------------------------------------------------------------------===//
+
+// TODO: This should be the llvm.rocdl dialect once this is supported.
+void VCIXDialect::initialize() {
+  addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/LLVMIR/VCIXOps.cpp.inc"
+      >();
+
+  addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.cpp.inc"
+      >();
+}
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOps.cpp.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/LLVMIR/VCIXOpsAttributes.cpp.inc"
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index 94280a2ec9012b..08e10fc3d965bb 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -58,6 +58,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
   MLIROpenACCToLLVMIRTranslation
   MLIROpenMPToLLVMIRTranslation
   MLIRROCDLToLLVMIRTranslation
+  MLIRVCIXToLLVMIRTranslation
   MLIRSPIRVToLLVMIRTranslation
   )
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
index c9d916d8a5d82d..87bed032d2e2da 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
@@ -9,5 +9,6 @@ add_subdirectory(NVVM)
 add_subdirectory(OpenACC)
 add_subdirectory(OpenMP)
 add_subdirectory(ROCDL)
+add_subdirectory(VCIX)
 add_subdirectory(SPIRV)
 add_subdirectory(X86Vector)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt
new file mode 100644
index 00000000000000..d2622af16d9383
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_mlir_translation_library(MLIRVCIXToLLVMIRTranslation
+  VCIXToLLVMIRTranslation.cpp
+
+  DEPENDS
+  MLIRVCIXConversionsIncGen
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRVCIXDialect
+  MLIRSupport
+  MLIRTargetLLVMIRExport
+  )
diff --git a/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp
new file mode 100644
index 00000000000000..40aec7eb406782
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.cpp
@@ -0,0 +1,89 @@
+//===- VCIXToLLVMIRTranslation.cpp - Translate VCIX to LLVM IR ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a translation between the MLIR VCIX dialect and
+// LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
+#include "mlir/Dialect/LLVMIR/VCIXDialect.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace mlir;
+using namespace mlir::LLVM;
+using mlir::LLVM::detail::createIntrinsicCall;
+
+/// Infer XLen type from opcode's type. This is done to avoid passing target
+/// option around
+static llvm::Type *getXlenType(Attribute opcodeAttr,
+                               LLVM::ModuleTranslation &moduleTranslation) {
+  auto intAttr = opcodeAttr.cast<IntegerAttr>();
+  unsigned xlenWidth = intAttr.getType().cast<IntegerType>().getWidth();
+  return llvm::Type::getIntNTy(moduleTranslation.getLLVMContext(), xlenWidth);
+}
+
+/// Return VL for VCIX intrinsic. If vl was previously set, return it,
+/// otherwise construct a constant using fixed vector type
+static llvm::Value *createVL(llvm::IRBuilderBase &builder, llvm::Value *vl,
+                             VectorType vtype, llvm::Type *xlen, Location loc,
+                             LLVM::ModuleTranslation &moduleTranslation) {
+  if (vl) {
+    assert(vtype.isScalable() &&
+           "vl parameter must be set for scalable vectors");
+    return builder.CreateZExtOrTrunc(vl, xlen);
+  }
+
+  assert(vtype.getRank() == 1 && "Only 1-d fixed vectors are supported");
+  return mlir::LLVM::detail::getLLVMConstant(
+      xlen,
+      IntegerAttr::get(IntegerType::get(&moduleTranslation.getContext(), 64),
+                       vtype.getShape()[0]),
+      loc, moduleTranslation);
+}
+
+namespace {
+/// Implementation of the dialect interface that converts operations belonging
+/// to the VCIX dialect to LLVM IR.
+class VCIXDialectLLVMIRTranslationInterface
+    : public LLVMTranslationDialectInterface {
+public:
+  using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
+
+  /// Translates the given operation to LLVM IR using the provided IR builder
+  /// and saving the state in `moduleTranslation`.
+  LogicalResult
+  convertOperation(Operation *op, llvm::IRBuilderBase &builder,
+                   LLVM::ModuleTranslation &moduleTranslation) const final {
+    Operation &opInst = *op;
+#include "mlir/Dialect/LLVMIR/VCIXConversions.inc"
+
+    return failure();
+  }
+};
+} // namespace
+
+void mlir::registerVCIXDialectTranslation(DialectRegistry &registry) {
+  registry.insert<vcix::VCIXDialect>();
+  registry.addExtension(+[](MLIRContext *ctx, vcix::VCIXDialect *dialect) {
+    dialect->addInterfaces<VCIXDialectLLVMIRTranslationInterface>();
+  });
+}
+
+void mlir::registerVCIXDialectTranslation(MLIRContext &context) {
+  DialectRegistry registry;
+  registerVCIXDialectTranslation(registry);
+  context.appendDialectRegistry(registry);
+}
+
diff --git a/mlir/test/Target/LLVMIR/vcix-rv32.mlir b/mlir/test/Target/LLVMIR/vcix-rv32.mlir
new file mode 100644
index 00000000000000..d9aaf390b462ea
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/vcix-rv32.mlir
@@ -0,0 +1,73 @@
+// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_fv(<vscale x 4 x float> %0, float %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.fv.se.nxv4f32.i32.nxv4f32.f32.i32(i32 1, <vscale x 4 x float> %0, float %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_fv(%arg0: vector<[4]xf32>, %arg1: f32, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 1 : i32}> : (vector<[4]xf32>, f32, i32) -> vector<[4]xf32>
+  llvm.return %0 : vector<[4]xf32>
+}
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_xv(<vscale x 4 x float> %0, i32 %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.xv.se.nxv4f32.i32.nxv4f32.i32.i32(i32 3, <vscale x 4 x float> %0, i32 %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_xv(%arg0: vector<[4]xf32>, %arg1: i32, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 3 : i32}> : (vector<[4]xf32>, i32, i32) -> vector<[4]xf32>
+  llvm.return %0 : vector<[4]xf32>
+}
+
+// CHECK-LABEL: define <vscale x 4 x float> @binary_vv(<vscale x 4 x float> %0, <vscale x 4 x float> %1, i32 %2) {
+// CHECK-NEXT:   %4 = call <vscale x 4 x float> @llvm.riscv.sf.vc.v.vv.se.nxv4f32.i32.nxv4f32.nxv4f32.i32(i32 3, <vscale x 4 x float> %0, <vscale x 4 x float> %1, i32 %2)
+// CHECK-NEXT:   ret <vscale x 4 x float> %4
+// CHECK-NEXT: }
+llvm.func @binary_vv(%arg0: vector<[4]xf32>, %arg1: vector<[4]xf32>, %vl: i32) -> vector<[4]xf32> {
+  %0 = "vcix.v.sv"(%arg0, %arg1, %vl) <{opcode = 3 : i32}> : (vector<[4]xf32>, vector<[4]xf32>, i32) -> vector<...
[truncated]

Copy link

github-actions bot commented Dec 18, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@dcaballe dcaballe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking a quick look for now. I think we need to add some conversion testing, at least under the test folder.

mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt Outdated Show resolved Hide resolved
mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt Outdated Show resolved Hide resolved
Copy link
Contributor

@dcaballe dcaballe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't mean to approve :)

@nikolaypanchenko
Copy link
Contributor Author

Thanks. Added few more tests, but if you do have in mind to test something else I'll be glad to add such tests

Copy link
Contributor

@dcaballe dcaballe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went over it again. It looks mostly ready!

Regarding testing, I meant you could add a test conversion pass to make sure this is a bit more exercised. You can go to mlir/test/lib/Conversion/VectorToVCIX (or any other dialect) and create a TestVectorToVCIXPass there that does a dummy conversion from arbitrary vector ops to vcix ops. Then you can create a test file using that pass under mlir/test/Conversion/VectorToVCIX. That should be all!

//
// The file defines the basic operations for the VCIX dialect.
//
// The SiFive Vector Coprocessor Interface (VCIX) provides a flexible mechanism
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any official RISC-V ratification that we should mention/point to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VCIX is a custom extension. The official link is given at the line 18

mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td Outdated Show resolved Hide resolved
mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td Outdated Show resolved Hide resolved
mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td Show resolved Hide resolved
mlir/lib/Dialect/LLVMIR/IR/VCIXDialect.cpp Outdated Show resolved Hide resolved
mlir/lib/Target/LLVMIR/CMakeLists.txt Outdated Show resolved Hide resolved
mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt Outdated Show resolved Hide resolved
@llvmbot llvmbot added the mlir:core MLIR Core Infrastructure label Feb 6, 2024
Copy link
Contributor

@dcaballe dcaballe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the tests! They look great! LGTM! I just added a bunch of nits. Feel free to address them before submitting.

Thanks!

mlir/test/Conversion/MathToVCIX/math-to-vcix.mlir Outdated Show resolved Hide resolved
@@ -0,0 +1,148 @@
// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if --split-input-file is supported by mlir-translate but please try to add it as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does have this option. Will add it and delimiters to these tests

mlir/include/mlir/Dialect/LLVMIR/VCIXOps.td Outdated Show resolved Hide resolved
Comment on lines 71 to 72
Mnemonic funct6 vm rs2 rs1 funct3 rd Destination Sources
sf.vc.v.iv 0010-- 0 vs2 simm 011 vd vector vd simm[4:0], vector vs2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how this will look like on the web. You may want to consider a markdown table?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's good suggestion. I'll rewrite it to markdown

@nikolaypanchenko
Copy link
Contributor Author

@dcaballe thanks for the review.

@npanchen npanchen merged commit 9f6c005 into llvm:main Feb 7, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mlir:core MLIR Core Infrastructure mlir:llvm mlir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants