Skip to content

Commit

Permalink
feat(avm)!: variants for binary operations (#8473)
Browse files Browse the repository at this point in the history
Gets us another ~30% bytecode size gain.

I still have to remove tags.
  • Loading branch information
fcarreiro authored Sep 10, 2024
1 parent 26706e9 commit 8de1f2a
Show file tree
Hide file tree
Showing 27 changed files with 904 additions and 638 deletions.
2 changes: 1 addition & 1 deletion avm-transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Debug for AvmInstruction {
impl Default for AvmInstruction {
fn default() -> Self {
AvmInstruction {
opcode: AvmOpcode::ADD,
opcode: AvmOpcode::ADD_8,
// TODO(4266): default to Some(0), since all instructions have indirect flag except jumps
indirect: None,
tag: None,
Expand Down
78 changes: 52 additions & 26 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,33 @@
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
pub enum AvmOpcode {
// Compute
ADD,
SUB,
MUL,
DIV,
FDIV,
EQ,
LT,
LTE,
AND,
OR,
XOR,
ADD_8,
ADD_16,
SUB_8,
SUB_16,
MUL_8,
MUL_16,
DIV_8,
DIV_16,
FDIV_8,
FDIV_16,
EQ_8,
EQ_16,
LT_8,
LT_16,
LTE_8,
LTE_16,
AND_8,
AND_16,
OR_8,
OR_16,
XOR_8,
XOR_16,
NOT,
SHL,
SHR,
SHL_8,
SHL_16,
SHR_8,
SHR_16,
CAST,
// Execution environment
ADDRESS,
Expand Down Expand Up @@ -89,22 +102,35 @@ impl AvmOpcode {
match self {
// Compute
// Compute - Arithmetic
AvmOpcode::ADD => "ADD",
AvmOpcode::SUB => "SUB",
AvmOpcode::MUL => "MUL",
AvmOpcode::DIV => "DIV",
AvmOpcode::FDIV => "FDIV",
AvmOpcode::ADD_8 => "ADD_8",
AvmOpcode::ADD_16 => "ADD_16",
AvmOpcode::SUB_8 => "SUB_8",
AvmOpcode::SUB_16 => "SUB_16",
AvmOpcode::MUL_8 => "MUL_8",
AvmOpcode::MUL_16 => "MUL_16",
AvmOpcode::DIV_8 => "DIV_8",
AvmOpcode::DIV_16 => "DIV_16",
AvmOpcode::FDIV_8 => "FDIV_8",
AvmOpcode::FDIV_16 => "FDIV_16",
// Compute - Comparators
AvmOpcode::EQ => "EQ",
AvmOpcode::LT => "LT",
AvmOpcode::LTE => "LTE",
AvmOpcode::EQ_8 => "EQ_8",
AvmOpcode::EQ_16 => "EQ_16",
AvmOpcode::LT_8 => "LT_8",
AvmOpcode::LT_16 => "LT_16",
AvmOpcode::LTE_8 => "LTE_8",
AvmOpcode::LTE_16 => "LTE_16",
// Compute - Bitwise
AvmOpcode::AND => "AND",
AvmOpcode::OR => "OR",
AvmOpcode::XOR => "XOR",
AvmOpcode::AND_8 => "AND_8",
AvmOpcode::AND_16 => "AND_16",
AvmOpcode::OR_8 => "OR_8",
AvmOpcode::OR_16 => "OR_16",
AvmOpcode::XOR_8 => "XOR_8",
AvmOpcode::XOR_16 => "XOR_16",
AvmOpcode::NOT => "NOT",
AvmOpcode::SHL => "SHL",
AvmOpcode::SHR => "SHR",
AvmOpcode::SHL_8 => "SHL_8",
AvmOpcode::SHL_16 => "SHL_16",
AvmOpcode::SHR_8 => "SHR_8",
AvmOpcode::SHR_16 => "SHR_16",
// Compute - Type Conversions
AvmOpcode::CAST => "CAST",

Expand Down
155 changes: 126 additions & 29 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,65 @@ pub fn brillig_to_avm(
for brillig_instr in brillig_bytecode {
match brillig_instr {
BrilligOpcode::BinaryFieldOp { destination, op, lhs, rhs } => {
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();

assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryFieldOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryFieldOp::Add => AvmOpcode::ADD,
BinaryFieldOp::Sub => AvmOpcode::SUB,
BinaryFieldOp::Mul => AvmOpcode::MUL,
BinaryFieldOp::Div => AvmOpcode::FDIV,
BinaryFieldOp::IntegerDiv => AvmOpcode::DIV,
BinaryFieldOp::Equals => AvmOpcode::EQ,
BinaryFieldOp::LessThan => AvmOpcode::LT,
BinaryFieldOp::LessThanEquals => AvmOpcode::LTE,
BinaryFieldOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryFieldOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryFieldOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryFieldOp::Div => match bits_needed {
8 => AvmOpcode::FDIV_8,
16 => AvmOpcode::FDIV_16,
_ => unreachable!(),
},
BinaryFieldOp::IntegerDiv => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryFieldOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: if avm_opcode == AvmOpcode::FDIV { None } else { Some(AvmTypeTag::FIELD) },
tag: Some(AvmTypeTag::FIELD),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand All @@ -57,28 +98,84 @@ pub fn brillig_to_avm(
"BinaryIntOp bit size should be integral: {:?}",
brillig_instr
);
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();
assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryIntOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryIntOp::Add => AvmOpcode::ADD,
BinaryIntOp::Sub => AvmOpcode::SUB,
BinaryIntOp::Mul => AvmOpcode::MUL,
BinaryIntOp::Div => AvmOpcode::DIV,
BinaryIntOp::Equals => AvmOpcode::EQ,
BinaryIntOp::LessThan => AvmOpcode::LT,
BinaryIntOp::LessThanEquals => AvmOpcode::LTE,
BinaryIntOp::And => AvmOpcode::AND,
BinaryIntOp::Or => AvmOpcode::OR,
BinaryIntOp::Xor => AvmOpcode::XOR,
BinaryIntOp::Shl => AvmOpcode::SHL,
BinaryIntOp::Shr => AvmOpcode::SHR,
BinaryIntOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryIntOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryIntOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryIntOp::Div => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryIntOp::And => match bits_needed {
8 => AvmOpcode::AND_8,
16 => AvmOpcode::AND_16,
_ => unreachable!(),
},
BinaryIntOp::Or => match bits_needed {
8 => AvmOpcode::OR_8,
16 => AvmOpcode::OR_16,
_ => unreachable!(),
},
BinaryIntOp::Xor => match bits_needed {
8 => AvmOpcode::XOR_8,
16 => AvmOpcode::XOR_16,
_ => unreachable!(),
},
BinaryIntOp::Shl => match bits_needed {
8 => AvmOpcode::SHL_8,
16 => AvmOpcode::SHL_16,
_ => unreachable!(),
},
BinaryIntOp::Shr => match bits_needed {
8 => AvmOpcode::SHR_8,
16 => AvmOpcode::SHR_16,
_ => unreachable!(),
},
BinaryIntOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryIntOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryIntOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: Some(tag_from_bit_size(BitSize::Integer(*bit_size))),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand Down Expand Up @@ -214,9 +311,9 @@ pub fn brillig_to_avm(
// We are adding a MOV instruction that moves a value to itself.
// This should therefore not affect the program's execution.
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::MOV_8,
opcode: AvmOpcode::MOV_16,
indirect: Some(ALL_DIRECT),
operands: vec![AvmOperand::U32 { value: 0x18ca }, AvmOperand::U32 { value: 0x18ca }],
operands: vec![AvmOperand::U16 { value: 0x18ca }, AvmOperand::U16 { value: 0x18ca }],
..Default::default()
});

Expand Down
Loading

0 comments on commit 8de1f2a

Please sign in to comment.