// Base class for standard arithmetic operations. Requires operands and
// results to be of the same type, but does not constrain them to specific
-// types. Individual classes will have `lhs` and `rhs` accessor to operands.
+// types.
class ArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
Op<StandardOps_Dialect, mnemonic,
!listconcat(traits, [NoSideEffect,
}];
}
+// Base class for standard binary arithmetic operations.
+class ArithmeticBinaryOp<string mnemonic, list<OpTrait> traits = []> :
+ ArithmeticOp<mnemonic, traits> {
+
+ let parser = [{
+ return impl::parseOneResultSameOperandTypeOp(parser, result);
+ }];
+
+ let printer = [{
+ return printStandardBinaryOp(this->getOperation(), p);
+ }];
+}
+
+// Base class for standard ternary arithmetic operations.
+class ArithmeticTernaryOp<string mnemonic, list<OpTrait> traits = []> :
+ ArithmeticOp<mnemonic, traits> {
+
+ let parser = [{
+ return impl::parseOneResultSameOperandTypeOp(parser, result);
+ }];
+
+ let printer = [{
+ return printStandardTernaryOp(this->getOperation(), p);
+ }];
+}
+
// Base class for standard arithmetic operations on integers, vectors and
// tensors thereof. This operation takes two operands and returns one result,
// each of these is required to be of the same type. This type may be an
//
// <op>i %0, %1 : i32
//
-class IntArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
- ArithmeticOp<mnemonic,
+class IntBinaryOp<string mnemonic, list<OpTrait> traits = []> :
+ ArithmeticBinaryOp<mnemonic,
!listconcat(traits,
[DeclareOpInterfaceMethods<VectorUnrollOpInterface>])>,
Arguments<(ins SignlessIntegerLike:$lhs, SignlessIntegerLike:$rhs)>;
//
// <op>f %0, %1 : f32
//
-class FloatArithmeticOp<string mnemonic, list<OpTrait> traits = []> :
- ArithmeticOp<mnemonic,
+class FloatBinaryOp<string mnemonic, list<OpTrait> traits = []> :
+ ArithmeticBinaryOp<mnemonic,
!listconcat(traits,
[DeclareOpInterfaceMethods<VectorUnrollOpInterface>])>,
Arguments<(ins FloatLike:$lhs, FloatLike:$rhs)>;
+// Base class for standard arithmetic ternary operations on floats, vectors and
+// tensors thereof. This operation has three operands and returns one result,
+// each of these is required to be of the same type. This type may be a
+// floating point scalar type, a vector whose element type is a floating point
+// type, or a floating point tensor. The custom assembly form of the operation
+// is as follows
+//
+// <op> %0, %1, %2 : f32
+//
+class FloatTernaryOp<string mnemonic, list<OpTrait> traits = []> :
+ ArithmeticTernaryOp<mnemonic,
+ !listconcat(traits,
+ [DeclareOpInterfaceMethods<VectorUnrollOpInterface>])>,
+ Arguments<(ins FloatLike:$a, FloatLike:$b, FloatLike:$c)>;
+
// Base class for memref allocating ops: alloca and alloc.
//
// %0 = alloclike(%m)[%s] : memref<8x?xf32, (d0, d1)[s0] -> ((d0 + s0), d1)>
// AddFOp
//===----------------------------------------------------------------------===//
-def AddFOp : FloatArithmeticOp<"addf"> {
+def AddFOp : FloatBinaryOp<"addf"> {
let summary = "floating point addition operation";
let description = [{
Syntax:
// AddIOp
//===----------------------------------------------------------------------===//
-def AddIOp : IntArithmeticOp<"addi", [Commutative]> {
+def AddIOp : IntBinaryOp<"addi", [Commutative]> {
let summary = "integer addition operation";
let description = [{
Syntax:
// AndOp
//===----------------------------------------------------------------------===//
-def AndOp : IntArithmeticOp<"and", [Commutative]> {
+def AndOp : IntBinaryOp<"and", [Commutative]> {
let summary = "integer binary and";
let description = [{
Syntax:
// CopySignOp
//===----------------------------------------------------------------------===//
-def CopySignOp : FloatArithmeticOp<"copysign"> {
+def CopySignOp : FloatBinaryOp<"copysign"> {
let summary = "A copysign operation";
let description = [{
Syntax:
// DivFOp
//===----------------------------------------------------------------------===//
-def DivFOp : FloatArithmeticOp<"divf"> {
+def DivFOp : FloatBinaryOp<"divf"> {
let summary = "floating point division operation";
let hasFolder = 1;
}
//===----------------------------------------------------------------------===//
+// FmaFOp
+//===----------------------------------------------------------------------===//
+
+def FmaFOp : FloatTernaryOp<"fmaf"> {
+ let summary = "floating point fused multipy-add operation";
+ let description = [{
+ Syntax:
+
+ ```
+ operation ::= ssa-id `=` `std.fmaf` ssa-use `,` ssa-use `,` ssa-use `:` type
+ ```
+
+ The `fmaf` operation takes three operands and returns one result, each of
+ these is required to be the same type. This type may be a floating point
+ scalar type, a vector whose element type is a floating point type, or a
+ floating point tensor.
+
+ Example:
+
+ ```mlir
+ // Scalar fused multiply-add: d = a*b + c
+ %d = fmaf %a, %b, %c : f64
+
+ // SIMD vector fused multiply-add, e.g. for Intel SSE.
+ %i = fmaf %f, %g, %h : vector<4xf32>
+
+ // Tensor fused multiply-add.
+ %w = fmaf %x, %y, %z : tensor<4x?xbf16>
+ ```
+
+ The semantics of the operation correspond to those of the `llvm.fma`
+ [intrinsic](https://llvm.org/docs/LangRef.html#llvm-fma-intrinsic). In the
+ particular case of lowering to LLVM, this is guaranteed to lower
+ to the `llvm.fma.*` intrinsic.
+ }];
+}
+
+//===----------------------------------------------------------------------===//
// FPExtOp
//===----------------------------------------------------------------------===//
// MulFOp
//===----------------------------------------------------------------------===//
-def MulFOp : FloatArithmeticOp<"mulf"> {
+def MulFOp : FloatBinaryOp<"mulf"> {
let summary = "floating point multiplication operation";
let description = [{
Syntax:
// MulIOp
//===----------------------------------------------------------------------===//
-def MulIOp : IntArithmeticOp<"muli", [Commutative]> {
+def MulIOp : IntBinaryOp<"muli", [Commutative]> {
let summary = "integer multiplication operation";
let hasFolder = 1;
}
// OrOp
//===----------------------------------------------------------------------===//
-def OrOp : IntArithmeticOp<"or", [Commutative]> {
+def OrOp : IntBinaryOp<"or", [Commutative]> {
let summary = "integer binary or";
let description = [{
Syntax:
// RemFOp
//===----------------------------------------------------------------------===//
-def RemFOp : FloatArithmeticOp<"remf"> {
+def RemFOp : FloatBinaryOp<"remf"> {
let summary = "floating point division remainder operation";
}
// ShiftLeftOp
//===----------------------------------------------------------------------===//
-def ShiftLeftOp : IntArithmeticOp<"shift_left"> {
+def ShiftLeftOp : IntBinaryOp<"shift_left"> {
let summary = "integer left-shift";
let description = [{
The shift_left operation shifts an integer value to the left by a variable
// SignedDivIOp
//===----------------------------------------------------------------------===//
-def SignedDivIOp : IntArithmeticOp<"divi_signed"> {
+def SignedDivIOp : IntBinaryOp<"divi_signed"> {
let summary = "signed integer division operation";
let description = [{
Syntax:
// SignedFloorDivIOp
//===----------------------------------------------------------------------===//
-def SignedFloorDivIOp : IntArithmeticOp<"floordivi_signed"> {
+def SignedFloorDivIOp : IntBinaryOp<"floordivi_signed"> {
let summary = "signed floor integer division operation";
let description = [{
Syntax:
// SignedCeilDivIOp
//===----------------------------------------------------------------------===//
-def SignedCeilDivIOp : IntArithmeticOp<"ceildivi_signed"> {
+def SignedCeilDivIOp : IntBinaryOp<"ceildivi_signed"> {
let summary = "signed ceil integer division operation";
let description = [{
Syntax:
// SignedRemIOp
//===----------------------------------------------------------------------===//
-def SignedRemIOp : IntArithmeticOp<"remi_signed"> {
+def SignedRemIOp : IntBinaryOp<"remi_signed"> {
let summary = "signed integer division remainder operation";
let description = [{
Syntax:
// SignedShiftRightOp
//===----------------------------------------------------------------------===//
-def SignedShiftRightOp : IntArithmeticOp<"shift_right_signed"> {
+def SignedShiftRightOp : IntBinaryOp<"shift_right_signed"> {
let summary = "signed integer right-shift";
let description = [{
The shift_right_signed operation shifts an integer value to the right by
// SubFOp
//===----------------------------------------------------------------------===//
-def SubFOp : FloatArithmeticOp<"subf"> {
+def SubFOp : FloatBinaryOp<"subf"> {
let summary = "floating point subtraction operation";
let hasFolder = 1;
}
// SubIOp
//===----------------------------------------------------------------------===//
-def SubIOp : IntArithmeticOp<"subi"> {
+def SubIOp : IntBinaryOp<"subi"> {
let summary = "integer subtraction operation";
let hasFolder = 1;
}
// UnsignedDivIOp
//===----------------------------------------------------------------------===//
-def UnsignedDivIOp : IntArithmeticOp<"divi_unsigned"> {
+def UnsignedDivIOp : IntBinaryOp<"divi_unsigned"> {
let summary = "unsigned integer division operation";
let description = [{
Syntax:
// UnsignedRemIOp
//===----------------------------------------------------------------------===//
-def UnsignedRemIOp : IntArithmeticOp<"remi_unsigned"> {
+def UnsignedRemIOp : IntBinaryOp<"remi_unsigned"> {
let summary = "unsigned integer division remainder operation";
let description = [{
Syntax:
// UnsignedShiftRightOp
//===----------------------------------------------------------------------===//
-def UnsignedShiftRightOp : IntArithmeticOp<"shift_right_unsigned"> {
+def UnsignedShiftRightOp : IntBinaryOp<"shift_right_unsigned"> {
let summary = "unsigned integer right-shift";
let description = [{
The shift_right_unsigned operation shifts an integer value to the right by
// XOrOp
//===----------------------------------------------------------------------===//
-def XOrOp : IntArithmeticOp<"xor", [Commutative]> {
+def XOrOp : IntBinaryOp<"xor", [Commutative]> {
let summary = "integer binary xor";
let description = [{
The `xor` operation takes two operands and returns one result, each of these