Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix singlepass codegen regression #2787

Merged
merged 8 commits into from Feb 14, 2022
8 changes: 4 additions & 4 deletions lib/compiler-singlepass/src/codegen.rs
Expand Up @@ -737,8 +737,8 @@ impl<'a, M: Machine> FuncGen<'a, M> {
.collect();

// Save used GPRs. Preserve correct stack alignment
let mut used_stack = self.machine.push_used_gpr();
let used_gprs = self.machine.get_used_gprs();
let mut used_stack = self.machine.push_used_gpr(&used_gprs);
for r in used_gprs.iter() {
let content = self.state.register_values[self.machine.index_from_gpr(*r).0].clone();
if content == MachineValue::Undefined {
Expand All @@ -752,7 +752,7 @@ impl<'a, M: Machine> FuncGen<'a, M> {
// Save used SIMD registers.
let used_simds = self.machine.get_used_simd();
if used_simds.len() > 0 {
used_stack += self.machine.push_used_simd();
used_stack += self.machine.push_used_simd(&used_simds);

for r in used_simds.iter().rev() {
let content =
Expand Down Expand Up @@ -915,14 +915,14 @@ impl<'a, M: Machine> FuncGen<'a, M> {

// Restore SIMDs.
if !used_simds.is_empty() {
self.machine.pop_used_simd();
self.machine.pop_used_simd(&used_simds);
for _ in 0..used_simds.len() {
self.state.stack_values.pop().unwrap();
}
}

// Restore GPRs.
self.machine.pop_used_gpr();
self.machine.pop_used_gpr(&used_gprs);
for _ in used_gprs.iter().rev() {
self.state.stack_values.pop().unwrap();
}
Expand Down
8 changes: 4 additions & 4 deletions lib/compiler-singlepass/src/machine.rs
Expand Up @@ -83,9 +83,9 @@ pub trait Machine {
/// reserve a GPR
fn reserve_gpr(&mut self, gpr: Self::GPR);
/// Push used gpr to the stack. Return the bytes taken on the stack
fn push_used_gpr(&mut self) -> usize;
fn push_used_gpr(&mut self, grps: &Vec<Self::GPR>) -> usize;
/// Pop used gpr to the stack
fn pop_used_gpr(&mut self);
fn pop_used_gpr(&mut self, grps: &Vec<Self::GPR>);
/// Picks an unused SIMD register.
///
/// This method does not mark the register as used
Expand All @@ -101,9 +101,9 @@ pub trait Machine {
/// Releases a temporary XMM register.
fn release_simd(&mut self, simd: Self::SIMD);
/// Push used simd regs to the stack. Return bytes taken on the stack
fn push_used_simd(&mut self) -> usize;
fn push_used_simd(&mut self, simds: &Vec<Self::SIMD>) -> usize;
/// Pop used simd regs to the stack
fn pop_used_simd(&mut self);
fn pop_used_simd(&mut self, simds: &Vec<Self::SIMD>);
/// Return a rounded stack adjustement value (must be multiple of 16bytes on ARM64 for example)
fn round_stack_adjust(&self, value: usize) -> usize;
/// Set the source location of the Wasm to the given offset.
Expand Down
16 changes: 4 additions & 12 deletions lib/compiler-singlepass/src/machine_arm64.rs
Expand Up @@ -1175,9 +1175,7 @@ impl Machine for MachineARM64 {
self.used_gprs.insert(gpr);
}

fn push_used_gpr(&mut self) -> usize {
let mut used_gprs = self.get_used_gprs();
used_gprs.sort();
fn push_used_gpr(&mut self, used_gprs: &Vec<GPR>) -> usize {
if used_gprs.len() % 2 == 1 {
self.emit_push(Size::S64, Location::GPR(GPR::XzrSp));
}
Expand All @@ -1186,9 +1184,7 @@ impl Machine for MachineARM64 {
}
((used_gprs.len() + 1) / 2) * 16
}
fn pop_used_gpr(&mut self) {
let mut used_gprs = self.get_used_gprs();
used_gprs.sort();
fn pop_used_gpr(&mut self, used_gprs: &Vec<GPR>) {
for r in used_gprs.iter().rev() {
self.emit_pop(Size::S64, Location::GPR(*r));
}
Expand Down Expand Up @@ -1239,9 +1235,7 @@ impl Machine for MachineARM64 {
assert_eq!(self.used_simd.remove(&simd), true);
}

fn push_used_simd(&mut self) -> usize {
let mut used_neons = self.get_used_simd();
used_neons.sort();
fn push_used_simd(&mut self, used_neons: &Vec<NEON>) -> usize {
let stack_adjust = if used_neons.len() & 1 == 1 {
(used_neons.len() * 8) as u32 + 8
} else {
Expand All @@ -1258,9 +1252,7 @@ impl Machine for MachineARM64 {
}
stack_adjust as usize
}
fn pop_used_simd(&mut self) {
let mut used_neons = self.get_used_simd();
used_neons.sort();
fn pop_used_simd(&mut self, used_neons: &Vec<NEON>) {
for (i, r) in used_neons.iter().enumerate() {
self.assembler.emit_ldr(
Size::S64,
Expand Down
16 changes: 4 additions & 12 deletions lib/compiler-singlepass/src/machine_x64.rs
Expand Up @@ -1626,17 +1626,13 @@ impl Machine for MachineX86_64 {
self.used_gprs.insert(gpr);
}

fn push_used_gpr(&mut self) -> usize {
let mut used_gprs = self.get_used_gprs();
used_gprs.sort();
fn push_used_gpr(&mut self, used_gprs: &Vec<GPR>) -> usize {
for r in used_gprs.iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashSet still has a randomized iteration order so this makes the codegen of singlepass non-deterministic (but still correct).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but do we need to generate the same code on each run?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do want to have deterministic reproducible builds for a given input. See #2173.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I'll remove the hashmaps

self.assembler.emit_push(Size::S64, Location::GPR(*r));
}
used_gprs.len() * 8
}
fn pop_used_gpr(&mut self) {
let mut used_gprs = self.get_used_gprs();
used_gprs.sort();
fn pop_used_gpr(&mut self, used_gprs: &Vec<GPR>) {
for r in used_gprs.iter().rev() {
self.assembler.emit_pop(Size::S64, Location::GPR(*r));
}
Expand Down Expand Up @@ -1684,9 +1680,7 @@ impl Machine for MachineX86_64 {
assert_eq!(self.used_simd.remove(&simd), true);
}

fn push_used_simd(&mut self) -> usize {
let mut used_xmms = self.get_used_simd();
used_xmms.sort();
fn push_used_simd(&mut self, used_xmms: &Vec<XMM>) -> usize {
self.adjust_stack((used_xmms.len() * 8) as u32);

for (i, r) in used_xmms.iter().enumerate() {
Expand All @@ -1699,9 +1693,7 @@ impl Machine for MachineX86_64 {

used_xmms.len() * 8
}
fn pop_used_simd(&mut self) {
let mut used_xmms = self.get_used_simd();
used_xmms.sort();
fn pop_used_simd(&mut self, used_xmms: &Vec<XMM>) {
for (i, r) in used_xmms.iter().enumerate() {
self.move_location(
Size::S64,
Expand Down