[Mlir-commits] [mlir] 9a42e5b - [mlir][tosa] Remove 'Pure' trait from operations that are not speculatable (#185700)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Mar 17 05:48:11 PDT 2026


Author: Luke Hutton
Date: 2026-03-17T12:48:06Z
New Revision: 9a42e5ba6fd8d4b57f04381101b0ff6c4caf906d

URL: https://github.com/llvm/llvm-project/commit/9a42e5ba6fd8d4b57f04381101b0ff6c4caf906d
DIFF: https://github.com/llvm/llvm-project/commit/9a42e5ba6fd8d4b57f04381101b0ff6c4caf906d.diff

LOG: [mlir][tosa] Remove 'Pure' trait from operations that are not speculatable (#185700)

This commit removes the 'Pure' trait from a number of TOSA operations.
Instead of marking most ops as pure by default, the trait is now opt-in
for operations that are provably side-effect free and speculatable.

Several operations were previously marked as pure unintentionally.

The following operations have had 'Pure' removed (reason in brackets):
- ARGMAX (out-of-range index)
- AVG_POOL2D (accumulator overflow/underflow)
- AVG_POOL2D_ADAPTIVE (same as above)
- CONV2D (accumulator overflow/underflow)
- CONV2D_BLOCK_SCALED (accumulator overflow/underflow)
- CONV3D (accumulator overflow/underflow)
- DEPTHWISE_CONV2D (accumulator overflow/underflow)
- MATMUL (accumulator overflow/underflow)
- MATMUL_T_BLOCK_SCALED (accumulator overflow/underflow)
- TRANSPOSE_CONV2D (accumulator overflow/underflow)
- ADD (overflow)
- SUB (underflow)
- MUL (invalid shift, overflow)
- ARITHMETIC_RIGHT_SHIFT (invalid shift value)
- LOGICAL_LEFT_SHIFT (invalid shift value)
- LOGICAL_RIGHT_SHIFT (invalid shift value)
- INTDIV (division by zero)
- POW (negative exponent restrictions)
- TABLE (invalid slope computation)
- ABS (underflow)
- NEGATE (overflow/underflow)
- REDUCE_PRODUCT (overflow)
- REDUCE_SUM (overflow)
- GATHER (out-of-range indices)
- SCATTER (out-of-range or duplicate indices)
- RESCALE (overflow/underflow)

Many of these operations can exhibit undefined behaviour when a
`REQUIRE` condition in the TOSA specification pseudocode fails. Whether
such failures result in a runtime error is implementation-defined. As a
result, speculating or reordering these operations can change program
behaviour.

For this reason, the `AlwaysSpeculatable` property implied by `Pure` is
not valid for these ops. The `NoMemoryEffect` trait is retained, as
these operations do not have direct memory side effects.

Added: 
    

Modified: 
    mlir/docs/Dialects/TOSA.md
    mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
    mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td

Removed: 
    


################################################################################
diff  --git a/mlir/docs/Dialects/TOSA.md b/mlir/docs/Dialects/TOSA.md
index 15a2b459f8b91e..695d4d4210c78c 100644
--- a/mlir/docs/Dialects/TOSA.md
+++ b/mlir/docs/Dialects/TOSA.md
@@ -113,3 +113,23 @@ scheme vs the other.
 ## Operation definitions
 
 [include "Dialects/TosaOps.md"]
+
+### Operation purity
+Some TOSA operations may exhibit undefined behaviour. In the TOSA specification
+this is indicated by a `REQUIRE` condition in the operation pesudo-code. An
+implementation is not required to detect unpredictable behaviour, see
+[Section 4.3](https://www.mlplatform.org/tosa/tosa_spec_1_0_0.html#_operator_validation_helpers).
+
+If an operation can exhibit undefined behaviour, speculating or reordering it
+may change program behaviour. For example, `INTDIV` may exhibit undefined
+behaviour if the divisor is zero. If such an operation were speculated it could
+be executed in situations where the original program would not have executed
+it.
+
+Therefore, operations that may exhibit undefined behaviour must not declare
+the `AlwaysSpeculatable` trait and should not be treated as `Pure`.
+
+Conversely, most TOSA operations are functional tensor computations and do not
+mutate external system resources. These operations therefore typically declare
+the `NoMemoryEffect` trait. Variable operations are an example of an exception
+to this rule.

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
index 1498fad2f08e00..9df17ed89b818c 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
@@ -549,7 +549,7 @@ class Tosa_ElementwiseOp<string mnemonic, list<Trait> traits = []> :
               ResultsBroadcastableShape,
               TosaElementwiseOperator,
               SameOperandsAndResultRank,
-              Pure])> {}
+              NoMemoryEffect])> {}
 
 class Tosa_ElementwiseUnaryOp<string mnemonic, list<Trait> traits = []> :
     Tosa_ElementwiseOp<mnemonic, !listconcat(traits, [
@@ -557,16 +557,16 @@ class Tosa_ElementwiseUnaryOp<string mnemonic, list<Trait> traits = []> :
               SameOperandsAndResultElementType])> {}
 
 class Tosa_InferTensorTypeOp<string mnemonic, list<Trait> traits = []>
-    : Tosa_Op<mnemonic, !listconcat(traits, [InferTensorTypeAdaptor, Pure])> {}
+    : Tosa_Op<mnemonic, !listconcat(traits, [InferTensorTypeAdaptor])> {}
 
 class Tosa_InferShapedTypeOp<string mnemonic, list<Trait> traits = []>
