diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -56,4 +56,10 @@ class LLVM_Op traits = []> : LLVM_OpBase; +// 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 traits = []> : + LLVM_Op<"intr."#mnemonic, traits>; + #endif // LLVMIR_OP_BASE diff --git a/mlir/test/mlir-tblgen/llvm-intrinsics.td b/mlir/test/mlir-tblgen/llvm-intrinsics.td --- a/mlir/test/mlir-tblgen/llvm-intrinsics.td +++ b/mlir/test/mlir-tblgen/llvm-intrinsics.td @@ -10,16 +10,18 @@ // // 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().getUnderlyingType(), // CHECK: opInst.getOperand(0).getType().cast().getUnderlyingType(), +// CHECK: opInst.getOperand(1).getType().cast().getUnderlyingType(), // CHECK: }); // CHECK: lookupValues(opInst.getOperands()); @@ -36,3 +38,11 @@ // 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 diff --git a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp --- a/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp @@ -32,6 +32,12 @@ "substring in their record name"), llvm::cl::cat(IntrinsicGenCat)); +static llvm::cl::opt + 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 @@ "LLVM intrinsic names are expected to start with 'int_'"); name = name.drop_front(4); llvm::SmallVector 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 @@ "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);