From 33a4fde9cb2a6d7fcf9b89e0f24e0e9c88ccf24b Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Mon, 11 May 2026 09:47:50 -0400 Subject: 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. --- zjit/src/hir.rs | 18 ++++++++++++------ 1 file 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 = 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 = 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 = 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; } -- cgit v1.2.3