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
//
// 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
"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;
"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.
"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);