summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}