Optimize call.

This commit is contained in:
losfair 2019-04-02 11:11:45 +08:00
parent 84e5a0c8eb
commit 4d6bbed905
2 changed files with 88 additions and 19 deletions

View File

@ -850,7 +850,10 @@ impl FunctionCodeGenerator for X64FunctionCode {
a.emit_mov(Size::S64, Self::get_param_location(0), self.vmctx_location.unwrap());
for i in 0..self.num_params {
a.emit_mov(Size::S64, Self::get_param_location(i + 1), self.locals[i]);
Self::emit_relaxed_binop(
a, &mut self.machine, Assembler::emit_mov,
Size::S64, Self::get_param_location(i + 1), self.locals[i],
);
}
for i in self.num_params..self.num_locals {
a.emit_mov(Size::S32, Location::Imm32(0), self.locals[i]);
@ -1161,7 +1164,12 @@ impl FunctionCodeGenerator for X64FunctionCode {
let return_types: Vec<WpType> =
sig.returns().iter().cloned().map(type_to_wp_type).collect();
let params = &self.value_stack[self.value_stack.len() - param_types.len()..];
let params: Vec<_> = self.value_stack.drain(self.value_stack.len() - param_types.len()..).collect();
let released: Vec<Location> = params.iter()
.filter(|&&(_, lot)| lot == LocalOrTemp::Temp)
.map(|&(x, _)| x)
.collect();
self.machine.release_locations_only_regs(&released);
let used_gprs = self.machine.get_used_gprs();
for r in used_gprs.iter() {
@ -1170,19 +1178,26 @@ impl FunctionCodeGenerator for X64FunctionCode {
let mut stack_offset: usize = 0;
for i in (0..param_types.len()).rev() {
a.emit_push(Size::S64, params[i].0);
stack_offset += 8;
}
let mut call_movs: Vec<(Location, GPR)> = vec![];
for i in 0..param_types.len() {
for i in (0..param_types.len()).rev() {
let loc = Self::get_param_location(1 + i);
match loc {
Location::GPR(_) => {
a.emit_pop(Size::S64, loc);
stack_offset -= 8;
},
_ => break
Location::GPR(x) => {
call_movs.push((params[i].0, x));
}
Location::Memory(_, _) => {
a.emit_push(Size::S64, params[i].0);
stack_offset += 8;
}
_ => unreachable!()
}
}
sort_call_movs(&mut call_movs);
for (loc, gpr) in call_movs {
if loc != Location::GPR(gpr) {
a.emit_mov(Size::S64, loc, Location::GPR(gpr));
}
}
@ -1197,11 +1212,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
a.emit_pop(Size::S64, Location::GPR(*r));
}
let released: Vec<Location> = self.value_stack.drain(self.value_stack.len() - param_types.len()..)
.filter(|&(_, lot)| lot == LocalOrTemp::Temp)
.map(|(x, _)| x)
.collect();
self.machine.release_locations(a, &released);
self.machine.release_locations_only_stack(a, &released);
let ret = self.machine.acquire_locations(a, &[WpType::I64], false)[0];
self.value_stack.push((ret, LocalOrTemp::Temp));
@ -1454,3 +1465,15 @@ fn get_location_released(a: &mut Assembler, m: &mut Machine, (loc, lot): (Locati
}
loc
}
fn sort_call_movs(movs: &mut [(Location, GPR)]) {
for i in 0..movs.len() {
for j in (i + 1)..movs.len() {
if let Location::GPR(src_gpr) = movs[j].0 {
if src_gpr == movs[i].1 {
movs.swap(i, j);
}
}
}
}
}

View File

@ -220,7 +220,7 @@ impl Machine {
) {
let mut delta_stack_offset: usize = 0;
for loc in locs {
for loc in locs.iter().rev() {
match *loc {
Location::GPR(ref x) => {
assert_eq!(self.used_gprs.remove(x), true);
@ -248,6 +248,52 @@ impl Machine {
}
}
pub fn release_locations_only_regs(
&mut self,
locs: &[Location]
) {
for loc in locs.iter().rev() {
match *loc {
Location::GPR(ref x) => {
assert_eq!(self.used_gprs.remove(x), true);
},
Location::XMM(ref x) => {
assert_eq!(self.used_xmms.remove(x), true);
},
_ => {}
}
}
}
pub fn release_locations_only_stack<E: Emitter>(
&mut self,
assembler: &mut E,
locs: &[Location]
) {
let mut delta_stack_offset: usize = 0;
for loc in locs.iter().rev() {
match *loc {
Location::Memory(GPR::RBP, x) => {
if x >= 0 {
unreachable!();
}
let offset = (-x) as usize;
if offset != self.stack_offset.0 {
unreachable!();
}
self.stack_offset.0 -= 8;
delta_stack_offset += 8;
},
_ => {}
}
}
if delta_stack_offset != 0 {
assembler.emit_add(Size::S64, Location::Imm32(delta_stack_offset as u32), Location::GPR(GPR::RSP));
}
}
pub fn release_locations_keep_state<E: Emitter>(
&self,
assembler: &mut E,
@ -255,7 +301,7 @@ impl Machine {
) {
let mut delta_stack_offset: usize = 0;
for loc in locs {
for loc in locs.iter().rev() {
match *loc {
Location::Memory(GPR::RBP, x) => {
if x >= 0 {