summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp68
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)) ?