diff --git a/crates/polkavm-common/src/program.rs b/crates/polkavm-common/src/program.rs index 60b65631..2450bd92 100644 --- a/crates/polkavm-common/src/program.rs +++ b/crates/polkavm-common/src/program.rs @@ -673,6 +673,9 @@ define_opcodes! { branch_less_signed = 48, branch_greater_or_equal_unsigned = 41, branch_greater_or_equal_signed = 43, + + cmov_if_zero_imm = 85, + cmov_if_not_zero_imm = 86, ] // Instructions with args: reg, reg, reg @@ -978,11 +981,19 @@ impl<'a> InstructionVisitor for core::fmt::Formatter<'a> { } fn cmov_if_zero(&mut self, d: Reg, s: Reg, c: Reg) -> Self::ReturnTy { - write!(self, "{d} = ({c} == 0) ? {s} : 0") + write!(self, "{d} = {s} if {c} == 0") } fn cmov_if_not_zero(&mut self, d: Reg, s: Reg, c: Reg) -> Self::ReturnTy { - write!(self, "{d} = ({c} != 0) ? {s} : 0") + write!(self, "{d} = {s} if {c} != 0") + } + + fn cmov_if_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + write!(self, "{d} = {s} if {c} == 0") + } + + fn cmov_if_not_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + write!(self, "{d} = {s} if {c} != 0") } fn add_imm(&mut self, d: Reg, s1: Reg, s2: u32) -> Self::ReturnTy { diff --git a/crates/polkavm-linker/src/program_from_elf.rs b/crates/polkavm-linker/src/program_from_elf.rs index bda88172..a98a6df0 100644 --- a/crates/polkavm-linker/src/program_from_elf.rs +++ b/crates/polkavm-linker/src/program_from_elf.rs @@ -537,7 +537,7 @@ enum BasicInst { Cmov { kind: CmovKind, dst: Reg, - src: Reg, + src: RegImm, cond: Reg, }, Ecalli { @@ -550,6 +550,13 @@ enum BasicInst { Nop, } +#[derive(Copy, Clone)] +enum OpKind { + Read, + Write, + ReadWrite, +} + impl BasicInst { fn is_nop(&self) -> bool { match self { @@ -582,7 +589,7 @@ impl BasicInst { BasicInst::StoreIndirect { src, base, .. } => RegMask::from(src) | RegMask::from(base), BasicInst::RegReg { src1, src2, .. } => RegMask::from(src1) | RegMask::from(src2), BasicInst::AnyAny { src1, src2, .. } => RegMask::from(src1) | RegMask::from(src2), - BasicInst::Cmov { src, cond, .. } => RegMask::from(src) | RegMask::from(cond), + BasicInst::Cmov { dst, src, cond, .. } => RegMask::from(dst) | RegMask::from(src) | RegMask::from(cond), BasicInst::Ecalli { nth_import } => imports[nth_import].src_mask(), BasicInst::Sbrk { size, .. } => RegMask::from(size), } @@ -618,68 +625,71 @@ impl BasicInst { } } - fn map_register(self, mut map: impl FnMut(Reg, bool) -> Reg) -> Option { + fn map_register(self, mut map: impl FnMut(Reg, OpKind) -> Reg) -> Option { // Note: ALWAYS map the inputs first; otherwise `regalloc2` might break! match self { - BasicInst::LoadImmediate { dst, imm } => Some(BasicInst::LoadImmediate { dst: map(dst, true), imm }), + BasicInst::LoadImmediate { dst, imm } => Some(BasicInst::LoadImmediate { + dst: map(dst, OpKind::Write), + imm, + }), BasicInst::LoadAbsolute { kind, dst, target } => Some(BasicInst::LoadAbsolute { kind, - dst: map(dst, true), + dst: map(dst, OpKind::Write), target, }), BasicInst::StoreAbsolute { kind, src, target } => Some(BasicInst::StoreAbsolute { kind, - src: src.map_register(|reg| map(reg, false)), + src: src.map_register(|reg| map(reg, OpKind::Read)), target, }), BasicInst::LoadAddress { dst, target } => Some(BasicInst::LoadAddress { - dst: map(dst, true), + dst: map(dst, OpKind::Write), target, }), BasicInst::LoadAddressIndirect { dst, target } => Some(BasicInst::LoadAddressIndirect { - dst: map(dst, true), + dst: map(dst, OpKind::Write), target, }), BasicInst::LoadIndirect { kind, dst, base, offset } => Some(BasicInst::LoadIndirect { kind, - base: map(base, false), - dst: map(dst, true), + base: map(base, OpKind::Read), + dst: map(dst, OpKind::Write), offset, }), BasicInst::StoreIndirect { kind, src, base, offset } => Some(BasicInst::StoreIndirect { kind, - src: src.map_register(|reg| map(reg, false)), - base: map(base, false), + src: src.map_register(|reg| map(reg, OpKind::Read)), + base: map(base, OpKind::Read), offset, }), BasicInst::RegReg { kind, dst, src1, src2 } => Some(BasicInst::RegReg { kind, - src1: map(src1, false), - src2: map(src2, false), - dst: map(dst, true), + src1: map(src1, OpKind::Read), + src2: map(src2, OpKind::Read), + dst: map(dst, OpKind::Write), }), BasicInst::AnyAny { kind, dst, src1, src2 } => Some(BasicInst::AnyAny { kind, - src1: src1.map_register(|reg| map(reg, false)), - src2: src2.map_register(|reg| map(reg, false)), - dst: map(dst, true), + src1: src1.map_register(|reg| map(reg, OpKind::Read)), + src2: src2.map_register(|reg| map(reg, OpKind::Read)), + dst: map(dst, OpKind::Write), }), BasicInst::Cmov { kind, dst, src, cond } => Some(BasicInst::Cmov { kind, - src: map(src, false), - cond: map(cond, false), - dst: map(dst, true), + src: src.map_register(|reg| map(reg, OpKind::Read)), + cond: map(cond, OpKind::Read), + dst: map(dst, OpKind::ReadWrite), }), BasicInst::Ecalli { .. } => None, BasicInst::Sbrk { dst, size } => Some(BasicInst::Sbrk { - size: map(size, false), - dst: map(dst, true), + size: map(size, OpKind::Read), + dst: map(dst, OpKind::Write), }), BasicInst::Nop => Some(BasicInst::Nop), } } - fn operands(&self, imports: &[Import]) -> impl Iterator + fn operands(&self, imports: &[Import]) -> impl Iterator where T: Clone, { @@ -688,8 +698,8 @@ impl BasicInst { // Abuse the `map_register` to avoid matching on everything again. let is_special_instruction = self .clone() - .map_register(|reg, is_dst| { - list[length] = Some((reg, is_dst)); + .map_register(|reg, kind| { + list[length] = Some((reg, kind)); length += 1; reg }) @@ -700,29 +710,28 @@ impl BasicInst { let import = &imports[nth_import]; for reg in import.src_mask() { - list[length] = Some((reg, false)); + list[length] = Some((reg, OpKind::Read)); length += 1; } for reg in import.dst_mask() { - list[length] = Some((reg, true)); + list[length] = Some((reg, OpKind::Write)); length += 1; } }; let mut seen_dst = false; - list.into_iter() - .take_while(|reg| reg.is_some()) - .flatten() - .map(move |(reg, is_dst)| { - // Sanity check to make sure inputs always come before outputs, so that `regalloc2` doesn't break. - if seen_dst { - assert!(is_dst); - } - seen_dst |= is_dst; + list.into_iter().take_while(|reg| reg.is_some()).flatten().map(move |(reg, kind)| { + let is_dst = matches!(kind, OpKind::Write | OpKind::ReadWrite); - (reg, is_dst) - }) + // Sanity check to make sure inputs always come before outputs, so that `regalloc2` doesn't break. + if seen_dst { + assert!(is_dst); + } + seen_dst |= is_dst; + + (reg, kind) + }) } fn map_target(self, map: impl Fn(T) -> Result) -> Result, E> { @@ -1424,15 +1433,14 @@ fn emit_minmax( mut emit: impl FnMut(InstExt), ) { // This is supposed to emit something like this: - // dst = src1 ? src2 - // tmp = (dst != 0) ? src1 : 0 - // dst = (dst == 0) ? src2 : 0 - // dst = dst | tmp + // tmp = src1 ? src2 + // dst = src1 + // dst = src2 if tmp == 0 assert_ne!(dst, tmp); - assert_ne!(Some(dst), src1); - assert_ne!(Some(dst), src2); + assert_ne!(Some(tmp), src1); assert_ne!(Some(tmp), src2); + assert_ne!(Some(dst), src2); let (cmp_src1, cmp_src2, cmp_kind) = match kind { MinMax::MinUnsigned => (src1, src2, AnyAnyKind::SetLessThanUnsigned), @@ -1443,36 +1451,28 @@ fn emit_minmax( emit(InstExt::Basic(BasicInst::AnyAny { kind: cmp_kind, - dst, + dst: tmp, src1: cmp_src1.map_or(RegImm::Imm(0), RegImm::Reg), src2: cmp_src2.map_or(RegImm::Imm(0), RegImm::Reg), })); + if let Some(src1) = src1 { - emit(InstExt::Basic(BasicInst::Cmov { - kind: CmovKind::NotEqZero, - dst: tmp, - src: src1, - cond: dst, - })); - } else { - emit(InstExt::Basic(BasicInst::LoadImmediate { dst: tmp, imm: 0 })); - } - if let Some(src2) = src2 { - emit(InstExt::Basic(BasicInst::Cmov { - kind: CmovKind::EqZero, + emit(InstExt::Basic(BasicInst::AnyAny { + kind: AnyAnyKind::Add, dst, - src: src2, - cond: dst, + src1: RegImm::Reg(src1), + src2: RegImm::Imm(0), })); } else { - emit(InstExt::Basic(BasicInst::LoadImmediate { dst, imm: 0 })); + emit(InstExt::Basic(BasicInst::LoadImmediate { dst: tmp, imm: 0 })); } - emit(InstExt::Basic(BasicInst::AnyAny { - kind: AnyAnyKind::Or, + + emit(InstExt::Basic(BasicInst::Cmov { + kind: CmovKind::EqZero, dst, - src1: dst.into(), - src2: tmp.into(), - })) + src: src2.map_or(RegImm::Imm(0), RegImm::Reg), + cond: tmp, + })); } fn convert_instruction( @@ -1688,14 +1688,13 @@ fn convert_instruction( )); }; - if let Some(src) = cast_reg_non_zero(src)? { - emit(InstExt::Basic(BasicInst::Cmov { kind, dst, src, cond })); - Ok(()) - } else { - Err(ProgramFromElfError::other( - "unimplemented: found a conditional move with a zero register as the source", - )) - } + emit(InstExt::Basic(BasicInst::Cmov { + kind, + dst, + src: cast_reg_any(src)?, + cond, + })); + Ok(()) } Inst::LoadReserved { dst, src, .. } => { let Some(dst) = cast_reg_non_zero(dst)? else { @@ -3334,6 +3333,21 @@ impl BlockRegs { }); } } + BasicInst::Cmov { + kind, + dst, + src: RegImm::Reg(src), + cond, + } => { + if let RegValue::Constant(src_value) = self.get_reg(src) { + return Some(BasicInst::Cmov { + kind, + dst, + src: RegImm::Imm(src_value as u32), + cond, + }); + } + } BasicInst::LoadIndirect { kind, dst, base, offset } => { if let RegValue::DataAddress(base) = self.get_reg(base) { return Some(BasicInst::LoadAbsolute { @@ -4175,33 +4189,60 @@ fn spill_fake_registers( let (_, instruction) = &block.ops[nth_instruction]; let mut operands = Vec::new(); - for (reg, is_dst) in instruction.operands(imports) { - if is_dst { - let value_index = counter; - counter += 1; - reg_to_value_index[reg as usize] = value_index; - operands.push(regalloc2::Operand::new( - regalloc2::VReg::new(value_index, regalloc2::RegClass::Int), - if reg.fake_register_index().is_none() { - regalloc2::OperandConstraint::FixedReg(regalloc2::PReg::new(reg as usize, regalloc2::RegClass::Int)) - } else { - regalloc2::OperandConstraint::Reg - }, - regalloc2::OperandKind::Def, - regalloc2::OperandPos::Late, - )); - } else { - let value_index = reg_to_value_index[reg as usize]; - operands.push(regalloc2::Operand::new( - regalloc2::VReg::new(value_index, regalloc2::RegClass::Int), - if reg.fake_register_index().is_none() { - regalloc2::OperandConstraint::FixedReg(regalloc2::PReg::new(reg as usize, regalloc2::RegClass::Int)) - } else { - regalloc2::OperandConstraint::Reg - }, - regalloc2::OperandKind::Use, - regalloc2::OperandPos::Early, - )); + for (reg, kind) in instruction.operands(imports) { + match kind { + OpKind::Write => { + let value_index = counter; + counter += 1; + reg_to_value_index[reg as usize] = value_index; + operands.push(regalloc2::Operand::new( + regalloc2::VReg::new(value_index, regalloc2::RegClass::Int), + if reg.fake_register_index().is_none() { + regalloc2::OperandConstraint::FixedReg(regalloc2::PReg::new(reg as usize, regalloc2::RegClass::Int)) + } else { + regalloc2::OperandConstraint::Reg + }, + regalloc2::OperandKind::Def, + regalloc2::OperandPos::Late, + )); + } + OpKind::Read => { + let value_index = reg_to_value_index[reg as usize]; + operands.push(regalloc2::Operand::new( + regalloc2::VReg::new(value_index, regalloc2::RegClass::Int), + if reg.fake_register_index().is_none() { + regalloc2::OperandConstraint::FixedReg(regalloc2::PReg::new(reg as usize, regalloc2::RegClass::Int)) + } else { + regalloc2::OperandConstraint::Reg + }, + regalloc2::OperandKind::Use, + regalloc2::OperandPos::Early, + )); + } + OpKind::ReadWrite => { + let value_index_read = reg_to_value_index[reg as usize]; + operands.push(regalloc2::Operand::new( + regalloc2::VReg::new(value_index_read, regalloc2::RegClass::Int), + if reg.fake_register_index().is_none() { + regalloc2::OperandConstraint::FixedReg(regalloc2::PReg::new(reg as usize, regalloc2::RegClass::Int)) + } else { + regalloc2::OperandConstraint::Reg + }, + regalloc2::OperandKind::Use, + regalloc2::OperandPos::Early, + )); + + let value_index_write = counter; + counter += 1; + + reg_to_value_index[reg as usize] = value_index_write; + operands.push(regalloc2::Operand::new( + regalloc2::VReg::new(value_index_write, regalloc2::RegClass::Int), + regalloc2::OperandConstraint::Reuse(operands.len() - 1), + regalloc2::OperandKind::Def, + regalloc2::OperandPos::Late, + )); + } } } @@ -4433,6 +4474,9 @@ fn replace_immediates_with_registers( BasicInst::StoreIndirect { src, .. } => { replace!(src); } + BasicInst::Cmov { src, .. } => { + replace!(src); + } _ => {} } @@ -5336,16 +5380,28 @@ fn emit_code( } } } - BasicInst::Cmov { kind, dst, src, cond } => { - codegen! { - args = (conv_reg(dst), conv_reg(src), conv_reg(cond)), - kind = kind, - { - CmovKind::EqZero => cmov_if_zero, - CmovKind::NotEqZero => cmov_if_not_zero, + BasicInst::Cmov { kind, dst, src, cond } => match src { + RegImm::Reg(src) => { + codegen! { + args = (conv_reg(dst), conv_reg(src), conv_reg(cond)), + kind = kind, + { + CmovKind::EqZero => cmov_if_zero, + CmovKind::NotEqZero => cmov_if_not_zero, + } } } - } + RegImm::Imm(imm) => { + codegen! { + args = (conv_reg(dst), conv_reg(cond), imm), + kind = kind, + { + CmovKind::EqZero => cmov_if_zero_imm, + CmovKind::NotEqZero => cmov_if_not_zero_imm, + } + } + } + }, BasicInst::Ecalli { nth_import } => { assert!(used_imports.contains(&nth_import)); let import = &imports[nth_import]; diff --git a/crates/polkavm-linker/src/riscv.rs b/crates/polkavm-linker/src/riscv.rs index bdc875a5..501e9b7b 100644 --- a/crates/polkavm-linker/src/riscv.rs +++ b/crates/polkavm-linker/src/riscv.rs @@ -286,8 +286,8 @@ pub enum AtomicKind { #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum CmovKind { - EqZero = 0b111, - NotEqZero = 0b101, + EqZero = 0, + NotEqZero = 1, } impl Reg { @@ -561,23 +561,6 @@ impl Inst { 0b0000001_00000_00000_110_00000_0000000 => RegRegKind::Rem, 0b0000001_00000_00000_111_00000_0000000 => RegRegKind::RemUnsigned, - 0b0000111_00000_00000_101_00000_0000000 => { - return Some(Inst::Cmov { - kind: CmovKind::NotEqZero, - dst, - src: src1, - cond: src2, - }); - } - 0b0000111_00000_00000_111_00000_0000000 => { - return Some(Inst::Cmov { - kind: CmovKind::EqZero, - dst, - src: src1, - cond: src2, - }); - } - _ => return None, }; @@ -658,6 +641,34 @@ impl Inst { } } } + 0b0001011 => { + let dst = Reg::decode(op >> 7); + let src1 = Reg::decode(op >> 15); + let src2 = Reg::decode(op >> 20); + let hi = op >> 25; + let lo = (op >> 12) & 0b111; + if lo == 0b001 { + if hi == 0b0100000 { + // th.mveqz + return Some(Inst::Cmov { + kind: CmovKind::EqZero, + dst, + src: src1, + cond: src2, + }); + } else if hi == 0b0100001 { + // th.mvnez + return Some(Inst::Cmov { + kind: CmovKind::NotEqZero, + dst, + src: src1, + cond: src2, + }); + } + } + + None + } _ => None, } } @@ -816,9 +827,15 @@ impl Inst { | (u32::from(acquire) << 26) | ((kind as u32) << 27), ), - Inst::Cmov { kind, dst, src, cond } => { - Some(0b0110011 | ((kind as u32) << 12) | ((dst as u32) << 7) | ((src as u32) << 15) | ((cond as u32) << 20) | (0b111 << 25)) - } + Inst::Cmov { kind, dst, src, cond } => Some( + 0b0001011 + | (0b001 << 12) + | ((dst as u32) << 7) + | ((src as u32) << 15) + | ((cond as u32) << 20) + | ((kind as u32) << 25) + | (1 << 30), + ), } } } @@ -896,22 +913,12 @@ fn test_decode_multiply() { #[test] fn test_decode_cmov() { assert_eq!( - Inst::decode(0xec5f5b3).unwrap(), - Inst::Cmov { - kind: CmovKind::EqZero, - dst: Reg::A1, - src: Reg::A1, - cond: Reg::A2 - } - ); - - assert_eq!( - Inst::decode(0xec55533).unwrap(), + Inst::decode(0x42a6158b).unwrap(), Inst::Cmov { kind: CmovKind::NotEqZero, - dst: Reg::A0, - src: Reg::A0, - cond: Reg::A2 + dst: Reg::A1, + src: Reg::A2, + cond: Reg::A0 } ); } diff --git a/crates/polkavm/src/api.rs b/crates/polkavm/src/api.rs index 56730a7b..4568029c 100644 --- a/crates/polkavm/src/api.rs +++ b/crates/polkavm/src/api.rs @@ -614,6 +614,20 @@ where Ok(()) } + #[inline(always)] + fn cmov_if_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + self.0.before_instruction(); + self.0.cmov_if_zero_imm(d, c, s); + Ok(()) + } + + #[inline(always)] + fn cmov_if_not_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + self.0.before_instruction(); + self.0.cmov_if_not_zero_imm(d, c, s); + Ok(()) + } + #[inline(always)] fn add_imm(&mut self, d: Reg, s: Reg, imm: u32) -> Self::ReturnTy { self.0.before_instruction(); diff --git a/crates/polkavm/src/compiler/amd64.rs b/crates/polkavm/src/compiler/amd64.rs index b884d8a4..e00efd43 100644 --- a/crates/polkavm/src/compiler/amd64.rs +++ b/crates/polkavm/src/compiler/amd64.rs @@ -358,33 +358,26 @@ impl<'a> Compiler<'a> { #[cfg_attr(not(debug_assertions), inline(always))] fn cmov(&mut self, d: Reg, s: Reg, c: Reg, condition: Condition) { + if d == s { + return; + } + let d = conv_reg(d); let s = conv_reg(s); let c = conv_reg(c); - if d == s { - let condition = match condition { - Condition::Equal => Condition::NotEqual, - Condition::NotEqual => Condition::Equal, - _ => unreachable!() - }; - - self.push(xor((RegSize::R32, TMP_REG, TMP_REG))); - self.push(test((self.reg_size(), c, c))); - self.push(cmov(condition, self.reg_size(), d, TMP_REG)); - } else if d != c { - debug_assert_ne!(d, s); - self.push(xor((RegSize::R32, d, d))); - self.push(test((self.reg_size(), c, c))); - self.push(cmov(condition, self.reg_size(), d, s)); - } else { - debug_assert_ne!(d, s); - debug_assert_eq!(d, c); - self.push(xor((RegSize::R32, TMP_REG, TMP_REG))); - self.push(test((self.reg_size(), c, c))); - self.push(mov(self.reg_size(), d, TMP_REG)); - self.push(cmov(condition, self.reg_size(), d, s)); - } + self.push(test((self.reg_size(), c, c))); + self.push(cmov(condition, self.reg_size(), d, s)); + } + + #[cfg_attr(not(debug_assertions), inline(always))] + fn cmov_imm(&mut self, d: Reg, s: u32, c: Reg, condition: Condition) { + let d = conv_reg(d); + let c = conv_reg(c); + + self.push(test((self.reg_size(), c, c))); + self.push(mov_imm(TMP_REG, imm32(s))); + self.push(cmov(condition, self.reg_size(), d, TMP_REG)); } fn div_rem(&mut self, d: Reg, s1: Reg, s2: Reg, div_rem: DivRem, kind: Signedness) { @@ -1080,6 +1073,16 @@ impl<'a> InstructionVisitor for VisitorWrapper<'a, Compiler<'a>> { self.cmov(d, s, c, Condition::NotEqual); } + #[inline(always)] + fn cmov_if_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + self.cmov_imm(d, s, c, Condition::Equal); + } + + #[inline(always)] + fn cmov_if_not_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + self.cmov_imm(d, s, c, Condition::NotEqual); + } + #[inline(always)] fn add_imm(&mut self, d: Reg, s1: Reg, s2: u32) -> Self::ReturnTy { let reg_size = self.reg_size(); diff --git a/crates/polkavm/src/interpreter.rs b/crates/polkavm/src/interpreter.rs index 70a18e27..3f2db24d 100644 --- a/crates/polkavm/src/interpreter.rs +++ b/crates/polkavm/src/interpreter.rs @@ -888,11 +888,41 @@ impl<'a, 'b> InstructionVisitor for Visitor<'a, 'b> { } fn cmov_if_zero(&mut self, d: Reg, s: Reg, c: Reg) -> Self::ReturnTy { - self.set3(d, s, c, |s, c| if c == 0 { s } else { 0 }) + if self.get(c) == 0 { + let value = self.get(s); + self.set(d, value)?; + } + + self.inner.nth_instruction += 1; + Ok(()) + } + + fn cmov_if_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + if self.get(c) == 0 { + self.set(d, s)?; + } + + self.inner.nth_instruction += 1; + Ok(()) } fn cmov_if_not_zero(&mut self, d: Reg, s: Reg, c: Reg) -> Self::ReturnTy { - self.set3(d, s, c, |s, c| if c != 0 { s } else { 0 }) + if self.get(c) != 0 { + let value = self.get(s); + self.set(d, value)?; + } + + self.inner.nth_instruction += 1; + Ok(()) + } + + fn cmov_if_not_zero_imm(&mut self, d: Reg, c: Reg, s: u32) -> Self::ReturnTy { + if self.get(c) != 0 { + self.set(d, s)?; + } + + self.inner.nth_instruction += 1; + Ok(()) } fn add_imm(&mut self, d: Reg, s1: Reg, s2: u32) -> Self::ReturnTy { diff --git a/guest-programs/build-benchmarks.sh b/guest-programs/build-benchmarks.sh index 3c13bc0e..a5b587e0 100755 --- a/guest-programs/build-benchmarks.sh +++ b/guest-programs/build-benchmarks.sh @@ -64,7 +64,7 @@ function build_benchmark() { if [ "${RV32E_TOOLCHAIN:-}" != "" ]; then echo "> Building: '$1' (polkavm)" - RUSTFLAGS="-C target-feature=+lui-addi-fusion -C relocation-model=pie -C link-arg=--emit-relocs -C link-arg=--unique $extra_flags" rustup run $RV32E_TOOLCHAIN cargo build -q --release --bin $1 -p $1 + RUSTFLAGS="-C target-feature=+lui-addi-fusion,+fast-unaligned-access,+xtheadcondmov -C relocation-model=pie -C link-arg=--emit-relocs -C link-arg=--unique $extra_flags" rustup run $RV32E_TOOLCHAIN cargo build -q --release --bin $1 -p $1 cd .. cargo run -q -p polkatool link --run-only-if-newer guest-programs/target/riscv32ema-unknown-none-elf/release/$1 -o guest-programs/target/riscv32ema-unknown-none-elf/release/$1.polkavm cd $current_dir diff --git a/guest-programs/build-test-data.sh b/guest-programs/build-test-data.sh index 84f0fd51..41def216 100755 --- a/guest-programs/build-test-data.sh +++ b/guest-programs/build-test-data.sh @@ -6,7 +6,7 @@ function build_test_data() { output_path="../test-data/$1.elf.zst" echo "> Building: '$1' (-> $output_path)" - RUSTFLAGS="-C target-feature=+lui-addi-fusion -C relocation-model=pie -C link-arg=--emit-relocs -C link-arg=--unique --remap-path-prefix=$(pwd)= --remap-path-prefix=$HOME=~" cargo build -q --profile $2 --bin $1 -p $1 + RUSTFLAGS="-C target-feature=+lui-addi-fusion,+fast-unaligned-access,+xtheadcondmov -C relocation-model=pie -C link-arg=--emit-relocs -C link-arg=--unique --remap-path-prefix=$(pwd)= --remap-path-prefix=$HOME=~" cargo build -q --profile $2 --bin $1 -p $1 zstd -f -q -19 -o $output_path target/riscv32ema-unknown-none-elf/$2/$1 chmod -x $output_path } diff --git a/test-data/bench-pinky.elf.zst b/test-data/bench-pinky.elf.zst index 7a359e8c..70d25869 100644 Binary files a/test-data/bench-pinky.elf.zst and b/test-data/bench-pinky.elf.zst differ diff --git a/test-data/test-blob.elf.zst b/test-data/test-blob.elf.zst index 45715d3d..cf3dba6d 100644 Binary files a/test-data/test-blob.elf.zst and b/test-data/test-blob.elf.zst differ