-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[mlir][llvm][x86vector] One-to-one intrinsic op interface #140055
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
Conversation
Adds an LLVMIR op interface that can used by external operations to model LLVM intrinsics. Related 'op to llvm.call_intrinsic' rewriter helper is moved into common LLVM conversion patterns. The x86vector dialect is refactored to use the new common abstraction. The one-to-one intrinsic op is tied to LLVM intrinsic call semantics. Thus, the op interface, previously defined as a part of x86vector dialect, is moved into the LLVMIR interfaces to allow other low-level dialects to define operations abstracting specific intrinsic semantics while minimizing infrastructure duplication. Related RFC: https://discourse.llvm.org/t/rfc-simplify-x86-intrinsic-generation/85581
@llvm/pr-subscribers-mlir-llvm @llvm/pr-subscribers-mlir-vector Author: Adam Siemieniuk (adam-smnk) ChangesAdds an LLVMIR op interface that can used by external operations to model LLVM intrinsics. Related 'op to llvm.call_intrinsic' rewriter helper is moved into common LLVM conversion patterns. The x86vector dialect is refactored to use the new common abstraction. The one-to-one intrinsic op is tied to LLVM intrinsic call semantics. Thus, the op interface, previously defined as a part of x86vector dialect, is moved into the LLVMIR interfaces to allow other low-level dialects to define operations abstracting specific intrinsic semantics while minimizing infrastructure duplication. Related RFC: https://discourse.llvm.org/t/rfc-simplify-x86-intrinsic-generation/85581 Patch is 29.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140055.diff 8 Files Affected:
diff --git a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h
index 7a58e4fc2f984..ddbac85aa34fd 100644
--- a/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h
+++ b/mlir/include/mlir/Conversion/LLVMCommon/Pattern.h
@@ -30,6 +30,32 @@ LogicalResult oneToOneRewrite(
const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter,
IntegerOverflowFlags overflowFlags = IntegerOverflowFlags::none);
+/// Replaces the given operation "op" with a call to an LLVM intrinsic with the
+/// specified name "intrinsic" and operands.
+///
+/// The rewrite performs a simple one-to-one matching between the op and LLVM
+/// intrinsic. For example:
+///
+/// ```mlir
+/// %res = intr.op %val : vector<16xf32>
+/// ```
+///
+/// can be converted to
+///
+/// ```mlir
+/// %res = llvm.call_intrinsic "intrinsic"(%val)
+/// ```
+///
+/// The provided operands must be LLVM-compatible.
+///
+/// Upholds a convention that multi-result operations get converted into an
+/// operation returning the LLVM IR structure type, in which case individual
+/// values are first extracted before replacing the original results.
+LogicalResult intrinsicRewrite(Operation *op, StringRef intrinsic,
+ ValueRange operands,
+ const LLVMTypeConverter &typeConverter,
+ RewriterBase &rewriter);
+
} // namespace detail
/// Decomposes a `src` value into a set of values of type `dstType` through
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
index 05bd32c5d45da..d3e5408b73764 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
@@ -16,6 +16,10 @@
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
namespace mlir {
+
+class LLVMTypeConverter;
+class RewriterBase;
+
namespace LLVM {
namespace detail {
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 9db019af68b8e..2824f09dab6ce 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -435,6 +435,57 @@ def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> {
];
}
+def OneToOneIntrinsicOpInterface : OpInterface<"OneToOneIntrinsicOpInterface"> {
+ let description = [{
+ An interface for operations modelling LLVM intrinsics suitable for
+ 1-to-1 conversion.
+
+ An op implementing this interface can be directly replaced by a call
+ to a matching intrinsic function.
+ The op must ensure that the combinations of its arguments and results
+ have valid intrinsic counterparts.
+
+ For example, an operation supporting different inputs:
+ ```mlir
+ %res_v8 = intr.op %value_v8 : vector<8xf32>
+ %res_v16 = intr.op %value_v16 : vector<16xf32>
+ ```
+ can be converted to the following intrinsic calls:
+ ```mlir
+ %res_v8 = llvm.call_intrinsic "llvm.x86.op.intr.256"(%value_v8)
+ %res_v16 = llvm.call_intrinsic "llvm.x86.op.intr.512"(%value_v16)
+ ```
+ }];
+
+ let cppNamespace = "::mlir::LLVM";
+
+ let methods = [
+ InterfaceMethod<
+ /*desc=*/[{
+ Returns mangled LLVM intrinsic function name matching the operation
+ variant.
+ }],
+ /*retType=*/"std::string",
+ /*methodName=*/"getIntrinsicName"
+ >,
+ InterfaceMethod<
+ /*desc=*/[{
+ Returns operands for a corresponding LLVM intrinsic.
+
+ Additional operations may be created to facilitate mapping
+ between the source operands and the target intrinsic.
+ }],
+ /*retType=*/"SmallVector<Value>",
+ /*methodName=*/"getIntrinsicOperands",
+ /*args=*/(ins "::mlir::ArrayRef<Value>":$operands,
+ "const ::mlir::LLVMTypeConverter &":$typeConverter,
+ "::mlir::RewriterBase &":$rewriter),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/"return SmallVector<Value>(operands);"
+ >,
+ ];
+}
+
//===----------------------------------------------------------------------===//
// LLVM dialect type interfaces.
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/X86Vector/X86Vector.td b/mlir/include/mlir/Dialect/X86Vector/X86Vector.td
index 25d9c404f0181..66213b0041958 100644
--- a/mlir/include/mlir/Dialect/X86Vector/X86Vector.td
+++ b/mlir/include/mlir/Dialect/X86Vector/X86Vector.td
@@ -40,14 +40,15 @@ class AVX512_Op<string mnemonic, list<Trait> traits = []> :
//----------------------------------------------------------------------------//
def MaskCompressOp : AVX512_Op<"mask.compress", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- // TODO: Support optional arguments in `AllTypesMatch`. "type($src)" could
- // then be removed from assemblyFormat.
- AllTypesMatch<["a", "dst"]>,
- TypesMatchWith<"`k` has the same number of bits as elements in `dst`",
- "dst", "k",
- "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
- "IntegerType::get($_self.getContext(), 1))">]> {
+ IntrinsicOpInterface,
+ // TODO: Support optional arguments in `AllTypesMatch`. "type($src)" could
+ // then be removed from assemblyFormat.
+ AllTypesMatch<["a", "dst"]>,
+ TypesMatchWith<"`k` has the same number of bits as elements in `dst`",
+ "dst", "k",
+ "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
+ "IntegerType::get($_self.getContext(), 1))">
+ ]> {
let summary = "Masked compress op";
let description = [{
The mask.compress op is an AVX512 specific op that can lower to the
@@ -75,14 +76,13 @@ def MaskCompressOp : AVX512_Op<"mask.compress", [Pure,
" `:` type($dst) (`,` type($src)^)?";
let hasVerifier = 1;
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
// Call the baseline overloaded intrisic.
// Final overload name mangling is resolved by the created function call.
return "llvm.x86.avx512.mask.compress";
}
- }];
- let extraClassDeclaration = [{
+
SmallVector<Value> getIntrinsicOperands(
::mlir::ArrayRef<Value> operands,
const ::mlir::LLVMTypeConverter &typeConverter,
@@ -95,12 +95,13 @@ def MaskCompressOp : AVX512_Op<"mask.compress", [Pure,
//----------------------------------------------------------------------------//
def MaskRndScaleOp : AVX512_Op<"mask.rndscale", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- AllTypesMatch<["src", "a", "dst"]>,
- TypesMatchWith<"imm has the same number of bits as elements in dst",
- "dst", "imm",
- "IntegerType::get($_self.getContext(), "
- "(::llvm::cast<VectorType>($_self).getShape()[0]))">]> {
+ IntrinsicOpInterface,
+ AllTypesMatch<["src", "a", "dst"]>,
+ TypesMatchWith<"imm has the same number of bits as elements in dst",
+ "dst", "imm",
+ "IntegerType::get($_self.getContext(), "
+ "(::llvm::cast<VectorType>($_self).getShape()[0]))">
+ ]> {
let summary = "Masked roundscale op";
let description = [{
The mask.rndscale op is an AVX512 specific op that can lower to the proper
@@ -126,8 +127,8 @@ def MaskRndScaleOp : AVX512_Op<"mask.rndscale", [Pure,
let assemblyFormat =
"$src `,` $k `,` $a `,` $imm `,` $rounding attr-dict `:` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
std::string intr = "llvm.x86.avx512.mask.rndscale";
VectorType vecType = getSrc().getType();
Type elemType = vecType.getElementType();
@@ -146,12 +147,13 @@ def MaskRndScaleOp : AVX512_Op<"mask.rndscale", [Pure,
//----------------------------------------------------------------------------//
def MaskScaleFOp : AVX512_Op<"mask.scalef", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- AllTypesMatch<["src", "a", "b", "dst"]>,
- TypesMatchWith<"k has the same number of bits as elements in dst",
- "dst", "k",
- "IntegerType::get($_self.getContext(), "
- "(::llvm::cast<VectorType>($_self).getShape()[0]))">]> {
+ IntrinsicOpInterface,
+ AllTypesMatch<["src", "a", "b", "dst"]>,
+ TypesMatchWith<"k has the same number of bits as elements in dst",
+ "dst", "k",
+ "IntegerType::get($_self.getContext(), "
+ "(::llvm::cast<VectorType>($_self).getShape()[0]))">
+ ]> {
let summary = "ScaleF op";
let description = [{
The `mask.scalef` op is an AVX512 specific op that can lower to the proper
@@ -178,8 +180,8 @@ def MaskScaleFOp : AVX512_Op<"mask.scalef", [Pure,
let assemblyFormat =
"$src `,` $a `,` $b `,` $k `,` $rounding attr-dict `:` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
std::string intr = "llvm.x86.avx512.mask.scalef";
VectorType vecType = getSrc().getType();
Type elemType = vecType.getElementType();
@@ -198,18 +200,19 @@ def MaskScaleFOp : AVX512_Op<"mask.scalef", [Pure,
//----------------------------------------------------------------------------//
def Vp2IntersectOp : AVX512_Op<"vp2intersect", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- AllTypesMatch<["a", "b"]>,
- TypesMatchWith<"k1 has the same number of bits as elements in a",
- "a", "k1",
- "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
- "IntegerType::get($_self.getContext(), 1))">,
- TypesMatchWith<"k2 has the same number of bits as elements in b",
- // Should use `b` instead of `a`, but that would require
- // adding `type($b)` to assemblyFormat.
- "a", "k2",
- "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
- "IntegerType::get($_self.getContext(), 1))">]> {
+ IntrinsicOpInterface,
+ AllTypesMatch<["a", "b"]>,
+ TypesMatchWith<"k1 has the same number of bits as elements in a",
+ "a", "k1",
+ "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
+ "IntegerType::get($_self.getContext(), 1))">,
+ TypesMatchWith<"k2 has the same number of bits as elements in b",
+ // Should use `b` instead of `a`, but that would require
+ // adding `type($b)` to assemblyFormat.
+ "a", "k2",
+ "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0]}, "
+ "IntegerType::get($_self.getContext(), 1))">
+ ]> {
let summary = "Vp2Intersect op";
let description = [{
The `vp2intersect` op is an AVX512 specific op that can lower to the proper
@@ -234,8 +237,8 @@ def Vp2IntersectOp : AVX512_Op<"vp2intersect", [Pure,
let assemblyFormat =
"$a `,` $b attr-dict `:` type($a)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
std::string intr = "llvm.x86.avx512.vp2intersect";
VectorType vecType = getA().getType();
Type elemType = vecType.getElementType();
@@ -254,13 +257,14 @@ def Vp2IntersectOp : AVX512_Op<"vp2intersect", [Pure,
//----------------------------------------------------------------------------//
def DotBF16Op : AVX512_Op<"dot", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- AllTypesMatch<["a", "b"]>,
- AllTypesMatch<["src", "dst"]>,
- TypesMatchWith<"`a` has twice an many elements as `src`",
- "src", "a",
- "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0] * 2}, "
- "BFloat16Type::get($_self.getContext()))">]> {
+ IntrinsicOpInterface,
+ AllTypesMatch<["a", "b"]>,
+ AllTypesMatch<["src", "dst"]>,
+ TypesMatchWith<"`a` has twice an many elements as `src`",
+ "src", "a",
+ "VectorType::get({::llvm::cast<VectorType>($_self).getShape()[0] * 2}, "
+ "BFloat16Type::get($_self.getContext()))">
+ ]> {
let summary = "Dot BF16 op";
let description = [{
The `dot` op is an AVX512-BF16 specific op that can lower to the proper
@@ -286,8 +290,8 @@ def DotBF16Op : AVX512_Op<"dot", [Pure,
let assemblyFormat =
"$src `,` $a `,` $b attr-dict `:` type($a) `->` type($src)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
std::string intr = "llvm.x86.avx512bf16.dpbf16ps";
VectorType vecType = getSrc().getType();
unsigned elemBitWidth = vecType.getElementTypeBitWidth();
@@ -303,8 +307,9 @@ def DotBF16Op : AVX512_Op<"dot", [Pure,
//----------------------------------------------------------------------------//
def CvtPackedF32ToBF16Op : AVX512_Op<"cvt.packed.f32_to_bf16", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- AllElementCountsMatch<["a", "dst"]>]> {
+ IntrinsicOpInterface,
+ AllElementCountsMatch<["a", "dst"]>
+ ]> {
let summary = "Convert packed F32 to packed BF16 Data.";
let description = [{
The `convert_f32_to_bf16` op is an AVX512-BF16 specific op that can lower
@@ -326,8 +331,8 @@ def CvtPackedF32ToBF16Op : AVX512_Op<"cvt.packed.f32_to_bf16", [Pure,
let assemblyFormat =
"$a attr-dict `:` type($a) `->` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
std::string intr = "llvm.x86.avx512bf16.cvtneps2bf16";
VectorType vecType = getA().getType();
unsigned elemBitWidth = vecType.getElementTypeBitWidth();
@@ -357,15 +362,16 @@ class AVX_LowOp<string mnemonic, list<Trait> traits = []> :
//----------------------------------------------------------------------------//
def RsqrtOp : AVX_Op<"rsqrt", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- SameOperandsAndResultType]> {
+ IntrinsicOpInterface,
+ SameOperandsAndResultType
+ ]> {
let summary = "Rsqrt";
let arguments = (ins VectorOfLengthAndType<[8], [F32]>:$a);
let results = (outs VectorOfLengthAndType<[8], [F32]>:$b);
let assemblyFormat = "$a attr-dict `:` type($a)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
return "llvm.x86.avx.rsqrt.ps.256";
}
}];
@@ -376,8 +382,9 @@ def RsqrtOp : AVX_Op<"rsqrt", [Pure,
//----------------------------------------------------------------------------//
def DotOp : AVX_LowOp<"dot", [Pure,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>,
- SameOperandsAndResultType]> {
+ IntrinsicOpInterface,
+ SameOperandsAndResultType
+ ]> {
let summary = "Dot";
let description = [{
Computes the 4-way dot products of the lower and higher parts of the source
@@ -400,13 +407,12 @@ def DotOp : AVX_LowOp<"dot", [Pure,
let results = (outs VectorOfLengthAndType<[8], [F32]>:$res);
let assemblyFormat = "$a `,` $b attr-dict `:` type($res)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
// Only one variant is supported right now - no extra mangling.
return "llvm.x86.avx.dp.ps.256";
}
- }];
- let extraClassDeclaration = [{
+
SmallVector<Value> getIntrinsicOperands(
::mlir::ArrayRef<Value> operands,
const ::mlir::LLVMTypeConverter &typeConverter,
@@ -418,8 +424,11 @@ def DotOp : AVX_LowOp<"dot", [Pure,
// AVX: Convert BF16/F16 to F32 and broadcast into packed F32
//----------------------------------------------------------------------------//
-def BcstToPackedF32Op : AVX_Op<"bcst_to_f32.packed", [MemoryEffects<[MemRead]>,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>]> {
+def BcstToPackedF32Op
+ : AVX_Op<"bcst_to_f32.packed", [
+ MemoryEffects<[MemRead]>,
+ IntrinsicOpInterface
+ ]> {
let summary = "AVX: Broadcasts BF16/F16 into packed F32 Data.";
let description = [{
#### From the Intel Intrinsics Guide:
@@ -440,8 +449,8 @@ def BcstToPackedF32Op : AVX_Op<"bcst_to_f32.packed", [MemoryEffects<[MemRead]>,
let assemblyFormat =
"$a attr-dict`:` type($a)`->` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
auto elementType =
getA().getType().getElementType();
std::string intr = "llvm.x86.";
@@ -455,9 +464,7 @@ def BcstToPackedF32Op : AVX_Op<"bcst_to_f32.packed", [MemoryEffects<[MemRead]>,
intr += std::to_string(opBitWidth);
return intr;
}
- }];
- let extraClassDeclaration = [{
SmallVector<Value> getIntrinsicOperands(
::mlir::ArrayRef<Value> operands,
const ::mlir::LLVMTypeConverter &typeConverter,
@@ -470,8 +477,11 @@ def BcstToPackedF32Op : AVX_Op<"bcst_to_f32.packed", [MemoryEffects<[MemRead]>,
// AVX: Convert packed BF16/F16 even-indexed/odd-indexed elements into packed F32
//------------------------------------------------------------------------------//
-def CvtPackedEvenIndexedToF32Op : AVX_Op<"cvt.packed.even.indexed_to_f32", [MemoryEffects<[MemRead]>,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>]> {
+def CvtPackedEvenIndexedToF32Op
+ : AVX_Op<"cvt.packed.even.indexed_to_f32", [
+ MemoryEffects<[MemRead]>,
+ IntrinsicOpInterface
+ ]> {
let summary = "AVX: Convert packed BF16/F16 even-indexed elements into packed F32 Data.";
let description = [{
#### From the Intel Intrinsics Guide:
@@ -491,8 +501,8 @@ def CvtPackedEvenIndexedToF32Op : AVX_Op<"cvt.packed.even.indexed_to_f32", [Memo
let assemblyFormat =
"$a attr-dict`:` type($a)`->` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
auto elementType =
getA().getType().getElementType();
std::string intr = "llvm.x86.";
@@ -506,9 +516,7 @@ def CvtPackedEvenIndexedToF32Op : AVX_Op<"cvt.packed.even.indexed_to_f32", [Memo
intr += std::to_string(opBitWidth);
return intr;
}
- }];
- let extraClassDeclaration = [{
SmallVector<Value> getIntrinsicOperands(
::mlir::ArrayRef<Value> operands,
const ::mlir::LLVMTypeConverter &typeConverter,
@@ -516,8 +524,11 @@ def CvtPackedEvenIndexedToF32Op : AVX_Op<"cvt.packed.even.indexed_to_f32", [Memo
}];
}
-def CvtPackedOddIndexedToF32Op : AVX_Op<"cvt.packed.odd.indexed_to_f32", [MemoryEffects<[MemRead]>,
- DeclareOpInterfaceMethods<OneToOneIntrinsicOpInterface>]> {
+def CvtPackedOddIndexedToF32Op
+ : AVX_Op<"cvt.packed.odd.indexed_to_f32", [
+ MemoryEffects<[MemRead]>,
+ IntrinsicOpInterface
+ ]> {
let summary = "AVX: Convert packed BF16/F16 odd-indexed elements into packed F32 Data.";
let description = [{
#### From the Intel Intrinsics Guide:
@@ -537,8 +548,8 @@ def CvtPackedOddIndexedToF32Op : AVX_Op<"cvt.packed.odd.indexed_to_f32", [Memory
let assemblyFormat =
"$a attr-dict`:` type($a)`->` type($dst)";
- let extraClassDefinition = [{
- std::string $cppClass::getIntrinsicName() {
+ let extraClassDeclaration = [{
+ std::string getIntrinsicName() {
auto elementType =
getA().getType().getElementType();
std::string intr = "llvm.x86.";
@@ -552,9 +563,7 @@ def CvtPackedOddIndexedToF32Op : AVX_Op<"cvt.packed.odd.indexed_to_f32", [Memory
intr += std::to_string(opBitWidth);
return intr;
}
- }];
- let extraClassDeclaration = [{
SmallVector<Value> getInt...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, this way other targets can re-use this logic.
Thanks, LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, LGTM!
Adds an LLVMIR op interface that can used by external operations to model LLVM intrinsics. Related 'op to llvm.call_intrinsic' rewriter helper is moved into common LLVM conversion patterns. The x86vector dialect is refactored to use the new common abstraction. The one-to-one intrinsic op is tied to LLVM intrinsic call semantics. Thus, the op interface, previously defined as a part of x86vector dialect, is moved into the LLVMIR interfaces to allow other low-level dialects to define operations abstracting specific intrinsic semantics while minimizing infrastructure duplication. Related RFC: https://discourse.llvm.org/t/rfc-simplify-x86-intrinsic-generation/85581/6
Adds an LLVMIR op interface that can used by external operations to model LLVM intrinsics. Related 'op to llvm.call_intrinsic' rewriter helper is moved into common LLVM conversion patterns. The x86vector dialect is refactored to use the new common abstraction.
The one-to-one intrinsic op is tied to LLVM intrinsic call semantics. Thus, the op interface, previously defined as a part of x86vector dialect, is moved into the LLVMIR interfaces to allow other low-level dialects to define operations abstracting specific intrinsic semantics while minimizing infrastructure duplication.
Related RFC: https://discourse.llvm.org/t/rfc-simplify-x86-intrinsic-generation/85581/6