summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bernstein <ruby@bernsteinbear.com>2026-05-11 09:47:50 -0400
committerMax Bernstein <tekknolagi@gmail.com>2026-05-12 13:03:27 -0400
commit33a4fde9cb2a6d7fcf9b89e0f24e0e9c88ccf24b (patch)
tree664da73502bc8518a828eafb6afed79e47648196
parentf1ca69b9de6243925a00073c54e18fb5db461a10 (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.rs18
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;
}