Skip to content

Commit e06e0f2

Browse files
authored
ConstraintAnalysis: Handle fallthrough values (#9000)
1 parent 3444b97 commit e06e0f2

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

src/passes/ConstraintAnalysis.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,33 @@ struct ConstraintAnalysis
543543
}
544544
#endif
545545

546-
constraints.set(set->index, set->value);
546+
// Look at the fallthrough. It is valid to do so, because our constraints
547+
// only track two things, constants and locals. For a constant, it does
548+
// not change while falling through. For a local, the only way for the
549+
// local to change while falling through is to go through a tee of that
550+
// local - but that would keep the same value there anyhow. That is:
551+
//
552+
// (local.set $other
553+
// (block
554+
// ..
555+
// (local.tee $source
556+
// (block
557+
// ..
558+
// (local.get $source)
559+
// )
560+
// )
561+
// )
562+
// )
563+
//
564+
// The fallthrough here is the local.get of $source. We can set $other to
565+
// the value in $source, because while $source did have a write while
566+
// falling through, it did not alter the value, and there is no
567+
// opportunity to write any other value while falling through. (And, any
568+
// local.tee appearing here would have been reached earlier in the
569+
// traversal, and handled.)
570+
auto* value =
571+
Properties::getFallthrough(set->value, getPassOptions(), *getModule());
572+
constraints.set(set->index, value);
547573
}
548574
}
549575

test/lit/passes/constraint-analysis.wast

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4608,4 +4608,45 @@
46084608
)
46094609
)
46104610
)
4611+
4612+
;; CHECK: (func $fallthrough (type $1)
4613+
;; CHECK-NEXT: (local $x i32)
4614+
;; CHECK-NEXT: (local.set $x
4615+
;; CHECK-NEXT: (block (result i32)
4616+
;; CHECK-NEXT: (call $fallthrough)
4617+
;; CHECK-NEXT: (i32.const 10)
4618+
;; CHECK-NEXT: )
4619+
;; CHECK-NEXT: )
4620+
;; CHECK-NEXT: (drop
4621+
;; CHECK-NEXT: (i32.const 1)
4622+
;; CHECK-NEXT: )
4623+
;; CHECK-NEXT: )
4624+
;; OPTIN: (func $fallthrough (type $1)
4625+
;; OPTIN-NEXT: (local $x i32)
4626+
;; OPTIN-NEXT: (local.set $x
4627+
;; OPTIN-NEXT: (block (result i32)
4628+
;; OPTIN-NEXT: (call $fallthrough)
4629+
;; OPTIN-NEXT: (i32.const 10)
4630+
;; OPTIN-NEXT: )
4631+
;; OPTIN-NEXT: )
4632+
;; OPTIN-NEXT: (drop
4633+
;; OPTIN-NEXT: (i32.const 1)
4634+
;; OPTIN-NEXT: )
4635+
;; OPTIN-NEXT: )
4636+
(func $fallthrough
4637+
;; We can read values through a fallthrough.
4638+
(local $x i32)
4639+
(local.set $x
4640+
(block (result i32)
4641+
(call $fallthrough)
4642+
(i32.const 10)
4643+
)
4644+
)
4645+
(drop
4646+
(i32.eq
4647+
(local.get $x)
4648+
(i32.const 10)
4649+
)
4650+
)
4651+
)
46114652
)

0 commit comments

Comments
 (0)