ConstraintAnalysis: Handle tees (#8998)
diff --git a/src/ir/constraint.cpp b/src/ir/constraint.cpp
index 0d30545..a151628 100644
--- a/src/ir/constraint.cpp
+++ b/src/ir/constraint.cpp
@@ -544,6 +544,10 @@
set(index, Constraint{Abstract::Eq, {get->index}});
return;
}
+ if (auto* tee = value->dynCast<LocalSet>()) {
+ set(index, Constraint{Abstract::Eq, {tee->index}});
+ return;
+ }
// Apply an increment of a local, x = y + 1.
Index y;
diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast
index 0f9a7f0..8325cd8 100644
--- a/test/lit/passes/constraint-analysis.wast
+++ b/test/lit/passes/constraint-analysis.wast
@@ -4555,4 +4555,57 @@
)
)
)
+
+ ;; CHECK: (func $tee (type $1)
+ ;; CHECK-NEXT: (local $x i32)
+ ;; CHECK-NEXT: (local $y i32)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (local.tee $y
+ ;; CHECK-NEXT: (i32.const 10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; OPTIN: (func $tee (type $1)
+ ;; OPTIN-NEXT: (local $x i32)
+ ;; OPTIN-NEXT: (local $y i32)
+ ;; OPTIN-NEXT: (local.set $x
+ ;; OPTIN-NEXT: (local.tee $y
+ ;; OPTIN-NEXT: (i32.const 10)
+ ;; OPTIN-NEXT: )
+ ;; OPTIN-NEXT: )
+ ;; OPTIN-NEXT: (drop
+ ;; OPTIN-NEXT: (i32.const 1)
+ ;; OPTIN-NEXT: )
+ ;; OPTIN-NEXT: (drop
+ ;; OPTIN-NEXT: (i32.const 1)
+ ;; OPTIN-NEXT: )
+ ;; OPTIN-NEXT: )
+ (func $tee
+ ;; We can read values through tees.
+ (local $x i32)
+ (local $y i32)
+ (local.set $x
+ (local.tee $y
+ (i32.const 10)
+ )
+ )
+ (drop
+ (i32.eq
+ (local.get $x)
+ (i32.const 10)
+ )
+ )
+ (drop
+ (i32.eq
+ (local.get $y)
+ (i32.const 10)
+ )
+ )
+ )
)