diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 127 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-bulk-memory.wast | 230 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-ignore-traps.wast | 196 |
3 files changed, 469 insertions, 84 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 768ea5702..217312501 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1158,6 +1158,16 @@ struct OptimizeInstructions } } + void visitMemoryFill(MemoryFill* curr) { + if (curr->type == Type::unreachable) { + return; + } + assert(getModule()->features.hasBulkMemory()); + if (auto* ret = optimizeMemoryFill(curr)) { + return replaceCurrent(ret); + } + } + void visitCallRef(CallRef* curr) { if (curr->target->type == Type::unreachable) { // The call_ref is not reached; leave this for DCE. @@ -2863,7 +2873,7 @@ private: // memory.copy(dst, src, C) ==> store(dst, load(src)) if (auto* csize = memCopy->size->dynCast<Const>()) { - auto bytes = csize->value.geti32(); + auto bytes = csize->value.getInteger(); Builder builder(*getModule()); switch (bytes) { @@ -2919,6 +2929,121 @@ private: return nullptr; } + Expression* optimizeMemoryFill(MemoryFill* memFill) { + if (!memFill->size->is<Const>()) { + return nullptr; + } + + PassOptions options = getPassOptions(); + Builder builder(*getModule()); + + auto* csize = memFill->size->cast<Const>(); + auto bytes = csize->value.getInteger(); + + if (bytes == 0LL && + (options.ignoreImplicitTraps || options.trapsNeverHappen)) { + // memory.fill(d, v, 0) ==> { drop(d), drop(v) } + return builder.makeBlock( + {builder.makeDrop(memFill->dest), builder.makeDrop(memFill->value)}); + } + + const uint32_t offset = 0, align = 1; + + if (auto* cvalue = memFill->value->dynCast<Const>()) { + uint32_t value = cvalue->value.geti32() & 0xFF; + // memory.fill(d, C1, C2) ==> + // store(d, (C1 & 0xFF) * (-1U / max(bytes))) + switch (bytes) { + case 1: { + return builder.makeStore(1, // bytes + offset, + align, + memFill->dest, + builder.makeConst<uint32_t>(value), + Type::i32); + } + case 2: { + return builder.makeStore(2, + offset, + align, + memFill->dest, + builder.makeConst<uint32_t>(value * 0x0101U), + Type::i32); + } + case 4: { + // transform only when "value" or shrinkLevel equal to zero due to + // it could increase size by several bytes + if (value == 0 || options.shrinkLevel == 0) { + return builder.makeStore( + 4, + offset, + align, + memFill->dest, + builder.makeConst<uint32_t>(value * 0x01010101U), + Type::i32); + } + break; + } + case 8: { + // transform only when "value" or shrinkLevel equal to zero due to + // it could increase size by several bytes + if (value == 0 || options.shrinkLevel == 0) { + return builder.makeStore( + 8, + offset, + align, + memFill->dest, + builder.makeConst<uint64_t>(value * 0x0101010101010101ULL), + Type::i64); + } + break; + } + case 16: { + if (options.shrinkLevel == 0) { + if (getModule()->features.hasSIMD()) { + uint8_t values[16]; + std::fill_n(values, 16, (uint8_t)value); + return builder.makeStore(16, + offset, + align, + memFill->dest, + builder.makeConst<uint8_t[16]>(values), + Type::v128); + } else { + // { i64.store(d, C', 0), i64.store(d, C', 8) } + return builder.makeBlock({ + builder.makeStore( + 8, + offset, + align, + memFill->dest, + builder.makeConst<uint64_t>(value * 0x0101010101010101ULL), + Type::i64), + builder.makeStore( + 8, + offset + 8, + align, + memFill->dest, + builder.makeConst<uint64_t>(value * 0x0101010101010101ULL), + Type::i64), + }); + } + } + break; + } + default: { + } + } + } + // memory.fill(d, v, 1) ==> store8(d, v) + if (bytes == 1LL) { + return builder.makeStore( + 1, offset, align, memFill->dest, memFill->value, Type::i32); + } + + return nullptr; + } + // given a binary expression with equal children and no side effects in // either, we can fold various things Expression* optimizeBinaryWithEqualEffectlessChildren(Binary* binary) { diff --git a/test/lit/passes/optimize-instructions-bulk-memory.wast b/test/lit/passes/optimize-instructions-bulk-memory.wast index 37d17dba8..5c9efc893 100644 --- a/test/lit/passes/optimize-instructions-bulk-memory.wast +++ b/test/lit/passes/optimize-instructions-bulk-memory.wast @@ -1,5 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-bulk-memory -S -o - | filecheck %s +;; RUN: wasm-opt %s --all-features --optimize-instructions --enable-bulk-memory -S -o - | filecheck %s (module (memory 0) @@ -58,10 +58,11 @@ ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy + ;; CHECK-NEXT: (v128.store align=1 ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 16) + ;; CHECK-NEXT: (v128.load align=1 + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (memory.copy ;; CHECK-NEXT: (local.get $dst) @@ -157,4 +158,225 @@ ) ) ) + + ;; CHECK: (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store8 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store8 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store8 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store8 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store16 align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store16 align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 257) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store16 align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 65535) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (v128.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 16843009) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i64.const 72340172838076673) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (v128.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (v128.store align=1 + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (v128.const i32x4 0xffffffff 0xffffffff 0xffffffff 0xffffffff) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $sz) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: (local.get $sz) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 17) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 0) + ) + + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 1) + ) + + (memory.fill + (local.get $dst) + (local.get $val) + (i32.const 1) + ) + + (memory.fill + (local.get $dst) + (i32.const 1) + (i32.const 1) + ) + + (memory.fill + (local.get $dst) + (i32.const 1023) + (i32.const 1) + ) + + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 2) + ) + + (memory.fill + (local.get $dst) + (i32.const 1) + (i32.const 2) + ) + + (memory.fill + (local.get $dst) + (i32.const 255) + (i32.const 2) + ) + + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 4) + ) + + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 8) + ) + + (memory.fill + (local.get $dst) + (i32.const 0) + (i32.const 16) + ) + + (memory.fill + (local.get $dst) + (i32.const 1) + (i32.const 4) + ) + + (memory.fill + (local.get $dst) + (i32.const 1) + (i32.const 8) + ) + + (memory.fill + (local.get $dst) + (i32.const 1) + (i32.const 16) + ) + + (memory.fill + (local.get $dst) + (i32.const 1023) + (i32.const 16) + ) + + (memory.fill ;; skip + (local.get $dst) + (local.get $val) + (i32.const 0) + ) + + (memory.fill ;; skip + (local.get $dst) + (i32.const 0) + (local.get $sz) + ) + + (memory.fill ;; skip + (local.get $dst) + (local.get $val) + (local.get $sz) + ) + + (memory.fill ;; skip + (local.get $dst) + (i32.const 0) + (i32.const 3) + ) + + (memory.fill ;; skip + (local.get $dst) + (i32.const 1) + (i32.const 3) + ) + + (memory.fill ;; skip + (local.get $dst) + (i32.const 0) + (i32.const 17) + ) + ) ) diff --git a/test/lit/passes/optimize-instructions-ignore-traps.wast b/test/lit/passes/optimize-instructions-ignore-traps.wast index 71baba86f..f76410a03 100644 --- a/test/lit/passes/optimize-instructions-ignore-traps.wast +++ b/test/lit/passes/optimize-instructions-ignore-traps.wast @@ -1,5 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --all-features --optimize-level=2 --ignore-implicit-traps -S -o - \ +;; RUN: wasm-opt %s --all-features --optimize-instructions --optimize-level=2 --ignore-implicit-traps -S -o - \ ;; RUN: | filecheck %s (module @@ -30,50 +30,47 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (i32.rem_s + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.mul + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (local.tee $7 + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: (i32.const 17) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 5) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 11) + ;; CHECK-NEXT: (i32.rem_u + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.mul + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (i32.const 11) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: (local.tee $3 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -207,13 +204,10 @@ ;; CHECK-NEXT: (i32.rem_s ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.mul + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 17) ;; CHECK-NEXT: ) @@ -238,14 +232,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: (local.tee $3 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -374,50 +368,44 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (i32.rem_u + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.mul + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: (i32.const 100) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.rem_s + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.mul + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 100) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (i32.const 17) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 5) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: (local.tee $3 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -527,13 +515,13 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 24) ;; CHECK-NEXT: ) @@ -594,14 +582,17 @@ ;; CHECK: (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 24) ;; CHECK-NEXT: ) @@ -611,12 +602,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (return @@ -735,15 +721,24 @@ (f64.const -nan:0xfffffffffffff) ) ;; CHECK: (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $sz) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $sz) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $src) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) @@ -759,4 +754,47 @@ (i32.const 0) ) ) + + ;; CHECK: (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $dst) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $val) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (memory.fill + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $sz) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) + (memory.fill ;; drops + (local.get $dst) + (i32.const 0) + (i32.const 0) + ) + + (memory.fill ;; drops + (local.get $dst) + (local.get $val) + (i32.const 0) + ) + + (memory.fill ;; skip + (i32.const 0) + (i32.const 0) + (local.get $sz) + ) + ) ) |