Try fix for simplifylocals when a throw is present
diff --git a/src/ir/linear-execution.h b/src/ir/linear-execution.h
index 9e69405..430271f 100644
--- a/src/ir/linear-execution.h
+++ b/src/ir/linear-execution.h
@@ -76,6 +76,7 @@
   // cases (calls, if without an else) and it has very low overhead (we still
   // only do a simple postorder walk on the IR, no CFG is constructed, etc.).
   bool connectAdjacentBlocks = false;
+  bool connectAdjacentCalls = false;
 
   static void scan(SubType* self, Expression** currp) {
     Expression* curr = *currp;
@@ -89,7 +90,7 @@
         // Control is nonlinear if we return or throw. Traps don't need to be
         // taken into account since they don't break control flow in a way
         // that's observable.
-        if (mayThrow || isReturn) {
+        if (isReturn || (!self->connectAdjacentCalls && mayThrow)) {
           self->pushTask(SubType::doNoteNonLinear, currp);
         }
       }
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index 0879138..605799e 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -76,13 +76,17 @@
       SimplifyLocals<allowTee, allowStructure, allowNesting>>();
   }
 
+  bool connectAdjacentCalls = true;
+
   // information for a local.set we can sink
   struct SinkableInfo {
     Expression** item;
     EffectAnalyzer effects;
 
     SinkableInfo(Expression** item, PassOptions& passOptions, Module& module)
-      : item(item), effects(passOptions, module, *item) {}
+      : item(item),
+        effects(
+          passOptions, module, (*item)->template cast<LocalSet>()->value) {}
   };
 
   // a list of sinkables in a linear execution trace
diff --git a/test/lit/ctor-eval/multivalue-local.wast b/test/lit/ctor-eval/multivalue-local.wast
index 306e26a..aa9e80e 100644
--- a/test/lit/ctor-eval/multivalue-local.wast
+++ b/test/lit/ctor-eval/multivalue-local.wast
@@ -44,13 +44,6 @@
 ;; CHECK:      (export "multivalue-local" (func $multivalue-local_2))
 
 ;; CHECK:      (func $multivalue-local_2 (type $1) (result i32)
-;; CHECK-NEXT:  (local $0 i32)
-;; CHECK-NEXT:  (local.set $0
-;; CHECK-NEXT:   (i32.const 42)
-;; CHECK-NEXT:  )
 ;; CHECK-NEXT:  (call $import)
-;; CHECK-NEXT:  (i32.add
-;; CHECK-NEXT:   (local.get $0)
-;; CHECK-NEXT:   (local.get $0)
-;; CHECK-NEXT:  )
+;; CHECK-NEXT:  (i32.const 84)
 ;; CHECK-NEXT: )
diff --git a/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast b/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast
index f719700..0ab4ed4 100644
--- a/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast
+++ b/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast
@@ -3133,9 +3133,7 @@
   ;; CHECK-NEXT:   (local.set $y
   ;; CHECK-NEXT:    (i32.const 2)
   ;; CHECK-NEXT:   )
