diff options
-rw-r--r-- | src/passes/OptimizeAddedConstants.cpp | 33 | ||||
-rw-r--r-- | test/lit/passes/optimize-added-constants-memory64.wast | 57 |
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) + ) + ) +) |