[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