summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 1970cf08f..37207ffc7 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -326,7 +326,10 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
if (br->condition) {
br->condition = optimizeBoolean(br->condition);
}
+ } else if (auto* load = curr->dynCast<Load>()) {
+ optimizeMemoryAccess(load->ptr, load->offset);
} else if (auto* store = curr->dynCast<Store>()) {
+ optimizeMemoryAccess(store->ptr, store->offset);
// stores of fewer bits truncates anyhow
if (auto* binary = store->value->dynCast<Binary>()) {
if (binary->op == AndInt32) {
@@ -430,6 +433,43 @@ private:
return builder.makeIf(left, right, builder.makeConst(Literal(int32_t(0))));
}
}
+
+ // fold constant factors into the offset
+ void optimizeMemoryAccess(Expression*& ptr, Address& offset) {
+ while (1) {
+ auto* add = ptr->dynCast<Binary>();
+ if (!add) break;
+ if (add->op != AddInt32) break;
+ auto* left = add->left->dynCast<Const>();
+ auto* right = add->right->dynCast<Const>();
+ // note: in optimized code, we shouldn't see an add of two constants, so don't worry about that much
+ // (precompute would optimize that)
+ if (left) {
+ auto value = left->value.geti32();
+ if (value >= 0) {
+ offset = offset + value;
+ ptr = add->right;
+ continue;
+ }
+ }
+ if (right) {
+ auto value = right->value.geti32();
+ if (value >= 0) {
+ offset = offset + value;
+ ptr = add->left;
+ continue;
+ }
+ }
+ break;
+ }
+ // finally, ptr may be a const, but it isn't worth folding that in (we still have a const); in fact,
+ // it's better to do the opposite for gzip purposes as well as for readability.
+ auto* last = ptr->dynCast<Const>();
+ if (last) {
+ last->value = Literal(int32_t(last->value.geti32() + offset));
+ offset = 0;
+ }
+ }
};
Pass *createOptimizeInstructionsPass() {