[Mlir-commits] [mlir] 12b7754 - [MLIR][WasmSSA] Add f32/f64.nearest and trapped float to int trunc operations (#193873)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jun 17 04:05:20 PDT 2026


Author: Max Graey
Date: 2026-06-17T20:05:14+09:00
New Revision: 12b775409b1a0c238c3c1c5c0c270d0af23a1852

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

LOG: [MLIR][WasmSSA] Add f32/f64.nearest and trapped float to int trunc operations (#193873)

- `f32.nearest` (wasmssa.nearest)
- `f64.nearest` (wasmssa.nearest)
- `i32.trunc_f32_s` (wasmssa.trunc_si)
- `i32.trunc_f64_s` (wasmssa.trunc_si)
- `i64.trunc_f32_s` (wasmssa.trunc_si)
- `i64.trunc_f64_s` (wasmssa.trunc_si)
- `i32.trunc_f32_u` (wasmssa.trunc_ui)
- `i32.trunc_f64_u` (wasmssa.trunc_ui)
- `i64.trunc_f32_u` (wasmssa.trunc_ui)
- `i64.trunc_f64_u` (wasmssa.trunc_ui)

Added: 
    mlir/test/Target/Wasm/inputs/nearest.yaml.wasm
    mlir/test/Target/Wasm/inputs/trunc_si.yaml.wasm
    mlir/test/Target/Wasm/inputs/trunc_ui.yaml.wasm
    mlir/test/Target/Wasm/nearest.mlir
    mlir/test/Target/Wasm/trunc_si.mlir
    mlir/test/Target/Wasm/trunc_ui.mlir

Modified: 
    mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
    mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
    mlir/lib/Target/Wasm/TranslateFromWasm.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
index 835515d5199b1..a18731f4fd285 100644
--- a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
+++ b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
@@ -1027,6 +1027,34 @@ def WasmSSA_ConvertSOp : WasmSSA_ConversionOp<"convert_s",
     [WasmSSA_IntegerType],
     [WasmSSA_FPType]>{}
 
+def WasmSSA_TruncSIOp : WasmSSA_ConversionOp<"trunc_si",
+    [{Truncate floating point value to signed integer.
+
+    Consume a floating point value and produces a signed integer holding the value truncated toward zero.
+    Traps if the value is NaN, is infinity, or is outside the range of the target integer type.}],
+    [{Example:
+
+     ```mlir
+     %a = wasmssa.trunc_si %b : f32 to i32
+     ```
+    }],
+    [WasmSSA_FPType],
+    [WasmSSA_IntegerType]>{}
+
+def WasmSSA_TruncUIOp : WasmSSA_ConversionOp<"trunc_ui",
+    [{Truncate floating point value to unsigned integer.
+
+    Consume a floating point value and produces an unsigned integer holding the value truncated toward zero.
+    Traps if the value is NaN, is infinity, is negative, or is outside the range of the target integer type.}],
+    [{Example:
+
+     ```mlir
+     %a = wasmssa.trunc_ui %b : f32 to i32
+     ```
+    }],
+    [WasmSSA_FPType],
+    [WasmSSA_IntegerType]>{}
+
 def WasmSSA_DemoteOp : WasmSSA_ConversionOp<"demote",
     "Convert a f64 value to f32",
     [{Example:
@@ -1198,6 +1226,16 @@ def WasmSSA_TruncOp : WasmSSA_UnaryNumericalOp<"trunc",
                                         }],
                                        [WasmSSA_FPType]>{}
 
+def WasmSSA_NearestOp : WasmSSA_UnaryNumericalOp<"nearest",
+                                       "Round floating point value to the nearest integer, ties to even",
+                                        [{Example:
+
+                                         ```mlir
+                                         %a = wasmssa.nearest %b : f32
+                                         ```
+                                        }],
+                                       [WasmSSA_FPType]>{}
+
 def WasmSSA_CtzOp : WasmSSA_UnaryNumericalOp<"ctz",
                                        "Count trailing zeroes of an integer",
                                         [{Example:

diff  --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
index cd9ef5b2132a4..fcaec612f913d 100644
--- a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
+++ b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
@@ -115,6 +115,7 @@ struct WasmBinaryEncoding {
     static constexpr std::byte ceilF32{0x8D};
     static constexpr std::byte floorF32{0x8E};
     static constexpr std::byte truncF32{0x8F};
+    static constexpr std::byte nearestF32{0x90};
     static constexpr std::byte sqrtF32{0x91};
     static constexpr std::byte addF32{0x92};
     static constexpr std::byte subF32{0x93};
@@ -128,6 +129,7 @@ struct WasmBinaryEncoding {
     static constexpr std::byte ceilF64{0x9B};
     static constexpr std::byte floorF64{0x9C};
     static constexpr std::byte truncF64{0x9D};
+    static constexpr std::byte nearestF64{0x9E};
     static constexpr std::byte sqrtF64{0x9F};
     static constexpr std::byte addF64{0xA0};
     static constexpr std::byte subF64{0xA1};
@@ -139,8 +141,16 @@ struct WasmBinaryEncoding {
     static constexpr std::byte wrap{0xA7};
 
     // Conversion operations
+    static constexpr std::byte truncSI32F32{0xA8};
+    static constexpr std::byte truncUI32F32{0xA9};
+    static constexpr std::byte truncSI32F64{0xAA};
+    static constexpr std::byte truncUI32F64{0xAB};
     static constexpr std::byte extendS{0xAC};
     static constexpr std::byte extendU{0xAD};
+    static constexpr std::byte truncSI64F32{0xAE};
+    static constexpr std::byte truncUI64F32{0xAF};
+    static constexpr std::byte truncSI64F64{0xB0};
+    static constexpr std::byte truncUI64F64{0xB1};
     static constexpr std::byte convertSI32F32{0xB2};
     static constexpr std::byte convertUI32F32{0xB3};
     static constexpr std::byte convertSI64F32{0xB4};

diff  --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 048e964037558..1a0d53f1207f6 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -1361,6 +1361,7 @@ BUILD_NUMERIC_BINOP_INTFP(SubOp, sub)
 BUILD_NUMERIC_UNARY_OP_FP(AbsOp, abs)
 BUILD_NUMERIC_UNARY_OP_FP(CeilOp, ceil)
 BUILD_NUMERIC_UNARY_OP_FP(FloorOp, floor)
+BUILD_NUMERIC_UNARY_OP_FP(NearestOp, nearest)
 BUILD_NUMERIC_UNARY_OP_FP(NegOp, neg)
 BUILD_NUMERIC_UNARY_OP_FP(SqrtOp, sqrt)
 BUILD_NUMERIC_UNARY_OP_FP(TruncOp, trunc)
@@ -1428,6 +1429,17 @@ BUILD_CONVERT_OP_FOR(double, 64)
 
 #undef BUILD_CONVERT_OP_FOR
 
+#define BUILD_TRUNC_OP_FOR(SRC_T, WIDTH)                                       \
+  BUILD_CONVERSION_OP(SRC_T, int32_t, truncSI32F##WIDTH, TruncSIOp)            \
+  BUILD_CONVERSION_OP(SRC_T, uint32_t, truncUI32F##WIDTH, TruncUIOp)           \
+  BUILD_CONVERSION_OP(SRC_T, int64_t, truncSI64F##WIDTH, TruncSIOp)            \
+  BUILD_CONVERSION_OP(SRC_T, uint64_t, truncUI64F##WIDTH, TruncUIOp)
+
+BUILD_TRUNC_OP_FOR(float, 32)
+BUILD_TRUNC_OP_FOR(double, 64)
+
+#undef BUILD_TRUNC_OP_FOR
+
 BUILD_CONVERSION_OP(int32_t, int64_t, extendS, ExtendSI32Op)
 BUILD_CONVERSION_OP(int32_t, int64_t, extendU, ExtendUI32Op)
 

diff  --git a/mlir/test/Target/Wasm/inputs/nearest.yaml.wasm b/mlir/test/Target/Wasm/inputs/nearest.yaml.wasm
new file mode 100644
index 0000000000000..97b99530289a8
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/nearest.yaml.wasm
@@ -0,0 +1,33 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - F32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - F64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 1 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            nearest_f32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            nearest_f64
+        Kind:            FUNCTION
+        Index:           1
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            4300002041900B
+      - Index:           1
+        Locals:          []
+        Body:            4400000000000024409E0B
+...

diff  --git a/mlir/test/Target/Wasm/inputs/trunc_si.yaml.wasm b/mlir/test/Target/Wasm/inputs/trunc_si.yaml.wasm
new file mode 100644
index 0000000000000..590122675aa1f
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/trunc_si.yaml.wasm
@@ -0,0 +1,45 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - I64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 1, 1 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            trunc_si_f32_to_i32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            trunc_si_f64_to_i32
+        Kind:            FUNCTION
+        Index:           1
+      - Name:            trunc_si_f32_to_i64
+        Kind:            FUNCTION
+        Index:           2
+      - Name:            trunc_si_f64_to_i64
+        Kind:            FUNCTION
+        Index:           3
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            4300002041A80B
+      - Index:           1
+        Locals:          []
+        Body:            440000000000002440AA0B
+      - Index:           2
+        Locals:          []
+        Body:            4300002041AE0B
+      - Index:           3
+        Locals:          []
+        Body:            440000000000002440B00B
+...

diff  --git a/mlir/test/Target/Wasm/inputs/trunc_ui.yaml.wasm b/mlir/test/Target/Wasm/inputs/trunc_ui.yaml.wasm
new file mode 100644
index 0000000000000..492b06d3dac95
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/trunc_ui.yaml.wasm
@@ -0,0 +1,45 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - I64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 1, 1 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            trunc_ui_f32_to_i32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            trunc_ui_f64_to_i32
+        Kind:            FUNCTION
+        Index:           1
+      - Name:            trunc_ui_f32_to_i64
+        Kind:            FUNCTION
+        Index:           2
+      - Name:            trunc_ui_f64_to_i64
+        Kind:            FUNCTION
+        Index:           3
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            4300002041A90B
+      - Index:           1
+        Locals:          []
+        Body:            440000000000002440AB0B
+      - Index:           2
+        Locals:          []
+        Body:            4300002041AF0B
+      - Index:           3
+        Locals:          []
+        Body:            440000000000002440B10B
+...

diff  --git a/mlir/test/Target/Wasm/nearest.mlir b/mlir/test/Target/Wasm/nearest.mlir
new file mode 100644
index 0000000000000..9acd1c4569ebb
--- /dev/null
+++ b/mlir/test/Target/Wasm/nearest.mlir
@@ -0,0 +1,25 @@
+// RUN: yaml2obj %S/inputs/nearest.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to generate this test:
+(module
+    (func (export "nearest_f32") (result f32)
+        f32.const 10
+        f32.nearest
+    )
+
+    (func (export "nearest_f64") (result f64)
+        f64.const 10
+        f64.nearest
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func exported @nearest_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.nearest %[[VAL_0]] : f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func exported @nearest_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.nearest %[[VAL_0]] : f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64

diff  --git a/mlir/test/Target/Wasm/trunc_si.mlir b/mlir/test/Target/Wasm/trunc_si.mlir
new file mode 100644
index 0000000000000..2d246ccc27ea1
--- /dev/null
+++ b/mlir/test/Target/Wasm/trunc_si.mlir
@@ -0,0 +1,45 @@
+// RUN: yaml2obj %S/inputs/trunc_si.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to generate this test:
+(module
+    (func (export "trunc_si_f32_to_i32") (result i32)
+        f32.const 10
+        i32.trunc_f32_s
+    )
+
+    (func (export "trunc_si_f64_to_i32") (result i32)
+        f64.const 10
+        i32.trunc_f64_s
+    )
+
+    (func (export "trunc_si_f32_to_i64") (result i64)
+        f32.const 10
+        i64.trunc_f32_s
+    )
+
+    (func (export "trunc_si_f64_to_i64") (result i64)
+        f64.const 10
+        i64.trunc_f64_s
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_si_f32_to_i32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_si %[[VAL_0]] : f32 to i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_si_f64_to_i32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_si %[[VAL_0]] : f64 to i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_si_f32_to_i64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_si %[[VAL_0]] : f32 to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_si_f64_to_i64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_si %[[VAL_0]] : f64 to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64

diff  --git a/mlir/test/Target/Wasm/trunc_ui.mlir b/mlir/test/Target/Wasm/trunc_ui.mlir
new file mode 100644
index 0000000000000..9e929b648e745
--- /dev/null
+++ b/mlir/test/Target/Wasm/trunc_ui.mlir
@@ -0,0 +1,45 @@
+// RUN: yaml2obj %S/inputs/trunc_ui.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to generate this test:
+(module
+    (func (export "trunc_ui_f32_to_i32") (result i32)
+        f32.const 10
+        i32.trunc_f32_u
+    )
+
+    (func (export "trunc_ui_f64_to_i32") (result i32)
+        f64.const 10
+        i32.trunc_f64_u
+    )
+
+    (func (export "trunc_ui_f32_to_i64") (result i64)
+        f32.const 10
+        i64.trunc_f32_u
+    )
+
+    (func (export "trunc_ui_f64_to_i64") (result i64)
+        f64.const 10
+        i64.trunc_f64_u
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_ui_f32_to_i32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_ui %[[VAL_0]] : f32 to i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_ui_f64_to_i32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_ui %[[VAL_0]] : f64 to i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_ui_f32_to_i64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_ui %[[VAL_0]] : f32 to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func exported @trunc_ui_f64_to_i64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc_ui %[[VAL_0]] : f64 to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64


        


More information about the Mlir-commits mailing list