diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index 59f1f359f89..057392cfd21 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -2976,6 +2976,17 @@ void Flower::filterExpressionContents(PossibleContents& contents, std::cout << "TNHOracle informs us that " << *exprLoc.expr << " contains " << maximalContents << "\n"; #endif + + if (exprLoc.expr->is()) { + // ArrayLoad cannot filter, as we can have writes of different sizes than + // the type of the location (e.g. write i32, do an i64.load). If there is + // any content, just report the maximal content, basically like a Memory. + if (!contents.isNone()) { + contents = maximalContents; + } + return; + } + contents.intersect(maximalContents); if (contents.isNone()) { // Nothing was left here at all. diff --git a/test/lit/passes/gufa-multibyte.wast b/test/lit/passes/gufa-multibyte.wast new file mode 100644 index 00000000000..2af6f08b797 --- /dev/null +++ b/test/lit/passes/gufa-multibyte.wast @@ -0,0 +1,61 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: foreach %s %t wasm-opt -all --gufa --closed-world -S -o - | filecheck %s + +(module + ;; CHECK: (type $0 (func)) + + ;; CHECK: (type $array (array (mut i8))) + (type $array (array (mut i8))) + + ;; CHECK: (export "test" (func $test)) + + ;; CHECK: (func $test (type $0) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i64.load32_u (type $array) + ;; CHECK-NEXT: (array.new_default $array + ;; CHECK-NEXT: (i32.const 69) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (export "test") + ;; We initialize with i8s, and read an i64. That should not confuse us, and + ;; we do not optimize here (though we could, in theory, if we tracked the + ;; bytes and saw the i64 must be 0). + (drop + (i64.load32_u (type $array) + (array.new_default $array + (i32.const 69) + ) + (i32.const 0) + ) + ) + ) +) + +(module + ;; CHECK: (type $array (array (mut i8))) + (type $array (array (mut i8))) + + ;; CHECK: (type $1 (func (param (ref $array)))) + + ;; CHECK: (export "test" (func $test)) + + ;; CHECK: (func $test (type $1) (param $array (ref $array)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (export "test") (param $array (ref $array)) + ;; As above, but now no $array is ever created (and we are in closed world). + ;; We can optimize this to trap. + (drop + (i64.load32_u (type $array) + (local.get $array) + (i32.const 0) + ) + ) + ) +) +