[mlir] Add option to use custom base class for dialect in LLVMIRIntrinsicGen.
authorMarcello Maggioni <hayarms@gmail.com>
Wed, 22 Jan 2020 22:22:29 +0000 (14:22 -0800)
committerMarcello Maggioni <hayarms@gmail.com>
Thu, 23 Jan 2020 19:23:25 +0000 (11:23 -0800)
Summary:
LLVMIRIntrinsicGen is using LLVM_Op as the base class for intrinsics.
This works for LLVM intrinsics in the LLVM Dialect, but when we are
trying to convert custom intrinsics that originate from a custom
LLVM dialect (like NVVM or ROCDL) these usually have a different
"cppNamespace" that needs to be applied to these dialect.

These dialect specific characteristics (like "cppNamespace")
are typically organized by creating a custom op (like NVVM_Op or
ROCDL_Op) that passes the correct dialect to the LLVM_OpBase class.

It seems natural to allow LLVMIRIntrinsicGen to take that into
consideration when generating the conversion code from one of these
dialect to a set of target specific intrinsics.

Reviewers: rriddle, andydavis1, antiagainst, nicolasvasilache, ftynse

Subscribers: jdoerfert, mehdi_amini, jpienaar, burmako, shauheen, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, llvm-commits

Tags: #llvm

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

mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
mlir/test/mlir-tblgen/llvm-intrinsics.td
mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp

index 0ae70524af7baf4494203e875722b0cce9881fa1..e183d998b5b896b9536daf132d57f875795f9076 100644 (file)
@@ -56,4 +56,10 @@ class LLVM_OpBase<Dialect dialect, string mnemonic, list<OpTrait> traits = []> :
 class LLVM_Op<string mnemonic, list<OpTrait> traits = []> :
     LLVM_OpBase<LLVM_Dialect, mnemonic, traits>;
 
+// Base class for LLVM intrinsics operation. It is the same as an LLVM_Op
+// but the operation has a ".intr." element in the prefix becoming
+// "llvm.intr.*".
+class LLVM_IntrOp<string mnemonic, list<OpTrait> traits = []> :
+    LLVM_Op<"intr."#mnemonic, traits>;
+
 #endif  // LLVMIR_OP_BASE
index 8231abe40ca9a474adc393246c9c73a4b10c0875..f8d93586888d374781b374968f7b67f40ccc9834 100644 (file)
 //
 // RUN: cat %S/../../../llvm/include/llvm/IR/Intrinsics.td \
 // RUN: | grep -v "llvm/IR/Intrinsics" \
-// RUN: | mlir-tblgen -gen-llvmir-intrinsics -I %S/../../../llvm/include/ --llvmir-intrinsics-filter=is_constant \
+// RUN: | mlir-tblgen -gen-llvmir-intrinsics -I %S/../../../llvm/include/ --llvmir-intrinsics-filter=ptrmask \
 // RUN: | FileCheck %s
 
-// CHECK-LABEL: def LLVM_is_constant
-// CHECK: LLVM_Op<"intr
+// CHECK-LABEL: def LLVM_ptrmask
+// CHECK: LLVM_IntrOp<"ptrmask
 // CHECK: Arguments<(ins
 // CHECK: Results<(outs
 // CHECK: llvm::Function *fn = llvm::Intrinsic::getDeclaration(
-// CHECK:        module, llvm::Intrinsic::is_constant, {
+// CHECK:        module, llvm::Intrinsic::ptrmask, {
+// CHECK:        opInst.getResult(0).getType().cast<LLVM::LLVMType>().getUnderlyingType(),
 // CHECK:        opInst.getOperand(0).getType().cast<LLVM::LLVMType>().getUnderlyingType(),
+// CHECK:        opInst.getOperand(1).getType().cast<LLVM::LLVMType>().getUnderlyingType(),
 // CHECK: });
 // CHECK:        lookupValues(opInst.getOperands());
 
 // RUN: | FileCheck --check-prefix=ODS %s
 
 // ODS-LABEL: class vastart
+
+// RUN: cat %S/../../../llvm/include/llvm/IR/Intrinsics.td \
+// RUN: | grep -v "llvm/IR/Intrinsics" \
+// RUN: | mlir-tblgen -gen-llvmir-intrinsics -I %S/../../../llvm/include/ --llvmir-intrinsics-filter=ptrmask -dialect-opclass-base My_OpBase \
+// RUN: | FileCheck %s --check-prefix=DIALECT-OPBASE
+
+// DIALECT-OPBASE-LABEL: def LLVM_ptrmask
+// DIALECT-OPBASE: My_OpBase<"ptrmask
index 263e01db7fe18f596504fef922c6613ce228e844..ca047ad7b21bf5dd0e57c5ef4364c53af3fda29f 100644 (file)
@@ -32,6 +32,12 @@ static llvm::cl::opt<std::string>
                               "substring in their record name"),
                llvm::cl::cat(IntrinsicGenCat));
 
+static llvm::cl::opt<std::string>
+    opBaseClass("dialect-opclass-base",
+                llvm::cl::desc("The base class for the ops in the dialect we "
+                               "are planning to emit"),
+                llvm::cl::init("LLVM_IntrOp"), llvm::cl::cat(IntrinsicGenCat));
+
 // Used to represent the indices of overloadable operands/results.
 using IndicesTy = llvm::SmallBitVector;
 
@@ -84,8 +90,20 @@ public:
            "LLVM intrinsic names are expected to start with 'int_'");
     name = name.drop_front(4);
     llvm::SmallVector<llvm::StringRef, 8> chunks;
+    llvm::StringRef targetPrefix = record.getValueAsString("TargetPrefix");
     name.split(chunks, '_');
-    return llvm::join(chunks, ".");
+    auto chunksBegin = chunks.begin();
+    // Remove the target prefix from target specific intrinsics.
+    if (!targetPrefix.empty()) {
+      assert(targetPrefix == *chunksBegin &&
+             "Intrinsic has TargetPrefix, but "
+             "record name doesn't begin with it");
+      assert(chunks.size() >= 2 &&
+             "Intrinsic has TargetPrefix, but "
+             "chunks has only one element meaning the intrinsic name is empty");
+      ++chunksBegin;
+    }
+    return llvm::join(chunksBegin, chunks.end(), ".");
   }
 
   /// Get the name of the record without the "intrinsic" prefix.
@@ -205,8 +223,8 @@ static bool emitIntrinsic(const llvm::Record &record, llvm::raw_ostream &os) {
                                                  "LLVM_Type");
 
   // Emit the definition.
-  os << "def LLVM_" << intr.getProperRecordName() << " : LLVM_Op<\"intr."
-     << intr.getOperationName() << "\", [";
+  os << "def LLVM_" << intr.getProperRecordName() << " : " << opBaseClass
+     << "<\"" << intr.getOperationName() << "\", [";
   mlir::interleaveComma(traits, os);
   os << "]>, Arguments<(ins" << (operands.empty() ? "" : " ");
   mlir::interleaveComma(operands, os);