@@ -137,6 +137,20 @@ class Arith_CompareOpOfAnyRank<string mnemonic, list<Trait> traits = []> :
137137 let results = (outs BoolLikeOfAnyRank:$result);
138138}
139139
140+ class Arith_IntBinaryOpWithOverflowFlags<string mnemonic, list<Trait> traits = []> :
141+ Arith_BinaryOp<mnemonic, traits #
142+ [Pure, DeclareOpInterfaceMethods<InferIntRangeInterface>,
143+ DeclareOpInterfaceMethods<ArithIntegerOverflowFlagsInterface>]>,
144+ Arguments<(ins SignlessIntegerLike:$lhs, SignlessIntegerLike:$rhs,
145+ DefaultValuedAttr<
146+ Arith_IntegerOverflowAttr,
147+ "::mlir::arith::IntegerOverflowFlags::none">:$overflowFlags)>,
148+ Results<(outs SignlessIntegerLike:$result)> {
149+
150+ let assemblyFormat = [{ $lhs `,` $rhs (`overflow` `` $overflowFlags^)?
151+ attr-dict `:` type($result) }];
152+ }
153+
140154//===----------------------------------------------------------------------===//
141155// ConstantOp
142156//===----------------------------------------------------------------------===//
@@ -192,7 +206,7 @@ def Arith_ConstantOp : Op<Arith_Dialect, "constant",
192206// AddIOp
193207//===----------------------------------------------------------------------===//
194208
195- def Arith_AddIOp : Arith_TotalIntBinaryOp <"addi", [Commutative]> {
209+ def Arith_AddIOp : Arith_IntBinaryOpWithOverflowFlags <"addi", [Commutative]> {
196210 let summary = "integer addition operation";
197211 let description = [{
198212 Performs N-bit addition on the operands. The operands are interpreted as
@@ -203,16 +217,23 @@ def Arith_AddIOp : Arith_TotalIntBinaryOp<"addi", [Commutative]> {
203217
204218 The `addi` operation takes two operands and returns one result, each of
205219 these is required to be the same type. This type may be an integer scalar type,
206- a vector whose element type is integer, or a tensor of integers. It has no
207- standard attributes.
220+ a vector whose element type is integer, or a tensor of integers.
221+
222+ This op supports `nuw`/`nsw` overflow flags which stands stand for
223+ "No Unsigned Wrap" and "No Signed Wrap", respectively. If the `nuw` and/or
224+ `nsw` flags are present, and an unsigned/signed overflow occurs
225+ (respectively), the result is poison.
208226
209227 Example:
210228
211229 ```mlir
212230 // Scalar addition.
213231 %a = arith.addi %b, %c : i64
214232
215- // SIMD vector element-wise addition, e.g. for Intel SSE.
233+ // Scalar addition with overflow flags.
234+ %a = arith.addi %b, %c overflow<nsw, nuw> : i64
235+
236+ // SIMD vector element-wise addition.
216237 %f = arith.addi %g, %h : vector<4xi32>
217238
218239 // Tensor element-wise addition.
@@ -278,21 +299,41 @@ def Arith_AddUIExtendedOp : Arith_Op<"addui_extended", [Pure, Commutative,
278299// SubIOp
279300//===----------------------------------------------------------------------===//
280301
281- def Arith_SubIOp : Arith_TotalIntBinaryOp <"subi"> {
302+ def Arith_SubIOp : Arith_IntBinaryOpWithOverflowFlags <"subi"> {
282303 let summary = [{
283304 Integer subtraction operation.
284305 }];
285306 let description = [{
286- Performs N-bit subtraction on the operands. The operands are interpreted as unsigned
287- bitvectors. The result is represented by a bitvector containing the mathematical
288- value of the subtraction modulo 2^n, where `n` is the bitwidth. Because `arith`
289- integers use a two's complement representation, this operation is applicable on
307+ Performs N-bit subtraction on the operands. The operands are interpreted as unsigned
308+ bitvectors. The result is represented by a bitvector containing the mathematical
309+ value of the subtraction modulo 2^n, where `n` is the bitwidth. Because `arith`
310+ integers use a two's complement representation, this operation is applicable on
290311 both signed and unsigned integer operands.
291312
292313 The `subi` operation takes two operands and returns one result, each of
293- these is required to be the same type. This type may be an integer scalar type,
294- a vector whose element type is integer, or a tensor of integers. It has no
295- standard attributes.
314+ these is required to be the same type. This type may be an integer scalar type,
315+ a vector whose element type is integer, or a tensor of integers.
316+
317+ This op supports `nuw`/`nsw` overflow flags which stands stand for
318+ "No Unsigned Wrap" and "No Signed Wrap", respectively. If the `nuw` and/or
319+ `nsw` flags are present, and an unsigned/signed overflow occurs
320+ (respectively), the result is poison.
321+
322+ Example:
323+
324+ ```mlir
325+ // Scalar subtraction.
326+ %a = arith.subi %b, %c : i64
327+
328+ // Scalar subtraction with overflow flags.
329+ %a = arith.subi %b, %c overflow<nsw, nuw> : i64
330+
331+ // SIMD vector element-wise subtraction.
332+ %f = arith.subi %g, %h : vector<4xi32>
333+
334+ // Tensor element-wise subtraction.
335+ %x = arith.subi %y, %z : tensor<4x?xi8>
336+ ```
296337 }];
297338 let hasFolder = 1;
298339 let hasCanonicalizer = 1;
@@ -302,21 +343,41 @@ def Arith_SubIOp : Arith_TotalIntBinaryOp<"subi"> {
302343// MulIOp
303344//===----------------------------------------------------------------------===//
304345
305- def Arith_MulIOp : Arith_TotalIntBinaryOp <"muli", [Commutative]> {
346+ def Arith_MulIOp : Arith_IntBinaryOpWithOverflowFlags <"muli", [Commutative]> {
306347 let summary = [{
307348 Integer multiplication operation.
308349 }];
309350 let description = [{
310- Performs N-bit multiplication on the operands. The operands are interpreted as
311- unsigned bitvectors. The result is represented by a bitvector containing the
312- mathematical value of the multiplication modulo 2^n, where `n` is the bitwidth.
313- Because `arith` integers use a two's complement representation, this operation is
351+ Performs N-bit multiplication on the operands. The operands are interpreted as
352+ unsigned bitvectors. The result is represented by a bitvector containing the
353+ mathematical value of the multiplication modulo 2^n, where `n` is the bitwidth.
354+ Because `arith` integers use a two's complement representation, this operation is
314355 applicable on both signed and unsigned integer operands.
315356
316357 The `muli` operation takes two operands and returns one result, each of
317- these is required to be the same type. This type may be an integer scalar type,
318- a vector whose element type is integer, or a tensor of integers. It has no
319- standard attributes.
358+ these is required to be the same type. This type may be an integer scalar type,
359+ a vector whose element type is integer, or a tensor of integers.
360+
361+ This op supports `nuw`/`nsw` overflow flags which stands stand for
362+ "No Unsigned Wrap" and "No Signed Wrap", respectively. If the `nuw` and/or
363+ `nsw` flags are present, and an unsigned/signed overflow occurs
364+ (respectively), the result is poison.
365+
366+ Example:
367+
368+ ```mlir
369+ // Scalar multiplication.
370+ %a = arith.muli %b, %c : i64
371+
372+ // Scalar multiplication with overflow flags.
373+ %a = arith.muli %b, %c overflow<nsw, nuw> : i64
374+
375+ // SIMD vector element-wise multiplication.
376+ %f = arith.muli %g, %h : vector<4xi32>
377+
378+ // Tensor element-wise multiplication.
379+ %x = arith.muli %y, %z : tensor<4x?xi8>
380+ ```
320381 }];
321382 let hasFolder = 1;
322383 let hasCanonicalizer = 1;
0 commit comments