[Mlir-commits] [mlir] [mlir][llvm][x86vector] One-to-one intrinsic op interface (PR #140055)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu May 15 06:18:07 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-vector

Author: Adam Siemieniuk (adam-smnk)

<details>
<summary>Changes</summary>

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

---

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:

- (modified) mlir/include/mlir/Conversion/LLVMCommon/Pattern.h (+26) 
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h (+4) 
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td (+51) 
- (modified) mlir/include/mlir/Dialect/X86Vector/X86Vector.td (+92-83) 
- (modified) mlir/include/mlir/Dialect/X86Vector/X86VectorInterfaces.td (+5-44) 
- (modified) mlir/lib/Conversion/LLVMCommon/Pattern.cpp (+39) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMInterfaces.cpp (+3) 
- (modified) mlir/lib/Dialect/X86Vector/Transforms/LegalizeForLLVMExport.cpp (+9-73) 


``````````diff
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]

``````````

</details>


https://github.com/llvm/llvm-project/pull/140055


More information about the Mlir-commits mailing list