ZJIT: Parse duphash into HIR
This commit is contained in:
parent
5a3f3f0917
commit
f1fe3d809f
Notes:
git
2025-05-22 21:05:26 +00:00
@ -331,6 +331,8 @@ pub enum Insn {
|
|||||||
ArrayDup { val: InsnId, state: InsnId },
|
ArrayDup { val: InsnId, state: InsnId },
|
||||||
ArrayMax { elements: Vec<InsnId>, state: InsnId },
|
ArrayMax { elements: Vec<InsnId>, state: InsnId },
|
||||||
|
|
||||||
|
HashDup { val: InsnId, state: InsnId },
|
||||||
|
|
||||||
/// Check if the value is truthy and "return" a C boolean. In reality, we will likely fuse this
|
/// Check if the value is truthy and "return" a C boolean. In reality, we will likely fuse this
|
||||||
/// with IfTrue/IfFalse in the backend to generate jcc.
|
/// with IfTrue/IfFalse in the backend to generate jcc.
|
||||||
Test { val: InsnId },
|
Test { val: InsnId },
|
||||||
@ -424,6 +426,7 @@ impl Insn {
|
|||||||
Insn::StringCopy { .. } => false,
|
Insn::StringCopy { .. } => false,
|
||||||
Insn::NewArray { .. } => false,
|
Insn::NewArray { .. } => false,
|
||||||
Insn::ArrayDup { .. } => false,
|
Insn::ArrayDup { .. } => false,
|
||||||
|
Insn::HashDup { .. } => false,
|
||||||
Insn::Test { .. } => false,
|
Insn::Test { .. } => false,
|
||||||
Insn::Snapshot { .. } => false,
|
Insn::Snapshot { .. } => false,
|
||||||
Insn::FixnumAdd { .. } => false,
|
Insn::FixnumAdd { .. } => false,
|
||||||
@ -475,6 +478,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
|
|||||||
}
|
}
|
||||||
Insn::ArraySet { array, idx, val } => { write!(f, "ArraySet {array}, {idx}, {val}") }
|
Insn::ArraySet { array, idx, val } => { write!(f, "ArraySet {array}, {idx}, {val}") }
|
||||||
Insn::ArrayDup { val, .. } => { write!(f, "ArrayDup {val}") }
|
Insn::ArrayDup { val, .. } => { write!(f, "ArrayDup {val}") }
|
||||||
|
Insn::HashDup { val, .. } => { write!(f, "HashDup {val}") }
|
||||||
Insn::StringCopy { val } => { write!(f, "StringCopy {val}") }
|
Insn::StringCopy { val } => { write!(f, "StringCopy {val}") }
|
||||||
Insn::Test { val } => { write!(f, "Test {val}") }
|
Insn::Test { val } => { write!(f, "Test {val}") }
|
||||||
Insn::Jump(target) => { write!(f, "Jump {target}") }
|
Insn::Jump(target) => { write!(f, "Jump {target}") }
|
||||||
@ -866,6 +870,7 @@ impl Function {
|
|||||||
},
|
},
|
||||||
ArraySet { array, idx, val } => ArraySet { array: find!(*array), idx: *idx, val: find!(*val) },
|
ArraySet { array, idx, val } => ArraySet { array: find!(*array), idx: *idx, val: find!(*val) },
|
||||||
ArrayDup { val , state } => ArrayDup { val: find!(*val), state: *state },
|
ArrayDup { val , state } => ArrayDup { val: find!(*val), state: *state },
|
||||||
|
&HashDup { val , state } => HashDup { val: find!(val), state },
|
||||||
&CCall { cfun, ref args, name, return_type, elidable } => CCall { cfun: cfun, args: args.iter().map(|arg| find!(*arg)).collect(), name: name, return_type: return_type, elidable },
|
&CCall { cfun, ref args, name, return_type, elidable } => CCall { cfun: cfun, args: args.iter().map(|arg| find!(*arg)).collect(), name: name, return_type: return_type, elidable },
|
||||||
Defined { .. } => todo!("find(Defined)"),
|
Defined { .. } => todo!("find(Defined)"),
|
||||||
NewArray { elements, state } => NewArray { elements: find_vec!(*elements), state: find!(*state) },
|
NewArray { elements, state } => NewArray { elements: find_vec!(*elements), state: find!(*state) },
|
||||||
@ -918,6 +923,7 @@ impl Function {
|
|||||||
Insn::StringIntern { .. } => types::StringExact,
|
Insn::StringIntern { .. } => types::StringExact,
|
||||||
Insn::NewArray { .. } => types::ArrayExact,
|
Insn::NewArray { .. } => types::ArrayExact,
|
||||||
Insn::ArrayDup { .. } => types::ArrayExact,
|
Insn::ArrayDup { .. } => types::ArrayExact,
|
||||||
|
Insn::HashDup { .. } => types::HashExact,
|
||||||
Insn::CCall { return_type, .. } => *return_type,
|
Insn::CCall { return_type, .. } => *return_type,
|
||||||
Insn::GuardType { val, guard_type, .. } => self.type_of(*val).intersection(*guard_type),
|
Insn::GuardType { val, guard_type, .. } => self.type_of(*val).intersection(*guard_type),
|
||||||
Insn::GuardBitEquals { val, expected, .. } => self.type_of(*val).intersection(Type::from_value(*expected)),
|
Insn::GuardBitEquals { val, expected, .. } => self.type_of(*val).intersection(Type::from_value(*expected)),
|
||||||
@ -1434,7 +1440,7 @@ impl Function {
|
|||||||
worklist.push_back(val);
|
worklist.push_back(val);
|
||||||
worklist.extend(args);
|
worklist.extend(args);
|
||||||
}
|
}
|
||||||
Insn::ArrayDup { val , state } => {
|
Insn::ArrayDup { val, state } | Insn::HashDup { val, state } => {
|
||||||
worklist.push_back(val);
|
worklist.push_back(val);
|
||||||
worklist.push_back(state);
|
worklist.push_back(state);
|
||||||
}
|
}
|
||||||
@ -1923,6 +1929,12 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
|||||||
let insn_id = fun.push_insn(block, Insn::ArrayDup { val, state: exit_id });
|
let insn_id = fun.push_insn(block, Insn::ArrayDup { val, state: exit_id });
|
||||||
state.stack_push(insn_id);
|
state.stack_push(insn_id);
|
||||||
}
|
}
|
||||||
|
YARVINSN_duphash => {
|
||||||
|
let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
|
||||||
|
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||||
|
let insn_id = fun.push_insn(block, Insn::HashDup { val, state: exit_id });
|
||||||
|
state.stack_push(insn_id);
|
||||||
|
}
|
||||||
YARVINSN_putobject_INT2FIX_0_ => {
|
YARVINSN_putobject_INT2FIX_0_ => {
|
||||||
state.stack_push(fun.push_insn(block, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(0)) }));
|
state.stack_push(fun.push_insn(block, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(0)) }));
|
||||||
}
|
}
|
||||||
@ -2493,6 +2505,18 @@ mod tests {
|
|||||||
"#]]);
|
"#]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hash_dup() {
|
||||||
|
eval("def test = {a: 1, b: 2}");
|
||||||
|
assert_method_hir("test", expect![[r#"
|
||||||
|
fn test:
|
||||||
|
bb0():
|
||||||
|
v1:HashExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
|
||||||
|
v3:HashExact = HashDup v1
|
||||||
|
Return v3
|
||||||
|
"#]]);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(max): Test newhash when we have it
|
// TODO(max): Test newhash when we have it
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -3601,6 +3625,22 @@ mod opt_tests {
|
|||||||
"#]]);
|
"#]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_eliminate_hash_dup() {
|
||||||
|
eval("
|
||||||
|
def test
|
||||||
|
c = {a: 1, b: 2}
|
||||||
|
5
|
||||||
|
end
|
||||||
|
");
|
||||||
|
assert_optimized_method_hir("test", expect![[r#"
|
||||||
|
fn test:
|
||||||
|
bb0():
|
||||||
|
v5:Fixnum[5] = Const Value(5)
|
||||||
|
Return v5
|
||||||
|
"#]]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_eliminate_putself() {
|
fn test_eliminate_putself() {
|
||||||
eval("
|
eval("
|
||||||
|
Loading…
x
Reference in New Issue
Block a user