summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-04-23 08:33:09 -0700
committerGitHub <noreply@github.com>2024-04-23 08:33:09 -0700
commitbceb02d545aeabb21797ef4148e0f713c57e0e0d (patch)
tree15ac53562eee0308bb9f8349ae2a4040552d69b8 /src/passes/OptimizeInstructions.cpp
parenta3c789008726ccf891b5f5581c87194578c32af4 (diff)
downloadbinaryen-bceb02d545aeabb21797ef4148e0f713c57e0e0d.tar.gz
binaryen-bceb02d545aeabb21797ef4148e0f713c57e0e0d.tar.bz2
binaryen-bceb02d545aeabb21797ef4148e0f713c57e0e0d.zip
OptimizeInstructions: Optimize subsequent struct.sets after struct.new_with_default (#6523)
Before we preferred not to add default values, as that increases code size. But since #6495 we turn more things into struct.new_with default, so it is important to handle this. It seems likely that in most cases the code size downside of adding default values is offset by avoiding a local.set later, so always do this (rather than add some kind of heuristic).
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 5613aca11..3486fe82a 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1931,12 +1931,6 @@ struct OptimizeInstructions
return false;
}
- if (new_->isWithDefault()) {
- // Ignore a new_default for now. If the fields are defaultable then we
- // could add them, in principle, but that might increase code size.
- return false;
- }
-
auto index = set->index;
auto& operands = new_->operands;
@@ -1953,20 +1947,35 @@ struct OptimizeInstructions
}
// We must move the set's value past indexes greater than it (Y and Z in
- // the example in the comment on this function).
+ // the example in the comment on this function). If this is not with_default
+ // then we must check for effects.
// TODO When this function is called repeatedly in a sequence this can
// become quadratic - perhaps we should memoize (though, struct sizes
// tend to not be ridiculously large).
- for (Index i = index + 1; i < operands.size(); i++) {
- auto operandEffects = effects(operands[i]);
- if (operandEffects.invalidates(setValueEffects)) {
- // TODO: we could use locals to reorder everything
- return false;
+ if (!new_->isWithDefault()) {
+ for (Index i = index + 1; i < operands.size(); i++) {
+ auto operandEffects = effects(operands[i]);
+ if (operandEffects.invalidates(setValueEffects)) {
+ // TODO: we could use locals to reorder everything
+ return false;
+ }
}
}
+ // We can optimize here!
Builder builder(*getModule());
+ // If this was with_default then we add default values now. That does
+ // increase code size in some cases (if there are many values, and few sets
+ // that get removed), but in general this optimization is worth it.
+ if (new_->isWithDefault()) {
+ auto& fields = new_->type.getHeapType().getStruct().fields;
+ for (auto& field : fields) {
+ auto zero = Literal::makeZero(field.type);
+ operands.push_back(builder.makeConstantExpression(zero));
+ }
+ }
+
// See if we need to keep the old value.
if (effects(operands[index]).hasUnremovableSideEffects()) {
operands[index] =