SimplifyLocals: Check effects of set value rather than LocalSet in SinkableInfo

LinearExecutionWalker: Add connectAdjacentCalls and enable in SimplifyLocals
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..b60ed10 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -76,13 +76,16 @@
       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)->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 5a25d02..a5b32fb 100644
--- a/test/lit/passes/simplify-locals-eh.wast
+++ b/test/lit/passes/simplify-locals-eh.wast
@@ -2,15 +2,15 @@
 ;; RUN: wasm-opt %s --simplify-locals -all -S -o - | filecheck %s
 
 (module
-  ;; CHECK:      (tag $e-i32 (type $2) (param i32))
+  ;; CHECK:      (tag $e-i32 (type $1) (param i32))
   (tag $e-i32 (param i32))
 
-  ;; CHECK:      (func $bar (type $0) (result i32)
+  ;; CHECK:      (func $bar (type $2) (result i32)
   ;; CHECK-NEXT:  (i32.const 3)
   ;; CHECK-NEXT: )
   (func $bar (result i32) (i32.const 3))
 
-  ;; CHECK:      (func $call-cannot-be-sinked-into-try_table (type $1)
+  ;; CHECK:      (func $call-cannot-be-sinked-into-try_table (type $0)
   ;; CHECK-NEXT:  (local $0 i32)
   ;; CHECK-NEXT:  (local.set $0
   ;; CHECK-NEXT:   (call $bar)
@@ -46,7 +46,7 @@
     )
   )
 
-  ;; CHECK:      (func $non-call-can-be-sinked-into-try_table (type $1)
+  ;; CHECK:      (func $non-call-can-be-sinked-into-try_table (type $0)
   ;; CHECK-NEXT:  (local $0 i32)
   ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (block $tryend
@@ -80,7 +80,7 @@
     )
   )
 
-  ;; CHECK:      (func $return-call-can-be-sinked-into-try_table (type $0) (result i32)
+  ;; CHECK:      (func $return-call-can-be-sinked-into-try_table (type $2) (result i32)
   ;; CHECK-NEXT:  (local $0 i32)
   ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (block $tryend (result i32)
@@ -125,7 +125,7 @@
     )
   )
 
-  ;; CHECK:      (func $equivalent-set-removal-call (type $2) (param $0 i32)
+  ;; CHECK:      (func $equivalent-set-removal-call (type $1) (param $0 i32)
   ;; CHECK-NEXT:  (local $1 i32)
   ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (drop
@@ -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)
@@ -224,17 +222,15 @@
     (drop (local.get $1))
   )
 
-  ;; CHECK:      (func $nop (type $1)
+  ;; CHECK:      (func $nop (type $0)
   ;; CHECK-NEXT: )
   (func $nop)
 
   ;; CHECK:      (func $sink-across-control-flow (type $4) (param $bool i32) (result i32)
   ;; CHECK-NEXT:  (local $l i32)
-  ;; CHECK-NEXT:  (local.set $l
-  ;; CHECK-NEXT:   (i32.const 2)
-  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
   ;; CHECK-NEXT:  (call $nop)
-  ;; CHECK-NEXT:  (local.get $l)
+  ;; CHECK-NEXT:  (i32.const 2)
   ;; CHECK-NEXT: )
   (func $sink-across-control-flow (param $bool i32) (result i32)
     (local $l 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)