aarch64: Migrate {s,u}{div,rem} to ISLE (#3572)
* aarch64: Migrate {s,u}{div,rem} to ISLE
This commit migrates four different instructions at once to ISLE:
* `sdiv`
* `udiv`
* `srem`
* `urem`
These all share similar codegen and center around the `div` instruction
to use internally. The main feature of these was to model the manual
traps since the `div` instruction doesn't trap on overflow, instead
requiring manual checks to adhere to the semantics of the instruction
itself.
While I was here I went ahead and implemented an optimization for these
instructions when the right-hand-side is a constant with a known value.
For `udiv`, `srem`, and `urem` if the right-hand-side is a nonzero
constant then the checks for traps can be skipped entirely. For `sdiv`
if the constant is not 0 and not -1 then additionally all checks can be
elided. Finally if the right-hand-side of `sdiv` is -1 the zero-check is
elided, but it still needs a check for `i64::MIN` on the left-hand-side
and currently there's a TODO where `-1` is still checked too.
* Rebasing and review conflicts
This commit is contained in:
@@ -5,10 +5,10 @@ pub mod generated_code;
|
||||
|
||||
// Types that the generated ISLE code uses via `use super::*`.
|
||||
use super::{
|
||||
zero_reg, AMode, ASIMDFPModImm, ASIMDMovModImm, AtomicRmwOp, BranchTarget, CallIndInfo,
|
||||
CallInfo, Cond, CondBrKind, ExtendOp, FPUOpRI, Imm12, ImmLogic, ImmShift, Inst as MInst,
|
||||
JTSequenceInfo, MachLabel, MoveWideConst, NarrowValueMode, Opcode, OperandSize, PairAMode, Reg,
|
||||
ScalarSize, ShiftOpAndAmt, UImm5, VectorSize, NZCV,
|
||||
writable_zero_reg, zero_reg, AMode, ASIMDFPModImm, ASIMDMovModImm, AtomicRmwOp, BranchTarget,
|
||||
CallIndInfo, CallInfo, Cond, CondBrKind, ExtendOp, FPUOpRI, Imm12, ImmLogic, ImmShift,
|
||||
Inst as MInst, JTSequenceInfo, MachLabel, MoveWideConst, NarrowValueMode, Opcode, OperandSize,
|
||||
PairAMode, Reg, ScalarSize, ShiftOpAndAmt, UImm5, VectorSize, NZCV,
|
||||
};
|
||||
use crate::isa::aarch64::settings as aarch64_settings;
|
||||
use crate::machinst::isle::*;
|
||||
@@ -244,4 +244,35 @@ where
|
||||
fn emit(&mut self, inst: &MInst) -> Unit {
|
||||
self.emitted_insts.push(inst.clone());
|
||||
}
|
||||
|
||||
fn cond_br_zero(&mut self, reg: Reg) -> CondBrKind {
|
||||
CondBrKind::Zero(reg)
|
||||
}
|
||||
|
||||
fn cond_br_cond(&mut self, cond: &Cond) -> CondBrKind {
|
||||
CondBrKind::Cond(*cond)
|
||||
}
|
||||
|
||||
fn nzcv(&mut self, n: bool, z: bool, c: bool, v: bool) -> NZCV {
|
||||
NZCV::new(n, z, c, v)
|
||||
}
|
||||
|
||||
fn u8_into_uimm5(&mut self, x: u8) -> UImm5 {
|
||||
UImm5::maybe_from_u8(x).unwrap()
|
||||
}
|
||||
|
||||
fn u8_into_imm12(&mut self, x: u8) -> Imm12 {
|
||||
Imm12::maybe_from_u64(x.into()).unwrap()
|
||||
}
|
||||
|
||||
fn writable_zero_reg(&mut self) -> WritableReg {
|
||||
writable_zero_reg()
|
||||
}
|
||||
|
||||
fn safe_divisor_from_imm64(&mut self, val: Imm64) -> Option<u64> {
|
||||
match val.bits() {
|
||||
0 | -1 => None,
|
||||
n => Some(n as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user