From 520f2f36311e85d86e3b9607361eab87c70b63cf Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 13 Mar 2026 15:26:01 -0700 Subject: [PATCH 1/2] Fix effects for AtomicFence When we updated EffectsAnalzyer to handle atomic effects more precisely, we forgot to update AtomicFence. It previously was considered to access shared memories, but in fact it should be considered to access all possible shared locations. This properly prevents it from being reordered with accesses to shared structs and arrays as well. --- src/ir/effects.h | 4 ++ .../simplify-locals-atomic-effects.wast | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/ir/effects.h b/src/ir/effects.h index 2ff70910d46..a3525fd6d6c 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -846,6 +846,10 @@ class EffectAnalyzer { // so we set these to true. parent.readsSharedMemory = true; parent.writesSharedMemory = true; + parent.readsSharedMutableStruct = true; + parent.writesSharedStruct = true; + parent.readsSharedMutableArray = true; + parent.writesSharedArray = true; parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst; } void visitPause(Pause* curr) { diff --git a/test/lit/passes/simplify-locals-atomic-effects.wast b/test/lit/passes/simplify-locals-atomic-effects.wast index d7dd36e3434..2c3644e5a3c 100644 --- a/test/lit/passes/simplify-locals-atomic-effects.wast +++ b/test/lit/passes/simplify-locals-atomic-effects.wast @@ -795,4 +795,45 @@ ) (local.get $x) ) + + ;; CHECK: (func $fence-struct-mutable (type $3) (param $shared (ref null $shared-struct)) (result i32) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (struct.get $shared-struct 0 + ;; CHECK-NEXT: (local.get $shared) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (atomic.fence) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $fence-struct-mutable (param $shared (ref null $shared-struct)) (result i32) + (local $x i32) + ;; A shared struct read cannot be moved past an atomic.fence. + (local.set $x + (struct.get $shared-struct 0 (local.get $shared)) + ) + (atomic.fence) + (local.get $x) + ) + + ;; CHECK: (func $fence-array-mutable (type $2) (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (array.get $shared-array + ;; CHECK-NEXT: (local.get $shared-array) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (atomic.fence) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $fence-array-mutable (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) + (local $x i32) + ;; A shared array read cannot be moved past an atomic.fence. + (local.set $x + (array.get $shared-array (local.get $shared-array) (i32.const 0)) + ) + (atomic.fence) + (local.get $x) + ) ) From 67667d94eb9363d9e41f24521e9bb04e330c3e65 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 16 Mar 2026 10:27:34 -0700 Subject: [PATCH 2/2] add write tests, update names --- .../simplify-locals-atomic-effects.wast | 70 +++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/test/lit/passes/simplify-locals-atomic-effects.wast b/test/lit/passes/simplify-locals-atomic-effects.wast index 2c3644e5a3c..b10d57009c0 100644 --- a/test/lit/passes/simplify-locals-atomic-effects.wast +++ b/test/lit/passes/simplify-locals-atomic-effects.wast @@ -796,7 +796,7 @@ (local.get $x) ) - ;; CHECK: (func $fence-struct-mutable (type $3) (param $shared (ref null $shared-struct)) (result i32) + ;; CHECK: (func $read-struct-fence (type $3) (param $shared (ref null $shared-struct)) (result i32) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (struct.get $shared-struct 0 @@ -806,7 +806,7 @@ ;; CHECK-NEXT: (atomic.fence) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - (func $fence-struct-mutable (param $shared (ref null $shared-struct)) (result i32) + (func $read-struct-fence (param $shared (ref null $shared-struct)) (result i32) (local $x i32) ;; A shared struct read cannot be moved past an atomic.fence. (local.set $x @@ -816,7 +816,7 @@ (local.get $x) ) - ;; CHECK: (func $fence-array-mutable (type $2) (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) + ;; CHECK: (func $read-array-fence (type $2) (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (array.get $shared-array @@ -827,7 +827,7 @@ ;; CHECK-NEXT: (atomic.fence) ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - (func $fence-array-mutable (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) + (func $read-array-fence (param $shared (ref null $shared-struct)) (param $shared-array (ref null $shared-array)) (result i32) (local $x i32) ;; A shared array read cannot be moved past an atomic.fence. (local.set $x @@ -836,4 +836,66 @@ (atomic.fence) (local.get $x) ) + + ;; CHECK: (func $write-struct-fence (type $3) (param $shared (ref null $shared-struct)) (result i32) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (struct.set $shared-struct 0 + ;; CHECK-NEXT: (local.get $shared) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (atomic.fence) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $write-struct-fence (param $shared (ref null $shared-struct)) (result i32) + (local $x i32) + ;; A shared struct read cannot be moved past an atomic.fence. + (local.set $x + (block (result i32) + (struct.set $shared-struct 0 + (local.get $shared) + (i32.const 0) + ) + (i32.const 1) + ) + ) + (atomic.fence) + (local.get $x) + ) + + ;; CHECK: (func $write-array-fence (type $6) (param $shared (ref null $shared-array)) (result i32) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (array.set $shared-array + ;; CHECK-NEXT: (local.get $shared) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (atomic.fence) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $write-array-fence (param $shared (ref null $shared-array)) (result i32) + (local $x i32) + ;; A shared struct read cannot be moved past an atomic.fence. + (local.set $x + (block (result i32) + (array.set $shared-array + (local.get $shared) + (i32.const 0) + (i32.const 0) + ) + (i32.const 1) + ) + ) + (atomic.fence) + (local.get $x) + ) )