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..048eeb3149cf7 --- /dev/null +++ b/mlir/include/mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h @@ -0,0 +1,29 @@ +//===- 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 &); + +} // namespace mlir + +#endif // MLIR_CONVERSION_RAISEWASM_RAISEWASMMLIR_H diff --git a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td index e9425e884ae83..afa98c57f0ad9 100644 --- a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td +++ b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td @@ -318,7 +318,7 @@ def WasmSSA_GlobalOp : WasmSSA_Op<"global", [ } ``` }]; - let regions = (region AnyRegion: $initializer); + let regions = (region SizedRegion<1>: $initializer); let extraClassDeclaration = [{ ::mlir::SymbolTable::Visibility getVisibility() { @@ -326,8 +326,11 @@ def WasmSSA_GlobalOp : WasmSSA_Op<"global", [ ::mlir::SymbolTable::Visibility::Public : ::mlir::SymbolTable::Visibility::Nested; }; + + wasmssa::ReturnOp getInitTerminator(); }]; let hasCustomAssemblyFormat = 1; + let hasVerifier = 1; } def WasmSSA_GlobalImportOp : WasmSSA_Op<"import_global", [ diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt index bebf1b8fff3f9..c43b5f3ad5489 100644 --- a/mlir/lib/Conversion/CMakeLists.txt +++ b/mlir/lib/Conversion/CMakeLists.txt @@ -52,6 +52,7 @@ add_subdirectory(OpenACCToSCF) add_subdirectory(OpenMPToLLVM) add_subdirectory(PDLToPDLInterp) add_subdirectory(PtrToLLVM) +add_subdirectory(RaiseWasm) add_subdirectory(ReconcileUnrealizedCasts) add_subdirectory(SCFToControlFlow) add_subdirectory(SCFToEmitC) 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..83bfde7032ef8 --- /dev/null +++ b/mlir/lib/Conversion/RaiseWasm/RaiseWasmMLIR.cpp @@ -0,0 +1,469 @@ +//===- 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/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 + +#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 { + +template +struct IntFPDispatchMappingConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(SourceOp srcOp, typename SourceOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + Type type = srcOp.getRhs().getType(); + if (type.isInteger()) { + rewriter.replaceOpWithNewOp(srcOp, srcOp->getResultTypes(), + adaptor.getOperands()); + return success(); + } + if (!type.isFloat()) + return failure(); + rewriter.replaceOpWithNewOp(srcOp, srcOp->getResultTypes(), + adaptor.getOperands()); + return success(); + } +}; + +using WasmAddOpConversion = + IntFPDispatchMappingConversion; +using WasmMulOpConversion = + IntFPDispatchMappingConversion; +using WasmSubOpConversion = + IntFPDispatchMappingConversion; + +/// 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 +struct OpMappingConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(SourceOp srcOp, typename SourceOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(srcOp, srcOp->getResultTypes(), + adaptor.getOperands()); + return success(); + } +}; + +using WasmAndOpConversion = OpMappingConversion; +using WasmCeilOpConversion = OpMappingConversion; +/// TODO: SIToFP and UIToFP don't allow specification of the floating point +/// rounding mode +using WasmConvertSOpConversion = + OpMappingConversion; +using WasmConvertUOpConversion = + OpMappingConversion; +using WasmDemoteOpConversion = OpMappingConversion; +using WasmDivFPOpConversion = OpMappingConversion; +using WasmDivSIOpConversion = OpMappingConversion; +using WasmDivUIOpConversion = OpMappingConversion; +using WasmExtendSOpConversion = + OpMappingConversion; +using WasmExtendUOpConversion = + OpMappingConversion; +using WasmFloorOpConversion = OpMappingConversion; +using WasmMaxOpConversion = OpMappingConversion; +using WasmMinOpConversion = OpMappingConversion; +using WasmOrOpConversion = OpMappingConversion; +using WasmPromoteOpConversion = OpMappingConversion; +using WasmRemSIOpConversion = OpMappingConversion; +using WasmRemUIOpConversion = OpMappingConversion; +using WasmReinterpretOpConversion = + OpMappingConversion; +using WasmShLOpConversion = OpMappingConversion; +using WasmShRSOpConversion = OpMappingConversion; +using WasmShRUOpConversion = OpMappingConversion; +using WasmXOrOpConversion = OpMappingConversion; +using WasmNegOpConversion = OpMappingConversion; +using WasmCopySignOpConversion = + OpMappingConversion; +using WasmClzOpConversion = + OpMappingConversion; +using WasmCtzOpConversion = + OpMappingConversion; +using WasmPopCntOpConversion = OpMappingConversion; +using WasmAbsOpConversion = OpMappingConversion; +using WasmTruncOpConversion = OpMappingConversion; +using WasmSqrtOpConversion = OpMappingConversion; +using WasmWrapOpConversion = OpMappingConversion; + +struct WasmCallOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(FuncCallOp funcCallOp, FuncCallOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp( + funcCallOp, funcCallOp.getCallee(), funcCallOp.getResults().getTypes(), + funcCallOp.getOperands()); + return success(); + } +}; + +struct WasmConstOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(ConstOp constOp, ConstOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(constOp, constOp.getValue()); + return success(); + } +}; + +struct WasmFuncImportOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(FuncImportOp funcImportOp, FuncImportOp::Adaptor, + ConversionPatternRewriter &rewriter) const override { + auto nFunc = rewriter.replaceOpWithNewOp( + funcImportOp, funcImportOp.getSymName(), funcImportOp.getType()); + nFunc.setVisibility(SymbolTable::Visibility::Private); + return success(); + } +}; + +struct WasmFuncOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(FuncOp funcOp, FuncOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto newFunc = + func::FuncOp::create(rewriter, 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(blockArgTypes[i]); + if (!argType) + return failure(); + sC.addInputs(i, argType.getElementType()); + } + + rewriter.applySignatureConversion(oldEntryBlock, sC, getTypeConverter()); + rewriter.replaceOp(funcOp, newFunc); + return success(); + } +}; + +struct WasmGlobalImportOpConverter : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(GlobalImportOp gIOp, GlobalImportOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto memrefGOp = rewriter.replaceOpWithNewOp( + 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 +struct GlobalOpConverter : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(GlobalOp globalOp, GlobalOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + ReturnOp rop = globalOp.getInitTerminator(); + + if (rop->getNumOperands() != 1) + return rewriter.notifyMatchFailure( + globalOp, "globalOp initializer should return one value exactly"); + + auto initializerOp = + dyn_cast(rop->getOperand(0).getDefiningOp()); + + if (!initializerOp) + return rewriter.notifyMatchFailure( + globalOp, "invalid initializer op type for this pattern"); + + return static_cast(this)->handleInitializer( + globalOp, rewriter, initializerOp); + } +}; + +struct WasmGlobalWithConstInitConversion + : GlobalOpConverter { + using GlobalOpConverter::GlobalOpConverter; + LogicalResult handleInitializer(GlobalOp globalOp, + ConversionPatternRewriter &rewriter, + ConstOp constInit) const { + auto initializer = + DenseElementsAttr::get(RankedTensorType::get({1}, globalOp.getType()), + ArrayRef{constInit.getValueAttr()}); + auto globalReplacement = rewriter.replaceOpWithNewOp( + 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 { + using GlobalOpConverter::GlobalOpConverter; + LogicalResult handleInitializer(GlobalOp globalOp, + ConversionPatternRewriter &rewriter, + GlobalGetOp constInit) const { + auto globalReplacement = rewriter.replaceOpWithNewOp( + 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 = + func::FuncOp::create(rewriter, 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 = memref::GetGlobalOp::create( + rewriter, loc, MemRefType::get({1}, constInit.getType()), + constInit.getGlobal()); + auto destGlobalPtr = + memref::GetGlobalOp::create(rewriter, loc, globalReplacement.getType(), + globalReplacement.getSymName()); + auto idx = arith::ConstantIndexOp::create(rewriter, loc, 0).getResult(); + auto loadSrc = + memref::LoadOp::create(rewriter, loc, srcGlobalPtr, ValueRange{idx}); + memref::StoreOp::create(rewriter, loc, loadSrc.getResult(), + destGlobalPtr.getResult(), ValueRange{idx}); + func::ReturnOp::create(rewriter, 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 { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(LocalOp localOp, LocalOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto alloca = rewriter.replaceOpWithNewOp( + localOp, + MemRefType::get({}, localOp.getResult().getType().getElementType())); + auto initializer = arith::ConstantOp::create( + rewriter, localOp->getLoc(), + getInitializerAttr(localOp.getResult().getType().getElementType())); + memref::StoreOp::create(rewriter, localOp->getLoc(), + initializer.getResult(), alloca.getResult()); + return success(); + } +}; + +struct WasmLocalGetConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(LocalGetOp localGetOp, LocalGetOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp( + localGetOp, localGetOp.getResult().getType(), adaptor.getLocalVar(), + ValueRange{}); + return success(); + } +}; + +struct WasmLocalSetConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(LocalSetOp localSetOp, LocalSetOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp( + localSetOp, adaptor.getValue(), adaptor.getLocalVar(), ValueRange{}); + return success(); + } +}; + +struct WasmLocalTeeConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(LocalTeeOp localTeeOp, LocalTeeOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + memref::StoreOp::create(rewriter, localTeeOp->getLoc(), adaptor.getValue(), + adaptor.getLocalVar()); + rewriter.replaceOp(localTeeOp, adaptor.getValue()); + return success(); + } +}; + +struct WasmReturnOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(ReturnOp returnOp, ReturnOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(returnOp, + adaptor.getOperands()); + return success(); + } +}; + +struct RaiseWasmMLIRPass : public impl::RaiseWasmMLIRBase { + void runOnOperation() override { + ConversionTarget target{getContext()}; + target.addIllegalDialect(); + target.addLegalDialect(); + RewritePatternSet patterns(&getContext()); + TypeConverter tc{}; + tc.addConversion([](Type type) -> std::optional { return type; }); + tc.addConversion([](LocalRefType type) -> std::optional { + 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 = memref::AllocaOp::create(builder, loc, destType); + memref::StoreOp::create(builder, loc, values.front(), + localVar.getResult()); + return localVar.getResult(); + }); + populateRaiseWasmMLIRConversionPatterns(tc, patterns); + + llvm::DenseMap 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< + 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, + 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 +} + +std::unique_ptr createRaiseWasmMLIRPass() { + return std::make_unique(); +} diff --git a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp index a514ea9218bd7..144fbb21de915 100644 --- a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp +++ b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp @@ -246,6 +246,16 @@ void FuncImportOp::build(OpBuilder &odsBuilder, OperationState &odsState, //===----------------------------------------------------------------------===// // GlobalOp //===----------------------------------------------------------------------===// +namespace { +Operation *getGlobalOpTerminatorOp(GlobalOp gop) { + return gop.getInitializer().begin()->getTerminator(); +} +} // namespace + +ReturnOp GlobalOp::getInitTerminator() { + return llvm::cast(getGlobalOpTerminatorOp(*this)); +} + // Custom formats ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) { StringAttr symbolName; @@ -292,6 +302,10 @@ void GlobalOp::print(OpAsmPrinter &printer) { } } +LogicalResult GlobalOp::verify() { + return success(llvm::isa(getGlobalOpTerminatorOp(*this))); +} + //===----------------------------------------------------------------------===// // GlobalGetOp //===----------------------------------------------------------------------===// 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.absf %[[VAL_1]] : f32 +// CHECK: return %[[VAL_2]] : f32 +wasmssa.func @abs_f32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.absf %[[VAL_1]] : f64 +// CHECK: return %[[VAL_2]] : f64 +wasmssa.func @abs_f64(%arg0: !wasmssa) -> 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, %arg1: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @and_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @and_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.ctlz %[[VAL_1]] : i32 +// CHECK: return %[[VAL_2]] : i32 +wasmssa.func exported @clz_i32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.ctlz %[[VAL_1]] : i64 +// CHECK: return %[[VAL_2]] : i64 +wasmssa.func exported @clz_i64(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = math.copysign %[[VAL_2]], %[[VAL_3]] : f32 +// CHECK: return %[[VAL_4]] : f32 +wasmssa.func exported @copysign_f32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = math.copysign %[[VAL_2]], %[[VAL_3]] : f64 +// CHECK: return %[[VAL_4]] : f64 +wasmssa.func exported @copysign_f64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.cttz %[[VAL_1]] : i32 +// CHECK: return %[[VAL_2]] : i32 +wasmssa.func exported @ctz_i32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.cttz %[[VAL_1]] : i64 +// CHECK: return %[[VAL_2]] : i64 +wasmssa.func exported @ctz_i64(%arg0: !wasmssa) -> 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, %arg1: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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-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) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +%v0 = wasmssa.local_get %arg0 : ref to i32 +// CHECK: return %[[VAL_1]] : i32 +wasmssa.return %v0 : i32 +} + +wasmssa.func exported @caller(%arg0: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +%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 +} 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 +// CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: memref.store %[[VAL_1]], %[[VAL_0]][] : memref + %0 = wasmssa.local of type f32 +// CHECK: %[[VAL_2:.*]] = memref.alloca() : memref +// CHECK: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: memref.store %[[VAL_3]], %[[VAL_2]][] : memref + %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 + wasmssa.local_set %0 : ref to f32 to %2 : f32 +// CHECK: %[[VAL_5:.*]] = memref.load %[[VAL_0]][] : memref + %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 + %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 +// CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 +// CHECK: memref.store %[[VAL_1]], %[[VAL_0]][] : memref + %0 = wasmssa.local of type i32 +// CHECK: %[[VAL_2:.*]] = memref.alloca() : memref +// CHECK: %[[VAL_3:.*]] = arith.constant 0 : i32 +// CHECK: memref.store %[[VAL_3]], %[[VAL_2]][] : memref + %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 + wasmssa.local_set %0 : ref to i32 to %2 : i32 +// CHECK: %[[VAL_5:.*]] = memref.load %[[VAL_0]][] : memref + %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 + %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) -> i32 { +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[VAL_0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = arith.constant 3 : i32 + %1 = wasmssa.const 3 : i32 +// CHECK: memref.store %[[VAL_2]], %[[VAL_1]][] : memref + wasmssa.local_set %arg0 : ref to i32 to %1 : i32 +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_1]][] : memref + %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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.maximumf %[[VAL_2]], %[[VAL_3]] : f32 +// CHECK: return %[[VAL_4]] : f32 +wasmssa.func exported @max_f32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.maximumf %[[VAL_2]], %[[VAL_3]] : f64 +// CHECK: return %[[VAL_4]] : f64 +wasmssa.func exported @max_f64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.minimumf %[[VAL_2]], %[[VAL_3]] : f32 +// CHECK: return %[[VAL_4]] : f32 +wasmssa.func exported @min_f32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.minimumf %[[VAL_2]], %[[VAL_3]] : f64 +// CHECK: return %[[VAL_4]] : f64 +wasmssa.func exported @min_f64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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, %arg1: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = arith.negf %[[VAL_1]] : f32 +// CHECK: return %[[VAL_2]] : f32 +wasmssa.func @neg_f32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = arith.negf %[[VAL_1]] : f64 +// CHECK: return %[[VAL_2]] : f64 +wasmssa.func @neg_f64(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @or_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @or_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.ctpop %[[VAL_1]] : i32 +// CHECK: return %[[VAL_2]] : i32 +wasmssa.func exported @popcnt_i32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.ctpop %[[VAL_1]] : i64 +// CHECK: return %[[VAL_2]] : i64 +wasmssa.func exported @popcnt_i64(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.remui %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @rem_ui_32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.remsi %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @rem_si_32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.remui %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @rem_ui_64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.remsi %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @rem_si_64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shli %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @shl_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shli %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @shl_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @shr_s_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shrsi %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @shr_s_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shrui %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func exported @shr_u_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.shrui %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func exported @shr_u_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.sqrt %[[VAL_1]] : f32 +// CHECK: return %[[VAL_2]] : f32 +wasmssa.func @sqrt_f32(%arg0: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_2:.*]] = math.sqrt %[[VAL_1]] : f64 +// CHECK: return %[[VAL_2]] : f64 +wasmssa.func @sqrt_f64(%arg0: !wasmssa) -> 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, %arg1: !wasmssa) -> i32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> i64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f32 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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, %arg1: !wasmssa) -> f64 { +// CHECK: %[[VAL_0:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +%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) -> 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 +// CHECK: memref.store %[[ARG0]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.load %[[VAL_0]][] : memref +// 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.xori %[[VAL_2]], %[[VAL_3]] : i32 +// CHECK: return %[[VAL_4]] : i32 +wasmssa.func @xor_i32(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +// CHECK: memref.store %[[ARG1]], %[[VAL_0]][] : memref +// CHECK: %[[VAL_1:.*]] = memref.alloca() : memref +// CHECK: memref.store %[[ARG0]], %[[VAL_1]][] : memref +// CHECK: %[[VAL_2:.*]] = memref.load %[[VAL_1]][] : memref +// CHECK: %[[VAL_3:.*]] = memref.load %[[VAL_0]][] : memref +// CHECK: %[[VAL_4:.*]] = arith.xori %[[VAL_2]], %[[VAL_3]] : i64 +// CHECK: return %[[VAL_4]] : i64 +wasmssa.func @xor_i64(%arg0: !wasmssa, %arg1: !wasmssa) -> 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 +}