[Mlir-commits] [mlir] [MLIR][WASM] Introduce the RaiseWasmMLIRPass to lower WasmSSA MLIR to core dialects (PR #164562)
    Ferdinand Lemaire 
    llvmlistbot at llvm.org
       
    Tue Oct 21 23:58:43 PDT 2025
    
    
  
https://github.com/flemairen6 created https://github.com/llvm/llvm-project/pull/164562
This is following https://github.com/llvm/llvm-project/pull/154674 and still related to https://discourse.llvm.org/t/rfc-mlir-dialect-for-webassembly/86758.
This PR introduces the RaiseWasmMLIRPass. This pass lowers WasmSSA MLIR to other dialects of the LLVM ecosystem (namely: arith, math, cf and memref).
This is the first PR of a series of 2 or 3 to introduce the lowering, as an introduction it brings support for function calls, local and global variables and handling of arithmetic operations. As explained in the RFC, most WasmSSA operations have been made to stay close to other dialects' semantics so that conversion is trivialized. 
>From 3b5ed02e0e2cae307fa68a2ef2257675694e9728 Mon Sep 17 00:00:00 2001
From: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Date: Thu, 3 Jul 2025 10:38:53 +0900
Subject: [PATCH 1/2] [mlir][wasm] Introduce RaiseWasmMLIRPass - a pass to
 convert Wasm MLIR to lower level MLIR dialects
Introduce the structure of the pass along with conversion of wasm.func, wasm.call and local.get
lowerings for simple functions handling.
--
 Co-authored-by: Luc Forget <luc.forget at woven-planet.global>
 Co-authored-by: Jessica Paquette <jessica.paquette at woven-planet.global>
---
 mlir/include/mlir/Conversion/Passes.h         |   1 +
 mlir/include/mlir/Conversion/Passes.td        |  13 ++
 .../mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h |  30 +++
 mlir/lib/Conversion/CMakeLists.txt            |  14 +-
 mlir/lib/Conversion/RaiseWasm/CMakeLists.txt  |  19 ++
 .../Conversion/RaiseWasm/RaiseWasmMLIR.cpp    | 182 ++++++++++++++++++
 .../RaiseWasm/wasm-func-to-func.mlir          |  35 ++++
 7 files changed, 288 insertions(+), 6 deletions(-)
 create mode 100644 mlir/include/mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h
 create mode 100644 mlir/lib/Conversion/RaiseWasm/CMakeLists.txt
 create mode 100644 mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-func-to-func.mlir
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index 40d866ec7bf10..664bcb00ab45a 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -58,6 +58,7 @@
 #include "mlir/Conversion/OpenACCToSCF/ConvertOpenACCToSCF.h"
 #include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
 #include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
+#include "mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h"
 #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
 #include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
 #include "mlir/Conversion/SCFToEmitC/SCFToEmitC.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 70e3e45c225db..860e474a067a4 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -1582,6 +1582,19 @@ def ConvertVectorToAMX : Pass<"convert-vector-to-amx"> {
   ];
 }
 
+//===----------------------------------------------------------------------===//
+// RaiseWasmMLIR
+//===----------------------------------------------------------------------===//
+
+def RaiseWasmMLIR : Pass<"raise-wasm-mlir"> {
+  let summary = "Convert Wasm dialect to a group of dialect as a bridge to LLVM MLIR conversion";
+  let dependentDialects = [
+    "func::FuncDialect", "arith::ArithDialect", "cf::ControlFlowDialect",
+    "memref::MemRefDialect", "vector::VectorDialect", "wasmssa::WasmSSADialect",
+    "math::MathDialect"
+  ];
+}
+
 //===----------------------------------------------------------------------===//
 // XeVMToLLVM
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h b/mlir/include/mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h
new file mode 100644
index 0000000000000..a54fc45b5d048
--- /dev/null
+++ b/mlir/include/mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h
@@ -0,0 +1,30 @@
+//===- RaiseWasmMLIR.h - Convert wasm to standard dialects ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CONVERSION_RAISEWASM_RAISEWASMMLIR_H
+#define MLIR_CONVERSION_RAISEWASM_RAISEWASMMLIR_H
+
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+class Pass;
+class RewritePatternSet;
+
+#define GEN_PASS_DECL_RAISEWASMMLIR
+#include "mlir/Conversion/Passes.h.inc"
+
+/// Collect a set of patterns to convert from the Wasm dialect to standard dialects.
+void populateRaiseWasmMLIRConversionPatterns(TypeConverter&, RewritePatternSet &);
+
+/// Create a pass to convert ops from WasmDialect to standard dialects.
+std::unique_ptr<Pass> createRaiseWasmMLIRPass();
+
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_RAISEWASM_RAISEWASMMLIR_H
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index bebf1b8fff3f9..0f1c3c60ba182 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -1,5 +1,6 @@
-add_subdirectory(AffineToStandard)
+
 add_subdirectory(AMDGPUToROCDL)
+add_subdirectory(AffineToStandard)
 add_subdirectory(ArithCommon)
 add_subdirectory(ArithToAMDGPU)
 add_subdirectory(ArithToArmSME)
@@ -7,14 +8,14 @@ add_subdirectory(ArithToEmitC)
 add_subdirectory(ArithToLLVM)
 add_subdirectory(ArithToSPIRV)
 add_subdirectory(ArmNeon2dToIntr)
-add_subdirectory(ArmSMEToSCF)
 add_subdirectory(ArmSMEToLLVM)
+add_subdirectory(ArmSMEToSCF)
 add_subdirectory(AsyncToLLVM)
 add_subdirectory(BufferizationToMemRef)
 add_subdirectory(ComplexCommon)
-add_subdirectory(ComplexToLibm)
 add_subdirectory(ComplexToROCDLLibraryCalls)
 add_subdirectory(ComplexToLLVM)
+add_subdirectory(ComplexToLibm)
 add_subdirectory(ComplexToSPIRV)
 add_subdirectory(ComplexToStandard)
 add_subdirectory(ControlFlowToLLVM)
@@ -32,12 +33,12 @@ add_subdirectory(GPUToROCDL)
 add_subdirectory(GPUToSPIRV)
 add_subdirectory(IndexToLLVM)
 add_subdirectory(IndexToSPIRV)
-add_subdirectory(LinalgToStandard)
 add_subdirectory(LLVMCommon)
+add_subdirectory(LinalgToStandard)
 add_subdirectory(MathToEmitC)
 add_subdirectory(MathToFuncs)
-add_subdirectory(MathToLibm)
 add_subdirectory(MathToLLVM)
+add_subdirectory(MathToLibm)
 add_subdirectory(MathToROCDL)
 add_subdirectory(MathToSPIRV)
 add_subdirectory(MathToXeVM)
@@ -52,15 +53,16 @@ add_subdirectory(OpenACCToSCF)
 add_subdirectory(OpenMPToLLVM)
 add_subdirectory(PDLToPDLInterp)
 add_subdirectory(PtrToLLVM)
+add_subdirectory(RaiseWasm)
 add_subdirectory(ReconcileUnrealizedCasts)
 add_subdirectory(SCFToControlFlow)
 add_subdirectory(SCFToEmitC)
 add_subdirectory(SCFToGPU)
 add_subdirectory(SCFToOpenMP)
 add_subdirectory(SCFToSPIRV)
-add_subdirectory(ShapeToStandard)
 add_subdirectory(SPIRVCommon)
 add_subdirectory(SPIRVToLLVM)
+add_subdirectory(ShapeToStandard)
 add_subdirectory(TensorToLinalg)
 add_subdirectory(TensorToSPIRV)
 add_subdirectory(TosaToArith)
