[Mlir-commits] [mlir] ed2b1d7 - [mlir][tosa] Add new block-scaled tensor type and support for MXFP CAST (#203583)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Jul 6 05:56:41 PDT 2026


Author: Luke Hutton
Date: 2026-07-06T13:56:36+01:00
New Revision: ed2b1d7920365a59e2f6c01f732157f1144d0a00

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

LOG: [mlir][tosa] Add new block-scaled tensor type and support for MXFP CAST (#203583)

This commit adds a new compound-block scaled tensor type and uses this
type to implement support for MXFP in the CAST operation, as per the
following specification changes:
https://github.com/arm/tosa-specification/pull/50,
https://github.com/arm/tosa-specification/pull/53.

The new block-scaled type is closely modelled after the `quant` dialect
type and supports the following parameters:
- block shape - The size and axis of each block. Support for specifying
constant scale values has not been added in this commit, but will be
added in a later one.
- scale type - The type of the scale value associated with each block.
- value type - The type of the data values in each block.

Example syntax for the new block-scaled type:
```
tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
```

As a pre-requisite for supporting MXFP CAST, the commit also adds new
extensions intended to split the existing EXT-MXFP extension into
separate extensions for each block-scaled type. This allows for more
fine-grained control over which block-scaled types are supported by a
given target. See specification change
https://github.com/arm/tosa-specification/pull/26 for details.

Finally, support for casting to/from the new block-scaled type has been
added, aligning with the behaviour specified in the CAST operation
specification.

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc
    mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
    mlir/include/mlir/Dialect/Tosa/IR/TosaOps.h
    mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
    mlir/include/mlir/Dialect/Tosa/IR/TosaProfileCompliance.h
    mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td
    mlir/lib/Dialect/Tosa/IR/TargetEnv.cpp
    mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
    mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaProfileCompliance.cpp
    mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
    mlir/test/Dialect/Tosa/availability.mlir
    mlir/test/Dialect/Tosa/canonicalize.mlir
    mlir/test/Dialect/Tosa/invalid.mlir
    mlir/test/Dialect/Tosa/invalid_extension.mlir
    mlir/test/Dialect/Tosa/ops.mlir
    mlir/test/Dialect/Tosa/tosa-attach-target.mlir
    mlir/test/Dialect/Tosa/tosa-validation-version-1p0-invalid.mlir
    mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
    mlir/test/Dialect/Tosa/verifier.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc b/mlir/include/mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc
index 45d56416fdba0..ef644845ed937 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc
@@ -1137,7 +1137,125 @@ extensionComplianceMap = {
        {{{fp8e5m2T, fp16T}, SpecificationVersion::V_1_0},
         {{fp8e5m2T, fp32T}, SpecificationVersion::V_1_0},
         {{fp16T, fp8e5m2T}, SpecificationVersion::V_1_0},
-        {{fp32T, fp8e5m2T}, SpecificationVersion::V_1_0}}}}},
+        {{fp32T, fp8e5m2T}, SpecificationVersion::V_1_0}}},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_fp8e4m3},
+       {{{fp8e4m3T, bs32_fp8ue8m0_fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e4m3T, fp8e4m3T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_fp8e5m2},
+       {{{fp8e4m3T, bs32_fp8ue8m0_fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e5m2T, fp8e4m3T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_fp6e3m2},
+       {{{fp8e4m3T, bs32_fp8ue8m0_fp6e3m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e3m2T, fp8e4m3T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_fp6e2m3},
+       {{{fp8e4m3T, bs32_fp8ue8m0_fp6e2m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e2m3T, fp8e4m3T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_fp4e2m1},
+       {{{fp8e4m3T, bs32_fp8ue8m0_fp4e2m1T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp4e2m1T, fp8e4m3T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e4m3, Extension::mx_common, Extension::mx_int8},
+       {{{fp8e4m3T, bs32_fp8ue8m0_mxint8T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_mxint8T, fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_fp8e4m3},
+       {{{fp8e5m2T, bs32_fp8ue8m0_fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e4m3T, fp8e5m2T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_fp8e5m2},
+       {{{fp8e5m2T, bs32_fp8ue8m0_fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e5m2T, fp8e5m2T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_fp6e3m2},
+       {{{fp8e5m2T, bs32_fp8ue8m0_fp6e3m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e3m2T, fp8e5m2T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_fp6e2m3},
+       {{{fp8e5m2T, bs32_fp8ue8m0_fp6e2m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e2m3T, fp8e5m2T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_fp4e2m1},
+       {{{fp8e5m2T, bs32_fp8ue8m0_fp4e2m1T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp4e2m1T, fp8e5m2T},
+         SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::fp8e5m2, Extension::mx_common, Extension::mx_int8},
+       {{{fp8e5m2T, bs32_fp8ue8m0_mxint8T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_mxint8T, fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_fp8e4m3},
+       {{{fp16T, bs32_fp8ue8m0_fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e4m3T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e4m3T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_fp8e5m2},
+       {{{fp16T, bs32_fp8ue8m0_fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e5m2T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e5m2T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_fp6e3m2},
+       {{{fp16T, bs32_fp8ue8m0_fp6e3m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_fp6e3m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e3m2T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e3m2T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_fp6e2m3},
+       {{{fp16T, bs32_fp8ue8m0_fp6e2m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_fp6e2m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e2m3T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e2m3T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_fp4e2m1},
+       {{{fp16T, bs32_fp8ue8m0_fp4e2m1T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_fp4e2m1T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp4e2m1T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp4e2m1T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::mx_common, Extension::mx_int8},
+       {{{fp16T, bs32_fp8ue8m0_mxint8T}, SpecificationVersion::V_1_1_DRAFT},
+        {{fp32T, bs32_fp8ue8m0_mxint8T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_mxint8T, fp16T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_mxint8T, fp32T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_fp8e4m3},
+       {{{bf16T, bs32_fp8ue8m0_fp8e4m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e4m3T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_fp8e5m2},
+       {{{bf16T, bs32_fp8ue8m0_fp8e5m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp8e5m2T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_fp6e3m2},
+       {{{bf16T, bs32_fp8ue8m0_fp6e3m2T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e3m2T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_fp6e2m3},
+       {{{bf16T, bs32_fp8ue8m0_fp6e2m3T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp6e2m3T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_fp4e2m1},
+       {{{bf16T, bs32_fp8ue8m0_fp4e2m1T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_fp4e2m1T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf},
+      {{Extension::bf16, Extension::mx_common, Extension::mx_int8},
+       {{{bf16T, bs32_fp8ue8m0_mxint8T}, SpecificationVersion::V_1_1_DRAFT},
+        {{bs32_fp8ue8m0_mxint8T, bf16T}, SpecificationVersion::V_1_1_DRAFT}},
+       allOf}}},
     {"tosa.cast_from_block_scaled",
      {{{Extension::bf16, Extension::mxfp},
        {{{fp4e2m1T, fp8ue8m0T, bf16T}, SpecificationVersion::V_1_1_DRAFT},

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
index 3c7d870a44879..d527bde997a7d 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td
@@ -257,9 +257,16 @@ class Tosa_I32EnumAttr<string name, string description, string mnemonic,
 // DOUBLEROUND  : Adds double rounding support to the RESCALE operator.
 // INEXACTROUND : Adds inexact rounding support to the RESCALE operator.
 // DYNAMIC      : Removes all Compile Time Constant state for CTC inputs.
-// MXFP         : Microscaling formats.
-// MXFP_CONV    : Microscaling format convolution.
+// MXFP         : Microscaling formats. (Deprecated, this extension will be removed in the future.)
+// MXFP_CONV    : Microscaling format convolution. (Deprecated, this extension will be removed in the future.)
 // SHAPE        : Shape calcuation operators.
+// MX_COMMON    : Base for MXFP microscaling formats.
+// MX_FP4E2M1   : Microscaling format FP4E2M1.
+// MX_FP6E2M3   : Microscaling format FP6E2M3.
+// MX_FP6E3M2   : Microscaling format FP6E3M2.
+// MX_FP8E4M3   : Microscaling format FP8E4M3.
+// MX_FP8E5M2   : Microscaling format FP8E5M2.
+// MX_INT8      : Microscaling format INT8.
 //===----------------------------------------------------------------------===//
 
 def Tosa_NONE : I32EnumAttrCase<"none", 0>;
@@ -295,23 +302,35 @@ def Tosa_EXT_MXFP         : I32EnumAttrCase<"mxfp", 12>;
 def Tosa_EXT_INT64        : I32EnumAttrCase<"int64", 13>;
 def Tosa_EXT_MXFP_CONV    : I32EnumAttrCase<"mxfp_conv", 14>;
 def Tosa_EXT_SHAPE        : I32EnumAttrCase<"shape", 15>;
+def Tosa_EXT_MX_COMMON : I32EnumAttrCase<"mx_common", 16>;
+def Tosa_EXT_MX_FP4E2M1 : I32EnumAttrCase<"mx_fp4e2m1", 17>;
+def Tosa_EXT_MX_FP6E2M3 : I32EnumAttrCase<"mx_fp6e2m3", 18>;
+def Tosa_EXT_MX_FP6E3M2 : I32EnumAttrCase<"mx_fp6e3m2", 19>;
+def Tosa_EXT_MX_FP8E4M3 : I32EnumAttrCase<"mx_fp8e4m3", 20>;
+def Tosa_EXT_MX_FP8E5M2 : I32EnumAttrCase<"mx_fp8e5m2", 21>;
+def Tosa_EXT_MX_INT8 : I32EnumAttrCase<"mx_int8", 22>;
 
 def Tosa_ExtensionAttr
-    : Tosa_I32EnumAttr<"Extension", "supported TOSA extensions", "ext", [
-      Tosa_EXT_NONE, Tosa_EXT_INT16, Tosa_EXT_INT4, Tosa_EXT_BF16,
-      Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_FFT, Tosa_EXT_VARIABLE,
-      Tosa_EXT_CONTROLFLOW, Tosa_EXT_DOUBLEROUND, Tosa_EXT_INEXACTROUND,
-      Tosa_EXT_DYNAMIC, Tosa_EXT_MXFP, Tosa_EXT_INT64, Tosa_EXT_MXFP_CONV,
-      Tosa_EXT_SHAPE,
-    ]> {
+    : Tosa_I32EnumAttr<
+          "Extension", "supported TOSA extensions", "ext",
+          [Tosa_EXT_NONE, Tosa_EXT_INT16, Tosa_EXT_INT4, Tosa_EXT_BF16,
+           Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_FFT, Tosa_EXT_VARIABLE,
+           Tosa_EXT_CONTROLFLOW, Tosa_EXT_DOUBLEROUND, Tosa_EXT_INEXACTROUND,
+           Tosa_EXT_DYNAMIC, Tosa_EXT_MXFP, Tosa_EXT_INT64, Tosa_EXT_MXFP_CONV,
+           Tosa_EXT_SHAPE, Tosa_EXT_MX_COMMON, Tosa_EXT_MX_FP4E2M1,
+           Tosa_EXT_MX_FP6E2M3, Tosa_EXT_MX_FP6E3M2, Tosa_EXT_MX_FP8E4M3,
+           Tosa_EXT_MX_FP8E5M2, Tosa_EXT_MX_INT8]> {
   let extraClassDeclaration = [{
-    static llvm::SmallVector<Extension, 14> getAllValues() {
+    static llvm::SmallVector<Extension, 22> getAllValues() {
       return {
         Extension::int16, Extension::int4, Extension::bf16,
         Extension::fp8e4m3, Extension::fp8e5m2, Extension::fft,
         Extension::variable, Extension::controlflow, Extension::doubleround,
         Extension::inexactround, Extension::dynamic, Extension::mxfp,
-        Extension::int64, Extension::mxfp_conv, Extension::shape
+        Extension::int64, Extension::mxfp_conv, Extension::shape,
+        Extension::mx_common, Extension::mx_fp4e2m1, Extension::mx_fp6e2m3,
+        Extension::mx_fp6e3m2, Extension::mx_fp8e4m3, Extension::mx_fp8e5m2,
+        Extension::mx_int8
       };
     }
   }];
@@ -490,6 +509,7 @@ def Tosa_RoundingModeAttr
     : Tosa_I32EnumAttr<"RoundingMode", "Supported rounding modes", "rounding_mode",
                     [Tosa_ROUNDING_SINGLE_ROUND, Tosa_ROUNDING_INEXACT_ROUND, Tosa_ROUNDING_DOUBLE_ROUND]>;
 
+// Block_size attr is deprecated and will be removed in the future
 def Tosa_BLOCK_SIZE_1 : I32EnumAttrCase<"BLOCK_SIZE_1", 1>;
 def Tosa_BLOCK_SIZE_32 : I32EnumAttrCase<"BLOCK_SIZE_32", 32>;
 
@@ -503,6 +523,29 @@ def Tosa_BlockSizeAttr
   }];
 }
 
+def Tosa_BLOCK_SHAPE_32 : I32EnumAttrCase<"BLOCK_SHAPE_32", 32>;
+
+def Tosa_BlockShape
+    : Tosa_I32Enum<
+          "BlockShape",
+          "Block shape for the block_scaled formats."
+          "The names follow the convention of BLOCK_SHAPE_M where M "
+          "is the block size of the innermost dimension. Similarly, "
+          "BLOCK_SHAPE_MxN indicates block size of N in the innermost "
+          "dimension and block size of M in the next innermost dimension. "
+          "As of now, only 1 dimension (innermost) is supported for "
+          "block-scaling.",
+          [Tosa_BLOCK_SHAPE_32]>;
+
+def Tosa_BlockShapeAttr
+    : EnumAttr<Tosa_Dialect, Tosa_BlockShape, "block_shape"> {
+  let extraClassDeclaration = [{
+    static uint32_t getBlockShapeValue(BlockShape blockShape) {
+      return static_cast<uint32_t>(blockShape);
+    }
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // TOSA Interfaces.
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.h b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.h
index 2d96fb6891139..66c3753899124 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.h
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.h
@@ -92,6 +92,8 @@ class TosaShapeOperatorWithSameRanks
   }
 };
 
+LogicalResult verifyBlockScaledTensorType(Operation &op, mlir::Type type);
+
 } // namespace tosa
 } // namespace OpTrait
 

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
index 8b065a4794c43..3518a62800963 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td
@@ -2764,57 +2764,6 @@ def Tosa_CastOp: Tosa_Op<"cast", [Pure, SameOperandsAndResultShape,
 
   let description = [{
     Casts a tensor from one data type to another.
-    * This table is showing the supported conversions from the TOSA Specification.
-    * The MLIR dialect here can be used to represent other conversions.
-
-    | Mode                     | Input   | Output  |
-    |--------------------------|---------|---------|
-    | fp16 to fp32             | float16 | float32 |
-    | fp16 to int 16           | float16 | int16   |
-    | fp16 to int 32           | float16 | int32   |
-    | fp16 to int 8            | float16 | int8    |
-    | fp32 to fp16             | float32 | float16 |
-    | fp32 to int 16           | float32 | int16   |
-    | fp32 to int 32           | float32 | int32   |
-    | fp32 to int 8            | float32 | int8    |
-    | int 16 to fp16           | int16   | float16 |
-    | int 16 to fp32           | int16   | float32 |
-    | int 32 to fp16           | int32   | float16 |
-    | int 32 to fp32           | int32   | float32 |
-    | int 8 to fp16            | int8    | float16 |
-    | int 8 to fp32            | int8    | float32 |
-    | bool to int 16           | Boolean | int16   |
-    | bool to int 32           | Boolean | int32   |
-    | bool to int 8            | Boolean | int8    |
-    | int 16 to bool           | int16   | Boolean |
-    | int 16 to int 32         | int16   | int32   |
-    | int 16 to int 8          | int16   | int8    |
-    | int 32 to bool           | int32   | Boolean |
-    | int 32 to int 16         | int32   | int16   |
-    | int 32 to int 8          | int32   | int8    |
-    | int 8 to bool            | int8    | Boolean |
-    | int 8 to int 16          | int8    | int16   |
-    | int 8 to int 32          | int8    | int32   |
-    | bf16 to fp32             | bf16    | float32 |
-    | bf16 to int 16           | bf16    | int16   |
-    | bf16 to int 32           | bf16    | int32   |
-    | bf16 to int 8            | bf16    | int8    |
-    | fp32 to bf16             | float32 | bf16    |
-    | int 16 to bf16           | int16   | bf16    |
-    | int 32 to bf16           | int32   | bf16    |
-    | int 8 to bf16            | int8    | bf16    |
-    | bf16 to fp8e4m3          | bf16    | fp8e4m3 |
-    | fp8e4m3 to bf16          | fp8e4m3 | bf16    |
-    | bf16 to fp8e5m2          | bf16    | fp8e5m2 |
-    | fp8e5m2 to bf16          | fp8e5m2 | bf16    |
-    | fp16 to fp8e4m3          | float16 | fp8e4m3 |
-    | fp32 to fp8e4m3          | float32 | fp8e4m3 |
-    | fp8e4m3 to fp16          | fp8e4m3 | float16 |
-    | fp8e4m3 to fp32          | fp8e4m3 | float32 |
-    | fp16 to fp8e5m2          | float16 | fp8e5m2 |
-    | fp32 to fp8e5m2          | float32 | fp8e5m2 |
-    | fp8e5m2 to fp16          | fp8e5m2 | float16 |
-    | fp8e5m2 to fp32          | fp8e5m2 | float32 |
   }];
 
   let arguments = (ins
@@ -2825,19 +2774,25 @@ def Tosa_CastOp: Tosa_Op<"cast", [Pure, SameOperandsAndResultShape,
     Tosa_Tensor:$output
   );
 
-  list<Availability> availability = [
-    Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
-    Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16, Tosa_EXT_INT64]>,
+  list<Availability> availability =
+      [Profile<[Tosa_PRO_INT, Tosa_PRO_FP]>,
+       Extension<[Tosa_EXT_FP8E4M3, Tosa_EXT_FP8E5M2, Tosa_EXT_BF16,
+                  Tosa_EXT_INT64, Tosa_EXT_MX_COMMON, Tosa_EXT_MX_FP4E2M1,
+                  Tosa_EXT_MX_FP6E2M3, Tosa_EXT_MX_FP6E3M2, Tosa_EXT_MX_FP8E4M3,
+                  Tosa_EXT_MX_FP8E5M2, Tosa_EXT_MX_INT8]>,
   ];
 
   let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
 
   let hasFolder = 1;
   let hasCanonicalizer = 1;
+  let hasVerifier = 1;
 }
 
 //===----------------------------------------------------------------------===//
 // Operator: cast_from_block_scaled
+//
+// Note: This operation is deprecated. It will be removed in the future.
 //===----------------------------------------------------------------------===//
 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";
@@ -2846,6 +2801,8 @@ def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled",
     Apply the scales from a scale tensor to the values in a value tensor, casting
     the result to the output type. The block dimension must be the last dimension
     of the tensor.
+
+    Note: This operation is deprecated. It will be removed in the future.
   }];
 
   let arguments = (ins
@@ -2869,6 +2826,8 @@ def Tosa_CastFromBlockScaledOp: Tosa_InferShapedTypeOp<"cast_from_block_scaled",
 
 //===----------------------------------------------------------------------===//
 // Operator: cast_to_block_scaled
+//
+// Note: This operation is deprecated. It will be removed in the future.
 //===----------------------------------------------------------------------===//
 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.";
@@ -2878,6 +2837,8 @@ def Tosa_CastToBlockScaledOp : Tosa_InferShapedTypeOp<"cast_to_block_scaled", [P
     scaled data values from an input tensor. The output tensors are cast to the
     specified scale and value types. The block dimension will be the last dimension
     of the tensor.
+
+    Note: This operation is deprecated. It will be removed in the future.
   }];
 
   let arguments = (ins

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaProfileCompliance.h b/mlir/include/mlir/Dialect/Tosa/IR/TosaProfileCompliance.h
index 0135a651be481..34ccc675c8243 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaProfileCompliance.h
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaProfileCompliance.h
@@ -23,10 +23,22 @@ using namespace mlir::tosa;
 // Type Compilance Definition
 //===----------------------------------------------------------------------===//
 
-typedef struct {
+struct TypeInfo {
+  TypeInfo(mlir::TypeID typeID, uint32_t bitWidth)
+      : typeID(typeID), bitWidth(bitWidth), valueTypeID(mlir::TypeID()),
+        scaleTypeID(mlir::TypeID()), blockShape(std::nullopt) {}
+
+  TypeInfo(mlir::TypeID typeID, uint32_t bitWidth, mlir::TypeID valueTypeID,
+           mlir::TypeID scaleTypeID, tosa::BlockShape blockShape)
+      : typeID(typeID), bitWidth(bitWidth), valueTypeID(valueTypeID),
+        scaleTypeID(scaleTypeID), blockShape(blockShape) {}
+
   mlir::TypeID typeID;
   uint32_t bitWidth;
-} TypeInfo;
+  mlir::TypeID valueTypeID;
+  mlir::TypeID scaleTypeID;
+  std::optional<tosa::BlockShape> blockShape;
+};
 
 enum CheckCondition {
   invalid,
@@ -70,6 +82,12 @@ class ProfileInfoDepot {
 
 private:
   TypeInfo convertTypeToInfo(Type type) {
+    if (auto blockScaledTy = dyn_cast<tosa::BlockScaledType>(type)) {
+      Type valueTy = blockScaledTy.getValueType();
+      Type scaleTy = blockScaledTy.getScaleType();
+      return {type.getTypeID(), tosa::getBitWidth(valueTy), valueTy.getTypeID(),
+              scaleTy.getTypeID(), blockScaledTy.getBlockShape()};
+    }
     return {type.getTypeID(), tosa::getBitWidth(type)};
   }
 
@@ -128,7 +146,9 @@ class TosaProfileCompliance {
       const SmallVector<ArrayRef<T>> &specDefinedProfileSet);
 
   bool isSameTypeInfo(TypeInfo a, TypeInfo b) {
-    return a.typeID == b.typeID && a.bitWidth == b.bitWidth;
+    return a.typeID == b.typeID && a.bitWidth == b.bitWidth &&
+           a.valueTypeID == b.valueTypeID && a.scaleTypeID == b.scaleTypeID &&
+           a.blockShape == b.blockShape;
   }
 
   // Find the required profiles or extensions from the compliance info according
@@ -145,7 +165,7 @@ class TosaProfileCompliance {
   SmallVector<StringRef>
   stringifyProfile(const SmallVector<ArrayRef<T>> &profileSet);
 
-  static llvm::SmallString<7> stringifyTypeInfo(const TypeInfo &typeInfo);
+  static llvm::SmallString<32> stringifyTypeInfo(const TypeInfo &typeInfo);
 
 private:
   template <typename T>

diff  --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td
index b7d9ed45f3a03..69f836cf1b9d3 100644
--- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td
+++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td
@@ -103,15 +103,43 @@ def Tosa_MXInt8
   }];
 }
 
+def Tosa_MXFPValue
+    : AnyTypeOf<[F8E4M3FN, F8E5M2, F4E2M1FN, F6E2M3FN, F6E3M2FN, Tosa_MXInt8],
+                "micro-scaling format number">;
+def Tosa_MXFPScale
+    : AnyTypeOf<[F8E8M0FNU], "micro-scaling format scale number">;
+
+def Tosa_BlockScaled : Tosa_Type<"BlockScaled", "block_scaled"> {
+  let summary = "Block scaled tensor element type.";
+
+  let description = [{
+    This does not specify an implementation type. A tensor of this type is a
+    tensor which has block-scaled quantization applied.
+
+    This compound type is made up of 3 components:
+    `block_shape` - The size and axis of each block. Currently only supports
+      specifying the block size along the innermost dimension.
+    `scale_type` - The type of the scale value associated with each block.
+    `value_type` - The type of the data values in each block.
+
+  }];
+
+  let parameters = (ins
+    EnumParameter<Tosa_BlockShape>:$block_shape,
+    Tosa_MXFPScale:$scale_type,
+    Tosa_MXFPValue:$value_type
+  );
+
+  let assemblyFormat =
+      "`<` $block_shape```:```$scale_type```:```$value_type `>`";
+}
+
 //===----------------------------------------------------------------------===//
 // Multi-category types.
 //===----------------------------------------------------------------------===//
-def Tosa_AnyNumber : AnyTypeOf<[Tosa_Int, Tosa_QuantizedInt, AnyFloat, Tosa_MXInt8],
-                                "number">;
-
-def Tosa_MXFPNumber : AnyTypeOf<[F8E4M3FN, F8E5M2, F4E2M1FN, F6E2M3FN, F6E3M2FN, Tosa_MXInt8],
-                                "micro-scaling format number">;
-def Tosa_MXFPScaleNumber : AnyTypeOf<[F8E8M0FNU], "micro-scaling format scale number">;
+def Tosa_AnyNumber : AnyTypeOf<[Tosa_Int, Tosa_QuantizedInt, AnyFloat,
+                                Tosa_MXInt8, Tosa_BlockScaled],
+                               "number">;
 
 //===----------------------------------------------------------------------===//
 // TOSA Tensor Conformance
@@ -129,16 +157,29 @@ def AtLeastRankOne : And<[
   IsRankedTensorTypePred,
   CPred<"::llvm::cast<::mlir::RankedTensorType>($_self).getRank() >= 1">]>;
 
-class TosaTensorOf<
-    list<Type> allowedTypes, string summary = "tosa-conformant tensor">
-    : TensorOf<allowedTypes, [Or<[HasNo0Dimensions, IsUnrankedTensorTypePred]>], summary>;
-
-class TosaRankedTensorOf<
-    list<Type> allowedTypes, list<Pred> preds = [], string summary = "tosa-conformant ranked tensor">
-    : RankedTensorOf<allowedTypes, !listconcat([HasNo0Dimensions], preds), summary>;
-
-class TosaUnrankedTensorOf<list<Type> allowedTypes, list<Pred> preds = [], string summary = "tosa-conformant unranked tensor">
-    : UnrankedTensorOf<allowedTypes, preds, summary>;
+def IsValidBlockScaledTensorType
+    : CPred<"::mlir::succeeded(::mlir::OpTrait::tosa::"
+            "verifyBlockScaledTensorType($_op, $_self))">;
+
+class TosaTensorOf<list<Type> allowedTypes,
+                   string summary = "tosa-conformant tensor">
+    : TensorOf<allowedTypes,
+               [Or<[HasNo0Dimensions, IsUnrankedTensorTypePred]>,
+                IsValidBlockScaledTensorType],
+               summary>;
+
+class TosaRankedTensorOf<list<Type> allowedTypes, list<Pred> preds = [],
+                         string summary = "tosa-conformant ranked tensor">
+    : RankedTensorOf<
+          allowedTypes,
+          !listconcat([HasNo0Dimensions, IsValidBlockScaledTensorType], preds),
+          summary>;
+
+class TosaUnrankedTensorOf<list<Type> allowedTypes, list<Pred> preds = [],
+                           string summary = "tosa-conformant unranked tensor">
+    : UnrankedTensorOf<allowedTypes,
+                       !listconcat([IsValidBlockScaledTensorType], preds),
+                       summary>;
 
 class TosaTensorRankOf<list<Type> allowedTypes, list<int> ranks>
     : TosaRankedTensorOf<allowedTypes,
@@ -217,32 +258,28 @@ def Tosa_IndexTensor2D : AnyTypeOf<[
 def Tosa_TensorAtLeast1D : AnyTypeOf<[
   Tosa_UnrankedTensor, TosaRankedTensorOf<[Tosa_AnyNumber], [AtLeastRankOne]>], "tosa-conformant tensor of at least rank 1", "::mlir::TensorType">;
 
-def Tosa_MXFPDataTensor3D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPNumber]>,
-  TosaTensorRankOf<[Tosa_MXFPNumber], [3]>
-]>;
-def Tosa_MXFPScaleTensor3D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPScaleNumber]>,
-  TosaTensorRankOf<[Tosa_MXFPScaleNumber], [3]>
-]>;
-def Tosa_MXFPDataTensor4D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPNumber]>,
-  TosaTensorRankOf<[Tosa_MXFPNumber], [4]>
-]>;
-def Tosa_MXFPScaleTensor4D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPScaleNumber]>,
-  TosaTensorRankOf<[Tosa_MXFPScaleNumber], [4]>
-]>;
-def Tosa_MXFPDataTensorAtLeast1D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPNumber]>,
-  TosaRankedTensorOf<[Tosa_MXFPNumber], [AtLeastRankOne]>],
-  "tosa-conformant tensor of at least rank 1", "::mlir::TensorType"
->;
-def Tosa_MXFPScaleTensorAtLeast1D : AnyTypeOf<[
-  TosaUnrankedTensorOf<[Tosa_MXFPScaleNumber]>,
-  TosaRankedTensorOf<[Tosa_MXFPScaleNumber], [AtLeastRankOne]>],
-  "tosa-conformant tensor of at least rank 1", "::mlir::TensorType"
->;
+def Tosa_MXFPDataTensor3D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPValue]>,
+                 TosaTensorRankOf<[Tosa_MXFPValue], [3]>]>;
+def Tosa_MXFPScaleTensor3D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPScale]>,
+                 TosaTensorRankOf<[Tosa_MXFPScale], [3]>]>;
+def Tosa_MXFPDataTensor4D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPValue]>,
+                 TosaTensorRankOf<[Tosa_MXFPValue], [4]>]>;
+def Tosa_MXFPScaleTensor4D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPScale]>,
+                 TosaTensorRankOf<[Tosa_MXFPScale], [4]>]>;
+def Tosa_MXFPDataTensorAtLeast1D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPValue]>,
+                 TosaRankedTensorOf<[Tosa_MXFPValue], [AtLeastRankOne]>],
+                "tosa-conformant tensor of at least rank 1",
+                "::mlir::TensorType">;
+def Tosa_MXFPScaleTensorAtLeast1D
+    : AnyTypeOf<[TosaUnrankedTensorOf<[Tosa_MXFPScale]>,
+                 TosaRankedTensorOf<[Tosa_MXFPScale], [AtLeastRankOne]>],
+                "tosa-conformant tensor of at least rank 1",
+                "::mlir::TensorType">;
 
 //===----------------------------------------------------------------------===//
 // Generic scalar, vector, or tensor of a particular type.

diff  --git a/mlir/lib/Dialect/Tosa/IR/TargetEnv.cpp b/mlir/lib/Dialect/Tosa/IR/TargetEnv.cpp
index dc18fcaa04c8a..56e4901811dcb 100644
--- a/mlir/lib/Dialect/Tosa/IR/TargetEnv.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TargetEnv.cpp
@@ -56,6 +56,13 @@ TosaSpecificationVersion getMinVersion(const Extension &extension) {
   case Extension::int64:
   case Extension::mxfp_conv:
   case Extension::shape:
+  case Extension::mx_common:
+  case Extension::mx_fp4e2m1:
+  case Extension::mx_fp6e2m3:
+  case Extension::mx_fp6e3m2:
+  case Extension::mx_fp8e4m3:
+  case Extension::mx_fp8e5m2:
+  case Extension::mx_int8:
     return TosaSpecificationVersion(1, 1, true);
   case Extension::none:
     return TosaSpecificationVersion(0, 0);
@@ -76,6 +83,13 @@ SmallVector<Profile, 2> getCooperativeProfiles(Extension ext) {
   case Extension::fft:
   case Extension::mxfp:
   case Extension::mxfp_conv:
+  case Extension::mx_common:
+  case Extension::mx_fp4e2m1:
+  case Extension::mx_fp6e2m3:
+  case Extension::mx_fp6e3m2:
+  case Extension::mx_fp8e4m3:
+  case Extension::mx_fp8e5m2:
+  case Extension::mx_int8:
     return {Profile::pro_fp};
   case Extension::variable:
   case Extension::controlflow:

diff  --git a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
index b2c6540aa74e2..4c98aca0ee8d7 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp
@@ -1235,12 +1235,50 @@ struct NonNarrowingCastsOptimization : public OpRewritePattern<tosa::CastOp> {
   }
 };
 
+struct CancellingBlockScaledCastsOptimization
+    : public OpRewritePattern<tosa::CastOp> {
+  using OpRewritePattern<tosa::CastOp>::OpRewritePattern;
+
+  LogicalResult matchAndRewrite(tosa::CastOp castOp,
+                                PatternRewriter &rewriter) const override {
+    const Value outerInput = castOp.getInput();
+    auto innerCastOp = outerInput.getDefiningOp<tosa::CastOp>();
+    if (!innerCastOp)
+      return rewriter.notifyMatchFailure(castOp,
+                                         "input must be a cast operation");
+
+    const Value innerInput = innerCastOp.getInput();
+    const auto innerInputTy = llvm::cast<ShapedType>(innerInput.getType());
+    const auto innerOutputTy = llvm::cast<ShapedType>(innerCastOp.getType());
+    const auto outerOutputTy = llvm::cast<ShapedType>(castOp.getType());
+
+    if (!llvm::isa<tosa::BlockScaledType>(innerInputTy.getElementType()))
+      return rewriter.notifyMatchFailure(
+          castOp, "inner cast input must have block scaled element type");
+
+    if (innerInputTy != outerOutputTy)
+      return rewriter.notifyMatchFailure(
+          castOp, "inner input type must match outer output type");
+
+    const Type innerOutputElemType = innerOutputTy.getElementType();
+    const bool isLosslessCast = isa<Float32Type>(innerOutputElemType);
+    if (!isLosslessCast)
+      return rewriter.notifyMatchFailure(
+          castOp, "avoid cancelling casts that should be lossy");
+
+    rewriter.replaceOp(castOp, innerInput);
+
+    return success();
+  }
+};
+
 void CastOp::getCanonicalizationPatterns(RewritePatternSet &results,
                                          MLIRContext *context) {
-  results.add<NonNarrowingCastsOptimization>(context);
+  results.add<NonNarrowingCastsOptimization,
+              CancellingBlockScaledCastsOptimization>(context);
 }
 
-struct CancellingBlockScaledCastsOptimization
+struct CancellingCastToFromBlockScaledOptimization
     : public OpRewritePattern<tosa::CastToBlockScaledOp> {
   using OpRewritePattern<tosa::CastToBlockScaledOp>::OpRewritePattern;
 
@@ -1286,7 +1324,7 @@ struct CancellingBlockScaledCastsOptimization
 
 void CastToBlockScaledOp::getCanonicalizationPatterns(
     RewritePatternSet &results, MLIRContext *context) {
-  results.add<CancellingBlockScaledCastsOptimization>(context);
+  results.add<CancellingCastToFromBlockScaledOptimization>(context);
 }
 
 struct RowGatherToGather : public OpRewritePattern<tosa::RowGatherOp> {

diff  --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index c4705c8080069..e25774856f59d 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -628,6 +628,8 @@ Value mlir::tosa::createPadConstTensor(OpBuilder &builder, Location loc,
 }
 
 unsigned mlir::tosa::getBitWidth(Type type) {
+  if (auto blockScaledTy = dyn_cast<tosa::BlockScaledType>(type))
+    return getBitWidth(blockScaledTy.getValueType());
   if (dyn_cast<tosa::mxint8Type>(type))
     return 8;
   return type.getIntOrFloatBitWidth();
@@ -734,6 +736,41 @@ LogicalResult mlir::tosa::mxint8Type::convertFromAttribute(
   return cast<IntegerType>(attrType).convertFromAttribute(attr, result);
 }
 
+//===----------------------------------------------------------------------===//
+// TOSA block scaling utilities.
+//===----------------------------------------------------------------------===//
+
+LogicalResult OpTrait::tosa::verifyBlockScaledTensorType(Operation &op,
+                                                         mlir::Type type) {
+  const auto tensorType = llvm::cast<ShapedType>(type);
+  const BlockScaledType elemType =
+      llvm::dyn_cast<BlockScaledType>(tensorType.getElementType());
+  if (!elemType)
+    return success();
+
+  if (!tensorType.hasRank())
+    return success();
+
+  if (tensorType.getRank() == 0)
+    return op.emitError()
+           << "tensor type " << type
+           << " does not support block scaling on scalar tensors";
+
+  const int64_t blockedDimension = tensorType.getShape().back();
+  if (ShapedType::isDynamic(blockedDimension))
+    return success();
+
+  const uint32_t blockSize =
+      BlockShapeAttr::getBlockShapeValue(elemType.getBlockShape());
+  if (blockedDimension % blockSize != 0)
+    return op.emitError()
+           << "tensor type " << type
+           << " blocked dimension must be a multiple of block size, got "
+           << blockedDimension << " and block size " << blockSize;
+
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // TOSA Operator Verifiers.
 //===----------------------------------------------------------------------===//
@@ -5187,6 +5224,34 @@ LogicalResult RescaleOp::inferReturnTypeComponents(
   return success();
 }
 
+LogicalResult CastOp::verify() {
+  const ShapedType inputType = llvm::cast<ShapedType>(getInput().getType());
+  const ShapedType outputType = llvm::cast<ShapedType>(getType());
+  const Type inputElementType = inputType.getElementType();
+  const Type outputElementType = outputType.getElementType();
+
+  const bool inputIsBlockScaled = llvm::isa<BlockScaledType>(inputElementType);
+  const bool outputIsBlockScaled =
+      llvm::isa<BlockScaledType>(outputElementType);
+  if (!inputIsBlockScaled && !outputIsBlockScaled)
+    return success();
+
+  if (inputIsBlockScaled && outputIsBlockScaled)
+    return emitOpError()
+           << "requires exactly one of input or output to have block scaled "
+              "element type";
+
+  const Type scalarElementType =
+      inputIsBlockScaled ? outputElementType : inputElementType;
+  if (!llvm::isa<FloatType>(scalarElementType))
+    return emitOpError()
+           << "requires non-block-scaled element type to be floating-point "
+              "when casting to or from block scaled element type, got "
+           << scalarElementType;
+
+  return success();
+}
+
 LogicalResult CastFromBlockScaledOp::inferReturnTypeComponents(
     MLIRContext *context, ::std::optional<Location> location,
     CastFromBlockScaledOp::Adaptor adaptor,

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaProfileCompliance.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaProfileCompliance.cpp
index 0b4983bea4bc6..348e4ec0ad44c 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaProfileCompliance.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaProfileCompliance.cpp
@@ -8,6 +8,7 @@
 
 #include "mlir/Dialect/Tosa/IR/TosaProfileCompliance.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace mlir;
 using namespace mlir::tosa;
@@ -27,12 +28,42 @@ TosaProfileCompliance::TosaProfileCompliance() {
   const TypeInfo fp8e5m2T = {mlir::Float8E5M2Type::getTypeID(), 8};
 
   // micro-scaling formats
+  // Note: these types exist to suppport the deprecated block_scaled operations
+  // and can be removed once those operations are removed.
   const TypeInfo fp6e2m3T = {mlir::Float6E2M3FNType::getTypeID(), 6};
   const TypeInfo fp6e3m2T = {mlir::Float6E3M2FNType::getTypeID(), 6};
   const TypeInfo fp4e2m1T = {mlir::Float4E2M1FNType::getTypeID(), 4};
   const TypeInfo fp8ue8m0T = {mlir::Float8E8M0FNUType::getTypeID(), 8};
   const TypeInfo mxint8T = {mlir::tosa::mxint8Type::getTypeID(), 8};
 
+  // Block scaled formats
+  const TypeID blockScaledID = mlir::tosa::BlockScaledType::getTypeID();
+  const TypeID fp4e2m1ID = mlir::Float4E2M1FNType::getTypeID();
+  const TypeID fp6e2m3ID = mlir::Float6E2M3FNType::getTypeID();
+  const TypeID fp6e3m2ID = mlir::Float6E3M2FNType::getTypeID();
+  const TypeID fp8e4m3ID = mlir::Float8E4M3FNType::getTypeID();
+  const TypeID fp8e5m2ID = mlir::Float8E5M2Type::getTypeID();
+  const TypeID fp8ue8m0ID = mlir::Float8E8M0FNUType::getTypeID();
+  const TypeID mxint8ID = mlir::tosa::mxint8Type::getTypeID();
+
+  const TypeInfo bs32_fp8ue8m0_fp4e2m1T = {blockScaledID, 4, fp4e2m1ID,
+                                           fp8ue8m0ID,
+                                           tosa::BlockShape::BLOCK_SHAPE_32};
+  const TypeInfo bs32_fp8ue8m0_fp6e2m3T = {blockScaledID, 6, fp6e2m3ID,
+                                           fp8ue8m0ID,
+                                           tosa::BlockShape::BLOCK_SHAPE_32};
+  const TypeInfo bs32_fp8ue8m0_fp6e3m2T = {blockScaledID, 6, fp6e3m2ID,
+                                           fp8ue8m0ID,
+                                           tosa::BlockShape::BLOCK_SHAPE_32};
+  const TypeInfo bs32_fp8ue8m0_fp8e4m3T = {blockScaledID, 8, fp8e4m3ID,
+                                           fp8ue8m0ID,
+                                           tosa::BlockShape::BLOCK_SHAPE_32};
+  const TypeInfo bs32_fp8ue8m0_fp8e5m2T = {blockScaledID, 8, fp8e5m2ID,
+                                           fp8ue8m0ID,
+                                           tosa::BlockShape::BLOCK_SHAPE_32};
+  const TypeInfo bs32_fp8ue8m0_mxint8T = {
+      blockScaledID, 8, mxint8ID, fp8ue8m0ID, tosa::BlockShape::BLOCK_SHAPE_32};
+
 // The profile-based compliance content below is auto-generated by a script
 // in https://github.com/arm/tosa-specification
 #include "mlir/Dialect/Tosa/IR/TosaComplianceData.h.inc"
@@ -687,31 +718,48 @@ SmallVector<StringRef> TosaProfileCompliance::stringifyProfile(
   return debugStrings;
 }
 
-llvm::SmallString<7>
+llvm::SmallString<32>
 TosaProfileCompliance::stringifyTypeInfo(const TypeInfo &typeInfo) {
-  if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
-    return {"i" + llvm::utostr(typeInfo.bitWidth)};
-  }
-  if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
-    return {"f16"};
-  } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
-    return {"f32"};
-  } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
-    return {"bf16"};
-  } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
-    return {"fp8e4m3"};
-  } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
-    return {"fp8e5m2"};
-  } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
-    return {"fp6e2m3"};
-  } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
-    return {"fp6e3m2"};
-  } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
-    return {"fp4e2m1"};
-  } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
-    return {"fp8e8m0"};
-  } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
-    return {"mxint8"};
+  const auto stringifyScalarTypeInfo =
+      [](const TypeInfo &typeInfo) -> llvm::SmallString<32> {
+    if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
+      return {"i" + llvm::utostr(typeInfo.bitWidth)};
+    }
+    if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
+      return {"f16"};
+    } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
+      return {"f32"};
+    } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
+      return {"bf16"};
+    } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
+      return {"fp8e4m3"};
+    } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
+      return {"fp8e5m2"};
+    } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
+      return {"fp6e2m3"};
+    } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
+      return {"fp6e3m2"};
+    } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
+      return {"fp4e2m1"};
+    } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
+      return {"fp8e8m0"};
+    } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
+      return {"mxint8"};
+    }
+    llvm_unreachable("unknown type");
+  };
+
+  if (typeInfo.typeID == tosa::BlockScaledType::getTypeID()) {
+    TypeInfo valueInfo = {typeInfo.valueTypeID, typeInfo.bitWidth};
+    TypeInfo scaleInfo = {typeInfo.scaleTypeID, 8};
+    llvm::SmallString<32> result;
+    llvm::raw_svector_ostream os(result);
+    os << "bs"
+       << tosa::BlockShapeAttr::getBlockShapeValue(typeInfo.blockShape.value())
+       << "_" << stringifyScalarTypeInfo(scaleInfo) << "_"
+       << stringifyScalarTypeInfo(valueInfo);
+    return result;
   }
-  llvm_unreachable("unknown type");
+
+  return stringifyScalarTypeInfo(typeInfo);
 }

diff  --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
index 5d4a2affbd7cd..a3d5d21294b0d 100644
--- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
+++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp
@@ -1495,7 +1495,7 @@ bool TosaValidation::isValidElementType(Type type, const bool allowUnsigned) {
     }
   } else if (isa<tosa::shapeType>(type))
     return true;
-  else if (isa<tosa::mxint8Type>(type))
+  else if (isa<tosa::mxint8Type, tosa::BlockScaledType>(type))
     return true;
   return false;
 }

diff  --git a/mlir/test/Dialect/Tosa/availability.mlir b/mlir/test/Dialect/Tosa/availability.mlir
index f4f31d3f476e8..c358460bbc662 100644
--- a/mlir/test/Dialect/Tosa/availability.mlir
+++ b/mlir/test/Dialect/Tosa/availability.mlir
@@ -637,10 +637,10 @@ func.func @test_resize(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x64x64x8xf32> {
 }
 
 // -----
-// CHECK-LABEL: cast
-func.func @test_cast1(%arg0: tensor<13x21x3xi32>) -> tensor<13x21x3xf32> {
+// CHECK-LABEL: test_cast
+func.func @test_cast(%arg0: tensor<13x21x3xi32>) -> tensor<13x21x3xf32> {
   // CHECK: profiles: [ [pro_int, pro_fp] ]
-  // CHECK: extensions: [ [fp8e4m3, fp8e5m2, bf16, int64] ]
+  // CHECK: extensions: [ [fp8e4m3, fp8e5m2, bf16, int64, mx_common, mx_fp4e2m1, mx_fp6e2m3, mx_fp6e3m2, mx_fp8e4m3, mx_fp8e5m2, mx_int8] ]
   %0 = tosa.cast %arg0 : (tensor<13x21x3xi32>) -> tensor<13x21x3xf32>
   return %0 : tensor<13x21x3xf32>
 }

diff  --git a/mlir/test/Dialect/Tosa/canonicalize.mlir b/mlir/test/Dialect/Tosa/canonicalize.mlir
index 992059e06e541..6a3d84e8d133b 100644
--- a/mlir/test/Dialect/Tosa/canonicalize.mlir
+++ b/mlir/test/Dialect/Tosa/canonicalize.mlir
@@ -1681,6 +1681,73 @@ func.func @test_canonicalize_non_narrowing_cast_i8_to_f8E4M3FN_unsupported(%arg0
 
 // -----
 
+// CHECK-LABEL: @test_canonicalize_cast_from_cast_to_block_scaled_type_f4E2M1
+// CHECK: return %arg0 : tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+func.func @test_canonicalize_cast_from_cast_to_block_scaled_type_f4E2M1(%arg0: tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  %0 = tosa.cast %arg0 : (tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<15x3x2x256xf32>
+  %1 = tosa.cast %0 : (tensor<15x3x2x256xf32>) -> tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %1 : tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+
+// CHECK-LABEL: @test_canonicalize_cast_from_cast_to_block_scaled_type_f8E5M2
+// CHECK: return %arg0 : tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+func.func @test_canonicalize_cast_from_cast_to_block_scaled_type_f8E5M2(%arg0: tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>> {
+  %0 = tosa.cast %arg0 : (tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<160xf32>
+  %1 = tosa.cast %0 : (tensor<160xf32>) -> tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+  return %1 : tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+}
+
+// -----
+
+// CHECK-LABEL: @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_
diff erent_types_f8E5M2_f6E2M3
+// CHECK: %[[values:.+]] = tosa.cast %arg0
+// CHECK: %[[block_scaled:.+]] = tosa.cast %[[values]]
+// CHECK: return %[[block_scaled]] : tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+func.func @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_
diff erent_types_f8E5M2_f6E2M3(%arg0: tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>> {
+  %0 = tosa.cast %arg0 : (tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<160xf32>
+  %1 = tosa.cast %0 : (tensor<160xf32>) -> tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+  return %1 : tensor<160x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+}
+
+// -----
+
+// CHECK-LABEL: @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_
diff erent_types_f6E2M3_f6E3M2
+// CHECK: %[[values:.+]] = tosa.cast %arg0
+// CHECK: %[[block_scaled:.+]] = tosa.cast %[[values]]
+// CHECK: return %[[block_scaled]] : tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>
+func.func @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_
diff erent_types_f6E2M3_f6E3M2(%arg0: tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>> {
+  %0 = tosa.cast %arg0 : (tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<32xf32>
+  %1 = tosa.cast %0 : (tensor<32xf32>) -> tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>
+  return %1 : tensor<32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>
+}
+
+// -----
+
+// CHECK-LABEL: @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_unranked
+// CHECK: %[[values:.+]] = tosa.cast %arg0
+// CHECK: %[[block_scaled:.+]] = tosa.cast %[[values]]
+// CHECK: return %[[block_scaled]] : tensor<*x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+func.func @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_unranked(%arg0: tensor<3x64x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<*x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>> {
+  %0 = tosa.cast %arg0 : (tensor<3x64x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<*xf32>
+  %1 = tosa.cast %0 : (tensor<*xf32>) -> tensor<*x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+  return %1 : tensor<*x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+}
+
+// -----
+
+// CHECK-LABEL: @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_f8E5M2_f8E4M3
+// CHECK: tosa.cast
+// CHECK: tosa.cast
+func.func @test_do_not_canonicalize_cast_from_cast_to_block_scaled_type_f8E5M2_f8E4M3(%arg0: tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>> {
+  %0 = tosa.cast %arg0 : (tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<15x3x2x256xf8E4M3FN>
+  %1 = tosa.cast %0 : (tensor<15x3x2x256xf8E4M3FN>) -> tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+  return %1 : tensor<15x3x2x256x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+}
+
+// -----
+
 // CHECK-LABEL: @test_canonicalize_cast_from_cast_to_block_scaled_f4E2M1
 // CHECK: return %arg0, %arg1 : tensor<15x3x2x256xf4E2M1FN>, tensor<15x3x2x8xf8E8M0FNU>
 func.func @test_canonicalize_cast_from_cast_to_block_scaled_f4E2M1(%arg0: tensor<15x3x2x256xf4E2M1FN>, %arg1: tensor<15x3x2x8xf8E8M0FNU>) -> (tensor<15x3x2x256xf4E2M1FN>, tensor<15x3x2x8xf8E8M0FNU>) {

diff  --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir
index 5e8111061cb3a..d0336da15cee8 100644
--- a/mlir/test/Dialect/Tosa/invalid.mlir
+++ b/mlir/test/Dialect/Tosa/invalid.mlir
@@ -2266,3 +2266,35 @@ func.func @test_shape_func_output() -> !tosa.shape<4> {
   %cst = tosa.const_shape {values = dense<[1, 2, 3, 4]> : tensor<4xindex>} : () -> !tosa.shape<4>
   return %cst : !tosa.shape<4>
 }
+
+// -----
+
+func.func @test_cast_f32_plain_fp4(%arg0: tensor<4x32xf32>) -> tensor<4x32xf4E2M1FN> {
+  // expected-error at +1 {{'tosa.cast' op illegal: operation operand/result data types did not align with any profile or extension, got (f32,fp4e2m1)}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf32>) -> tensor<4x32xf4E2M1FN>
+  return %0 : tensor<4x32xf4E2M1FN>
+}
+
+// -----
+
+func.func @test_cast_fp4_block_scaled(%arg0: tensor<4x32xf4E2M1FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: operation operand/result data types did not align with any profile or extension, got (fp4e2m1,bs32_fp8e8m0_fp4e2m1), did you mean (fp8e4m3,bs32_fp8e8m0_fp4e2m1)? Otherwise, please refer to the 'supported data types' for 'tosa.cast' in the specification.}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf4E2M1FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+
+func.func @test_cast_block_scaled_fp6e2m3(%arg0: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf6E2M3FN> {
+  // expected-error at +1 {{'tosa.cast' op illegal: operation operand/result data types did not align with any profile or extension, got (bs32_fp8e8m0_fp4e2m1,fp6e2m3), did you mean (bs32_fp8e8m0_fp4e2m1,fp8e4m3)? Otherwise, please refer to the 'supported data types' for 'tosa.cast' in the specification.}}
+  %0 = tosa.cast %arg0 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf6E2M3FN>
+  return %0 : tensor<4x32xf6E2M3FN>
+}
+
+// -----
+
+func.func @test_cast_fp6e3m2_block_scaled(%arg0: tensor<4x32xf6E3M2FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: operation operand/result data types did not align with any profile or extension, got (fp6e3m2,bs32_fp8e8m0_mxint8), did you mean (fp8e4m3,bs32_fp8e8m0_mxint8)? Otherwise, please refer to the 'supported data types' for 'tosa.cast' in the specification.}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf6E3M2FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+}

diff  --git a/mlir/test/Dialect/Tosa/invalid_extension.mlir b/mlir/test/Dialect/Tosa/invalid_extension.mlir
index c69ea83f5ef36..5e4dd17b24090 100644
--- a/mlir/test/Dialect/Tosa/invalid_extension.mlir
+++ b/mlir/test/Dialect/Tosa/invalid_extension.mlir
@@ -303,6 +303,34 @@ func.func @test_cast_f32_bf16(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xbf16
   return %0 : tensor<13x21x3xbf16>
 }
 
+// -----
+func.func @test_cast_f32_block_scaled(%arg0: tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: requires all of [mx_common, mx_fp4e2m1] profiles/extensions to be specified in the target environment}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+func.func @test_cast_block_scaled_f32(%arg0: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf32> {
+  // expected-error at +1 {{'tosa.cast' op illegal: requires all of [mx_common, mx_fp4e2m1] profiles/extensions to be specified in the target environment}}
+  %0 = tosa.cast %arg0 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf32>
+  return %0 : tensor<4x32xf32>
+}
+
+// -----
+func.func @test_cast_bf16_block_scaled(%arg0: tensor<4x32xbf16>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: requires all of [bf16, mx_common, mx_fp4e2m1] profiles/extensions to be specified in the target environment}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xbf16>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+func.func @test_cast_fp8_block_scaled(%arg0: tensor<4x32xf8E4M3FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: requires all of [fp8e4m3, mx_common, mx_int8] profiles/extensions to be specified in the target environment}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf8E4M3FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+}
+
 // -----
 func.func @test_fft2d(%arg0: tensor<1x4x8xf32>, %arg1: tensor<1x4x8xf32>) -> (tensor<1x4x8xf32>, tensor<1x4x8xf32>) {
   // expected-error at +1 {{'tosa.fft2d' op illegal: requires any of [fft] profiles/extensions to be specified in the target environment}}

diff  --git a/mlir/test/Dialect/Tosa/ops.mlir b/mlir/test/Dialect/Tosa/ops.mlir
index 262b8aa548506..ec3d0c881d857 100644
--- a/mlir/test/Dialect/Tosa/ops.mlir
+++ b/mlir/test/Dialect/Tosa/ops.mlir
@@ -1179,6 +1179,32 @@ func.func @test_cast3(%arg0: tensor<13x21x3xi32>) -> tensor<13x21x3x!quant.unifo
   return %0 : tensor<13x21x3x!quant.uniform<i16:f32, 0.078431375324726104:128>>
 }
 
+// -----
+// CHECK-LABEL: test_cast_to_block_scaled
+func.func @test_cast_to_block_scaled(%arg0: tensor<4x32xf32>, %arg1: tensor<4x32xbf16>, %arg2: tensor<4x32xf8E4M3FN>) -> (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) {
+  %0 = tosa.cast %arg0 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  %1 = tosa.cast %arg1 : (tensor<4x32xbf16>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>
+  %2 = tosa.cast %arg2 : (tensor<4x32xf8E4M3FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+  return %0, %1, %2 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+}
+
+// -----
+// CHECK-LABEL: test_cast_from_block_scaled
+func.func @test_cast_from_block_scaled(%arg0: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>, %arg1: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>, %arg2: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) -> (tensor<4x32xf32>, tensor<4x32xbf16>, tensor<4x32xf8E5M2>) {
+  %0 = tosa.cast %arg0 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<4x32xf32>
+  %1 = tosa.cast %arg1 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<4x32xbf16>
+  %2 = tosa.cast %arg2 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) -> tensor<4x32xf8E5M2>
+  return %0, %1, %2 : tensor<4x32xf32>, tensor<4x32xbf16>, tensor<4x32xf8E5M2>
+}
+
+// -----
+// CHECK-LABEL: test_cast_block_scaled_dynamic
+func.func @test_cast_block_scaled_dynamic(%arg0: tensor<?x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>, %arg1: tensor<4x?x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> (tensor<?x32xf32>, tensor<4x?xf32>) {
+  %0 = tosa.cast %arg0 : (tensor<?x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<?x32xf32>
+  %1 = tosa.cast %arg1 : (tensor<4x?x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<4x?xf32>
+  return %0, %1 : tensor<?x32xf32>, tensor<4x?xf32>
+}
+
 // -----
 // CHECK-LABEL: rescale
 func.func @test_rescale(%arg0: tensor<13x21x3x!quant.uniform<u8:f32, 0.015655439347028732:127>>) -> tensor<13x21x3x!quant.uniform<i8:f32, 0.015655439347028732:-1>> {

diff  --git a/mlir/test/Dialect/Tosa/tosa-attach-target.mlir b/mlir/test/Dialect/Tosa/tosa-attach-target.mlir
index a0c59c0c4bb3b..558a599fbbc1e 100644
--- a/mlir/test/Dialect/Tosa/tosa-attach-target.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-attach-target.mlir
@@ -1,11 +1,26 @@
-// RUN: mlir-opt %s -split-input-file -tosa-attach-target="profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,doubleround,inexactround,dynamic level=none" | FileCheck %s --check-prefix=CHECK-ALL
+// DEFINE: %{core_extensions} = int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable
+// DEFINE: %{rounding_extensions} = controlflow,doubleround,inexactround,dynamic
+// DEFINE: %{mx_float_extensions} = mx_common,mx_fp4e2m1,mx_fp6e2m3,mx_fp6e3m2
+// DEFINE: %{mx_int_extensions} = mx_fp8e4m3,mx_fp8e5m2,mx_int8
+// DEFINE: %{all_extensions} = %{core_extensions},%{rounding_extensions},%{mx_float_extensions},%{mx_int_extensions}
+// DEFINE: %{all_target} = specification_version=1.1.draft level=none \
+// DEFINE:    profiles=pro_int,pro_fp extensions=%{all_extensions}
+
+// RUN: mlir-opt %s -split-input-file -tosa-attach-target="%{all_target}" | FileCheck %s --check-prefix=CHECK-ALL
 // RUN: mlir-opt %s -split-input-file -tosa-attach-target="level=8k" | FileCheck %s --check-prefix=CHECK-LVL-8K
 // RUN: mlir-opt %s -split-input-file -tosa-attach-target | FileCheck %s --check-prefix=CHECK-DEFAULT
 // RUN: mlir-opt %s -split-input-file -tosa-attach-target="specification_version=1.1.draft" | FileCheck %s --check-prefix=CHECK-VERSION-1P1
 
 // -----
 
-// CHECK-ALL: module attributes {tosa.target_env = #tosa.target_env<specification_version = "1.0", level = none, profiles = [pro_int, pro_fp], extensions = [int16, int4, bf16, fp8e4m3, fp8e5m2, fft, variable, controlflow, doubleround, inexactround, dynamic]>}
+// CHECK-ALL: module attributes {
+// CHECK-ALL-SAME: tosa.target_env = #tosa.target_env<specification_version = "1.1.draft",
+// CHECK-ALL-SAME: level = none,
+// CHECK-ALL-SAME: profiles = [pro_int, pro_fp],
+// CHECK-ALL-SAME: extensions = [int16, int4, bf16, fp8e4m3, fp8e5m2, fft,
+// CHECK-ALL-SAME: variable, controlflow, doubleround, inexactround, dynamic,
+// CHECK-ALL-SAME: mx_common, mx_fp4e2m1, mx_fp6e2m3, mx_fp6e3m2,
+// CHECK-ALL-SAME: mx_fp8e4m3, mx_fp8e5m2, mx_int8]>}
 // CHECK-LVL-8K: module attributes {tosa.target_env = #tosa.target_env<specification_version = "1.0", level = "8k", profiles = [], extensions = []>}
 // CHECK-DEFAULT: module attributes {tosa.target_env = #tosa.target_env<specification_version = "1.0", level = "8k", profiles = [], extensions = []>}
 // CHECK-VERSION-1P1: module attributes {tosa.target_env = #tosa.target_env<specification_version = "1.1.draft", level = "8k", profiles = [], extensions = []>}

diff  --git a/mlir/test/Dialect/Tosa/tosa-validation-version-1p0-invalid.mlir b/mlir/test/Dialect/Tosa/tosa-validation-version-1p0-invalid.mlir
index cbff768ec1ecb..a5e4d4397f290 100644
--- a/mlir/test/Dialect/Tosa/tosa-validation-version-1p0-invalid.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-validation-version-1p0-invalid.mlir
@@ -154,6 +154,14 @@ func.func @test_cast_i64_bool(%arg0: tensor<13x21x3xi64>) -> tensor<13x21x3xi1>
 
 // -----
 
+func.func @test_cast_fp32_block_scaled(%arg0: tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  // expected-error at +1 {{'tosa.cast' op illegal: requires specification version compatible with 1.1.draft (got 1.0)}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+
 func.func @test_dyanmic_dims(%arg0: tensor<?x8x16xi8>) -> tensor<?x16xi32> {
   // expected-error at +1 {{'tosa.argmax' op failed level check: operand shape dimension cannot be dynamic when targeting TOSA specification version 1.0 or below}}
   %0 = tosa.argmax %arg0 { axis = 1 : i32 } : (tensor<?x8x16xi8>) -> tensor<?x16xi32>

diff  --git a/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir b/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
index f4b5ab5dd11fd..e7a4fe6735457 100644
--- a/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
+++ b/mlir/test/Dialect/Tosa/tosa-validation-version-1p1-valid.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt %s -split-input-file -verify-diagnostics -tosa-attach-target="specification_version=1.1.draft profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,doubleround,inexactround,mxfp,int64,mxfp_conv,shape" -tosa-validate="strict-op-spec-alignment" | FileCheck %s
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics -tosa-attach-target="specification_version=1.1.draft profiles=pro_int,pro_fp extensions=int16,int4,bf16,fp8e4m3,fp8e5m2,fft,variable,controlflow,doubleround,inexactround,mxfp,int64,mxfp_conv,shape,mx_common,mx_fp4e2m1,mx_fp6e2m3,mx_fp6e3m2,mx_fp8e4m3,mx_fp8e5m2,mx_int8" -tosa-validate="strict-op-spec-alignment" | FileCheck %s
 
 // -----
 
@@ -389,6 +389,34 @@ func.func @test_cast_i64_bool(%arg0: tensor<13x21x3xi64>) -> tensor<13x21x3xi1>
 
 // -----
 
+// CHECK-LABEL: test_cast_to_block_scaled_types
+func.func @test_cast_to_block_scaled_types(%fp16: tensor<4x32xf16>, %fp32: tensor<4x32xf32>, %bf16: tensor<4x32xbf16>, %fp8e4m3: tensor<4x32xf8E4M3FN>, %fp8e5m2: tensor<4x32xf8E5M2>) -> (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) {
+  %0 = tosa.cast %fp32 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  %1 = tosa.cast %fp32 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+  %2 = tosa.cast %fp32 : (tensor<4x32xf32>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>
+  %3 = tosa.cast %fp16 : (tensor<4x32xf16>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>
+  %4 = tosa.cast %bf16 : (tensor<4x32xbf16>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>
+  %5 = tosa.cast %fp8e4m3 : (tensor<4x32xf8E4M3FN>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+  %6 = tosa.cast %fp8e5m2 : (tensor<4x32xf8E5M2>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>
+  return %0, %1, %2, %3, %4, %5 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>, tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>
+}
+
+// -----
+
+// CHECK-LABEL: test_cast_from_block_scaled_types
+func.func @test_cast_from_block_scaled_types(%fp4: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>, %fp6e2m3: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>, %fp6e3m2: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>, %fp8e4m3: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>, %fp8e5m2: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>, %mxint8: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) -> (tensor<4x32xf32>, tensor<4x32xf16>, tensor<4x32xbf16>, tensor<4x32xf8E4M3FN>, tensor<4x32xf8E5M2>) {
+  %0 = tosa.cast %fp4 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf32>
+  %1 = tosa.cast %fp6e2m3 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E2M3FN>>) -> tensor<4x32xf32>
+  %2 = tosa.cast %fp6e3m2 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f6E3M2FN>>) -> tensor<4x32xf32>
+  %3 = tosa.cast %fp8e4m3 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>) -> tensor<4x32xf16>
+  %4 = tosa.cast %fp8e5m2 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E5M2>>) -> tensor<4x32xbf16>
+  %5 = tosa.cast %mxint8 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:!tosa.mxint8>>) -> tensor<4x32xf8E4M3FN>
+  %6 = tosa.cast %fp4 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xf8E5M2>
+  return %0, %3, %4, %5, %6 : tensor<4x32xf32>, tensor<4x32xf16>, tensor<4x32xbf16>, tensor<4x32xf8E4M3FN>, tensor<4x32xf8E5M2>
+}
+
+// -----
+
 // CHECK-LABEL: test_dynamic_dims
 func.func @test_dynamic_dims(%arg0: tensor<?x8x16xi8>) -> tensor<?x16xi32> {
   %0 = tosa.argmax %arg0 { axis = 1 : i32 } : (tensor<?x8x16xi8>) -> tensor<?x16xi32>

diff  --git a/mlir/test/Dialect/Tosa/verifier.mlir b/mlir/test/Dialect/Tosa/verifier.mlir
index 0eb679ca7ced3..20c0dfd2a094c 100644
--- a/mlir/test/Dialect/Tosa/verifier.mlir
+++ b/mlir/test/Dialect/Tosa/verifier.mlir
@@ -1650,6 +1650,48 @@ func.func @test_cast_to_block_scaled_block_size_mismatch(%arg0: tensor<4x32xf32>
 
 // -----
 
+func.func @test_cast_i8_block_scaled(%arg0: tensor<4x32xi8>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>> {
+  // expected-error at +1 {{'tosa.cast' op requires non-block-scaled element type to be floating-point when casting to or from block scaled element type, got 'i8'}}
+  %0 = tosa.cast %arg0 : (tensor<4x32xi8>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>
+}
+
+// -----
+
+func.func @test_cast_block_scaled_i32(%arg0: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xi32> {
+  // expected-error at +1 {{'tosa.cast' op requires non-block-scaled element type to be floating-point when casting to or from block scaled element type, got 'i32'}}
+  %0 = tosa.cast %arg0 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32xi32>
+  return %0 : tensor<4x32xi32>
+}
+
+// -----
+
+func.func @test_cast_between_block_scaled(%arg0: tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>> {
+  // expected-error at +1 {{'tosa.cast' op requires exactly one of input or output to have block scaled element type}}
+  %0 = tosa.cast %arg0 : (tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f4E2M1FN>>) -> tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>
+  return %0 : tensor<4x32x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>
+}
+
+// -----
+
+func.func @test_block_scaled_cast_invalid_block_shape(%arg0: tensor<1x16x31x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>) -> tensor<1x16x31xf32> {
+  // expected-error at +2 {{tensor type 'tensor<1x16x31x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>' blocked dimension must be a multiple of block size, got 31 and block size 32}}
+  // expected-error at +1 {{'tosa.cast' op operand #0 must be tosa-conformant tensor of number values, but got 'tensor<1x16x31x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>'}}
+  %0 = tosa.cast %arg0 : (tensor<1x16x31x!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>) -> tensor<1x16x31xf32>
+  return %0 : tensor<1x16x31xf32>
+}
+
+// -----
+
+func.func @test_block_scaled_cast_scalar(%arg0: tensor<!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>) -> tensor<f32> {
+  // expected-error at +2 {{tensor type 'tensor<!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>' does not support block scaling on scalar tensors}}
+  // expected-error at +1 {{'tosa.cast' op operand #0 must be tosa-conformant tensor of number values, but got 'tensor<!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>'}}
+  %0 = tosa.cast %arg0 : (tensor<!tosa.block_scaled<BLOCK_SHAPE_32:f8E8M0FNU:f8E4M3FN>>) -> tensor<f32>
+  return %0 : tensor<f32>
+}
+
+// -----
+
 func.func @test_clamp_quantized(%arg0:tensor<?x112x112x32x!quant.uniform<u8:f32, 0.023529412224888802:-128>>) -> (tensor<?x112x112x32x!quant.uniform<u8:f32, 0.023529412224888802:-128>>) {
     // expected-error at +1 {{'tosa.clamp' op min/max attributes types are incompatible with input/output element types.}}
     %0 = tosa.clamp %arg0 {max_val = 127 : i8, min_val = -128 : i8} : (tensor<?x112x112x32x!quant.uniform<u8:f32, 0.023529412224888802:-128>>) -> tensor<?x112x112x32x!quant.uniform<u8:f32, 0.023529412224888802:-128>>


        


More information about the Mlir-commits mailing list