Skip to content

Commit

Permalink
Merge branch 'master' into type-resolve-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
tritao authored Oct 17, 2024
2 parents b8518cd + fa4dac8 commit 9086173
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 12 deletions.
19 changes: 13 additions & 6 deletions sway-core/src/asm_generation/fuel/abstract_instruction_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl AbstractInstructionSet {
.simplify_cfg()
.remove_sequential_jumps()
.remove_redundant_moves()
.remove_unused_ops()
.remove_redundant_ops()
}

/// Removes any jumps to the subsequent line.
Expand Down Expand Up @@ -114,11 +114,18 @@ impl AbstractInstructionSet {
self
}

fn remove_unused_ops(mut self) -> AbstractInstructionSet {
// Just remove NOPs for now.
self.ops.retain(|op| match &op.opcode {
Either::Left(VirtualOp::NOOP) => false,
_otherwise => true,
fn remove_redundant_ops(mut self) -> AbstractInstructionSet {
self.ops.retain(|op| {
// It is easier to think in terms of operations we want to remove
// than the operations we want to retain ;-)
#[allow(clippy::match_like_matches_macro)]
// Keep the `match` for adding more ops in the future.
let remove = match &op.opcode {
Either::Left(VirtualOp::NOOP) => true,
_ => false,
};

!remove
});

self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ pub struct AllocatedAbstractInstructionSet {
}

impl AllocatedAbstractInstructionSet {
pub(crate) fn optimize(self) -> AllocatedAbstractInstructionSet {
self.remove_redundant_ops()
}

fn remove_redundant_ops(mut self) -> AllocatedAbstractInstructionSet {
self.ops.retain(|op| {
// It is easier to think in terms of operations we want to remove
// than the operations we want to retain ;-)
let remove = match &op.opcode {
// `cfei i0` and `cfsi i0` pairs.
Either::Left(AllocatedOpcode::CFEI(imm))
| Either::Left(AllocatedOpcode::CFSI(imm)) => imm.value == 0u32,
// `cfe $zero` and `cfs $zero` pairs.
Either::Left(AllocatedOpcode::CFE(reg))
| Either::Left(AllocatedOpcode::CFS(reg)) => reg.is_zero(),
_ => false,
};

!remove
});

self
}

/// Replace each PUSHA instruction with stores of all used registers to the stack, and each
/// POPA with respective loads from the stack.
///
Expand Down
15 changes: 10 additions & 5 deletions sway-core/src/asm_generation/fuel/programs/abstract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl AbstractProgram {
&& self.data_section.value_pairs.is_empty()
}

/// Adds prologue, globals allocation, before entries, contract method switch, and allocates virtual register
/// Adds prologue, globals allocation, before entries, contract method switch, and allocates virtual register.
pub(crate) fn into_allocated_program(
mut self,
fallback_fn: Option<crate::asm_lang::Label>,
Expand Down Expand Up @@ -111,29 +111,34 @@ impl AbstractProgram {
})
.collect();

// Gather all functions
// Gather all functions.
let all_functions = self
.entries
.into_iter()
.map(|entry| entry.ops)
.chain(self.non_entries);

// optimise and then verify these functions.
// Optimize and then verify abstract functions.
let abstract_functions = all_functions
.map(|instruction_set| instruction_set.optimize(&self.data_section))
.map(AbstractInstructionSet::verify)
.collect::<Result<Vec<AbstractInstructionSet>, CompileError>>()?;

// Allocate the registers for each function.
let functions = abstract_functions
let allocated_functions = abstract_functions
.into_iter()
.map(|abstract_instruction_set| {
let allocated = abstract_instruction_set.allocate_registers()?;
Ok(allocated.emit_pusha_popa())
})
.collect::<Result<Vec<AllocatedAbstractInstructionSet>, CompileError>>()?;

// XXX need to verify that the stack use for each function is balanced.
// Optimize allocated functions.
// TODO: Add verification. E.g., verify that the stack use for each function is balanced.
let functions = allocated_functions
.into_iter()
.map(|instruction_set| instruction_set.optimize())
.collect::<Vec<AllocatedAbstractInstructionSet>>();

Ok(AllocatedProgram {
kind: self.kind,
Expand Down
4 changes: 4 additions & 0 deletions sway-core/src/asm_lang/allocated_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ impl AllocatedRegister {
AllocatedRegister::Constant(constant) => constant.to_reg_id(),
}
}

pub fn is_zero(&self) -> bool {
matches!(self, Self::Constant(ConstantRegister::Zero))
}
}

/// This enum is unfortunately a redundancy of the [fuel_asm::Opcode] and [crate::VirtualOp] enums. This variant, however,
Expand Down
3 changes: 2 additions & 1 deletion test/src/ir_generation/tests/empty.sw
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ fn main() {
// ::check-asm::
// The data section setup:
// check: move $$$$locbase $$sp
// check: cfei i0
// not: cfei i0
// not: cfsi i0
// check: ret $$zero
// nextln: .data
// not: data_

0 comments on commit 9086173

Please sign in to comment.