diff options
author | Alon Zakai <azakai@google.com> | 2024-04-23 08:33:09 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-23 08:33:09 -0700 |
commit | bceb02d545aeabb21797ef4148e0f713c57e0e0d (patch) | |
tree | 15ac53562eee0308bb9f8349ae2a4040552d69b8 /src/passes/OptimizeInstructions.cpp | |
parent | a3c789008726ccf891b5f5581c87194578c32af4 (diff) | |
download | binaryen-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.cpp | 33 |
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] = |