diff options
| author | Max Bernstein <ruby@bernsteinbear.com> | 2026-05-11 09:47:50 -0400 |
|---|---|---|
| committer | Max Bernstein <tekknolagi@gmail.com> | 2026-05-12 13:03:27 -0400 |
| commit | 33a4fde9cb2a6d7fcf9b89e0f24e0e9c88ccf24b (patch) | |
| tree | 664da73502bc8518a828eafb6afed79e47648196 | |
| parent | f1ca69b9de6243925a00073c54e18fb5db461a10 (diff) | |
ZJIT: Infer block param types with parallel phi semantics
In infer_types, snapshot the types of all branch arguments before
writing to any target block param. Previously, when a self-loop's
branch args referenced the target's own params (e.g. a phi swap),
updating params sequentially could observe values updated earlier
in the same loop iteration.
| -rw-r--r-- | zjit/src/hir.rs | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index b7eee653a6..8b671dd815 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -3027,9 +3027,13 @@ impl Function { assert!(!self.type_of(val).bit_equal(types::Empty)); if self.type_of(val).could_be(Type::from_cbool(true)) { reachable.insert(target); - for (idx, arg) in args.iter().enumerate() { + // Snapshot arg types before any param updates so phi-style + // updates happen in parallel (the args of a self-loop may name + // params of `target` itself). + let arg_types: Vec<Type> = args.iter().map(|a| self.type_of(*a)).collect(); + for (idx, arg_type) in arg_types.into_iter().enumerate() { let param = self.blocks[target.0].params[idx]; - self.insn_types[param.0] = self.type_of(param).union(self.type_of(*arg)); + self.insn_types[param.0] = self.type_of(param).union(arg_type); } } continue; @@ -3038,18 +3042,20 @@ impl Function { assert!(!self.type_of(val).bit_equal(types::Empty)); if self.type_of(val).could_be(Type::from_cbool(false)) { reachable.insert(target); - for (idx, arg) in args.iter().enumerate() { + let arg_types: Vec<Type> = args.iter().map(|a| self.type_of(*a)).collect(); + for (idx, arg_type) in arg_types.into_iter().enumerate() { let param = self.blocks[target.0].params[idx]; - self.insn_types[param.0] = self.type_of(param).union(self.type_of(*arg)); + self.insn_types[param.0] = self.type_of(param).union(arg_type); } } continue; } &Insn::Jump(BranchEdge { target, ref args }) => { reachable.insert(target); - for (idx, arg) in args.iter().enumerate() { + let arg_types: Vec<Type> = args.iter().map(|a| self.type_of(*a)).collect(); + for (idx, arg_type) in arg_types.into_iter().enumerate() { let param = self.blocks[target.0].params[idx]; - self.insn_types[param.0] = self.type_of(param).union(self.type_of(*arg)); + self.insn_types[param.0] = self.type_of(param).union(arg_type); } continue; } |