-  ;; CHECK-NEXT:   (local.set $z
-  ;; CHECK-NEXT:    (i32.const 3)
-  ;; CHECK-NEXT:   )
+  ;; CHECK-NEXT:   (nop)
   ;; CHECK-NEXT:   (loop $loopy
   ;; CHECK-NEXT:    (local.set $x
   ;; CHECK-NEXT:     (i32.const 4)
@@ -3151,18 +3149,18 @@
   ;; CHECK-NEXT:    (br_if $loopy
   ;; CHECK-NEXT:     (local.get $t)
   ;; CHECK-NEXT:    )
-  ;; CHECK-NEXT:    (local.set $z
-  ;; CHECK-NEXT:     (i32.const 6)
-  ;; CHECK-NEXT:    )
+  ;; CHECK-NEXT:    (nop)
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (nop)
   ;; CHECK-NEXT:   (nop)
-  ;; CHECK-NEXT:   (nop)
+  ;; CHECK-NEXT:   (local.set $8
+  ;; CHECK-NEXT:    (i32.const 6)
+  ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (local.set $9
   ;; CHECK-NEXT:    (select
   ;; CHECK-NEXT:     (local.get $x)
   ;; CHECK-NEXT:     (local.get $y)
-  ;; CHECK-NEXT:     (local.get $z)
+  ;; CHECK-NEXT:     (local.get $8)
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (return
@@ -3534,13 +3532,13 @@
   ;; CHECK-NEXT:      (nop)
   ;; CHECK-NEXT:     )
   ;; CHECK-NEXT:     (nop)
-  ;; CHECK-NEXT:     (local.set $10
-  ;; CHECK-NEXT:      (f64.const 0)
-  ;; CHECK-NEXT:     )
+  ;; CHECK-NEXT:     (nop)
   ;; CHECK-NEXT:    )
-  ;; CHECK-NEXT:    (nop)
+  ;; CHECK-NEXT:    (local.set $11
+  ;; CHECK-NEXT:     (f64.const 0)
+  ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:    (drop
-  ;; CHECK-NEXT:     (local.get $10)
+  ;; CHECK-NEXT:     (local.get $11)
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
diff --git a/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast b/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast
index d57df65..08a4bf6 100644
--- a/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast
+++ b/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast
@@ -3200,9 +3200,7 @@
   ;; CHECK-NEXT:   (local.set $y
   ;; CHECK-NEXT:    (i32.const 2)
   ;; CHECK-NEXT:   )
-  ;; CHECK-NEXT:   (local.set $z
-  ;; CHECK-NEXT:    (i32.const 3)
-  ;; CHECK-NEXT:   )
+  ;; CHECK-NEXT:   (nop)
   ;; CHECK-NEXT:   (loop $loopy
   ;; CHECK-NEXT:    (local.set $x
   ;; CHECK-NEXT:     (i32.const 4)
@@ -3218,18 +3216,18 @@
   ;; CHECK-NEXT:    (br_if $loopy
   ;; CHECK-NEXT:     (local.get $t)
   ;; CHECK-NEXT:    )
-  ;; CHECK-NEXT:    (local.set $z
-  ;; CHECK-NEXT:     (i32.const 6)
-  ;; CHECK-NEXT:    )
+  ;; CHECK-NEXT:    (nop)
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (nop)
   ;; CHECK-NEXT:   (nop)
-  ;; CHECK-NEXT:   (nop)
+  ;; CHECK-NEXT:   (local.set $8
+  ;; CHECK-NEXT:    (i32.const 6)
+  ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (local.set $9
   ;; CHECK-NEXT:    (select
   ;; CHECK-NEXT:     (local.get $x)
   ;; CHECK-NEXT:     (local.get $y)
-  ;; CHECK-NEXT:     (local.get $z)
+  ;; CHECK-NEXT:     (local.get $8)
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:   (return
@@ -3601,13 +3599,13 @@
   ;; CHECK-NEXT:      (nop)
   ;; CHECK-NEXT:     )
   ;; CHECK-NEXT:     (nop)
-  ;; CHECK-NEXT:     (local.set $10
-  ;; CHECK-NEXT:      (f64.const 0)
-  ;; CHECK-NEXT:     )
+  ;; CHECK-NEXT:     (nop)
   ;; CHECK-NEXT:    )
-  ;; CHECK-NEXT:    (nop)
+  ;; CHECK-NEXT:    (local.set $11
+  ;; CHECK-NEXT:     (f64.const 0)
+  ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:    (drop
-  ;; CHECK-NEXT:     (local.get $10)
+  ;; CHECK-NEXT:     (local.get $11)
   ;; CHECK-NEXT:    )
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
diff --git a/test/lit/passes/simplify-locals-eh.wast b/test/lit/passes/simplify-locals-eh.wast
index b65b5ba..adc34e8 100644
--- a/test/lit/passes/simplify-locals-eh.wast
+++ b/test/lit/passes/simplify-locals-eh.wast
@@ -138,9 +138,7 @@
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (local.get $0)
   ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT:  (drop
-  ;; CHECK-NEXT:   (local.get $0)
-  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT: )
   (func $equivalent-set-removal-call (param $0 i32)
     (local $1 i32)
diff --git a/test/lit/passes/simplify-locals-global-effects-eh.wast b/test/lit/passes/simplify-locals-global-effects-eh.wast
index 2fed91f..0e7badf 100644
--- a/test/lit/passes/simplify-locals-global-effects-eh.wast
+++ b/test/lit/passes/simplify-locals-global-effects-eh.wast
@@ -38,17 +38,16 @@
 
   ;; CHECK:      (func $read-g-with-throw-in-between (type $1) (result i32)
   ;; CHECK-NEXT:  (local $x i32)
-  ;; CHECK-NEXT:  (local.set $x
-  ;; CHECK-NEXT:   (global.get $g)
-  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (call $throws)
-  ;; CHECK-NEXT:  (local.get $x)
+  ;; CHECK-NEXT:  (global.get $g)
   ;; CHECK-NEXT: )
   (func $read-g-with-throw-in-between (result i32)
     (local $x i32)
     (local.set $x (global.get $g))
 
-    ;; A potential throw halts our optimizations.
+    ;; Sinking across a throw is valid here because reading the global has no
+    ;; side effects.
     (call $throws)
 
     (local.get $x)
@@ -132,22 +131,19 @@
 
   ;; CHECK:      (func $read-g-with-effectful-call-ref (type $3) (param $ref (ref $throw-type)) (result i32)
   ;; CHECK-NEXT:  (local $x i32)
-  ;; CHECK-NEXT:  (local.set $x
-  ;; CHECK-NEXT:   (global.get $g)
-  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (call_ref $throw-type
   ;; CHECK-NEXT:    (local.get $ref)
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT:  (local.get $x)
+  ;; CHECK-NEXT:  (global.get $g)
   ;; CHECK-NEXT: )
   (func $read-g-with-effectful-call-ref (param $ref (ref $throw-type)) (result i32)
     (local $x i32)
     (local.set $x (global.get $g))
 
-    ;; Similar to above, except here we can tell that the indirect call may
-    ;; throw so optimization is halted.
+    ;; Sinking across a potentially throwing call is valid here.
     (drop (call_ref $throw-type (local.get $ref)))
 
     (local.get $x)
@@ -155,22 +151,19 @@
 
   ;; CHECK:      (func $read-g-with-effectful-call-indirect (type $3) (param $ref (ref $throw-type)) (result i32)
   ;; CHECK-NEXT:  (local $x i32)
-  ;; CHECK-NEXT:  (local.set $x
-  ;; CHECK-NEXT:   (global.get $g)
-  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (drop
   ;; CHECK-NEXT:   (call_indirect $t (type $throw-type)
   ;; CHECK-NEXT:    (i32.const 0)
   ;; CHECK-NEXT:   )
   ;; CHECK-NEXT:  )
-  ;; CHECK-NEXT:  (local.get $x)
+  ;; CHECK-NEXT:  (global.get $g)
   ;; CHECK-NEXT: )
   (func $read-g-with-effectful-call-indirect (param $ref (ref $throw-type)) (result i32)
     (local $x i32)
     (local.set $x (global.get $g))
 
-    ;; Similar to above, except here we can tell that the indirect call may
-    ;; throw so optimization is halted.
+    ;; Sinking across a potentially throwing call is valid here.
     (drop (call_indirect (type $throw-type) (i32.const 0)))
 
     (local.get $x)