From 69591ded5acab404cba96af7ebc1afd54034c545 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Sat, 16 Nov 2024 00:40:01 -0800 Subject: Rename memory-copy-fill-lowering pass (#7082) Since the resulting code has the same undefined behavior as LLVM, make the pass name reflect that. --- src/passes/CMakeLists.txt | 2 +- src/passes/LLVMMemoryCopyFillLowering.cpp | 260 +++++++++++++++++++++++++ src/passes/MemoryCopyFillLowering.cpp | 260 ------------------------- src/passes/pass.cpp | 4 +- src/passes/passes.h | 2 +- test/lit/exec/memory-copy.wat | 2 +- test/lit/exec/memory-fill.wat | 2 +- test/lit/help/wasm-metadce.test | 8 +- test/lit/help/wasm-opt.test | 8 +- test/lit/help/wasm2js.test | 8 +- test/lit/passes/memory-copy-fill-lowering.wast | 2 +- 11 files changed, 279 insertions(+), 279 deletions(-) create mode 100644 src/passes/LLVMMemoryCopyFillLowering.cpp delete mode 100644 src/passes/MemoryCopyFillLowering.cpp diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 6053c5522..c6e079079 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -58,12 +58,12 @@ set(passes_SOURCES JSPI.cpp LegalizeJSInterface.cpp LimitSegments.cpp + LLVMMemoryCopyFillLowering.cpp LocalCSE.cpp LocalSubtyping.cpp LogExecution.cpp LoopInvariantCodeMotion.cpp Memory64Lowering.cpp - MemoryCopyFillLowering.cpp MemoryPacking.cpp MergeBlocks.cpp MergeSimilarFunctions.cpp diff --git a/src/passes/LLVMMemoryCopyFillLowering.cpp b/src/passes/LLVMMemoryCopyFillLowering.cpp new file mode 100644 index 000000000..e5b940a5a --- /dev/null +++ b/src/passes/LLVMMemoryCopyFillLowering.cpp @@ -0,0 +1,260 @@ +/* + * Copyright 2024 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ir/names.h" +#include "pass.h" +#include "wasm-builder.h" +#include "wasm.h" + +// Replace memory.copy and memory.fill with a call to a function that +// implements the same semantics. This is intended to be used with LLVM output, +// so anything considered undefined behavior in LLVM is ignored. (In +// particular, pointer overflow is UB and not handled here). + +namespace wasm { +struct LLVMMemoryCopyFillLowering + : public WalkerPass> { + bool needsMemoryCopy = false; + bool needsMemoryFill = false; + Name memCopyFuncName; + Name memFillFuncName; + + void visitMemoryCopy(MemoryCopy* curr) { + assert(curr->destMemory == + curr->sourceMemory); // multi-memory not supported. + Builder builder(*getModule()); + replaceCurrent(builder.makeCall( + "__memory_copy", {curr->dest, curr->source, curr->size}, Type::none)); + needsMemoryCopy = true; + } + + void visitMemoryFill(MemoryFill* curr) { + Builder builder(*getModule()); + replaceCurrent(builder.makeCall( + "__memory_fill", {curr->dest, curr->value, curr->size}, Type::none)); + needsMemoryFill = true; + } + + void run(Module* module) override { + if (!module->features.hasBulkMemory()) { + return; + } + if (module->features.hasMemory64() || module->features.hasMultiMemory()) { + Fatal() + << "Memory64 and multi-memory not supported by memory.copy lowering"; + } + + // Check for the presence of any passive data or table segments. + for (auto& segment : module->dataSegments) { + if (segment->isPassive) { + Fatal() << "memory.copy lowering should only be run on modules with " + "no passive segments"; + } + } + for (auto& segment : module->elementSegments) { + if (!segment->table.is()) { + Fatal() << "memory.copy lowering should only be run on modules with" + " no passive segments"; + } + } + + // In order to introduce a call to a function, it must first exist, so + // create an empty stub. + Builder b(*module); + + memCopyFuncName = Names::getValidFunctionName(*module, "__memory_copy"); + memFillFuncName = Names::getValidFunctionName(*module, "__memory_fill"); + auto memCopyFunc = b.makeFunction( + memCopyFuncName, + {{"dst", Type::i32}, {"src", Type::i32}, {"size", Type::i32}}, + Signature({Type::i32, Type::i32, Type::i32}, {Type::none}), + {{"start", Type::i32}, + {"end", Type::i32}, + {"step", Type::i32}, + {"i", Type::i32}}); + memCopyFunc->body = b.makeBlock(); + module->addFunction(memCopyFunc.release()); + auto memFillFunc = b.makeFunction( + memFillFuncName, + {{"dst", Type::i32}, {"val", Type::i32}, {"size", Type::i32}}, + Signature({Type::i32, Type::i32, Type::i32}, {Type::none}), + {}); + memFillFunc->body = b.makeBlock(); + module->addFunction(memFillFunc.release()); + + Super::run(module); + + if (needsMemoryCopy) { + createMemoryCopyFunc(module); + } else { + module->removeFunction(memCopyFuncName); + } + + if (needsMemoryFill) { + createMemoryFillFunc(module); + } else { + module->removeFunction(memFillFuncName); + } + module->features.disable(FeatureSet::BulkMemory); + } + + void createMemoryCopyFunc(Module* module) { + Builder b(*module); + Index dst = 0, src = 1, size = 2, start = 3, end = 4, step = 5, i = 6; + Name memory = module->memories.front()->name; + Block* body = b.makeBlock(); + // end = memory size in bytes + body->list.push_back( + b.makeLocalSet(end, + b.makeBinary(BinaryOp::MulInt32, + b.makeMemorySize(memory), + b.makeConst(Memory::kPageSize)))); + // if dst + size > memsize or src + size > memsize, then trap. + body->list.push_back(b.makeIf( + b.makeBinary(BinaryOp::OrInt32, + b.makeBinary(BinaryOp::GtUInt32, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(dst, Type::i32), + b.makeLocalGet(size, Type::i32)), + b.makeLocalGet(end, Type::i32)), + b.makeBinary(BinaryOp::GtUInt32, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(src, Type::i32), + b.makeLocalGet(size, Type::i32)), + b.makeLocalGet(end, Type::i32))), + b.makeUnreachable())); + // start and end are the starting and past-the-end indexes + // if src < dest: start = size - 1, end = -1, step = -1 + // else: start = 0, end = size, step = 1 + body->list.push_back( + b.makeIf(b.makeBinary(BinaryOp::LtUInt32, + b.makeLocalGet(src, Type::i32), + b.makeLocalGet(dst, Type::i32)), + b.makeBlock({ + b.makeLocalSet(start, + b.makeBinary(BinaryOp::SubInt32, + b.makeLocalGet(size, Type::i32), + b.makeConst(1))), + b.makeLocalSet(end, b.makeConst(-1U)), + b.makeLocalSet(step, b.makeConst(-1U)), + }), + b.makeBlock({ + b.makeLocalSet(start, b.makeConst(0)), + b.makeLocalSet(end, b.makeLocalGet(size, Type::i32)), + b.makeLocalSet(step, b.makeConst(1)), + }))); + // i = start + body->list.push_back(b.makeLocalSet(i, b.makeLocalGet(start, Type::i32))); + body->list.push_back(b.makeBlock( + "out", + b.makeLoop( + "copy", + b.makeBlock( + {// break if i == end + b.makeBreak("out", + nullptr, + b.makeBinary(BinaryOp::EqInt32, + b.makeLocalGet(i, Type::i32), + b.makeLocalGet(end, Type::i32))), + // dst[i] = src[i] + b.makeStore(1, + 0, + 1, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(dst, Type::i32), + b.makeLocalGet(i, Type::i32)), + b.makeLoad(1, + false, + 0, + 1, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(src, Type::i32), + b.makeLocalGet(i, Type::i32)), + Type::i32, + memory), + Type::i32, + memory), + // i += step + b.makeLocalSet(i, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(i, Type::i32), + b.makeLocalGet(step, Type::i32))), + // loop + b.makeBreak("copy", nullptr)})))); + module->getFunction(memCopyFuncName)->body = body; + } + + void createMemoryFillFunc(Module* module) { + Builder b(*module); + Index dst = 0, val = 1, size = 2; + Name memory = module->memories.front()->name; + Block* body = b.makeBlock(); + + // if dst + size > memsize in bytes, then trap. + body->list.push_back( + b.makeIf(b.makeBinary(BinaryOp::GtUInt32, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(dst, Type::i32), + b.makeLocalGet(size, Type::i32)), + b.makeBinary(BinaryOp::MulInt32, + b.makeMemorySize(memory), + b.makeConst(Memory::kPageSize))), + b.makeUnreachable())); + + body->list.push_back(b.makeBlock( + "out", + b.makeLoop( + "copy", + b.makeBlock( + {// break if size == 0 + b.makeBreak( + "out", + nullptr, + b.makeUnary(UnaryOp::EqZInt32, b.makeLocalGet(size, Type::i32))), + // size-- + b.makeLocalSet(size, + b.makeBinary(BinaryOp::SubInt32, + b.makeLocalGet(size, Type::i32), + b.makeConst(1))), + // *(dst+size) = val + b.makeStore(1, + 0, + 1, + b.makeBinary(BinaryOp::AddInt32, + b.makeLocalGet(dst, Type::i32), + b.makeLocalGet(size, Type::i32)), + b.makeLocalGet(val, Type::i32), + Type::i32, + memory), + b.makeBreak("copy", nullptr)})))); + module->getFunction(memFillFuncName)->body = body; + } + + void VisitTableCopy(TableCopy* curr) { + Fatal() << "table.copy instruction found. Memory copy lowering is not " + "designed to work on modules with bulk table operations"; + } + void VisitTableFill(TableCopy* curr) { + Fatal() << "table.fill instruction found. Memory copy lowering is not " + "designed to work on modules with bulk table operations"; + } +}; + +Pass* createLLVMMemoryCopyFillLoweringPass() { + return new LLVMMemoryCopyFillLowering(); +} + +} // namespace wasm diff --git a/src/passes/MemoryCopyFillLowering.cpp b/src/passes/MemoryCopyFillLowering.cpp deleted file mode 100644 index 5855e5450..000000000 --- a/src/passes/MemoryCopyFillLowering.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2024 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/names.h" -#include "pass.h" -#include "wasm-builder.h" -#include "wasm.h" - -// Replace memory.copy and memory.fill with a call to a function that -// implements the same semantics. This is intended to be used with LLVM output, -// so anything considered undefined behavior in LLVM is ignored. (In -// particular, pointer overflow is UB and not handled here). - -namespace wasm { -struct MemoryCopyFillLowering - : public WalkerPass> { - bool needsMemoryCopy = false; - bool needsMemoryFill = false; - Name memCopyFuncName; - Name memFillFuncName; - - void visitMemoryCopy(MemoryCopy* curr) { - assert(curr->destMemory == - curr->sourceMemory); // multi-memory not supported. - Builder builder(*getModule()); - replaceCurrent(builder.makeCall( - "__memory_copy", {curr->dest, curr->source, curr->size}, Type::none)); - needsMemoryCopy = true; - } - - void visitMemoryFill(MemoryFill* curr) { - Builder builder(*getModule()); - replaceCurrent(builder.makeCall( - "__memory_fill", {curr->dest, curr->value, curr->size}, Type::none)); - needsMemoryFill = true; - } - - void run(Module* module) override { - if (!module->features.hasBulkMemory()) { - return; - } - if (module->features.hasMemory64() || module->features.hasMultiMemory()) { - Fatal() - << "Memory64 and multi-memory not supported by memory.copy lowering"; - } - - // Check for the presence of any passive data or table segments. - for (auto& segment : module->dataSegments) { - if (segment->isPassive) { - Fatal() << "memory.copy lowering should only be run on modules with " - "no passive segments"; - } - } - for (auto& segment : module->elementSegments) { - if (!segment->table.is()) { - Fatal() << "memory.copy lowering should only be run on modules with" - " no passive segments"; - } - } - - // In order to introduce a call to a function, it must first exist, so - // create an empty stub. - Builder b(*module); - - memCopyFuncName = Names::getValidFunctionName(*module, "__memory_copy"); - memFillFuncName = Names::getValidFunctionName(*module, "__memory_fill"); - auto memCopyFunc = b.makeFunction( - memCopyFuncName, - {{"dst", Type::i32}, {"src", Type::i32}, {"size", Type::i32}}, - Signature({Type::i32, Type::i32, Type::i32}, {Type::none}), - {{"start", Type::i32}, - {"end", Type::i32}, - {"step", Type::i32}, - {"i", Type::i32}}); - memCopyFunc->body = b.makeBlock(); - module->addFunction(memCopyFunc.release()); - auto memFillFunc = b.makeFunction( - memFillFuncName, - {{"dst", Type::i32}, {"val", Type::i32}, {"size", Type::i32}}, - Signature({Type::i32, Type::i32, Type::i32}, {Type::none}), - {}); - memFillFunc->body = b.makeBlock(); - module->addFunction(memFillFunc.release()); - - Super::run(module); - - if (needsMemoryCopy) { - createMemoryCopyFunc(module); - } else { - module->removeFunction(memCopyFuncName); - } - - if (needsMemoryFill) { - createMemoryFillFunc(module); - } else { - module->removeFunction(memFillFuncName); - } - module->features.disable(FeatureSet::BulkMemory); - } - - void createMemoryCopyFunc(Module* module) { - Builder b(*module); - Index dst = 0, src = 1, size = 2, start = 3, end = 4, step = 5, i = 6; - Name memory = module->memories.front()->name; - Block* body = b.makeBlock(); - // end = memory size in bytes - body->list.push_back( - b.makeLocalSet(end, - b.makeBinary(BinaryOp::MulInt32, - b.makeMemorySize(memory), - b.makeConst(Memory::kPageSize)))); - // if dst + size > memsize or src + size > memsize, then trap. - body->list.push_back(b.makeIf( - b.makeBinary(BinaryOp::OrInt32, - b.makeBinary(BinaryOp::GtUInt32, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(dst, Type::i32), - b.makeLocalGet(size, Type::i32)), - b.makeLocalGet(end, Type::i32)), - b.makeBinary(BinaryOp::GtUInt32, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(src, Type::i32), - b.makeLocalGet(size, Type::i32)), - b.makeLocalGet(end, Type::i32))), - b.makeUnreachable())); - // start and end are the starting and past-the-end indexes - // if src < dest: start = size - 1, end = -1, step = -1 - // else: start = 0, end = size, step = 1 - body->list.push_back( - b.makeIf(b.makeBinary(BinaryOp::LtUInt32, - b.makeLocalGet(src, Type::i32), - b.makeLocalGet(dst, Type::i32)), - b.makeBlock({ - b.makeLocalSet(start, - b.makeBinary(BinaryOp::SubInt32, - b.makeLocalGet(size, Type::i32), - b.makeConst(1))), - b.makeLocalSet(end, b.makeConst(-1U)), - b.makeLocalSet(step, b.makeConst(-1U)), - }), - b.makeBlock({ - b.makeLocalSet(start, b.makeConst(0)), - b.makeLocalSet(end, b.makeLocalGet(size, Type::i32)), - b.makeLocalSet(step, b.makeConst(1)), - }))); - // i = start - body->list.push_back(b.makeLocalSet(i, b.makeLocalGet(start, Type::i32))); - body->list.push_back(b.makeBlock( - "out", - b.makeLoop( - "copy", - b.makeBlock( - {// break if i == end - b.makeBreak("out", - nullptr, - b.makeBinary(BinaryOp::EqInt32, - b.makeLocalGet(i, Type::i32), - b.makeLocalGet(end, Type::i32))), - // dst[i] = src[i] - b.makeStore(1, - 0, - 1, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(dst, Type::i32), - b.makeLocalGet(i, Type::i32)), - b.makeLoad(1, - false, - 0, - 1, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(src, Type::i32), - b.makeLocalGet(i, Type::i32)), - Type::i32, - memory), - Type::i32, - memory), - // i += step - b.makeLocalSet(i, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(i, Type::i32), - b.makeLocalGet(step, Type::i32))), - // loop - b.makeBreak("copy", nullptr)})))); - module->getFunction(memCopyFuncName)->body = body; - } - - void createMemoryFillFunc(Module* module) { - Builder b(*module); - Index dst = 0, val = 1, size = 2; - Name memory = module->memories.front()->name; - Block* body = b.makeBlock(); - - // if dst + size > memsize in bytes, then trap. - body->list.push_back( - b.makeIf(b.makeBinary(BinaryOp::GtUInt32, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(dst, Type::i32), - b.makeLocalGet(size, Type::i32)), - b.makeBinary(BinaryOp::MulInt32, - b.makeMemorySize(memory), - b.makeConst(Memory::kPageSize))), - b.makeUnreachable())); - - body->list.push_back(b.makeBlock( - "out", - b.makeLoop( - "copy", - b.makeBlock( - {// break if size == 0 - b.makeBreak( - "out", - nullptr, - b.makeUnary(UnaryOp::EqZInt32, b.makeLocalGet(size, Type::i32))), - // size-- - b.makeLocalSet(size, - b.makeBinary(BinaryOp::SubInt32, - b.makeLocalGet(size, Type::i32), - b.makeConst(1))), - // *(dst+size) = val - b.makeStore(1, - 0, - 1, - b.makeBinary(BinaryOp::AddInt32, - b.makeLocalGet(dst, Type::i32), - b.makeLocalGet(size, Type::i32)), - b.makeLocalGet(val, Type::i32), - Type::i32, - memory), - b.makeBreak("copy", nullptr)})))); - module->getFunction(memFillFuncName)->body = body; - } - - void VisitTableCopy(TableCopy* curr) { - Fatal() << "table.copy instruction found. Memory copy lowering is not " - "designed to work on modules with bulk table operations"; - } - void VisitTableFill(TableCopy* curr) { - Fatal() << "table.fill instruction found. Memory copy lowering is not " - "designed to work on modules with bulk table operations"; - } -}; - -Pass* createMemoryCopyFillLoweringPass() { - return new MemoryCopyFillLowering(); -} - -} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index fcefb89ad..5cbf4a31f 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -272,10 +272,10 @@ void PassRegistry::registerPasses() { registerPass("table64-lowering", "lower 64-bit tables 32-bit ones", createTable64LoweringPass); - registerPass("memory-copy-fill-lowering", + registerPass("llvm-memory-copy-fill-lowering", "Lower memory.copy and memory.fill to wasm mvp and disable " "the bulk-memory feature.", - createMemoryCopyFillLoweringPass); + createLLVMMemoryCopyFillLoweringPass); registerPass("memory-packing", "packs memory into separate segments, skipping zeros", createMemoryPackingPass); diff --git a/src/passes/passes.h b/src/passes/passes.h index 121dbcd9d..212a2b0e4 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -80,6 +80,7 @@ Pass* createIntrinsicLoweringPass(); Pass* createTraceCallsPass(); Pass* createInstrumentLocalsPass(); Pass* createInstrumentMemoryPass(); +Pass* createLLVMMemoryCopyFillLoweringPass(); Pass* createLoopInvariantCodeMotionPass(); Pass* createMemory64LoweringPass(); Pass* createMemoryPackingPass(); @@ -116,7 +117,6 @@ Pass* createOptimizeForJSPass(); Pass* createOutliningPass(); #endif Pass* createPickLoadSignsPass(); -Pass* createMemoryCopyFillLoweringPass(); Pass* createModAsyncifyAlwaysOnlyUnwindPass(); Pass* createModAsyncifyNeverUnwindPass(); Pass* createPoppifyPass(); diff --git a/test/lit/exec/memory-copy.wat b/test/lit/exec/memory-copy.wat index 793f94656..3583b048e 100644 --- a/test/lit/exec/memory-copy.wat +++ b/test/lit/exec/memory-copy.wat @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. -;; RUN: wasm-opt %s --enable-bulk-memory --memory-copy-fill-lowering --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s +;; RUN: wasm-opt %s --enable-bulk-memory --llvm-memory-copy-fill-lowering --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s ;; Tests derived from bulk-memory.wast spec tests diff --git a/test/lit/exec/memory-fill.wat b/test/lit/exec/memory-fill.wat index dc9aead6d..c63dcef0c 100644 --- a/test/lit/exec/memory-fill.wat +++ b/test/lit/exec/memory-fill.wat @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. -;; RUN: wasm-opt %s --enable-bulk-memory --memory-copy-fill-lowering --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s +;; RUN: wasm-opt %s --enable-bulk-memory --llvm-memory-copy-fill-lowering --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s ;; Tests derived from bulk-memory.wast spec tests diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 908b381e8..50f71f8f5 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -230,6 +230,10 @@ ;; CHECK-NEXT: --limit-segments attempt to merge segments to fit ;; CHECK-NEXT: within web limits ;; CHECK-NEXT: +;; CHECK-NEXT: --llvm-memory-copy-fill-lowering Lower memory.copy and +;; CHECK-NEXT: memory.fill to wasm mvp and +;; CHECK-NEXT: disable the bulk-memory feature. +;; CHECK-NEXT: ;; CHECK-NEXT: --local-cse common subexpression elimination ;; CHECK-NEXT: inside basic blocks ;; CHECK-NEXT: @@ -239,10 +243,6 @@ ;; CHECK-NEXT: --log-execution instrument the build with ;; CHECK-NEXT: logging of where execution goes ;; CHECK-NEXT: -;; CHECK-NEXT: --memory-copy-fill-lowering Lower memory.copy and -;; CHECK-NEXT: memory.fill to wasm mvp and -;; CHECK-NEXT: disable the bulk-memory feature. -;; CHECK-NEXT: ;; CHECK-NEXT: --memory-packing packs memory into separate ;; CHECK-NEXT: segments, skipping zeros ;; CHECK-NEXT: diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 7d173b084..b30f62150 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -239,6 +239,10 @@ ;; CHECK-NEXT: --limit-segments attempt to merge segments to fit ;; CHECK-NEXT: within web limits ;; CHECK-NEXT: +;; CHECK-NEXT: --llvm-memory-copy-fill-lowering Lower memory.copy and +;; CHECK-NEXT: memory.fill to wasm mvp and +;; CHECK-NEXT: disable the bulk-memory feature. +;; CHECK-NEXT: ;; CHECK-NEXT: --local-cse common subexpression elimination ;; CHECK-NEXT: inside basic blocks ;; CHECK-NEXT: @@ -248,10 +252,6 @@ ;; CHECK-NEXT: --log-execution instrument the build with ;; CHECK-NEXT: logging of where execution goes ;; CHECK-NEXT: -;; CHECK-NEXT: --memory-copy-fill-lowering Lower memory.copy and -;; CHECK-NEXT: memory.fill to wasm mvp and -;; CHECK-NEXT: disable the bulk-memory feature. -;; CHECK-NEXT: ;; CHECK-NEXT: --memory-packing packs memory into separate ;; CHECK-NEXT: segments, skipping zeros ;; CHECK-NEXT: diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 514f638d9..69923a064 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -193,6 +193,10 @@ ;; CHECK-NEXT: --limit-segments attempt to merge segments to fit ;; CHECK-NEXT: within web limits ;; CHECK-NEXT: +;; CHECK-NEXT: --llvm-memory-copy-fill-lowering Lower memory.copy and +;; CHECK-NEXT: memory.fill to wasm mvp and +;; CHECK-NEXT: disable the bulk-memory feature. +;; CHECK-NEXT: ;; CHECK-NEXT: --local-cse common subexpression elimination ;; CHECK-NEXT: inside basic blocks ;; CHECK-NEXT: @@ -202,10 +206,6 @@ ;; CHECK-NEXT: --log-execution instrument the build with ;; CHECK-NEXT: logging of where execution goes ;; CHECK-NEXT: -;; CHECK-NEXT: --memory-copy-fill-lowering Lower memory.copy and -;; CHECK-NEXT: memory.fill to wasm mvp and -;; CHECK-NEXT: disable the bulk-memory feature. -;; CHECK-NEXT: ;; CHECK-NEXT: --memory-packing packs memory into separate ;; CHECK-NEXT: segments, skipping zeros ;; CHECK-NEXT: diff --git a/test/lit/passes/memory-copy-fill-lowering.wast b/test/lit/passes/memory-copy-fill-lowering.wast index 540237ff7..551f5a4e6 100644 --- a/test/lit/passes/memory-copy-fill-lowering.wast +++ b/test/lit/passes/memory-copy-fill-lowering.wast @@ -1,6 +1,6 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: wasm-opt --enable-bulk-memory %s --memory-copy-fill-lowering -S -o - | filecheck %s +;; RUN: wasm-opt --enable-bulk-memory %s --llvm-memory-copy-fill-lowering -S -o - | filecheck %s (module (memory 0) -- cgit v1.2.3