-    : Tosa_Op<mnemonic, !listconcat(traits, [InferShapedTypeOpAdaptor, Pure])> {}
+    : Tosa_Op<mnemonic, !listconcat(traits, [InferShapedTypeOpAdaptor])> {}
 
 // The "SameVariadicOperandSize" trait allows us to pass optional arguments
 // for multiple zero points in convolution ops.
 class Tosa_ConvOp<string mnemonic, list<Trait> traits = []>
     : Tosa_InferShapedTypeOp<mnemonic, !listconcat(traits,
-      [SameVariadicOperandSize])> {
+      [SameVariadicOperandSize, NoMemoryEffect])> {
   let assemblyFormat =
       "operands attr-dict `:` functional-type(operands, results)";
 }

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
index 0005b6f5a0c634..cab2bccfc27b33 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
@@ -32,13 +32,16 @@ include "mlir/Dialect/Tosa/IR/TosaOpBase.td"
 //===----------------------------------------------------------------------===//
 // Operator: argmax
 //===----------------------------------------------------------------------===//
-def Tosa_ArgMaxOp : Tosa_InferShapedTypeOp<"argmax"> {
+def Tosa_ArgMaxOp : Tosa_InferShapedTypeOp<"argmax", [NoMemoryEffect]> {
   let summary = "Perform argmax on the input.";
 
   let description = [{
     This returns the index with the largest value across the given axis of the
     input tensor. If multiple locations have equal values, returns the first
     match along the search axis.
+
+    This operation is not pure. Undefined behaviour may occur if the max index
+    is out of bounds for the output data type.
   }];
 
   let arguments = (ins
@@ -70,7 +73,7 @@ def Tosa_AccType : AnyTypeOf<[I<32>, I<48>, F16, F32]>;
 //===----------------------------------------------------------------------===//
 // Operator: avg_pool2d
 //===----------------------------------------------------------------------===//
-def Tosa_AvgPool2dOp : Tosa_InferShapedTypeOp<"avg_pool2d"> {
+def Tosa_AvgPool2dOp : Tosa_InferShapedTypeOp<"avg_pool2d", [NoMemoryEffect]> {
   let summary = "Performs average pooling on the input.";
 
   let description = [{
@@ -79,6 +82,9 @@ def Tosa_AvgPool2dOp : Tosa_InferShapedTypeOp<"avg_pool2d"> {
     the mean value being placed in the output tensor. When calculating the
     average, only the number of valid input tensor values, but not padding, are
     used to calculate the divisor.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -125,6 +131,9 @@ def Tosa_Conv2DOp : Tosa_ConvOp<"conv2d"> {
     Performs a 2D convolution over the given tensor input, using the weight
     tensor. Implementations may choose to skip calculation of multiplies in
     the padding area.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -166,13 +175,16 @@ def Tosa_Conv2DOp : Tosa_ConvOp<"conv2d"> {
 //===----------------------------------------------------------------------===//
 // Operator: conv2d_block_scaled
 //===----------------------------------------------------------------------===//
-def Tosa_Conv2DBlockScaledOp : Tosa_InferShapedTypeOp<"conv2d_block_scaled"> {
+def Tosa_Conv2DBlockScaledOp : Tosa_InferShapedTypeOp<"conv2d_block_scaled", [NoMemoryEffect]> {
   let summary = "Performs two dimensional convolution using block scaled tensors.";
 
   let description = [{
     Performs a 2D convolution over the given input data and scales, using
     the weight data and scales. Implementations may choose to skip calculation
     of multiplies in the padding area.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -209,6 +221,9 @@ def Tosa_Conv3DOp : Tosa_ConvOp<"conv3d"> {
   let description = [{
     Performs a 3D convolution over the given input tensor. Implementations
     may choose to skip calculation of multiplies in the padding area.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -255,6 +270,9 @@ def Tosa_DepthwiseConv2DOp : Tosa_ConvOp<"depthwise_conv2d"> {
     Performs 2D convolutions separately over each channel of the given tensor
     input, using the weight tensor. Implementations may choose to skip
     calculation of multiplies in the padding area.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -299,7 +317,8 @@ def Tosa_DepthwiseConv2DOp : Tosa_ConvOp<"depthwise_conv2d"> {
 def Tosa_FFT2dOp : Tosa_InferShapedTypeOp<"fft2d", [
     SameOperandsAndResultElementType,
     SameOperandsAndResultShape,
-    ResultsAreFloatLike]> {
+    ResultsAreFloatLike,
+    Pure]> {
   let summary = "Performs FFT2D operation on the input.";
 
   let description = [{
@@ -348,11 +367,14 @@ def Tosa_FFT2dOp : Tosa_InferShapedTypeOp<"fft2d", [
 //===----------------------------------------------------------------------===//
 // Operator: matmul
 //===----------------------------------------------------------------------===//
-def Tosa_MatMulOp : Tosa_InferShapedTypeOp<"matmul"> {
+def Tosa_MatMulOp : Tosa_InferShapedTypeOp<"matmul", [NoMemoryEffect]> {
   let summary = "Matrix multiplication operator.";
 
   let description = [{
     Performs two dimensional matrix multiplications.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -388,7 +410,7 @@ def Tosa_MatMulOp : Tosa_InferShapedTypeOp<"matmul"> {
 //===----------------------------------------------------------------------===//
 // Operator: matmul_t_block_scaled
 //===----------------------------------------------------------------------===//
-def Tosa_MatmulTBlockScaledOp : Tosa_InferShapedTypeOp<"matmul_t_block_scaled"> {
+def Tosa_MatmulTBlockScaledOp : Tosa_InferShapedTypeOp<"matmul_t_block_scaled", [NoMemoryEffect]> {
   let summary = "Performs two dimensional matrix multiplications using block scaled tensors.";
 
   let description = [{
@@ -396,6 +418,9 @@ def Tosa_MatmulTBlockScaledOp : Tosa_InferShapedTypeOp<"matmul_t_block_scaled">
     dimension is always the the last dimension of the tensor, so the result is effectively
     a matrix multiply of A by the transposed B matrix. If the N dimension of input B is of
     size 1, the B matrix will be broadcast.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -422,7 +447,7 @@ def Tosa_MatmulTBlockScaledOp : Tosa_InferShapedTypeOp<"matmul_t_block_scaled">
 //===----------------------------------------------------------------------===//
 // Operator: max_pool2d
 //===----------------------------------------------------------------------===//
-def Tosa_MaxPool2dOp : Tosa_InferShapedTypeOp<"max_pool2d"> {
+def Tosa_MaxPool2dOp : Tosa_InferShapedTypeOp<"max_pool2d", [Pure]> {
   let summary = "Performs max pooling on the input.";
 
   let description = [{
@@ -460,7 +485,8 @@ def Tosa_MaxPool2dOp : Tosa_InferShapedTypeOp<"max_pool2d"> {
 //===----------------------------------------------------------------------===//
 def Tosa_RFFT2dOp : Tosa_InferShapedTypeOp<"rfft2d", [
     SameOperandsAndResultElementType,
-    ResultsAreFloatLike]> {
+    ResultsAreFloatLike,
+    Pure]> {
   let summary = "Performs RFFT2D operation on the input.";
 
   let description = [{
@@ -515,6 +541,9 @@ def Tosa_TransposeConv2DOp : Tosa_ConvOp<"transpose_conv2d"> {
     Performs a 2D transposed convolution over the given tensor input, using the
     weights tensor. Implementations may choose to skip calculation of multiplies
     by zero at fractional input positions.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -557,7 +586,7 @@ def Tosa_TransposeConv2DOp : Tosa_ConvOp<"transpose_conv2d"> {
 //===----------------------------------------------------------------------===//
 // Operator: clamp
 //===----------------------------------------------------------------------===//
-def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp"> {
+def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp", [Pure]> {
   let summary = "Computes clamp(features, min, max).";
 
   let description = [{
@@ -592,7 +621,7 @@ def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp"> {
 //===----------------------------------------------------------------------===//
 // Operator: erf
 //===----------------------------------------------------------------------===//
-def Tosa_ErfOp : Tosa_ElementwiseUnaryOp<"erf"> {
+def Tosa_ErfOp : Tosa_ElementwiseUnaryOp<"erf", [Pure]> {
   let summary = "Computes gauss error function of input.";
 
   let description = [{
@@ -621,7 +650,7 @@ def Tosa_ErfOp : Tosa_ElementwiseUnaryOp<"erf"> {
 //===----------------------------------------------------------------------===//
 // Operator: sigmoid
 //===----------------------------------------------------------------------===//
-def Tosa_SigmoidOp : Tosa_ElementwiseUnaryOp<"sigmoid"> {
+def Tosa_SigmoidOp : Tosa_ElementwiseUnaryOp<"sigmoid", [Pure]> {
   let summary = "Computes elementwise sigmoid of input.";
 
   let description = [{
@@ -653,7 +682,7 @@ def Tosa_SigmoidOp : Tosa_ElementwiseUnaryOp<"sigmoid"> {
 //===----------------------------------------------------------------------===//
 // Operator: tanh
 //===----------------------------------------------------------------------===//
-def Tosa_TanhOp : Tosa_ElementwiseUnaryOp<"tanh"> {
+def Tosa_TanhOp : Tosa_ElementwiseUnaryOp<"tanh", [Pure]> {
   let summary = "Computes elementwise hyperbolic tangent of input.";
 
   let description = [{
@@ -697,6 +726,9 @@ def Tosa_AddOp : Tosa_ElementwiseOp<"add", [
     Elementwise addition of input1 and input2. Axis of size 1 will be broadcast,
     as necessary. Rank of input tensors must match.
 
+    This operation is not pure. Undefined behaviour may occur if the calculated
+    result overflows.
+
     Example:
 
     ```mlir
@@ -738,6 +770,9 @@ def Tosa_ArithmeticRightShiftOp : Tosa_ElementwiseOp<"arithmetic_right_shift",
     Elementwise arithmetic right shift of input1 by the amount specified in
     input2. Axis of size 1 will be broadcast, as necessary. Rank of input tensors
     must match.
+
+    This operation is not pure. Undefined behaviour may occur if the specified
+    shift is out of range.
   }];
 
   let arguments = (ins
@@ -763,7 +798,8 @@ def Tosa_ArithmeticRightShiftOp : Tosa_ElementwiseOp<"arithmetic_right_shift",
 //===----------------------------------------------------------------------===//
 def Tosa_BitwiseAndOp : Tosa_ElementwiseOp<"bitwise_and", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Bitwise AND operator.";
 
   let description = [{
@@ -793,7 +829,8 @@ def Tosa_BitwiseAndOp : Tosa_ElementwiseOp<"bitwise_and", [
 //===----------------------------------------------------------------------===//
 def Tosa_BitwiseOrOp : Tosa_ElementwiseOp<"bitwise_or", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Bitwise OR operator.";
 
   let description = [{
@@ -823,7 +860,8 @@ def Tosa_BitwiseOrOp : Tosa_ElementwiseOp<"bitwise_or", [
 //===----------------------------------------------------------------------===//
 def Tosa_BitwiseXorOp : Tosa_ElementwiseOp<"bitwise_xor", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Bitwise XOR operator.";
 
   let description = [{
@@ -860,6 +898,8 @@ def Tosa_IntDivOp : Tosa_ElementwiseOp<"intdiv", [SameOperandsAndResultElementTy
     divide is truncated towards zero. Expected use is for operations on
     non-scaled integers. Floating point divide should use RECIPROCAL and MUL.
     Quantized integer divide should use TABLE (for 1/x) and MUL.
+
+    This operation is not pure. Undefined behaviour may occur on division by zero.
   }];
 
   let arguments = (ins
@@ -886,7 +926,8 @@ def Tosa_IntDivOp : Tosa_ElementwiseOp<"intdiv", [SameOperandsAndResultElementTy
 //===----------------------------------------------------------------------===//
 def Tosa_LogicalAndOp : Tosa_ElementwiseOp<"logical_and", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Returns the truth value of input1 AND input2 element-wise.";
 
   let description = [{
@@ -922,6 +963,9 @@ def Tosa_LogicalLeftShiftOp : Tosa_ElementwiseOp<"logical_left_shift",
     Elementwise logical left-shift of input1 by the amount specified in input2.
     Axis of size 1 will be broadcast, as necessary.
     Rank of input tensors must match.
+
+    This operation is not pure. Undefined behaviour may occur if the specified
+    shift is out of range.
   }];
 
   let arguments = (ins
@@ -952,6 +996,9 @@ def Tosa_LogicalRightShiftOp : Tosa_ElementwiseOp<"logical_right_shift",
     Elementwise logical right shift of input1 by the amount specified in input2.
     Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
     match.
+
+    This operation is not pure. Undefined behaviour may occur if the specified
+    shift is out of range.
   }];
 
   let arguments = (ins
@@ -976,7 +1023,8 @@ def Tosa_LogicalRightShiftOp : Tosa_ElementwiseOp<"logical_right_shift",
 //===----------------------------------------------------------------------===//
 def Tosa_LogicalOrOp : Tosa_ElementwiseOp<"logical_or", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Returns the truth value of x OR y element-wise.";
 
   let description = [{
@@ -1006,7 +1054,8 @@ def Tosa_LogicalOrOp : Tosa_ElementwiseOp<"logical_or", [
 //===----------------------------------------------------------------------===//
 def Tosa_LogicalXorOp : Tosa_ElementwiseOp<"logical_xor", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Returns the truth value of input1 XOR input2 element-wise.";
 
   let description = [{
@@ -1036,7 +1085,8 @@ def Tosa_LogicalXorOp : Tosa_ElementwiseOp<"logical_xor", [
 //===----------------------------------------------------------------------===//
 def Tosa_MaximumOp : Tosa_ElementwiseOp<"maximum", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Elementwise Maximum.";
 
   let description = [{
@@ -1066,7 +1116,8 @@ def Tosa_MaximumOp : Tosa_ElementwiseOp<"maximum", [
 //===----------------------------------------------------------------------===//
 def Tosa_MinimumOp : Tosa_ElementwiseOp<"minimum", [
     Commutative,
-    SameOperandsAndResultElementType]> {
+    SameOperandsAndResultElementType,
+    Pure]> {
   let summary = "Elementwise Minimum.";
 
   let description = [{
@@ -1098,13 +1149,16 @@ def Tosa_MinimumOp : Tosa_ElementwiseOp<"minimum", [
 def Tosa_MulOp : Tosa_Op<"mul", [
     DeclareOpInterfaceMethods<InferShapedTypeOpInterface,
                               ["inferReturnTypeComponents"]>,
-    Pure]> {
+    NoMemoryEffect]> {
   let summary = "Multiplication operator.";
 
   let description = [{
     Elementwise multiplication (Hadamard product) of input1 and input2.
     Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
     match.
+
+    This operation is not pure. Undefined behaviour may occur if the specifed
+    shift is out of range or the result overflows.
   }];
 
   let arguments = (ins
@@ -1140,6 +1194,9 @@ def Tosa_PowOp : Tosa_ElementwiseOp<"pow", [SameOperandsAndResultElementType]> {
     Elementwise input1 value raised to the power of input2.
     Axis of size 1 will be broadcast, as necessary. Rank of input tensors must
     match.
+
+    This operation is not pure. Undefined behaviour may occur if specified
+    exponent is negative.
   }];
 
   let arguments = (ins
@@ -1168,6 +1225,9 @@ def Tosa_SubOp : Tosa_ElementwiseOp<"sub", [SameOperandsAndResultElementType]> {
   let description = [{
     Elementwise subtraction of input1 and input2. Axis of size 1 will be
     broadcast as necessary. Rank of input tensors must match.
+
+    This operation is not pure. Undefined behaviour may occur if the calculated
+    result underflows.
   }];
 
   let arguments = (ins
@@ -1192,7 +1252,7 @@ def Tosa_SubOp : Tosa_ElementwiseOp<"sub", [SameOperandsAndResultElementType]> {
 //===----------------------------------------------------------------------===//
 // Operator: table
 //===----------------------------------------------------------------------===//
-def Tosa_TableOp : Tosa_InferShapedTypeOp<"table"> {
+def Tosa_TableOp : Tosa_InferShapedTypeOp<"table", [NoMemoryEffect]> {
   let summary = "Table lookup operator.";
 
   let description = [{
@@ -1210,6 +1270,9 @@ def Tosa_TableOp : Tosa_InferShapedTypeOp<"table"> {
     * Use the TABLE operator to produce a fixed point 16.7 interpolated result
     * Use RESCALE (in_t=int32_t, out_t=int16_t, scale=1<<14, shift=21) to
       scale the output to int16_t range (or alternate scale as required)
+
+    This operation is not pure. Undefined behaviour may occur if the calculated
+    slope is out of range.
   }];
 
   let arguments = (ins
@@ -1243,12 +1306,15 @@ def Tosa_TableOp : Tosa_InferShapedTypeOp<"table"> {
 //===----------------------------------------------------------------------===//
 // Operator: abs
 //===----------------------------------------------------------------------===//
-def Tosa_AbsOp : Tosa_ElementwiseUnaryOp<"abs"> {
+def Tosa_AbsOp : Tosa_ElementwiseUnaryOp<"abs", [NoMemoryEffect]> {
   let summary = "Elementwise abs operator.";
 
   let description = [{
     Elementwise absolute value operation.
 
+    This operation is not pure. Undefined behaviour may occur if the
+    calculated result underflows.
+
     Example:
 
     ```mlir
@@ -1277,7 +1343,7 @@ def Tosa_AbsOp : Tosa_ElementwiseUnaryOp<"abs"> {
 //===----------------------------------------------------------------------===//
 // Operator: bitwise_not
 //===----------------------------------------------------------------------===//
-def Tosa_BitwiseNotOp : Tosa_ElementwiseUnaryOp<"bitwise_not"> {
+def Tosa_BitwiseNotOp : Tosa_ElementwiseUnaryOp<"bitwise_not", [Pure]> {
   let summary = "Bitwise NOT operator.";
 
   let description = [{
@@ -1303,7 +1369,7 @@ def Tosa_BitwiseNotOp : Tosa_ElementwiseUnaryOp<"bitwise_not"> {
 //===----------------------------------------------------------------------===//
 // Operator: ceil
 //===----------------------------------------------------------------------===//
-def Tosa_CeilOp : Tosa_ElementwiseUnaryOp<"ceil"> {
+def Tosa_CeilOp : Tosa_ElementwiseUnaryOp<"ceil", [Pure]> {
   let summary = "Elementwise ceil operator.";
 
   let description = [{
@@ -1329,7 +1395,7 @@ def Tosa_CeilOp : Tosa_ElementwiseUnaryOp<"ceil"> {
 //===----------------------------------------------------------------------===//
 // Operator: clz
 //===----------------------------------------------------------------------===//
-def Tosa_ClzOp : Tosa_ElementwiseUnaryOp<"clz"> {
+def Tosa_ClzOp : Tosa_ElementwiseUnaryOp<"clz", [Pure]> {
   let summary = "Elementwise count leading zero operator.";
 
   let description = [{
@@ -1355,7 +1421,7 @@ def Tosa_ClzOp : Tosa_ElementwiseUnaryOp<"clz"> {
 //===----------------------------------------------------------------------===//
 // Operator: cos
 //===----------------------------------------------------------------------===//
-def Tosa_CosOp : Tosa_ElementwiseUnaryOp<"cos"> {
+def Tosa_CosOp : Tosa_ElementwiseUnaryOp<"cos", [Pure]> {
   let summary = "Elementwise cos operator.";
 
   let description = [{
@@ -1381,7 +1447,7 @@ def Tosa_CosOp : Tosa_ElementwiseUnaryOp<"cos"> {
 //===----------------------------------------------------------------------===//
 // Operator: exp
 //===----------------------------------------------------------------------===//
-def Tosa_ExpOp : Tosa_ElementwiseUnaryOp<"exp"> {
+def Tosa_ExpOp : Tosa_ElementwiseUnaryOp<"exp", [Pure]> {
   let summary = "Elementwise exp operator.";
 
   let description = [{
@@ -1407,7 +1473,7 @@ def Tosa_ExpOp : Tosa_ElementwiseUnaryOp<"exp"> {
 //===----------------------------------------------------------------------===//
 // Operator: floor
 //===----------------------------------------------------------------------===//
-def Tosa_FloorOp : Tosa_ElementwiseUnaryOp<"floor"> {
+def Tosa_FloorOp : Tosa_ElementwiseUnaryOp<"floor", [Pure]> {
   let summary = "Elementwise floor operator.";
 
   let description = [{
@@ -1433,7 +1499,7 @@ def Tosa_FloorOp : Tosa_ElementwiseUnaryOp<"floor"> {
 //===----------------------------------------------------------------------===//
 // Operator: log
 //===----------------------------------------------------------------------===//
-def Tosa_LogOp : Tosa_ElementwiseUnaryOp<"log"> {
+def Tosa_LogOp : Tosa_ElementwiseUnaryOp<"log", [Pure]> {
   let summary = "Elementwise log operator.";
 
   let description = [{
@@ -1459,7 +1525,7 @@ def Tosa_LogOp : Tosa_ElementwiseUnaryOp<"log"> {
 //===----------------------------------------------------------------------===//
 // Operator: logical_not
 //===----------------------------------------------------------------------===//
-def Tosa_LogicalNotOp : Tosa_ElementwiseUnaryOp<"logical_not"> {
+def Tosa_LogicalNotOp : Tosa_ElementwiseUnaryOp<"logical_not", [Pure]> {
   let summary = "Returns the truth value of NOT input1 element-wise.";
 
   let description = [{
@@ -1487,11 +1553,14 @@ def Tosa_LogicalNotOp : Tosa_ElementwiseUnaryOp<"logical_not"> {
 //===----------------------------------------------------------------------===//
 def Tosa_NegateOp : Tosa_InferShapedTypeOp<"negate", [
     TosaElementwiseOperator,
-    Pure]> {
+    NoMemoryEffect]> {
   let summary = "Elementwise negate operator.";
 
   let description = [{
     Elementwise negation operation.
+
+    This operation is not pure. Undefined behaviour may occur if the calculated
+    result underflows or overflows.
   }];
 
   let arguments = (ins
@@ -1528,7 +1597,7 @@ def Tosa_NegateOp : Tosa_InferShapedTypeOp<"negate", [
 //===----------------------------------------------------------------------===//
 // Operator: reciprocal
 //===----------------------------------------------------------------------===//
-def Tosa_ReciprocalOp : Tosa_ElementwiseUnaryOp<"reciprocal"> {
+def Tosa_ReciprocalOp : Tosa_ElementwiseUnaryOp<"reciprocal", [Pure]> {
   let summary = "Elementwise reciprocal operator.";
 
   let description = [{
@@ -1566,7 +1635,7 @@ def Tosa_ReciprocalOp : Tosa_ElementwiseUnaryOp<"reciprocal"> {
 //===----------------------------------------------------------------------===//
 // Operator: rsqrt
 //===----------------------------------------------------------------------===//
-def Tosa_RsqrtOp : Tosa_ElementwiseUnaryOp<"rsqrt"> {
+def Tosa_RsqrtOp : Tosa_ElementwiseUnaryOp<"rsqrt", [Pure]> {
   let summary = "Elementwise 1/sqrt operator.";
 
   let description = [{
@@ -1593,7 +1662,7 @@ def Tosa_RsqrtOp : Tosa_ElementwiseUnaryOp<"rsqrt"> {
 //===----------------------------------------------------------------------===//
 // Operator: sin
 //===----------------------------------------------------------------------===//
-def Tosa_SinOp : Tosa_ElementwiseUnaryOp<"sin"> {
+def Tosa_SinOp : Tosa_ElementwiseUnaryOp<"sin", [Pure]> {
   let summary = "Elementwise sin operator.";
 
   let description = [{
@@ -1623,7 +1692,7 @@ def Tosa_SinOp : Tosa_ElementwiseUnaryOp<"sin"> {
 //===----------------------------------------------------------------------===//
 // Operator: select
 //===----------------------------------------------------------------------===//
-def Tosa_SelectOp : Tosa_ElementwiseOp<"select"> {
+def Tosa_SelectOp : Tosa_ElementwiseOp<"select", [Pure]> {
   let summary = "Elementwise select operator.";
 
   let description = [{
@@ -1674,7 +1743,8 @@ def Tosa_SelectOp : Tosa_ElementwiseOp<"select"> {
 def Tosa_EqualOp : Tosa_ElementwiseOp<"equal", [
     InferTensorType,
     Commutative,
-    SameOperandsElementType]> {
+    SameOperandsElementType,
+    Pure]> {
   let summary = "Returns the truth value of (input1 == input2) element-wise.";
 
   let description = [{
@@ -1709,7 +1779,8 @@ def Tosa_EqualOp : Tosa_ElementwiseOp<"equal", [
 //===----------------------------------------------------------------------===//
 // Operator: greater
 //===----------------------------------------------------------------------===//
-def Tosa_GreaterOp : Tosa_ElementwiseOp<"greater", [SameOperandsElementType]> {
+def Tosa_GreaterOp : Tosa_ElementwiseOp<"greater", [SameOperandsElementType,
+    Pure]> {
   let summary = "Returns the truth value of (input1 > input2) element-wise.";
 
   let description = [{
@@ -1739,7 +1810,7 @@ def Tosa_GreaterOp : Tosa_ElementwiseOp<"greater", [SameOperandsElementType]> {
 // Operator: greater_equal
 //===----------------------------------------------------------------------===//
 def Tosa_GreaterEqualOp : Tosa_ElementwiseOp<"greater_equal",
-    [SameOperandsElementType]> {
+    [SameOperandsElementType, Pure]> {
   let summary = "Returns the truth value of (input1 >= input2) element-wise.";
 
   let description = [{
@@ -1772,7 +1843,7 @@ def Tosa_GreaterEqualOp : Tosa_ElementwiseOp<"greater_equal",
 //===----------------------------------------------------------------------===//
 // Operator: reduce_all
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceAllOp : Tosa_InferTensorTypeOp<"reduce_all"> {
+def Tosa_ReduceAllOp : Tosa_InferTensorTypeOp<"reduce_all", [Pure]> {
   let summary = "Reduce All operator.";
 
   let description = [{
@@ -1813,7 +1884,7 @@ def Tosa_ReduceAllOp : Tosa_InferTensorTypeOp<"reduce_all"> {
 //===----------------------------------------------------------------------===//
 // Operator: reduce_any
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceAnyOp : Tosa_InferTensorTypeOp<"reduce_any"> {
+def Tosa_ReduceAnyOp : Tosa_InferTensorTypeOp<"reduce_any", [Pure]> {
   let summary = "Reduce Any operator.";
 
   let description = [{
@@ -1854,7 +1925,7 @@ def Tosa_ReduceAnyOp : Tosa_InferTensorTypeOp<"reduce_any"> {
 //===----------------------------------------------------------------------===//
 // Operator: reduce_max
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceMaxOp : Tosa_InferTensorTypeOp<"reduce_max"> {
+def Tosa_ReduceMaxOp : Tosa_InferTensorTypeOp<"reduce_max", [Pure]> {
   let summary = "Reduce Max operator.";
 
   let description = [{
@@ -1896,7 +1967,7 @@ def Tosa_ReduceMaxOp : Tosa_InferTensorTypeOp<"reduce_max"> {
 //===----------------------------------------------------------------------===//
 // Operator: reduce_min
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceMinOp : Tosa_InferTensorTypeOp<"reduce_min"> {
+def Tosa_ReduceMinOp : Tosa_InferTensorTypeOp<"reduce_min", [Pure]> {
   let summary = "Reduce Min operator.";
 
   let description = [{
@@ -1936,13 +2007,16 @@ def Tosa_ReduceMinOp : Tosa_InferTensorTypeOp<"reduce_min"> {
 }
 
 //===----------------------------------------------------------------------===//
-// Operator: reduce_prod
+// Operator: reduce_product
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceProductOp : Tosa_InferTensorTypeOp<"reduce_product"> {
+def Tosa_ReduceProductOp : Tosa_InferTensorTypeOp<"reduce_product", [NoMemoryEffect]> {
   let summary = "Reduce Product operator.";
 
   let description = [{
     Reduce a tensor along the given axis by computing the product of the axis.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -1979,11 +2053,14 @@ def Tosa_ReduceProductOp : Tosa_InferTensorTypeOp<"reduce_product"> {
 //===----------------------------------------------------------------------===//
 // Operator: reduce_sum
 //===----------------------------------------------------------------------===//
-def Tosa_ReduceSumOp : Tosa_InferTensorTypeOp<"reduce_sum"> {
+def Tosa_ReduceSumOp : Tosa_InferTensorTypeOp<"reduce_sum", [NoMemoryEffect]> {
   let summary = "Reduce Sum operator.";
 
   let description = [{
     Reduce a tensor along the given axis by computing the sum of the axis.
+
+    This operation is not pure. Undefined behaviour may occur if the accumulated
+    result overflows.
   }];
 
   let arguments = (ins
@@ -2024,7 +2101,7 @@ def Tosa_ReduceSumOp : Tosa_InferTensorTypeOp<"reduce_sum"> {
 //===----------------------------------------------------------------------===//
 // Operator: concat
 //===----------------------------------------------------------------------===//
-def Tosa_ConcatOp : Tosa_InferTensorTypeOp<"concat"> {
+def Tosa_ConcatOp : Tosa_InferTensorTypeOp<"concat", [Pure]> {
   let summary = "Concatenates tensors along one dimension.";
 
   let description = [{
@@ -2062,7 +2139,7 @@ def Tosa_ConcatOp : Tosa_InferTensorTypeOp<"concat"> {
 //===----------------------------------------------------------------------===//
 // Operator: pad
 //===----------------------------------------------------------------------===//
-def Tosa_PadOp : Tosa_InferShapedTypeOp<"pad"> {
+def Tosa_PadOp : Tosa_InferShapedTypeOp<"pad", [Pure]> {
   let summary = "Pads a tensor with value specified.";
 
   let description = [{
@@ -2114,7 +2191,7 @@ def Tosa_PadOp : Tosa_InferShapedTypeOp<"pad"> {
 //===----------------------------------------------------------------------===//
 // Operator: reshape
 //===----------------------------------------------------------------------===//
-def Tosa_ReshapeOp : Tosa_InferTensorTypeOp<"reshape"> {
+def Tosa_ReshapeOp : Tosa_InferTensorTypeOp<"reshape", [Pure]> {
   let summary = "Reshape operator.";
 
   let description = [{
@@ -2186,7 +2263,7 @@ def Tosa_ReverseOp: Tosa_Op<"reverse", [
 //===----------------------------------------------------------------------===//
 // Operator: slice
 //===----------------------------------------------------------------------===//
-def Tosa_SliceOp : Tosa_InferShapedTypeOp<"slice"> {
+def Tosa_SliceOp : Tosa_InferShapedTypeOp<"slice", [Pure]> {
   let summary = "Slice operator.";
 
   let description = [{
@@ -2221,7 +2298,7 @@ def Tosa_SliceOp : Tosa_InferShapedTypeOp<"slice"> {
 //===----------------------------------------------------------------------===//
 // Operator: tile
 //===----------------------------------------------------------------------===//
-def Tosa_TileOp : Tosa_InferShapedTypeOp<"tile"> {
+def Tosa_TileOp : Tosa_InferShapedTypeOp<"tile", [Pure]> {
   let summary = "Tile operator.";
 
   let description = [{
@@ -2258,7 +2335,8 @@ def Tosa_TileOp : Tosa_InferShapedTypeOp<"tile"> {
 def Tosa_TransposeOp : Tosa_InferShapedTypeOp<"transpose",
                 [DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface ,
                                            ["reifyResultShapes"]>,
-                 AllElementTypesMatch<["input1", "output"]>]> {
+                 AllElementTypesMatch<["input1", "output"]>,
+                 Pure]> {
   let summary = "Transpose operator.";
 
   let description = [{
@@ -2296,7 +2374,7 @@ def Tosa_TransposeOp : Tosa_InferShapedTypeOp<"transpose",
 //===----------------------------------------------------------------------===//
 // Operator: gather
 //===----------------------------------------------------------------------===//
-def Tosa_GatherOp : Tosa_InferShapedTypeOp<"gather"> {
+def Tosa_GatherOp : Tosa_InferShapedTypeOp<"gather", [NoMemoryEffect]> {
   let summary = "Gather operation.";
 
   let description = [{
@@ -2304,6 +2382,9 @@ def Tosa_GatherOp : Tosa_InferShapedTypeOp<"gather"> {
     values tensor based on the indices. N is the number of batches, W the number
     of indices in each batch, K the range of each index and C the number data
     channels for each index.
+
+    This operation is not pure. Undefined behaviour may occur if the specified
+    indices are out of range.
   }];
 
   let arguments = (ins
@@ -2329,7 +2410,7 @@ def Tosa_GatherOp : Tosa_InferShapedTypeOp<"gather"> {
 //===----------------------------------------------------------------------===//
 // Operator: scatter
 //===----------------------------------------------------------------------===//
-def Tosa_ScatterOp : Tosa_InferShapedTypeOp<"scatter"> {
+def Tosa_ScatterOp : Tosa_InferShapedTypeOp<"scatter", [NoMemoryEffect]> {
   let summary = "Scatter operation.";
 
   let description = [{
@@ -2341,6 +2422,9 @@ def Tosa_ScatterOp : Tosa_InferShapedTypeOp<"scatter"> {
     single SCATTER operation and so each output index occurs at most once. It
     follows that K >= W. In use cases that require multiple updates to the same
     output position, these must be decomposed into multiple SCATTER operations.
+
+    This operation is not pure. Undefined behaviour may occur if the specified
+    indices are out of range or duplicate indices are provided.
   }];
 
   let arguments = (ins
@@ -2371,7 +2455,7 @@ def Tosa_ScatterOp : Tosa_InferShapedTypeOp<"scatter"> {
 //===----------------------------------------------------------------------===//
 // Operator: resize
 //===----------------------------------------------------------------------===//
-def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize"> {
+def Tosa_ResizeOp : Tosa_InferShapedTypeOp<"resize", [Pure]> {
   let summary = "Resize operation, supports various resize/upsample modes.";
 
   let description = [{
@@ -2513,7 +2597,7 @@ def Tosa_CastOp: Tosa_Op<"cast", [Pure, SameOperandsAndResultShape,
 //===----------------------------------------------------------------------===//
 // Operator: cast_from_block_scaled
 //===----------------------------------------------------------------------===//
-def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled"> {
+def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled", [Pure]> {
   let summary = "Apply scales from a scale tensor to the values in a value tensor";
 
   let description = [{
@@ -2544,7 +2628,7 @@ def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled">
 //===----------------------------------------------------------------------===//
 // Operator: cast_to_block_scaled
 //===----------------------------------------------------------------------===//
-def Tosa_CastToBlockScaledOp : Tosa_InferShapedTypeOp<"cast_to_block_scaled"> {
+def Tosa_CastToBlockScaledOp : Tosa_InferShapedTypeOp<"cast_to_block_scaled", [Pure]> {
   let summary = "Calculate scale tensor values per block, output to separate scale and data tensors.";
 
   let description = [{
@@ -2576,7 +2660,7 @@ def Tosa_CastToBlockScaledOp : Tosa_InferShapedTypeOp<"cast_to_block_scaled"> {
 //===----------------------------------------------------------------------===//
 // Operator: rescale
 //===----------------------------------------------------------------------===//
-def Tosa_RescaleOp : Tosa_InferShapedTypeOp<"rescale"> {
+def Tosa_RescaleOp : Tosa_InferShapedTypeOp<"rescale", [NoMemoryEffect]> {
   let summary = "Tosa rescale operator.";
 
   let description = [{
@@ -2592,6 +2676,9 @@ def Tosa_RescaleOp : Tosa_InferShapedTypeOp<"rescale"> {
     The shift and value range are limited to allow a variety of implementations. The limit
     of 62 on shift allows the shift to be decomposed as two right shifts of 31.
 
+    This operation is not pure. Undefined behaviour may occur if the calculated
+    result underflows or overflows.
+
     Supported rescalings:
     * This table is showing the supported conversions from the TOSA Specification.
     * The MLIR dialect here can be used to represent other conversions.


        


More information about the Mlir-commits mailing list