summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeAddedConstants.cpp33
-rw-r--r--test/lit/passes/optimize-added-constants-memory64.wast57
2 files changed, 81 insertions, 9 deletions
diff --git a/src/passes/OptimizeAddedConstants.cpp b/src/passes/OptimizeAddedConstants.cpp
index 8256169c1..f48989d5b 100644
--- a/src/passes/OptimizeAddedConstants.cpp
+++ b/src/passes/OptimizeAddedConstants.cpp
@@ -45,7 +45,9 @@ public:
T* curr,
Module* module,
LocalGraph* localGraph)
- : parent(parent), curr(curr), module(module), localGraph(localGraph) {}
+ : parent(parent), curr(curr), module(module), localGraph(localGraph) {
+ memory64 = module->getMemory(curr->memory)->is64();
+ }
// Tries to optimize, and returns whether we propagated a change.
bool optimize() {
@@ -56,7 +58,7 @@ public:
return false;
}
if (auto* add = curr->ptr->template dynCast<Binary>()) {
- if (add->op == AddInt32) {
+ if (add->op == AddInt32 || add->op == AddInt64) {
// Look for a constant on both sides.
if (tryToOptimizeConstant(add->right, add->left) ||
tryToOptimizeConstant(add->left, add->right)) {
@@ -110,6 +112,7 @@ private:
T* curr;
Module* module;
LocalGraph* localGraph;
+ bool memory64;
void optimizeConstantPointer() {
// The constant and an offset are interchangeable:
@@ -123,11 +126,23 @@ private:
// code may know that is valid, even if we can't. Only handle the
// obviously valid case where an overflow can't occur.
auto* c = curr->ptr->template cast<Const>();
- uint32_t base = c->value.geti32();
- uint32_t offset = curr->offset;
- if (uint64_t(base) + uint64_t(offset) < (uint64_t(1) << 32)) {
- c->value = c->value.add(Literal(uint32_t(curr->offset)));
- curr->offset = 0;
+ if (memory64) {
+ uint64_t base = c->value.geti64();
+ uint64_t offset = curr->offset;
+
+ uint64_t max = std::numeric_limits<uint64_t>::max();
+ bool overflow = (base > max - offset);
+ if (!overflow) {
+ c->value = c->value.add(Literal(offset));
+ curr->offset = 0;
+ }
+ } else {
+ uint32_t base = c->value.geti32();
+ uint32_t offset = curr->offset;
+ if (uint64_t(base) + uint64_t(offset) < (uint64_t(1) << 32)) {
+ c->value = c->value.add(Literal(uint32_t(curr->offset)));
+ curr->offset = 0;
+ }
}
}
}
@@ -222,9 +237,9 @@ private:
// Sees if we can optimize a particular constant.
Result canOptimizeConstant(Literal literal) {
- auto value = literal.geti32();
+ uint64_t value = literal.getInteger();
// Avoid uninteresting corner cases with peculiar offsets.
- if (value >= 0 && value < PassOptions::LowMemoryBound) {
+ if (value < PassOptions::LowMemoryBound) {
// The total offset must not allow reaching reasonable memory
// by overflowing.
auto total = curr->offset + value;
diff --git a/test/lit/passes/optimize-added-constants-memory64.wast b/test/lit/passes/optimize-added-constants-memory64.wast
new file mode 100644
index 000000000..e44bc414b
--- /dev/null
+++ b/test/lit/passes/optimize-added-constants-memory64.wast
@@ -0,0 +1,57 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+
+;; RUN: wasm-opt %s -all --roundtrip --optimize-added-constants --low-memory-unused -S -o - | filecheck %s
+
+(module
+ ;; CHECK: (memory $0 i64 1 4294967296)
+ (memory $0 i64 1 4294967296)
+
+
+ ;; CHECK: (func $load_i64 (result i64)
+ ;; CHECK-NEXT: (i64.load
+ ;; CHECK-NEXT: (i64.const 579)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load_i64 (result i64)
+ (i64.load offset=123
+ (i64.const 456)
+ )
+ )
+
+ ;; CHECK: (func $load_overflow_i64 (result i64)
+ ;; CHECK-NEXT: (i64.load offset=32
+ ;; CHECK-NEXT: (i64.const -16)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $load_overflow_i64 (result i64)
+ (i64.load offset=32
+ (i64.const 0xfffffffffffffff0)
+ )
+ )
+
+ ;; CHECK: (func $store
+ ;; CHECK-NEXT: (i64.store
+ ;; CHECK-NEXT: (i64.const 579)
+ ;; CHECK-NEXT: (i64.const 123)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $store (result)
+ (i64.store offset=123
+ (i64.const 456)
+ (i64.const 123)
+ )
+ )
+
+ ;; CHECK: (func $store_overflow
+ ;; CHECK-NEXT: (i64.store offset=32
+ ;; CHECK-NEXT: (i64.const -16)
+ ;; CHECK-NEXT: (i64.const 123)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $store_overflow (result)
+ (i64.store offset=32
+ (i64.const 0xfffffffffffffff0)
+ (i64.const 123)
+ )
+ )
+)