diff --git a/mlir/lib/Conversion/RaiseWasm/CMakeLists.txt b/mlir/lib/Conversion/RaiseWasm/CMakeLists.txt
new file mode 100644
index 0000000000000..43b5fd79e49df
--- /dev/null
+++ b/mlir/lib/Conversion/RaiseWasm/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_mlir_conversion_library(MLIRWasmRaise
+  RaiseWasmMLIR.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/RaiseWasm
+
+  DEPENDS
+  MLIRConversionPassIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRArithDialect
+  MLIRControlFlowDialect
+  MLIRFuncDialect
+  MLIRMathDialect
+  MLIRMemRefDialect
+  MLIRTransforms
+  MLIRVectorDialect
+  MLIRWasmSSADialect
+  )
diff --git a/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp b/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
new file mode 100644
index 0000000000000..872fa7427dc84
--- /dev/null
+++ b/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
@@ -0,0 +1,182 @@
+//===- RaiseWasmMLIR.cpp - Convert Wasm to less abstract dialects ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements lowering of wasm operations to standard dialects ops.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h"
+
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/Math/IR/Math.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/Dialect/WasmSSA/IR/WasmSSA.h"
+#include "mlir/IR/BuiltinDialect.h"
+#include "mlir/IR/ValueRange.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/Passes.h"
+#include "llvm/Support/LogicalResult.h"
+
+#include <optional>
+
+
+#define DEBUG_TYPE "wasm-convert"
+
+namespace mlir {
+#define GEN_PASS_DEF_RAISEWASMMLIR
+#include "mlir/Conversion/Passes.h.inc"
+} // namespace mlir
+
+using namespace mlir;
+using namespace mlir::wasmssa;
+
+namespace {
+
+struct WasmCallOpConversion : OpConversionPattern<FuncCallOp> {
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(FuncCallOp funcCallOp, FuncCallOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<func::CallOp>(
+        funcCallOp, funcCallOp.getCallee(), funcCallOp.getResults().getTypes(),
+        funcCallOp.getOperands());
+    return success();
+  }
+};
+
+struct WasmFuncImportOpConversion : OpConversionPattern<FuncImportOp> {
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(FuncImportOp funcImportOp, FuncImportOp::Adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto nFunc = rewriter.replaceOpWithNewOp<func::FuncOp>(
+        funcImportOp, funcImportOp.getSymName(),
+        funcImportOp.getType());
+    nFunc.setVisibility(SymbolTable::Visibility::Private);
+    return success();
+  }
+};
+
+struct WasmFuncOpConversion : OpConversionPattern<FuncOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(FuncOp funcOp, FuncOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto newFunc = rewriter.create<func::FuncOp>(
+        funcOp->getLoc(), funcOp.getSymName(), funcOp.getFunctionType());
+    rewriter.cloneRegionBefore(funcOp.getBody(), newFunc.getBody(),
+                               newFunc.getBody().end());
+    Block *oldEntryBlock = &newFunc.getBody().front();
+    auto blockArgTypes = oldEntryBlock->getArgumentTypes();
+    TypeConverter::SignatureConversion sC{oldEntryBlock->getNumArguments()};
+    auto numArgs = blockArgTypes.size();
+    for (size_t i = 0; i < numArgs; ++i) {
+      auto argType = dyn_cast<LocalRefType>(blockArgTypes[i]);
+      if (!argType)
+        return failure();
+      sC.addInputs(i, argType.getElementType());
+    }
+
+    rewriter.applySignatureConversion(oldEntryBlock, sC, getTypeConverter());
+    rewriter.replaceOp(funcOp, newFunc);
+    return success();
+  }
+};
+
+struct WasmLocalGetConversion : OpConversionPattern<LocalGetOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(LocalGetOp localGetOp, LocalGetOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<memref::LoadOp>(localGetOp,
+                                                localGetOp.getResult().getType(),
+                                                adaptor.getLocalVar(),
+                                              ValueRange{});
+    return success();
+  }
+};
+
+struct WasmReturnOpConversion : OpConversionPattern<ReturnOp> {
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(ReturnOp returnOp, ReturnOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<func::ReturnOp>(returnOp, adaptor.getOperands());
+    return success();
+  }
+};
+
+struct RaiseWasmMLIRPass
+    : public impl::RaiseWasmMLIRBase<RaiseWasmMLIRPass> {
+  void runOnOperation() override {
+    ConversionTarget target{getContext()};
+    target.addIllegalDialect<WasmSSADialect>();
+    target.addLegalDialect<arith::ArithDialect, BuiltinDialect,
+                           cf::ControlFlowDialect, func::FuncDialect,
+                           memref::MemRefDialect, math::MathDialect>();
+    RewritePatternSet patterns(&getContext());
+    TypeConverter tc{};
+    tc.addConversion([](Type type) -> std::optional<Type> { return type; });
+    tc.addConversion([](LocalRefType type)->std::optional<Type> {
+      return MemRefType::get({}, type.getElementType());
+    });
+    tc.addTargetMaterialization([](OpBuilder& builder, MemRefType destType, ValueRange values, Location loc)->Value{
+      if (values.size() != 1 || values.front().getType() != destType.getElementType())
+        return {};
+      auto localVar = builder.create<memref::AllocaOp>(loc, destType);
+      builder.create<memref::StoreOp>(loc, values.front(), localVar.getResult());
+      return localVar.getResult();
+    });
+    populateRaiseWasmMLIRConversionPatterns(tc, patterns);
+
+    llvm::DenseMap<StringAttr, StringAttr> idxSymToImportSym{};
+    auto *topOp = getOperation();
+    topOp->walk([&idxSymToImportSym, this](ImportOpInterface importOp) {
+      auto const qualifiedImportName = importOp.getQualifiedImportName();
+      auto qualNameAttr = StringAttr::get(&getContext(), qualifiedImportName);
+      idxSymToImportSym.insert(
+          std::make_pair(importOp.getSymbolName(), qualNameAttr));
+    });
+
+    if (failed(applyFullConversion(topOp, target, std::move(patterns))))
+      return signalPassFailure();
+
+    auto symTable = SymbolTable{topOp};
+    for (auto &[oldName, newName] : idxSymToImportSym) {
+      if (failed(symTable.rename(oldName, newName)))
+        return signalPassFailure();
+    }
+  }
+};
+} // namespace
+
+void mlir::populateRaiseWasmMLIRConversionPatterns(
+    TypeConverter &tc, RewritePatternSet &patternSet) {
+  auto *ctx = patternSet.getContext();
+  // Disable clang-format in patternSet for readability + small diffs.
+  // clang-format off
+  patternSet
+      .add<
+           WasmCallOpConversion,
+           WasmFuncImportOpConversion,
+           WasmFuncOpConversion,
+           WasmLocalGetConversion,
+           WasmReturnOpConversion
+           >(tc, ctx);
+  // clang-format on
+}
+
+std::unique_ptr<Pass> mlir::createRaiseWasmMLIRPass() {
+  return std::make_unique<RaiseWasmMLIRPass>();
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-func-to-func.mlir b/mlir/test/Conversion/RaiseWasm/wasm-func-to-func.mlir
new file mode 100644
index 0000000000000..65a6831b442ca
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-func-to-func.mlir
@@ -0,0 +1,35 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @callee(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32) -> i32 {
+wasmssa.func exported @callee(%arg0: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+// CHECK:           return %[[VAL_1]] : i32
+wasmssa.return %v0 : i32
+}
+
+wasmssa.func exported @caller(%arg0: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+// CHECK:           %[[VAL_2:.*]] = call @callee(%[[VAL_1]]) : (i32) -> i32
+%0 = wasmssa.call @callee (%v0) : (i32) -> i32
+// CHECK:           return %[[VAL_2]] : i32
+wasmssa.return %0 : i32
+}
+
+// CHECK-LABEL:         func.func private @"my_module::foo"() -> i32
+wasmssa.import_func "foo" from "my_module" as @func_0 {sym_visibility = "nested", type = () -> (i32)}
+
+// CHECK-LABEL:   func.func @user_of_func0() -> i32 {
+wasmssa.func exported @user_of_func0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = call @"my_module::foo"() : () -> i32
+%0 = wasmssa.call @func_0 : () -> i32
+// CHECK:           return %[[VAL_0]] : i32
+wasmssa.return %0 : i32
+}
>From 23ee2dbb1a89bb88ba2facddb96935ad905c44dc Mon Sep 17 00:00:00 2001
From: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Date: Thu, 3 Jul 2025 11:06:55 +0900
Subject: [PATCH 2/2] [mlir][wasm] RaiseWasmMLIRPass: Local and global
 variables and arithmetic ops
--
 Co-authored-by: Luc Forget <luc.forget at woven-planet.global>
 Co-authored-by: Jessica Paquette <jessica.paquette at woven-planet.global>
---
 mlir/lib/Conversion/CMakeLists.txt            |  13 +-
 .../Conversion/RaiseWasm/RaiseWasmMLIR.cpp    | 322 +++++++++++++++++-
 .../RaiseWasm/wasm-abs-to-math-abs.mlir       |  27 ++
 .../RaiseWasm/wasm-add-to-arith-add.mlir      |  79 +++++
 .../RaiseWasm/wasm-and-to-arith-and.mlir      |  38 +++
 .../RaiseWasm/wasm-ceil-to-math-ceil.mlir     |  24 ++
 .../RaiseWasm/wasm-clz-to-math-clz.mlir       |  27 ++
 .../RaiseWasm/wasm-const-to-arith-const.mlir  |  15 +
 .../RaiseWasm/wasm-convert-to-arith-tofp.mlir |  81 +++++
 .../wasm-copysign-to-math-copysign.mlir       |  38 +++
 .../RaiseWasm/wasm-ctz-to-math-ctz.mlir       |  27 ++
 .../RaiseWasm/wasm-demote-to-arith-trunc.mlir |  14 +
 .../RaiseWasm/wasm-div-to-arith-div.mlir      | 109 ++++++
 .../RaiseWasm/wasm-floor-to-math-floor.mlir   |  24 ++
 .../wasm-global-to-memref-global.mlir         |  43 +++
 .../RaiseWasm/wasm-local-to-memref.mlir       |  68 ++++
 .../RaiseWasm/wasm-max-to-arith-maximumf.mlir |  37 ++
 .../RaiseWasm/wasm-min-to-arith-minimumf.mlir |  37 ++
 .../RaiseWasm/wasm-mul-to-arith-mul.mlir      |  78 +++++
 .../RaiseWasm/wasm-neg-to-arith-neg.mlir      |  27 ++
 .../RaiseWasm/wasm-or-to-arith-or.mlir        |  38 +++
 .../RaiseWasm/wasm-popcnt-to-math-ctpop.mlir  |  27 ++
 .../RaiseWasm/wasm-promote-to-arith-ext.mlir  |  11 +
 .../wasm-reinterpret-to-arith-bitcast.mlir    |  42 +++
 .../RaiseWasm/wasm-rem-to-arith-rem.mlir      |  74 ++++
 .../RaiseWasm/wasm-shl-to-arith-shl.mlir      |  38 +++
 .../RaiseWasm/wasm-shr_s-to-arith-shrs.mlir   |  38 +++
 .../RaiseWasm/wasm-shr_u-to-arith-shru.mlir   |  37 ++
 .../RaiseWasm/wasm-sqrt-to-math-sqrt.mlir     |  27 ++
 .../RaiseWasm/wasm-sub-to-arith-sub.mlir      |  80 +++++
 .../RaiseWasm/wasm-trunc-to-math-trunc.mlir   |  24 ++
 .../RaiseWasm/wasm-wrap-to-arith-trunc.mlir   |  17 +
 .../RaiseWasm/wasm-xor-to-arith-xor.mlir      |  37 ++
 33 files changed, 1593 insertions(+), 25 deletions(-)
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-abs-to-math-abs.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-add-to-arith-add.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-and-to-arith-and.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-ceil-to-math-ceil.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-clz-to-math-clz.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-const-to-arith-const.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-convert-to-arith-tofp.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-copysign-to-math-copysign.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-ctz-to-math-ctz.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-demote-to-arith-trunc.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-div-to-arith-div.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-floor-to-math-floor.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-global-to-memref-global.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-local-to-memref.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-max-to-arith-maximumf.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-min-to-arith-minimumf.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-mul-to-arith-mul.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-neg-to-arith-neg.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-or-to-arith-or.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-popcnt-to-math-ctpop.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-promote-to-arith-ext.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-reinterpret-to-arith-bitcast.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-rem-to-arith-rem.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-shl-to-arith-shl.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-shr_s-to-arith-shrs.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-shr_u-to-arith-shru.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-sqrt-to-math-sqrt.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-sub-to-arith-sub.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-trunc-to-math-trunc.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-wrap-to-arith-trunc.mlir
 create mode 100644 mlir/test/Conversion/RaiseWasm/wasm-xor-to-arith-xor.mlir
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 0f1c3c60ba182..c43b5f3ad5489 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -1,6 +1,5 @@
-
-add_subdirectory(AMDGPUToROCDL)
 add_subdirectory(AffineToStandard)
+add_subdirectory(AMDGPUToROCDL)
 add_subdirectory(ArithCommon)
 add_subdirectory(ArithToAMDGPU)
 add_subdirectory(ArithToArmSME)
@@ -8,14 +7,14 @@ add_subdirectory(ArithToEmitC)
 add_subdirectory(ArithToLLVM)
 add_subdirectory(ArithToSPIRV)
 add_subdirectory(ArmNeon2dToIntr)
-add_subdirectory(ArmSMEToLLVM)
 add_subdirectory(ArmSMEToSCF)
+add_subdirectory(ArmSMEToLLVM)
 add_subdirectory(AsyncToLLVM)
 add_subdirectory(BufferizationToMemRef)
 add_subdirectory(ComplexCommon)
+add_subdirectory(ComplexToLibm)
 add_subdirectory(ComplexToROCDLLibraryCalls)
 add_subdirectory(ComplexToLLVM)
-add_subdirectory(ComplexToLibm)
 add_subdirectory(ComplexToSPIRV)
 add_subdirectory(ComplexToStandard)
 add_subdirectory(ControlFlowToLLVM)
@@ -33,12 +32,12 @@ add_subdirectory(GPUToROCDL)
 add_subdirectory(GPUToSPIRV)
 add_subdirectory(IndexToLLVM)
 add_subdirectory(IndexToSPIRV)
-add_subdirectory(LLVMCommon)
 add_subdirectory(LinalgToStandard)
+add_subdirectory(LLVMCommon)
 add_subdirectory(MathToEmitC)
 add_subdirectory(MathToFuncs)
-add_subdirectory(MathToLLVM)
 add_subdirectory(MathToLibm)
+add_subdirectory(MathToLLVM)
 add_subdirectory(MathToROCDL)
 add_subdirectory(MathToSPIRV)
 add_subdirectory(MathToXeVM)
@@ -60,9 +59,9 @@ add_subdirectory(SCFToEmitC)
 add_subdirectory(SCFToGPU)
 add_subdirectory(SCFToOpenMP)
 add_subdirectory(SCFToSPIRV)
+add_subdirectory(ShapeToStandard)
 add_subdirectory(SPIRVCommon)
 add_subdirectory(SPIRVToLLVM)
-add_subdirectory(ShapeToStandard)
 add_subdirectory(TensorToLinalg)
 add_subdirectory(TensorToSPIRV)
 add_subdirectory(TosaToArith)
diff --git a/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp b/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
index 872fa7427dc84..d67572f3e67ba 100644
--- a/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
+++ b/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp
@@ -1,4 +1,5 @@
-//===- RaiseWasmMLIR.cpp - Convert Wasm to less abstract dialects ---*- C++ -*-===//
+//===- RaiseWasmMLIR.cpp - Convert Wasm to less abstract dialects ---*- C++
+//-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,6 +13,8 @@
 
 #include "mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h"
 
+
+#include "llvm/Support/LogicalResult.h"
 #include "mlir/Dialect/Arith/IR/Arith.h"
 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
@@ -19,15 +22,13 @@
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/Dialect/Vector/IR/VectorOps.h"
 #include "mlir/Dialect/WasmSSA/IR/WasmSSA.h"
+#include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
 #include "mlir/IR/ValueRange.h"
 #include "mlir/Transforms/DialectConversion.h"
 #include "mlir/Transforms/Passes.h"
-#include "llvm/Support/LogicalResult.h"
-
 #include <optional>
 
-
 #define DEBUG_TYPE "wasm-convert"
 
 namespace mlir {
@@ -40,6 +41,91 @@ using namespace mlir::wasmssa;
 
 namespace {
 
+template <typename SourceOp, typename TargetIntOp, typename TargetFPOp>
+struct IntFPDispatchMappingConversion : OpConversionPattern<SourceOp> {
+  using OpConversionPattern<SourceOp>::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(SourceOp srcOp, typename SourceOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    Type type = srcOp.getRhs().getType();
+    if (type.isInteger()) {
+      rewriter.replaceOpWithNewOp<TargetIntOp>(srcOp, srcOp->getResultTypes(),
+                                               adaptor.getOperands());
+      return success();
+    }
+    if (!type.isFloat())
+      return failure();
+    rewriter.replaceOpWithNewOp<TargetFPOp>(srcOp, srcOp->getResultTypes(),
+                                            adaptor.getOperands());
+    return success();
+  }
+};
+
+using WasmAddOpConversion =
+    IntFPDispatchMappingConversion<AddOp, arith::AddIOp, arith::AddFOp>;
+using WasmMulOpConversion =
+    IntFPDispatchMappingConversion<MulOp, arith::MulIOp, arith::MulFOp>;
+using WasmSubOpConversion =
+    IntFPDispatchMappingConversion<SubOp, arith::SubIOp, arith::SubFOp>;
+
+/// Convert a k-ary source operation \p SourceOp into an operation \p TargetOp.
+/// Both \p SourceOp and \p TargetOp must have the same number of operands.
+template <typename SourceOp, typename TargetOp>
+struct OpMappingConversion : OpConversionPattern<SourceOp> {
+  using OpConversionPattern<SourceOp>::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(SourceOp srcOp, typename SourceOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<TargetOp>(srcOp, srcOp->getResultTypes(),
+                                          adaptor.getOperands());
+    return success();
+  }
+};
+
+using WasmAndOpConversion = OpMappingConversion<AndOp, arith::AndIOp>;
+using WasmCeilOpConversion = OpMappingConversion<CeilOp, math::CeilOp>;
+/// TODO: SIToFP and UIToFP don't allow specification of the floating point
+/// rounding mode
+using WasmConvertSOpConversion =
+    OpMappingConversion<ConvertSOp, arith::SIToFPOp>;
+using WasmConvertUOpConversion =
+    OpMappingConversion<ConvertUOp, arith::UIToFPOp>;
+using WasmDemoteOpConversion = OpMappingConversion<DemoteOp, arith::TruncFOp>;
+using WasmDivFPOpConversion = OpMappingConversion<DivOp, arith::DivFOp>;
+using WasmDivSIOpConversion = OpMappingConversion<DivSIOp, arith::DivSIOp>;
+using WasmDivUIOpConversion = OpMappingConversion<DivUIOp, arith::DivUIOp>;
+using WasmExtendSOpConversion =
+    OpMappingConversion<ExtendSI32Op, arith::ExtSIOp>;
+using WasmExtendUOpConversion =
+    OpMappingConversion<ExtendUI32Op, arith::ExtUIOp>;
+using WasmFloorOpConversion = OpMappingConversion<FloorOp, math::FloorOp>;
+using WasmMaxOpConversion = OpMappingConversion<MaxOp, arith::MaximumFOp>;
+using WasmMinOpConversion = OpMappingConversion<MinOp, arith::MinimumFOp>;
+using WasmOrOpConversion = OpMappingConversion<OrOp, arith::OrIOp>;
+using WasmPromoteOpConversion = OpMappingConversion<PromoteOp, arith::ExtFOp>;
+using WasmRemSIOpConversion = OpMappingConversion<RemSIOp, arith::RemSIOp>;
+using WasmRemUIOpConversion = OpMappingConversion<RemUIOp, arith::RemUIOp>;
+using WasmReinterpretOpConversion =
+    OpMappingConversion<ReinterpretOp, arith::BitcastOp>;
+using WasmShLOpConversion = OpMappingConversion<ShLOp, arith::ShLIOp>;
+using WasmShRSOpConversion = OpMappingConversion<ShRSOp, arith::ShRSIOp>;
+using WasmShRUOpConversion = OpMappingConversion<ShRUOp, arith::ShRUIOp>;
+using WasmXOrOpConversion = OpMappingConversion<XOrOp, arith::XOrIOp>;
+using WasmNegOpConversion = OpMappingConversion<NegOp, arith::NegFOp>;
+using WasmCopySignOpConversion =
+    OpMappingConversion<CopySignOp, math::CopySignOp>;
+using WasmClzOpConversion =
+    OpMappingConversion<ClzOp, math::CountLeadingZerosOp>;
+using WasmCtzOpConversion =
+    OpMappingConversion<CtzOp, math::CountTrailingZerosOp>;
+using WasmPopCntOpConversion = OpMappingConversion<PopCntOp, math::CtPopOp>;
+using WasmAbsOpConversion = OpMappingConversion<AbsOp, math::AbsFOp>;
+using WasmTruncOpConversion = OpMappingConversion<TruncOp, math::TruncOp>;
+using WasmSqrtOpConversion = OpMappingConversion<SqrtOp, math::SqrtOp>;
+using WasmWrapOpConversion = OpMappingConversion<WrapOp, arith::TruncIOp>;
+
 struct WasmCallOpConversion : OpConversionPattern<FuncCallOp> {
   using OpConversionPattern::OpConversionPattern;
 
@@ -53,6 +139,17 @@ struct WasmCallOpConversion : OpConversionPattern<FuncCallOp> {
   }
 };
 
+struct WasmConstOpConversion : OpConversionPattern<ConstOp> {
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(ConstOp constOp, ConstOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<arith::ConstantOp>(constOp, constOp.getValue());
+    return success();
+  }
+};
+
 struct WasmFuncImportOpConversion : OpConversionPattern<FuncImportOp> {
   using OpConversionPattern::OpConversionPattern;
 
@@ -60,8 +157,7 @@ struct WasmFuncImportOpConversion : OpConversionPattern<FuncImportOp> {
   matchAndRewrite(FuncImportOp funcImportOp, FuncImportOp::Adaptor,
                   ConversionPatternRewriter &rewriter) const override {
     auto nFunc = rewriter.replaceOpWithNewOp<func::FuncOp>(
-        funcImportOp, funcImportOp.getSymName(),
-        funcImportOp.getType());
+        funcImportOp, funcImportOp.getSymName(), funcImportOp.getType());
     nFunc.setVisibility(SymbolTable::Visibility::Private);
     return success();
   }
@@ -69,6 +165,7 @@ struct WasmFuncImportOpConversion : OpConversionPattern<FuncImportOp> {
 
 struct WasmFuncOpConversion : OpConversionPattern<FuncOp> {
   using OpConversionPattern::OpConversionPattern;
+
   LogicalResult
   matchAndRewrite(FuncOp funcOp, FuncOp::Adaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
@@ -93,15 +190,160 @@ struct WasmFuncOpConversion : OpConversionPattern<FuncOp> {
   }
 };
 
+struct WasmGlobalImportOpConverter : OpConversionPattern<GlobalImportOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(GlobalImportOp gIOp, GlobalImportOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto memrefGOp = rewriter.replaceOpWithNewOp<memref::GlobalOp>(
+        gIOp, gIOp.getSymNameAttr(), rewriter.getStringAttr("nested"),
+        TypeAttr::get(MemRefType::get({1}, gIOp.getType())), Attribute{},
+        /*constant*/ UnitAttr{},
+        /*alignment*/ IntegerAttr{});
+    memrefGOp.setConstant(!gIOp.getIsMutable());
+    return success();
+  }
+};
+
+template <typename CRTP, typename OriginOpType>
+struct GlobalOpConverter : OpConversionPattern<GlobalOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(GlobalOp globalOp, GlobalOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    ReturnOp rop;
+    globalOp->walk([&rop](ReturnOp op) { rop = op; });
+
+    if (rop->getNumOperands() != 1)
+      return rewriter.notifyMatchFailure(
+          globalOp, "globalOp initializer should return one value exactly");
+
+    auto initializerOp =
+        dyn_cast<OriginOpType>(rop->getOperand(0).getDefiningOp());
+
+    if (!initializerOp)
+      return rewriter.notifyMatchFailure(
+          globalOp, "invalid initializer op type for this pattern");
+
+    return static_cast<CRTP const *>(this)->handleInitializer(
+        globalOp, rewriter, initializerOp);
+  }
+};
+
+struct WasmGlobalWithConstInitConversion
+    : GlobalOpConverter<WasmGlobalWithConstInitConversion, ConstOp> {
+  using GlobalOpConverter::GlobalOpConverter;
+  LogicalResult handleInitializer(GlobalOp globalOp,
+                                  ConversionPatternRewriter &rewriter,
+                                  ConstOp constInit) const {
+    auto initializer =
+        DenseElementsAttr::get(RankedTensorType::get({1}, globalOp.getType()),
+                               ArrayRef<Attribute>{constInit.getValueAttr()});
+    auto globalReplacement = rewriter.replaceOpWithNewOp<memref::GlobalOp>(
+        globalOp, globalOp.getSymNameAttr(), rewriter.getStringAttr("private"),
+        TypeAttr::get(MemRefType::get({1}, globalOp.getType())), initializer,
+        /*constant*/ UnitAttr{},
+        /*alignment*/ IntegerAttr{});
+    globalReplacement.setConstant(!globalOp.getIsMutable());
+    return success();
+  }
+};
+
+struct WasmGlobalWithGetGlobalInitConversion
+    : GlobalOpConverter<WasmGlobalWithGetGlobalInitConversion, GlobalGetOp> {
+  using GlobalOpConverter::GlobalOpConverter;
+  LogicalResult handleInitializer(GlobalOp globalOp,
+                                  ConversionPatternRewriter &rewriter,
+                                  GlobalGetOp constInit) const {
+    auto globalReplacement = rewriter.replaceOpWithNewOp<memref::GlobalOp>(
+        globalOp, globalOp.getSymNameAttr(), rewriter.getStringAttr("private"),
+        TypeAttr::get(MemRefType::get({1}, globalOp.getType())),
+        rewriter.getUnitAttr(),
+        /*constant*/ UnitAttr{},
+        /*alignment*/ IntegerAttr{});
+    globalReplacement.setConstant(!globalOp.getIsMutable());
+    auto loc = globalOp.getLoc();
+    auto initializerName = (globalOp.getSymName() + "::initializer").str();
+    auto globalInitializer = rewriter.create<func::FuncOp>(
+        loc, initializerName, FunctionType::get(getContext(), {}, {}));
+    globalInitializer->setAttr(rewriter.getStringAttr("initializer"),
+                               rewriter.getUnitAttr());
+    auto *initializerBody = globalInitializer.addEntryBlock();
+    auto sip = rewriter.saveInsertionPoint();
+    rewriter.setInsertionPointToStart(initializerBody);
+    auto srcGlobalPtr = rewriter.create<memref::GetGlobalOp>(
+        loc, MemRefType::get({1}, constInit.getType()), constInit.getGlobal());
+    auto destGlobalPtr = rewriter.create<memref::GetGlobalOp>(
+        loc, globalReplacement.getType(), globalReplacement.getSymName());
+    auto idx = rewriter.create<arith::ConstantIndexOp>(loc, 0).getResult();
+    auto loadSrc =
+        rewriter.create<memref::LoadOp>(loc, srcGlobalPtr, ValueRange{idx});
+    rewriter.create<memref::StoreOp>(
+        loc, loadSrc.getResult(), destGlobalPtr.getResult(), ValueRange{idx});
+    rewriter.create<func::ReturnOp>(loc);
+    rewriter.restoreInsertionPoint(sip);
+    return success();
+  }
+};
+
+inline TypedAttr getInitializerAttr(Type t) {
+  assert(t.isIntOrFloat() &&
+         "This helper is intended to use with int and float types");
+  if (t.isInteger())
+    return IntegerAttr::get(t, 0);
+  if (t.isFloat())
+    return FloatAttr::get(t, 0.);
+  return TypedAttr{};
+}
+
+struct WasmLocalConversion : OpConversionPattern<LocalOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(LocalOp localOp, LocalOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto alloca = rewriter.replaceOpWithNewOp<memref::AllocaOp>(
+        localOp,
+        MemRefType::get({}, localOp.getResult().getType().getElementType()));
+    auto initializer = rewriter.create<arith::ConstantOp>(
+        localOp->getLoc(),
+        getInitializerAttr(localOp.getResult().getType().getElementType()));
+    rewriter.create<memref::StoreOp>(localOp->getLoc(), initializer.getResult(),
+                                     alloca.getResult());
+    return success();
+  }
+};
+
 struct WasmLocalGetConversion : OpConversionPattern<LocalGetOp> {
   using OpConversionPattern::OpConversionPattern;
   LogicalResult
   matchAndRewrite(LocalGetOp localGetOp, LocalGetOp::Adaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    rewriter.replaceOpWithNewOp<memref::LoadOp>(localGetOp,
-                                                localGetOp.getResult().getType(),
-                                                adaptor.getLocalVar(),
-                                              ValueRange{});
+    rewriter.replaceOpWithNewOp<memref::LoadOp>(
+        localGetOp, localGetOp.getResult().getType(), adaptor.getLocalVar(),
+        ValueRange{});
+    return success();
+  }
+};
+
+struct WasmLocalSetConversion : OpConversionPattern<LocalSetOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(LocalSetOp localSetOp, LocalSetOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.replaceOpWithNewOp<memref::StoreOp>(
+        localSetOp, adaptor.getValue(), adaptor.getLocalVar(), ValueRange{});
+    return success();
+  }
+};
+
+struct WasmLocalTeeConversion : OpConversionPattern<LocalTeeOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(LocalTeeOp localTeeOp, LocalTeeOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    rewriter.create<memref::StoreOp>(localTeeOp->getLoc(), adaptor.getValue(),
+                                     adaptor.getLocalVar());
+    rewriter.replaceOp(localTeeOp, adaptor.getValue());
     return success();
   }
 };
@@ -112,13 +354,13 @@ struct WasmReturnOpConversion : OpConversionPattern<ReturnOp> {
   LogicalResult
   matchAndRewrite(ReturnOp returnOp, ReturnOp::Adaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    rewriter.replaceOpWithNewOp<func::ReturnOp>(returnOp, adaptor.getOperands());
+    rewriter.replaceOpWithNewOp<func::ReturnOp>(returnOp,
+                                                adaptor.getOperands());
     return success();
   }
 };
 
-struct RaiseWasmMLIRPass
-    : public impl::RaiseWasmMLIRBase<RaiseWasmMLIRPass> {
+struct RaiseWasmMLIRPass : public impl::RaiseWasmMLIRBase<RaiseWasmMLIRPass> {
   void runOnOperation() override {
     ConversionTarget target{getContext()};
     target.addIllegalDialect<WasmSSADialect>();
@@ -128,14 +370,17 @@ struct RaiseWasmMLIRPass
     RewritePatternSet patterns(&getContext());
     TypeConverter tc{};
     tc.addConversion([](Type type) -> std::optional<Type> { return type; });
-    tc.addConversion([](LocalRefType type)->std::optional<Type> {
+    tc.addConversion([](LocalRefType type) -> std::optional<Type> {
       return MemRefType::get({}, type.getElementType());
     });
-    tc.addTargetMaterialization([](OpBuilder& builder, MemRefType destType, ValueRange values, Location loc)->Value{
-      if (values.size() != 1 || values.front().getType() != destType.getElementType())
+    tc.addTargetMaterialization([](OpBuilder &builder, MemRefType destType,
+                                   ValueRange values, Location loc) -> Value {
+      if (values.size() != 1 ||
+          values.front().getType() != destType.getElementType())
         return {};
       auto localVar = builder.create<memref::AllocaOp>(loc, destType);
-      builder.create<memref::StoreOp>(loc, values.front(), localVar.getResult());
+      builder.create<memref::StoreOp>(loc, values.front(),
+                                      localVar.getResult());
       return localVar.getResult();
     });
     populateRaiseWasmMLIRConversionPatterns(tc, patterns);
@@ -168,11 +413,52 @@ void mlir::populateRaiseWasmMLIRConversionPatterns(
   // clang-format off
   patternSet
       .add<
+           WasmAbsOpConversion,
+           WasmAddOpConversion,
+           WasmAndOpConversion,
            WasmCallOpConversion,
+           WasmCeilOpConversion,
+           WasmClzOpConversion,
+           WasmConstOpConversion,
+           WasmConvertSOpConversion,
+           WasmConvertUOpConversion,
+           WasmCopySignOpConversion,
+           WasmCtzOpConversion,
+           WasmDemoteOpConversion,
+           WasmDivFPOpConversion,
+           WasmDivSIOpConversion,
+           WasmDivUIOpConversion,
+           WasmExtendSOpConversion,
+           WasmExtendUOpConversion,
+           WasmFloorOpConversion,
            WasmFuncImportOpConversion,
            WasmFuncOpConversion,
+           WasmGlobalImportOpConverter,
+           WasmGlobalWithConstInitConversion,
+           WasmGlobalWithGetGlobalInitConversion,
+           WasmLocalConversion,
            WasmLocalGetConversion,
-           WasmReturnOpConversion
+           WasmLocalSetConversion,
+           WasmLocalTeeConversion,
+           WasmMaxOpConversion,
+           WasmMinOpConversion,
+           WasmMulOpConversion,
+           WasmNegOpConversion,
+           WasmOrOpConversion,
+           WasmPopCntOpConversion,
+           WasmPromoteOpConversion,
+           WasmReinterpretOpConversion,
+           WasmRemSIOpConversion,
+           WasmRemUIOpConversion,
+           WasmReturnOpConversion,
+           WasmShLOpConversion,
+           WasmShRSOpConversion,
+           WasmShRUOpConversion,
+           WasmSqrtOpConversion,
+           WasmSubOpConversion,
+           WasmTruncOpConversion,
+           WasmWrapOpConversion,
+           WasmXOrOpConversion
            >(tc, ctx);
   // clang-format on
 }
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-abs-to-math-abs.mlir b/mlir/test/Conversion/RaiseWasm/wasm-abs-to-math-abs.mlir
new file mode 100644
index 0000000000000..eee03772589b9
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-abs-to-math-abs.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @abs_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = math.absf %[[VAL_1]] : f32
+// CHECK:           return %[[VAL_2]] : f32
+wasmssa.func @abs_f32(%arg0: !wasmssa<local ref to f32>) -> f32 {
+    %val = wasmssa.local_get %arg0 : ref to f32
+    %op = wasmssa.abs %val : f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @abs_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = math.absf %[[VAL_1]] : f64
+// CHECK:           return %[[VAL_2]] : f64
+wasmssa.func @abs_f64(%arg0: !wasmssa<local ref to f64>) -> f64 {
+    %val = wasmssa.local_get %arg0 : ref to f64
+    %op = wasmssa.abs %val : f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-add-to-arith-add.mlir b/mlir/test/Conversion/RaiseWasm/wasm-add-to-arith-add.mlir
new file mode 100644
index 0000000000000..377be5d1a2f1e
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-add-to-arith-add.mlir
@@ -0,0 +1,79 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @func_1(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+wasmssa.func @func_1(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+%v1 = wasmssa.local_get %arg1 : ref to i32
+// CHECK:           %[[VAL_4:.*]] = arith.addi %[[VAL_2]], %[[VAL_3]] : i32
+%0 = wasmssa.add %v0 %v1 : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.return %0 : i32
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @func_2(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+wasmssa.func @func_2(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+%v0 = wasmssa.local_get %arg0 : ref to i64
+%v1 = wasmssa.local_get %arg1 : ref to i64
+// CHECK:           %[[VAL_4:.*]] = arith.addi %[[VAL_2]], %[[VAL_3]] : i64
+%0 = wasmssa.add %v0 %v1 : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.return %0 : i64
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @func_3(
+// CHECK-SAME:                      %[[ARG0:.*]]: f32,
+// CHECK-SAME:                      %[[ARG1:.*]]: f32) -> f32 {
+wasmssa.func @func_3(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+%v0 = wasmssa.local_get %arg0 : ref to f32
+%v1 = wasmssa.local_get %arg1 : ref to f32
+// CHECK:           %[[VAL_4:.*]] = arith.addf %[[VAL_2]], %[[VAL_3]] : f32
+%0 = wasmssa.add %v0 %v1 : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.return %0 : f32
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @func_4(
+// CHECK-SAME:                      %[[ARG0:.*]]: f64,
+// CHECK-SAME:                      %[[ARG1:.*]]: f64) -> f64 {
+wasmssa.func @func_4(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+%v0 = wasmssa.local_get %arg0 : ref to f64
+%v1 = wasmssa.local_get %arg1 : ref to f64
+// CHECK:           %[[VAL_4:.*]] = arith.addf %[[VAL_2]], %[[VAL_3]] : f64
+%0 = wasmssa.add %v0 %v1 : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.return %0 : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-and-to-arith-and.mlir b/mlir/test/Conversion/RaiseWasm/wasm-and-to-arith-and.mlir
new file mode 100644
index 0000000000000..eebc76e7322ae
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-and-to-arith-and.mlir
@@ -0,0 +1,38 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @and_i32(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @and_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %and = wasmssa.and %v0 %v1 : i32
+    wasmssa.return %and : i32
+}
+
+// CHECK-LABEL:   func.func @and_i64(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @and_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %and = wasmssa.and %v0 %v1 : i64
+    wasmssa.return %and : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-ceil-to-math-ceil.mlir b/mlir/test/Conversion/RaiseWasm/wasm-ceil-to-math-ceil.mlir
new file mode 100644
index 0000000000000..15875f60c1c43
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-ceil-to-math-ceil.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+module {
+  wasmssa.func exported @func_0() -> f64 {
+    %0 = wasmssa.const -1.210000e+01 : f64
+    %1 = wasmssa.ceil %0 : f64
+    wasmssa.return %1 : f64
+  }
+  wasmssa.func exported @func_1() -> f32 {
+    %0 = wasmssa.const 1.618000e+00 : f32
+    %1 = wasmssa.ceil %0 : f32
+    wasmssa.return %1 : f32
+  }
+}
+
+// CHECK-LABEL:   func.func @func_0() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = math.ceil %[[VAL_0]] : f64
+// CHECK:           return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   func.func @func_1() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = math.ceil %[[VAL_0]] : f32
+// CHECK:           return %[[VAL_1]] : f32
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-clz-to-math-clz.mlir b/mlir/test/Conversion/RaiseWasm/wasm-clz-to-math-clz.mlir
new file mode 100644
index 0000000000000..944cf24ff40c2
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-clz-to-math-clz.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @clz_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = math.ctlz %[[VAL_1]] : i32
+// CHECK:           return %[[VAL_2]] : i32
+wasmssa.func exported @clz_i32(%arg0: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %op = wasmssa.clz %v0 : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @clz_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = math.ctlz %[[VAL_1]] : i64
+// CHECK:           return %[[VAL_2]] : i64
+wasmssa.func exported @clz_i64(%arg0: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %op = wasmssa.clz %v0 : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-const-to-arith-const.mlir b/mlir/test/Conversion/RaiseWasm/wasm-const-to-arith-const.mlir
new file mode 100644
index 0000000000000..06bd0acab4f96
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-const-to-arith-const.mlir
@@ -0,0 +1,15 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @get_some_const() -> (i32, i64, f32, f64) {
+wasmssa.func exported @get_some_const() -> (i32, i64, f32, f64) {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 17 : i32
+%0 = wasmssa.const 17: i32
+// CHECK:           %[[VAL_1:.*]] = arith.constant -163 : i64
+%1 = wasmssa.const -163 : i64
+// CHECK:           %[[VAL_2:.*]] = arith.constant 3.140000e+00 : f32
+%2 = wasmssa.const 3.14 : f32
+// CHECK:           %[[VAL_3:.*]] = arith.constant -1.575000e+02 : f64
+%3 = wasmssa.const -157.5 : f64
+// CHECK:           return %[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]] : i32, i64, f32, f64
+wasmssa.return %0, %1, %2, %3 : i32, i64, f32, f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-convert-to-arith-tofp.mlir b/mlir/test/Conversion/RaiseWasm/wasm-convert-to-arith-tofp.mlir
new file mode 100644
index 0000000000000..4eeea757d48d0
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-convert-to-arith-tofp.mlir
@@ -0,0 +1,81 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @convert_i32_u_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : i32
+// CHECK:           %[[VAL_1:.*]] = arith.uitofp %[[VAL_0]] : i32 to f32
+// CHECK:           return %[[VAL_1]] : f32
+wasmssa.func @convert_i32_u_to_f32() -> f32 {
+  %0 = wasmssa.const 10 : i32
+  %1 = wasmssa.convert_u %0 : i32 to f32
+  wasmssa.return %1 : f32
+}
+
+// CHECK-LABEL:   func.func @convert_i32_s_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 42 : i32
+// CHECK:           %[[VAL_1:.*]] = arith.sitofp %[[VAL_0]] : i32 to f32
+// CHECK:           return %[[VAL_1]] : f32
+wasmssa.func @convert_i32_s_to_f32() -> f32 {
+  %0 = wasmssa.const 42 : i32
+  %1 = wasmssa.convert_s %0 : i32 to f32
+  wasmssa.return %1 : f32
+}
+
+// CHECK-LABEL:   func.func @convert_i64_u_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 17 : i64
+// CHECK:           %[[VAL_1:.*]] = arith.uitofp %[[VAL_0]] : i64 to f32
+// CHECK:           return %[[VAL_1]] : f32
+wasmssa.func @convert_i64_u_to_f32() -> f32 {
+  %0 = wasmssa.const 17 : i64
+  %1 = wasmssa.convert_u %0 : i64 to f32
+  wasmssa.return %1 : f32
+}
+
+// CHECK-LABEL:   func.func @convert_i64s_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : i64
+// CHECK:           %[[VAL_1:.*]] = arith.sitofp %[[VAL_0]] : i64 to f32
+// CHECK:           return %[[VAL_1]] : f32
+wasmssa.func @convert_i64s_to_f32() -> f32 {
+  %0 = wasmssa.const 10 : i64
+  %1 = wasmssa.convert_s %0 : i64 to f32
+  wasmssa.return %1 : f32
+}
+
+// CHECK-LABEL:   func.func @convert_i32_u_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : i32
+// CHECK:           %[[VAL_1:.*]] = arith.uitofp %[[VAL_0]] : i32 to f64
+// CHECK:           return %[[VAL_1]] : f64
+wasmssa.func @convert_i32_u_to_f64() -> f64 {
+  %0 = wasmssa.const 10 : i32
+  %1 = wasmssa.convert_u %0 : i32 to f64
+  wasmssa.return %1 : f64
+}
+
+// CHECK-LABEL:   func.func @convert_i32_s_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 42 : i32
+// CHECK:           %[[VAL_1:.*]] = arith.sitofp %[[VAL_0]] : i32 to f64
+// CHECK:           return %[[VAL_1]] : f64
+wasmssa.func @convert_i32_s_to_f64() -> f64 {
+  %0 = wasmssa.const 42 : i32
+  %1 = wasmssa.convert_s %0 : i32 to f64
+  wasmssa.return %1 : f64
+}
+
+// CHECK-LABEL:   func.func @convert_i64_u_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 17 : i64
+// CHECK:           %[[VAL_1:.*]] = arith.uitofp %[[VAL_0]] : i64 to f64
+// CHECK:           return %[[VAL_1]] : f64
+wasmssa.func @convert_i64_u_to_f64() -> f64 {
+  %0 = wasmssa.const 17 : i64
+  %1 = wasmssa.convert_u %0 : i64 to f64
+  wasmssa.return %1 : f64
+}
+
+// CHECK-LABEL:   func.func @convert_i64s_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : i64
+// CHECK:           %[[VAL_1:.*]] = arith.sitofp %[[VAL_0]] : i64 to f64
+// CHECK:           return %[[VAL_1]] : f64
+wasmssa.func @convert_i64s_to_f64() -> f64 {
+  %0 = wasmssa.const 10 : i64
+  %1 = wasmssa.convert_s %0 : i64 to f64
+  wasmssa.return %1 : f64
+}
\ No newline at end of file
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-copysign-to-math-copysign.mlir b/mlir/test/Conversion/RaiseWasm/wasm-copysign-to-math-copysign.mlir
new file mode 100644
index 0000000000000..9ab2b7990e7c0
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-copysign-to-math-copysign.mlir
@@ -0,0 +1,38 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @copysign_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32,
+// CHECK-SAME:      %[[ARG1:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_4:.*]] = math.copysign %[[VAL_2]], %[[VAL_3]] : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.func exported @copysign_f32(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+    %v0 = wasmssa.local_get %arg0 : ref to f32
+    %v1 = wasmssa.local_get %arg1 : ref to f32
+    %op = wasmssa.copysign %v0 %v1: f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @copysign_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64,
+// CHECK-SAME:      %[[ARG1:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_4:.*]] = math.copysign %[[VAL_2]], %[[VAL_3]] : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.func exported @copysign_f64(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+    %v0 = wasmssa.local_get %arg0 : ref to f64
+    %v1 = wasmssa.local_get %arg1 : ref to f64
+    %op = wasmssa.copysign %v0 %v1: f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-ctz-to-math-ctz.mlir b/mlir/test/Conversion/RaiseWasm/wasm-ctz-to-math-ctz.mlir
new file mode 100644
index 0000000000000..6cc9394eea99c
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-ctz-to-math-ctz.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @ctz_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = math.cttz %[[VAL_1]] : i32
+// CHECK:           return %[[VAL_2]] : i32
+wasmssa.func exported @ctz_i32(%arg0: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %op = wasmssa.ctz %v0 : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @ctz_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = math.cttz %[[VAL_1]] : i64
+// CHECK:           return %[[VAL_2]] : i64
+wasmssa.func exported @ctz_i64(%arg0: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %op = wasmssa.ctz %v0 : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-demote-to-arith-trunc.mlir b/mlir/test/Conversion/RaiseWasm/wasm-demote-to-arith-trunc.mlir
new file mode 100644
index 0000000000000..342886e3bda00
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-demote-to-arith-trunc.mlir
@@ -0,0 +1,14 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+module {
+  wasmssa.func @func_0() -> f32 {
+    %0 = wasmssa.const 2.240000e+00 : f64
+    %1 = wasmssa.demote %0 : f64 to f32
+    wasmssa.return %1 : f32
+  }
+}
+
+// CHECK-LABEL:   func.func @func_0() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 2.240000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = arith.truncf %[[VAL_0]] : f64 to f32
+// CHECK:           return %[[VAL_1]] : f32
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-div-to-arith-div.mlir b/mlir/test/Conversion/RaiseWasm/wasm-div-to-arith-div.mlir
new file mode 100644
index 0000000000000..3d6fa9af95442
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-div-to-arith-div.mlir
@@ -0,0 +1,109 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @div_i32_si(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+wasmssa.func @div_i32_si(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+%v1 = wasmssa.local_get %arg1 : ref to i32
+// CHECK:           %[[VAL_4:.*]] = arith.divsi %[[VAL_2]], %[[VAL_3]] : i32
+%0 = wasmssa.div_si %v0 %v1 : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.return %0 : i32
+}
+
+// CHECK-LABEL:   func.func @div_i64_si(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+wasmssa.func @div_i64_si(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+%v0 = wasmssa.local_get %arg0 : ref to i64
+%v1 = wasmssa.local_get %arg1 : ref to i64
+// CHECK:           %[[VAL_4:.*]] = arith.divsi %[[VAL_2]], %[[VAL_3]] : i64
+%0 = wasmssa.div_si %v0 %v1 : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.return %0 : i64
+}
+
+// CHECK-LABEL:   func.func @div_i32_ui(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+wasmssa.func @div_i32_ui(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+%v1 = wasmssa.local_get %arg1 : ref to i32
+// CHECK:           %[[VAL_4:.*]] = arith.divui %[[VAL_2]], %[[VAL_3]] : i32
+%0 = wasmssa.div_ui %v0 %v1 : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.return %0 : i32
+}
+
+// CHECK-LABEL:   func.func @div_i64_ui(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+wasmssa.func @div_i64_ui(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+%v0 = wasmssa.local_get %arg0 : ref to i64
+%v1 = wasmssa.local_get %arg1 : ref to i64
+// CHECK:           %[[VAL_4:.*]] = arith.divui %[[VAL_2]], %[[VAL_3]] : i64
+%0 = wasmssa.div_ui %v0 %v1 : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.return %0 : i64
+}
+
+// CHECK-LABEL:   func.func @div_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32,
+// CHECK-SAME:      %[[ARG1:.*]]: f32) -> f32 {
+wasmssa.func @div_f32(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+%v0 = wasmssa.local_get %arg0 : ref to f32
+%v1 = wasmssa.local_get %arg1 : ref to f32
+// CHECK:           %[[VAL_4:.*]] = arith.divf %[[VAL_2]], %[[VAL_3]] : f32
+%0 = wasmssa.div %v0 %v1 : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.return %0 : f32
+}
+
+// CHECK-LABEL:   func.func @div_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64,
+// CHECK-SAME:      %[[ARG1:.*]]: f64) -> f64 {
+wasmssa.func @div_f64(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+%v0 = wasmssa.local_get %arg0 : ref to f64
+%v1 = wasmssa.local_get %arg1 : ref to f64
+// CHECK:           %[[VAL_4:.*]] = arith.divf %[[VAL_2]], %[[VAL_3]] : f64
+%0 = wasmssa.div %v0 %v1 : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.return %0 : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-floor-to-math-floor.mlir b/mlir/test/Conversion/RaiseWasm/wasm-floor-to-math-floor.mlir
new file mode 100644
index 0000000000000..5ca4694bdb824
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-floor-to-math-floor.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+module {
+  wasmssa.func @func_0() -> f64 {
+    %0 = wasmssa.const -1.210000e+01 : f64
+    %1 = wasmssa.floor %0 : f64
+    wasmssa.return %1 : f64
+  }
+  wasmssa.func @func_1() -> f32 {
+    %0 = wasmssa.const 1.618000e+00 : f32
+    %1 = wasmssa.floor %0 : f32
+    wasmssa.return %1 : f32
+  }
+}
+
+// CHECK-LABEL:   func.func @func_0() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = math.floor %[[VAL_0]] : f64
+// CHECK:           return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   func.func @func_1() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = math.floor %[[VAL_0]] : f32
+// CHECK:           return %[[VAL_1]] : f32
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-global-to-memref-global.mlir b/mlir/test/Conversion/RaiseWasm/wasm-global-to-memref-global.mlir
new file mode 100644
index 0000000000000..45a6636d89c22
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-global-to-memref-global.mlir
@@ -0,0 +1,43 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir | FileCheck %s
+
+wasmssa.global @global_i32 i32 mutable : {
+  %0 = wasmssa.const 66560 : i32
+  wasmssa.return %0 : i32
+}
+
+wasmssa.global @global_i64 i64 mutable : {
+  %0 = wasmssa.const 37017 : i64
+  wasmssa.return %0 : i64
+}
+
+wasmssa.global @global_f32 f32 mutable : {
+  %0 = wasmssa.const 0.125 : f32
+  wasmssa.return %0 : f32
+}
+
+wasmssa.global @global_f64 f64 mutable : {
+  %0 = wasmssa.const 3.14 : f64
+  wasmssa.return %0 : f64
+}
+
+wasmssa.global @global_user0 i32 mutable : {
+  %0 = wasmssa.global_get @global_top_define : i32
+  wasmssa.return %0 : i32
+}
+
+wasmssa.import_global "extern_global_var" from "module" as @global_top_define nested : i32
+
+// CHECK-LABEL:   memref.global "private" @global_i32 : memref<1xi32> = dense<66560>
+// CHECK:         memref.global "private" @global_i64 : memref<1xi64> = dense<37017>
+// CHECK:         memref.global "private" @global_f32 : memref<1xf32> = dense<1.250000e-01>
+// CHECK:         memref.global "private" @global_f64 : memref<1xf64> = dense<3.140000e+00>
+// CHECK:         memref.global "private" @global_user0 : memref<1xi32> = uninitialized
+
+// CHECK-LABEL:   func.func @"global_user0::initializer"() attributes {initializer} {
+// CHECK:           %[[VAL_0:.*]] = memref.get_global @"module::extern_global_var" : memref<1xi32>
+// CHECK:           %[[VAL_1:.*]] = memref.get_global @global_user0 : memref<1xi32>
+// CHECK:           %[[VAL_2:.*]] = arith.constant 0 : index
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]]{{\[}}%[[VAL_2]]] : memref<1xi32>
+// CHECK:           memref.store %[[VAL_3]], %[[VAL_1]]{{\[}}%[[VAL_2]]] : memref<1xi32>
+// CHECK:           return
+// CHECK:         memref.global "nested" constant @"module::extern_global_var" : memref<1xi32>
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-local-to-memref.mlir b/mlir/test/Conversion/RaiseWasm/wasm-local-to-memref.mlir
new file mode 100644
index 0000000000000..839975ab87daa
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-local-to-memref.mlir
@@ -0,0 +1,68 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @func_0() -> f32 {
+wasmssa.func exported @func_0() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f32
+// CHECK:           memref.store %[[VAL_1]], %[[VAL_0]][] : memref<f32>
+  %0 = wasmssa.local of type f32
+// CHECK:           %[[VAL_2:.*]] = memref.alloca() : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32
+// CHECK:           memref.store %[[VAL_3]], %[[VAL_2]][] : memref<f32>
+  %1 = wasmssa.local of type f32
+// CHECK:           %[[VAL_4:.*]] = arith.constant 8.000000e+00 : f32
+  %2 = wasmssa.const 8.000000e+00 : f32
+// CHECK:           memref.store %[[VAL_4]], %[[VAL_0]][] : memref<f32>
+  wasmssa.local_set %0 : ref to f32 to %2 : f32
+// CHECK:           %[[VAL_5:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+  %3 = wasmssa.local_get %0 : ref to f32
+// CHECK:           %[[VAL_6:.*]] = arith.constant 1.200000e+01 : f32
+  %4 = wasmssa.const 1.200000e+01 : f32
+// CHECK:           memref.store %[[VAL_6]], %[[VAL_2]][] : memref<f32>
+  %5 = wasmssa.local_tee %1 : ref to f32 to %4 : f32
+// CHECK:           %[[VAL_7:.*]] = arith.addf %[[VAL_5]], %[[VAL_6]] : f32
+  %6 = wasmssa.add %3 %5 : f32
+// CHECK:           return %[[VAL_7]] : f32
+  wasmssa.return %6 : f32
+}
+
+// CHECK-LABEL:   func.func @func_1() -> i32 {
+wasmssa.func exported @func_1() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = arith.constant 0 : i32
+// CHECK:           memref.store %[[VAL_1]], %[[VAL_0]][] : memref<i32>
+  %0 = wasmssa.local of type i32
+// CHECK:           %[[VAL_2:.*]] = memref.alloca() : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = arith.constant 0 : i32
+// CHECK:           memref.store %[[VAL_3]], %[[VAL_2]][] : memref<i32>
+  %1 = wasmssa.local of type i32
+// CHECK:           %[[VAL_4:.*]] = arith.constant 8 : i32
+  %2 = wasmssa.const 8 : i32
+// CHECK:           memref.store %[[VAL_4]], %[[VAL_0]][] : memref<i32>
+  wasmssa.local_set %0 : ref to i32 to %2 : i32
+// CHECK:           %[[VAL_5:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+  %3 = wasmssa.local_get %0 : ref to i32
+// CHECK:           %[[VAL_6:.*]] = arith.constant 12 : i32
+  %4 = wasmssa.const 12 : i32
+// CHECK:           memref.store %[[VAL_6]], %[[VAL_2]][] : memref<i32>
+  %5 = wasmssa.local_tee %1 : ref to i32 to %4 : i32
+// CHECK:           %[[VAL_7:.*]] = arith.addi %[[VAL_5]], %[[VAL_6]] : i32
+  %6 = wasmssa.add %3 %5 : i32
+// CHECK:           return %[[VAL_7]] : i32
+  wasmssa.return %6 : i32
+}
+
+// CHECK-LABEL:   func.func @func_2(
+// CHECK-SAME:                      %[[VAL_0:.*]]: i32) -> i32 {
+wasmssa.func exported @func_2(%arg0: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[VAL_0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = arith.constant 3 : i32
+  %1 = wasmssa.const 3 : i32
+// CHECK:           memref.store %[[VAL_2]], %[[VAL_1]][] : memref<i32>
+  wasmssa.local_set %arg0 : ref to i32 to %1 : i32
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+  %2 = wasmssa.local_get %arg0 : ref to i32
+// CHECK:           return %[[VAL_3]] : i32
+  wasmssa.return %2 : i32
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-max-to-arith-maximumf.mlir b/mlir/test/Conversion/RaiseWasm/wasm-max-to-arith-maximumf.mlir
new file mode 100644
index 0000000000000..2f0d10788f03c
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-max-to-arith-maximumf.mlir
@@ -0,0 +1,37 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @max_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32,
+// CHECK-SAME:      %[[ARG1:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_4:.*]] = arith.maximumf %[[VAL_2]], %[[VAL_3]] : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.func exported @max_f32(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+    %v0 = wasmssa.local_get %arg0 : ref to f32
+    %v1 = wasmssa.local_get %arg1 : ref to f32
+    %op = wasmssa.max %v0 %v1 : f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @max_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64,
+// CHECK-SAME:      %[[ARG1:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_4:.*]] = arith.maximumf %[[VAL_2]], %[[VAL_3]] : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.func exported @max_f64(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+    %v0 = wasmssa.local_get %arg0 : ref to f64
+    %v1 = wasmssa.local_get %arg1 : ref to f64
+    %op = wasmssa.max %v0 %v1 : f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-min-to-arith-minimumf.mlir b/mlir/test/Conversion/RaiseWasm/wasm-min-to-arith-minimumf.mlir
new file mode 100644
index 0000000000000..d6a0141a5199f
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-min-to-arith-minimumf.mlir
@@ -0,0 +1,37 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @min_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32,
+// CHECK-SAME:      %[[ARG1:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_4:.*]] = arith.minimumf %[[VAL_2]], %[[VAL_3]] : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.func exported @min_f32(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+    %v0 = wasmssa.local_get %arg0 : ref to f32
+    %v1 = wasmssa.local_get %arg1 : ref to f32
+    %op = wasmssa.min %v0 %v1 : f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @min_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64,
+// CHECK-SAME:      %[[ARG1:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_4:.*]] = arith.minimumf %[[VAL_2]], %[[VAL_3]] : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.func exported @min_f64(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+    %v0 = wasmssa.local_get %arg0 : ref to f64
+    %v1 = wasmssa.local_get %arg1 : ref to f64
+    %op = wasmssa.min %v0 %v1 : f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-mul-to-arith-mul.mlir b/mlir/test/Conversion/RaiseWasm/wasm-mul-to-arith-mul.mlir
new file mode 100644
index 0000000000000..51c8b43d980b5
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-mul-to-arith-mul.mlir
@@ -0,0 +1,78 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @mul_i32(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+wasmssa.func @mul_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+%v1 = wasmssa.local_get %arg1 : ref to i32
+// CHECK:           %[[VAL_4:.*]] = arith.muli %[[VAL_2]], %[[VAL_3]] : i32
+%0 = wasmssa.mul %v0 %v1 : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.return %0 : i32
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @mul_i64(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+wasmssa.func @mul_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+%v0 = wasmssa.local_get %arg0 : ref to i64
+%v1 = wasmssa.local_get %arg1 : ref to i64
+// CHECK:           %[[VAL_4:.*]] = arith.muli %[[VAL_2]], %[[VAL_3]] : i64
+%0 = wasmssa.mul %v0 %v1 : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.return %0 : i64
+}
+// -----
+
+// CHECK-LABEL:   func.func @mul_f32(
+// CHECK-SAME:                      %[[ARG0:.*]]: f32,
+// CHECK-SAME:                      %[[ARG1:.*]]: f32) -> f32 {
+wasmssa.func @mul_f32(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+%v0 = wasmssa.local_get %arg0 : ref to f32
+%v1 = wasmssa.local_get %arg1 : ref to f32
+// CHECK:           %[[VAL_4:.*]] = arith.mulf %[[VAL_2]], %[[VAL_3]] : f32
+%0 = wasmssa.mul %v0 %v1 : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.return %0 : f32
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @mul_f64(
+// CHECK-SAME:                      %[[ARG0:.*]]: f64,
+// CHECK-SAME:                      %[[ARG1:.*]]: f64) -> f64 {
+wasmssa.func @mul_f64(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+%v0 = wasmssa.local_get %arg0 : ref to f64
+%v1 = wasmssa.local_get %arg1 : ref to f64
+// CHECK:           %[[VAL_4:.*]] = arith.mulf %[[VAL_2]], %[[VAL_3]] : f64
+%0 = wasmssa.mul %v0 %v1 : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.return %0 : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-neg-to-arith-neg.mlir b/mlir/test/Conversion/RaiseWasm/wasm-neg-to-arith-neg.mlir
new file mode 100644
index 0000000000000..a15b9a6c25990
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-neg-to-arith-neg.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @neg_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = arith.negf %[[VAL_1]] : f32
+// CHECK:           return %[[VAL_2]] : f32
+wasmssa.func @neg_f32(%arg0: !wasmssa<local ref to f32>) -> f32 {
+    %val = wasmssa.local_get %arg0 : ref to f32
+    %op = wasmssa.neg %val : f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @neg_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = arith.negf %[[VAL_1]] : f64
+// CHECK:           return %[[VAL_2]] : f64
+wasmssa.func @neg_f64(%arg0: !wasmssa<local ref to f64>) -> f64 {
+    %val = wasmssa.local_get %arg0 : ref to f64
+    %op = wasmssa.neg %val : f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-or-to-arith-or.mlir b/mlir/test/Conversion/RaiseWasm/wasm-or-to-arith-or.mlir
new file mode 100644
index 0000000000000..44ce35209511d
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-or-to-arith-or.mlir
@@ -0,0 +1,38 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @or_i32(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @or_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %or = wasmssa.or %v0 %v1 : i32
+    wasmssa.return %or : i32
+}
+
+// CHECK-LABEL:   func.func @or_i64(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @or_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %or = wasmssa.or %v0 %v1 : i64
+    wasmssa.return %or : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-popcnt-to-math-ctpop.mlir b/mlir/test/Conversion/RaiseWasm/wasm-popcnt-to-math-ctpop.mlir
new file mode 100644
index 0000000000000..1c027cf1972e8
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-popcnt-to-math-ctpop.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @popcnt_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = math.ctpop %[[VAL_1]] : i32
+// CHECK:           return %[[VAL_2]] : i32
+wasmssa.func exported @popcnt_i32(%arg0: !wasmssa<local ref to i32>) -> i32 {
+    %v = wasmssa.local_get %arg0 : ref to i32
+    %op = wasmssa.popcnt %v : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @popcnt_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = math.ctpop %[[VAL_1]] : i64
+// CHECK:           return %[[VAL_2]] : i64
+wasmssa.func exported @popcnt_i64(%arg0: !wasmssa<local ref to i64>) -> i64 {
+    %v = wasmssa.local_get %arg0 : ref to i64
+    %op = wasmssa.popcnt %v : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-promote-to-arith-ext.mlir b/mlir/test/Conversion/RaiseWasm/wasm-promote-to-arith-ext.mlir
new file mode 100644
index 0000000000000..5cf04a0ccbd3c
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-promote-to-arith-ext.mlir
@@ -0,0 +1,11 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @promote_f32_to_f64() -> f64 {
+wasmssa.func @promote_f32_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 3.140000e+00 : f32
+  %0 = wasmssa.const 3.14 : f32
+// CHECK:           %[[VAL_1:.*]] = arith.extf %[[VAL_0]] : f32 to f64
+  %1 = wasmssa.promote %0 : f32 to f64
+// CHECK:           return %[[VAL_1]] : f64
+  wasmssa.return %1 : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-reinterpret-to-arith-bitcast.mlir b/mlir/test/Conversion/RaiseWasm/wasm-reinterpret-to-arith-bitcast.mlir
new file mode 100644
index 0000000000000..78e3984870d6b
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-reinterpret-to-arith-bitcast.mlir
@@ -0,0 +1,42 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+module {
+// CHECK-LABEL:   func.func @i32.reinterpret_f32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = arith.bitcast %[[VAL_0]] : f32 to i32
+// CHECK:           return %[[VAL_1]] : i32
+  wasmssa.func @i32.reinterpret_f32() -> i32 {
+    %0 = wasmssa.const -1.000000e+00 : f32
+    %1 = wasmssa.reinterpret %0 : f32 as i32
+    wasmssa.return %1 : i32
+  }
+
+// CHECK-LABEL:   func.func @i64.reinterpret_f64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = arith.bitcast %[[VAL_0]] : f64 to i64
+// CHECK:           return %[[VAL_1]] : i64
+  wasmssa.func @i64.reinterpret_f64() -> i64 {
+    %0 = wasmssa.const -1.000000e+00 : f64
+    %1 = wasmssa.reinterpret %0 : f64 as i64
+    wasmssa.return %1 : i64
+  }
+
+// CHECK-LABEL:   func.func @f32.reinterpret_i32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1 : i32
+// CHECK:           %[[VAL_1:.*]] = arith.bitcast %[[VAL_0]] : i32 to f32
+// CHECK:           return %[[VAL_1]] : f32
+  wasmssa.func @f32.reinterpret_i32() -> f32 {
+    %0 = wasmssa.const -1 : i32
+    %1 = wasmssa.reinterpret %0 : i32 as f32
+    wasmssa.return %1 : f32
+  }
+
+// CHECK-LABEL:   func.func @f64.reinterpret_i64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1 : i64
+// CHECK:           %[[VAL_1:.*]] = arith.bitcast %[[VAL_0]] : i64 to f64
+// CHECK:           return %[[VAL_1]] : f64
+  wasmssa.func @f64.reinterpret_i64() -> f64 {
+    %0 = wasmssa.const -1 : i64
+    %1 = wasmssa.reinterpret %0 : i64 as f64
+    wasmssa.return %1 : f64
+  }
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-rem-to-arith-rem.mlir b/mlir/test/Conversion/RaiseWasm/wasm-rem-to-arith-rem.mlir
new file mode 100644
index 0000000000000..05a5b5bd10cfa
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-rem-to-arith-rem.mlir
@@ -0,0 +1,74 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @rem_ui_32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.remui %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @rem_ui_32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0: ref to i32
+    %v1 = wasmssa.local_get %arg1: ref to i32
+    %rem = wasmssa.rem_ui %v0 %v1 : i32
+    wasmssa.return %rem : i32
+}
+
+// CHECK-LABEL:   func.func @rem_si_32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.remsi %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @rem_si_32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0: ref to i32
+    %v1 = wasmssa.local_get %arg1: ref to i32
+    %rem = wasmssa.rem_si %v0 %v1 : i32
+    wasmssa.return %rem : i32
+}
+
+// CHECK-LABEL:   func.func @rem_ui_64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.remui %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @rem_ui_64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0: ref to i64
+    %v1 = wasmssa.local_get %arg1: ref to i64
+    %rem = wasmssa.rem_ui %v0 %v1 : i64
+    wasmssa.return %rem : i64
+}
+
+// CHECK-LABEL:   func.func @rem_si_64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.remsi %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @rem_si_64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0: ref to i64
+    %v1 = wasmssa.local_get %arg1: ref to i64
+    %rem = wasmssa.rem_si %v0 %v1 : i64
+    wasmssa.return %rem : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-shl-to-arith-shl.mlir b/mlir/test/Conversion/RaiseWasm/wasm-shl-to-arith-shl.mlir
new file mode 100644
index 0000000000000..efc4b5ca49225
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-shl-to-arith-shl.mlir
@@ -0,0 +1,38 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @shl_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.shli %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @shl_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %op = wasmssa.shl %v0 by %v1 bits : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @shl_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.shli %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @shl_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %op = wasmssa.shl %v0 by %v1 bits : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-shr_s-to-arith-shrs.mlir b/mlir/test/Conversion/RaiseWasm/wasm-shr_s-to-arith-shrs.mlir
new file mode 100644
index 0000000000000..d0c3a94e611a8
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-shr_s-to-arith-shrs.mlir
@@ -0,0 +1,38 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+
+// CHECK-LABEL:   func.func @shr_s_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @shr_s_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %op = wasmssa.shr_s %v0 by %v1 bits : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @shr_s_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @shr_s_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %op = wasmssa.shr_s %v0 by %v1 bits : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-shr_u-to-arith-shru.mlir b/mlir/test/Conversion/RaiseWasm/wasm-shr_u-to-arith-shru.mlir
new file mode 100644
index 0000000000000..38925b6899c4b
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-shr_u-to-arith-shru.mlir
@@ -0,0 +1,37 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @shr_u_i32(
+// CHECK-SAME:      %[[ARG0:.*]]: i32,
+// CHECK-SAME:      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.shrui %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func exported @shr_u_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %op = wasmssa.shr_u %v0 by %v1 bits : i32
+    wasmssa.return %op : i32
+}
+
+// CHECK-LABEL:   func.func @shr_u_i64(
+// CHECK-SAME:      %[[ARG0:.*]]: i64,
+// CHECK-SAME:      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.shrui %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func exported @shr_u_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %op = wasmssa.shr_u %v0 by %v1 bits : i64
+    wasmssa.return %op : i64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-sqrt-to-math-sqrt.mlir b/mlir/test/Conversion/RaiseWasm/wasm-sqrt-to-math-sqrt.mlir
new file mode 100644
index 0000000000000..394dc9e3216af
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-sqrt-to-math-sqrt.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @sqrt_f32(
+// CHECK-SAME:      %[[ARG0:.*]]: f32) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = math.sqrt %[[VAL_1]] : f32
+// CHECK:           return %[[VAL_2]] : f32
+wasmssa.func @sqrt_f32(%arg0: !wasmssa<local ref to f32>) -> f32 {
+    %local = wasmssa.local_get %arg0 : ref to f32
+    %op = wasmssa.sqrt %local : f32
+    wasmssa.return %op : f32
+}
+
+// CHECK-LABEL:   func.func @sqrt_f64(
+// CHECK-SAME:      %[[ARG0:.*]]: f64) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = math.sqrt %[[VAL_1]] : f64
+// CHECK:           return %[[VAL_2]] : f64
+wasmssa.func @sqrt_f64(%arg0: !wasmssa<local ref to f64>) -> f64 {
+    %local = wasmssa.local_get %arg0 : ref to f64
+    %op = wasmssa.sqrt %local : f64
+    wasmssa.return %op : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-sub-to-arith-sub.mlir b/mlir/test/Conversion/RaiseWasm/wasm-sub-to-arith-sub.mlir
new file mode 100644
index 0000000000000..933d3d16add7b
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-sub-to-arith-sub.mlir
@@ -0,0 +1,80 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir | FileCheck %s
+
+// CHECK-LABEL:   func.func @func_1(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+wasmssa.func @func_1(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+%v0 = wasmssa.local_get %arg0 : ref to i32
+%v1 = wasmssa.local_get %arg1 : ref to i32
+// CHECK:           %[[VAL_4:.*]] = arith.subi %[[VAL_2]], %[[VAL_3]] : i32
+%res = wasmssa.sub %v0 %v1 : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.return %res : i32
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @func_2(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+wasmssa.func @func_2(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+%v0 = wasmssa.local_get %arg0 : ref to i64
+%v1 = wasmssa.local_get %arg1 : ref to i64
+// CHECK:           %[[VAL_4:.*]] = arith.subi %[[VAL_2]], %[[VAL_3]] : i64
+%res = wasmssa.sub %v0 %v1 : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.return %res : i64
+}
+
+// -----
+
+// CHECK-LABEL:   func.func @func_3(
+// CHECK-SAME:                      %[[ARG0:.*]]: f32,
+// CHECK-SAME:                      %[[ARG1:.*]]: f32) -> f32 {
+wasmssa.func @func_3(%arg0: !wasmssa<local ref to f32>, %arg1: !wasmssa<local ref to f32>) -> f32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f32>
+%v0 = wasmssa.local_get %arg0 : ref to f32
+%v1 = wasmssa.local_get %arg1 : ref to f32
+// CHECK:           %[[VAL_4:.*]] = arith.subf %[[VAL_2]], %[[VAL_3]] : f32
+%res = wasmssa.sub %v0 %v1 : f32
+// CHECK:           return %[[VAL_4]] : f32
+wasmssa.return %res : f32
+}
+
+
+// -----
+
+// CHECK-LABEL:   func.func @func_4(
+// CHECK-SAME:                      %[[ARG0:.*]]: f64,
+// CHECK-SAME:                      %[[ARG1:.*]]: f64) -> f64 {
+wasmssa.func @func_4(%arg0: !wasmssa<local ref to f64>, %arg1: !wasmssa<local ref to f64>) -> f64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<f64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<f64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<f64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<f64>
+%v0 = wasmssa.local_get %arg0 : ref to f64
+%v1 = wasmssa.local_get %arg1 : ref to f64
+// CHECK:           %[[VAL_4:.*]] = arith.subf %[[VAL_2]], %[[VAL_3]] : f64
+%res = wasmssa.sub %v0 %v1 : f64
+// CHECK:           return %[[VAL_4]] : f64
+wasmssa.return %res : f64
+}
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-trunc-to-math-trunc.mlir b/mlir/test/Conversion/RaiseWasm/wasm-trunc-to-math-trunc.mlir
new file mode 100644
index 0000000000000..a120967bc3c0e
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-trunc-to-math-trunc.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+module {
+  wasmssa.func @func_4() -> f64 {
+    %0 = wasmssa.const -1.210000e+01 : f64
+    %1 = wasmssa.trunc %0 : f64
+    wasmssa.return %1 : f64
+  }
+  wasmssa.func @func_5() -> f32 {
+    %0 = wasmssa.const 1.618000e+00 : f32
+    %1 = wasmssa.trunc %0 : f32
+    wasmssa.return %1 : f32
+  }
+}
+
+// CHECK-LABEL:   func.func @func_4() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = math.trunc %[[VAL_0]] : f64
+// CHECK:           return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   func.func @func_5() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = math.trunc %[[VAL_0]] : f32
+// CHECK:           return %[[VAL_1]] : f32
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-wrap-to-arith-trunc.mlir b/mlir/test/Conversion/RaiseWasm/wasm-wrap-to-arith-trunc.mlir
new file mode 100644
index 0000000000000..6164525626086
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-wrap-to-arith-trunc.mlir
@@ -0,0 +1,17 @@
+// RUN: mlir-opt %s --raise-wasm-mlir | FileCheck %s
+
+module {
+  wasmssa.func @i64_wrap(%arg0: !wasmssa<local ref to i64>) -> i32 {
+    %0 = wasmssa.local_get %arg0 :  ref to i64
+    %1 = wasmssa.wrap %0 : i64 to i32
+    wasmssa.return %1 : i32
+  }
+}
+
+// CHECK-LABEL:   func.func @i64_wrap(
+// CHECK-SAME:      %[[ARG0:.*]]: i64) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = arith.trunci %[[VAL_1]] : i64 to i32
+// CHECK:           return %[[VAL_2]] : i32
diff --git a/mlir/test/Conversion/RaiseWasm/wasm-xor-to-arith-xor.mlir b/mlir/test/Conversion/RaiseWasm/wasm-xor-to-arith-xor.mlir
new file mode 100644
index 0000000000000..810729d883c61
--- /dev/null
+++ b/mlir/test/Conversion/RaiseWasm/wasm-xor-to-arith-xor.mlir
@@ -0,0 +1,37 @@
+// RUN: mlir-opt --split-input-file %s --raise-wasm-mlir -o - | FileCheck %s
+
+// CHECK-LABEL:   func.func @xor_i32(
+// CHECK-SAME:                      %[[ARG0:.*]]: i32,
+// CHECK-SAME:                      %[[ARG1:.*]]: i32) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i32>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i32>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i32>
+// CHECK:           %[[VAL_4:.*]] = arith.xori %[[VAL_2]], %[[VAL_3]] : i32
+// CHECK:           return %[[VAL_4]] : i32
+wasmssa.func @xor_i32(%arg0: !wasmssa<local ref to i32>, %arg1: !wasmssa<local ref to i32>) -> i32 {
+    %v0 = wasmssa.local_get %arg0 : ref to i32
+    %v1 = wasmssa.local_get %arg1 : ref to i32
+    %xor = wasmssa.xor %v0 %v1 : i32
+    wasmssa.return %xor : i32
+}
+
+// CHECK-LABEL:   func.func @xor_i64(
+// CHECK-SAME:                      %[[ARG0:.*]]: i64,
+// CHECK-SAME:                      %[[ARG1:.*]]: i64) -> i64 {
+// CHECK:           %[[VAL_0:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG1]], %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_1:.*]] = memref.alloca() : memref<i64>
+// CHECK:           memref.store %[[ARG0]], %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref<i64>
+// CHECK:           %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref<i64>
+// CHECK:           %[[VAL_4:.*]] = arith.xori %[[VAL_2]], %[[VAL_3]] : i64
+// CHECK:           return %[[VAL_4]] : i64
+wasmssa.func @xor_i64(%arg0: !wasmssa<local ref to i64>, %arg1: !wasmssa<local ref to i64>) -> i64 {
+    %v0 = wasmssa.local_get %arg0 : ref to i64
+    %v1 = wasmssa.local_get %arg1 : ref to i64
+    %xor = wasmssa.xor %v0 %v1 : i64
+    wasmssa.return %xor : i64
+}
    
    
More information about the Mlir-commits
mailing list