diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index ad111433d..b8f038dac 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -710,6 +710,11 @@ struct OptimizeInstructions store->value = unary->value; } } + } else if (auto* memCopy = curr->dynCast<MemoryCopy>()) { + assert(features.hasBulkMemory()); + if (auto* ret = optimizeMemoryCopy(memCopy)) { + return ret; + } } return nullptr; } @@ -1393,6 +1398,69 @@ private: return binary; } + Expression* optimizeMemoryCopy(MemoryCopy* memCopy) { + FeatureSet features = getModule()->features; + + // memory.copy(x, x, sz) ==> nop + if (!EffectAnalyzer(getPassOptions(), features, memCopy->dest) + .hasSideEffects() && + ExpressionAnalyzer::equal(memCopy->dest, memCopy->source)) { + return ExpressionManipulator::nop(memCopy); + } + // memory.copy(dst, src, C) ==> store(dst, load(src)) + if (auto* csize = memCopy->size->dynCast<Const>()) { + auto bytes = csize->value.geti32(); + Builder builder(*getModule()); + + switch (bytes) { + case 0: { + return builder.makeBlock({builder.makeDrop(memCopy->dest), + builder.makeDrop(memCopy->source)}); + break; + } + case 1: + case 2: + case 4: { + return builder.makeStore( + bytes, // bytes + 0, // offset + 1, // align + memCopy->dest, + builder.makeLoad(bytes, false, 0, 1, memCopy->source, Type::i32), + Type::i32); + } + case 8: { + return builder.makeStore( + bytes, // bytes + 0, // offset + 1, // align + memCopy->dest, + builder.makeLoad(bytes, false, 0, 1, memCopy->source, Type::i64), + Type::i64); + } + case 16: { + if (getPassOptions().shrinkLevel == 0) { + // This adds an extra 2 bytes so apply it only for + // minimal shrink level + if (features.hasSIMD()) { + return builder.makeStore( + bytes, // bytes + 0, // offset + 1, // align + memCopy->dest, + builder.makeLoad( + bytes, false, 0, 1, memCopy->source, Type::v128), + Type::v128); + } + } + } + default: { + } + } + } + return nullptr; + } + // given a binary expression with equal children and no side effects in // either, we can fold various things // TODO: trinaries, things like (x & (y & x)) ? |