Optimize subcall into apply and down to just call when %this isn't used

This commit is contained in:
Andrew Morris
2023-07-26 09:16:50 +10:00
parent 296f24e6af
commit 68f122ec37
2 changed files with 92 additions and 11 deletions

View File

@@ -66,6 +66,7 @@ pub struct Object {
#[derive(Clone)]
pub struct KFunction {
pub pointer: Pointer,
pub uses_this: bool,
}
@@ -145,7 +146,7 @@ impl Kal {
}
}
pub fn from_function(fn_: &mut Function) -> Kal {
pub fn from_function(pointer: Pointer, fn_: &mut Function) -> Kal {
let mut uses_this = false;
for line in &mut fn_.body {
@@ -158,7 +159,7 @@ impl Kal {
}
}
Kal::Function(KFunction { uses_this })
Kal::Function(KFunction { pointer, uses_this })
}
fn try_to_value(&self) -> Option<Value> {
@@ -558,21 +559,98 @@ impl FnState {
self.set(dst.name.clone(), Kal::Unknown);
}
Apply(a, this, a3, dst) | SubCall(this, a, a3, dst) | ThisSubCall(this, a, a3, dst) => {
// TODO: Consider ordering here (only .take consideration (?))
self.eval_arg(a);
self.eval_arg(a3);
SubCall(this, key, args, dst) => {
let k_key = self.eval_arg(key);
self.eval_arg(args);
let k_this = self.get(this.name.clone());
let k_fn = k_this.sub(&k_key);
self.set(this.name.clone(), Kal::Unknown);
self.set(dst.name.clone(), Kal::Unknown);
if let Kal::Function(fn_) = k_fn {
if fn_.uses_this {
*instr = Instruction::Apply(
Value::Pointer(fn_.pointer),
this.clone(),
args.clone(),
dst.clone(),
);
} else {
*instr = Instruction::Call(Value::Pointer(fn_.pointer), args.clone(), dst.clone());
}
}
}
ConstSubCall(a1, a2, a3, dst) | ConstApply(a1, a2, a3, dst) => {
self.eval_arg(a1);
self.eval_arg(a2);
self.eval_arg(a3);
ConstSubCall(this, key, args, dst) => {
let k_this = self.eval_arg(this);
let k_key = self.eval_arg(key);
self.eval_arg(args);
let k_fn = k_this.sub(&k_key);
self.set(dst.name.clone(), Kal::Unknown);
if let Kal::Function(fn_) = k_fn {
if fn_.uses_this {
*instr = Instruction::ConstApply(
Value::Pointer(fn_.pointer),
this.clone(),
args.clone(),
dst.clone(),
);
} else {
*instr = Instruction::Call(Value::Pointer(fn_.pointer), args.clone(), dst.clone());
}
}
}
ThisSubCall(this, key, args, dst) => {
let k_key = self.eval_arg(key);
self.eval_arg(args);
let k_this = self.get(this.name.clone());
let k_fn = k_this.sub(&k_key);
self.set(this.name.clone(), Kal::Unknown);
self.set(dst.name.clone(), Kal::Unknown);
if let Kal::Function(fn_) = k_fn {
if !fn_.uses_this {
*instr = Instruction::Call(Value::Pointer(fn_.pointer), args.clone(), dst.clone());
}
}
}
Apply(fn_, this, args, dst) => {
let k_fn = self.eval_arg(fn_);
self.eval_arg(args);
self.set(this.name.clone(), Kal::Unknown);
self.set(dst.name.clone(), Kal::Unknown);
if let Kal::Function(fn_) = k_fn {
if !fn_.uses_this {
*instr = Instruction::Call(Value::Pointer(fn_.pointer), args.clone(), dst.clone());
}
}
}
ConstApply(fn_, this, args, dst) => {
let k_fn = self.eval_arg(fn_);
self.eval_arg(this);
self.eval_arg(args);
self.set(dst.name.clone(), Kal::Unknown);
if let Kal::Function(fn_) = k_fn {
if !fn_.uses_this {
*instr = Instruction::Call(Value::Pointer(fn_.pointer), args.clone(), dst.clone());
}
}
}
JmpIf(a1, _) | JmpIfNot(a1, _) => {

View File

@@ -10,7 +10,10 @@ pub fn simplify(module: &mut Module, take_registers: bool) {
for defn in &mut module.definitions {
match &mut defn.content {
DefinitionContent::Function(fn_) => {
pointer_kals.insert(defn.pointer.clone(), Kal::from_function(fn_));
pointer_kals.insert(
defn.pointer.clone(),
Kal::from_function(defn.pointer.clone(), fn_),
);
}
DefinitionContent::Value(value) => {
pointer_kals.insert(defn.pointer.clone(), Kal::from_value(value));