Skip to content

Commit c798e19

Browse files
authored
[mlir][llvm][x86vector] One-to-one intrinsic op interface (llvm#140055)
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
1 parent 6e857b4 commit c798e19

File tree

8 files changed

+228
-200
lines changed

8 files changed

+228
-200
lines changed

mlir/include/mlir/Conversion/LLVMCommon/Pattern.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,32 @@ LogicalResult oneToOneRewrite(
3030
const LLVMTypeConverter &typeConverter, ConversionPatternRewriter &rewriter,
3131
IntegerOverflowFlags overflowFlags = IntegerOverflowFlags::none);
3232

33+
/// Replaces the given operation "op" with a call to an LLVM intrinsic with the
34+
/// specified name "intrinsic" and operands.
35+
///
36+
/// The rewrite performs a simple one-to-one matching between the op and LLVM
37+
/// intrinsic. For example:
38+
///
39+
/// ```mlir
40+
/// %res = intr.op %val : vector<16xf32>
41+
/// ```
42+
///
43+
/// can be converted to
44+
///
45+
/// ```mlir
46+
/// %res = llvm.call_intrinsic "intrinsic"(%val)
47+
/// ```
48+
///
49+
/// The provided operands must be LLVM-compatible.
50+
///
51+
/// Upholds a convention that multi-result operations get converted into an
52+
/// operation returning the LLVM IR structure type, in which case individual
53+
/// values are first extracted before replacing the original results.
54+
LogicalResult intrinsicRewrite(Operation *op, StringRef intrinsic,
55+
ValueRange operands,
56+
const LLVMTypeConverter &typeConverter,
57+
RewriterBase &rewriter);
58+
3359
} // namespace detail
3460

3561
/// Decomposes a `src` value into a set of values of type `dstType` through

mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
1717

1818
namespace mlir {
19+
20+
class LLVMTypeConverter;
21+
class RewriterBase;
22+
1923
namespace LLVM {
2024
namespace detail {
2125

mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,57 @@ def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> {
435435
];
436436
}
437437

438+
def OneToOneIntrinsicOpInterface : OpInterface<"OneToOneIntrinsicOpInterface"> {
439+
let description = [{
440+
An interface for operations modelling LLVM intrinsics suitable for
441+
1-to-1 conversion.
442+
443+
An op implementing this interface can be directly replaced by a call
444+
to a matching intrinsic function.
445+
The op must ensure that the combinations of its arguments and results
446+
have valid intrinsic counterparts.
447+
448+
For example, an operation supporting different inputs:
449+
```mlir
450+
%res_v8 = intr.op %value_v8 : vector<8xf32>
451+
%res_v16 = intr.op %value_v16 : vector<16xf32>
452+
```
453+
can be converted to the following intrinsic calls:
454+
```mlir
455+
%res_v8 = llvm.call_intrinsic "llvm.x86.op.intr.256"(%value_v8)
456+
%res_v16 = llvm.call_intrinsic "llvm.x86.op.intr.512"(%value_v16)
457+
```
458+
}];
459+
460+
let cppNamespace = "::mlir::LLVM";
461+
462+
let methods = [
463+
InterfaceMethod<
464+
/*desc=*/[{
465+
Returns mangled LLVM intrinsic function name matching the operation
466+
variant.
467+
}],
468+
/*retType=*/"std::string",
469+
/*methodName=*/"getIntrinsicName"
470+
>,
471+
InterfaceMethod<
472+
/*desc=*/[{
473+
Returns operands for a corresponding LLVM intrinsic.
474+
475+
Additional operations may be created to facilitate mapping
476+
between the source operands and the target intrinsic.
477+
}],
478+
/*retType=*/"SmallVector<Value>",
479+
/*methodName=*/"getIntrinsicOperands",
480+
/*args=*/(ins "::mlir::ArrayRef<Value>":$operands,
481+
"const ::mlir::LLVMTypeConverter &":$typeConverter,
482+
"::mlir::RewriterBase &":$rewriter),
483+
/*methodBody=*/"",
484+
/*defaultImplementation=*/"return SmallVector<Value>(operands);"
485+
>,
486+
];
487+
}
488+
438489
//===----------------------------------------------------------------------===//
439490
// LLVM dialect type interfaces.
440491
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)