mach backend: reduce the size of the Inst enum down to 32 bytes;

This commit is contained in:
Benjamin Bouvier
2020-06-01 16:22:29 +02:00
parent e227608510
commit 67c7a3ed19
6 changed files with 111 additions and 101 deletions

View File

@@ -1276,33 +1276,39 @@ impl ABICall for AArch64ABICall {
); );
match &self.dest { match &self.dest {
&CallDest::ExtName(ref name, RelocDistance::Near) => ctx.emit(Inst::Call { &CallDest::ExtName(ref name, RelocDistance::Near) => ctx.emit(Inst::Call {
dest: Box::new(name.clone()), info: Box::new(CallInfo {
uses: uses.into_boxed_slice(), dest: name.clone(),
defs: defs.into_boxed_slice(), uses,
loc: self.loc, defs,
opcode: self.opcode, loc: self.loc,
opcode: self.opcode,
}),
}), }),
&CallDest::ExtName(ref name, RelocDistance::Far) => { &CallDest::ExtName(ref name, RelocDistance::Far) => {
ctx.emit(Inst::LoadExtName { ctx.emit(Inst::LoadExtName {
rd: writable_spilltmp_reg(), rd: writable_spilltmp_reg(),
name: name.clone(), name: Box::new(name.clone()),
offset: 0, offset: 0,
srcloc: self.loc, srcloc: self.loc,
}); });
ctx.emit(Inst::CallInd { ctx.emit(Inst::CallInd {
rn: spilltmp_reg(), info: Box::new(CallIndInfo {
uses: uses.into_boxed_slice(), rn: spilltmp_reg(),
defs: defs.into_boxed_slice(), uses,
loc: self.loc, defs,
opcode: self.opcode, loc: self.loc,
opcode: self.opcode,
}),
}); });
} }
&CallDest::Reg(reg) => ctx.emit(Inst::CallInd { &CallDest::Reg(reg) => ctx.emit(Inst::CallInd {
rn: reg, info: Box::new(CallIndInfo {
uses: uses.into_boxed_slice(), rn: reg,
defs: defs.into_boxed_slice(), uses,
loc: self.loc, defs,
opcode: self.opcode, loc: self.loc,
opcode: self.opcode,
}),
}), }),
} }
} }

View File

@@ -309,7 +309,7 @@ pub enum BranchTarget {
/// `lower_branch_group()`. /// `lower_branch_group()`.
Label(MachLabel), Label(MachLabel),
/// A fixed PC offset. /// A fixed PC offset.
ResolvedOffset(isize), ResolvedOffset(i32),
} }
impl BranchTarget { impl BranchTarget {

View File

@@ -1239,24 +1239,17 @@ impl MachInstEmit for Inst {
&Inst::EpiloguePlaceholder => { &Inst::EpiloguePlaceholder => {
// Noop; this is just a placeholder for epilogues. // Noop; this is just a placeholder for epilogues.
} }
&Inst::Call { &Inst::Call { ref info } => {
ref dest, sink.add_reloc(info.loc, Reloc::Arm64Call, &info.dest, 0);
loc,
opcode,
..
} => {
sink.add_reloc(loc, Reloc::Arm64Call, dest, 0);
sink.put4(enc_jump26(0b100101, 0)); sink.put4(enc_jump26(0b100101, 0));
if opcode.is_call() { if info.opcode.is_call() {
sink.add_call_site(loc, opcode); sink.add_call_site(info.loc, info.opcode);
} }
} }
&Inst::CallInd { &Inst::CallInd { ref info } => {
rn, loc, opcode, .. sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(info.rn) << 5));
} => { if info.opcode.is_call() {
sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(rn) << 5)); sink.add_call_site(info.loc, info.opcode);
if opcode.is_call() {
sink.add_call_site(loc, opcode);
} }
} }
&Inst::CondBr { &Inst::CondBr {
@@ -1318,7 +1311,7 @@ impl MachInstEmit for Inst {
ridx, ridx,
rtmp1, rtmp1,
rtmp2, rtmp2,
ref targets, ref info,
.. ..
} => { } => {
// This sequence is *one* instruction in the vcode, and is expanded only here at // This sequence is *one* instruction in the vcode, and is expanded only here at
@@ -1361,7 +1354,7 @@ impl MachInstEmit for Inst {
inst.emit(sink, flags, state); inst.emit(sink, flags, state);
// Emit jump table (table of 32-bit offsets). // Emit jump table (table of 32-bit offsets).
let jt_off = sink.cur_offset(); let jt_off = sink.cur_offset();
for &target in targets.iter() { for &target in info.targets.iter() {
let word_off = sink.cur_offset(); let word_off = sink.cur_offset();
let off_into_table = word_off - jt_off; let off_into_table = word_off - jt_off;
sink.use_label_at_offset( sink.use_label_at_offset(

View File

@@ -2113,11 +2113,13 @@ fn test_aarch64_binemit() {
insns.push(( insns.push((
Inst::Call { Inst::Call {
dest: Box::new(ExternalName::testcase("test0")), info: Box::new(CallInfo {
uses: Vec::new().into_boxed_slice(), dest: ExternalName::testcase("test0"),
defs: Vec::new().into_boxed_slice(), uses: Vec::new(),
loc: SourceLoc::default(), defs: Vec::new(),
opcode: Opcode::Call, loc: SourceLoc::default(),
opcode: Opcode::Call,
}),
}, },
"00000094", "00000094",
"bl 0", "bl 0",
@@ -2125,11 +2127,13 @@ fn test_aarch64_binemit() {
insns.push(( insns.push((
Inst::CallInd { Inst::CallInd {
rn: xreg(10), info: Box::new(CallIndInfo {
uses: Vec::new().into_boxed_slice(), rn: xreg(10),
defs: Vec::new().into_boxed_slice(), uses: Vec::new(),
loc: SourceLoc::default(), defs: Vec::new(),
opcode: Opcode::CallIndirect, loc: SourceLoc::default(),
opcode: Opcode::CallIndirect,
}),
}, },
"40013FD6", "40013FD6",
"blr x10", "blr x10",

View File

@@ -247,6 +247,36 @@ impl From<(Opcode, Type)> for BitOp {
} }
} }
/// Additional information for (direct) Call instructions, left out of line to lower the size of
/// the Inst enum.
#[derive(Clone, Debug)]
pub struct CallInfo {
pub dest: ExternalName,
pub uses: Vec<Reg>,
pub defs: Vec<Writable<Reg>>,
pub loc: SourceLoc,
pub opcode: Opcode,
}
/// Additional information for CallInd instructions, left out of line to lower the size of the Inst
/// enum.
#[derive(Clone, Debug)]
pub struct CallIndInfo {
pub rn: Reg,
pub uses: Vec<Reg>,
pub defs: Vec<Writable<Reg>>,
pub loc: SourceLoc,
pub opcode: Opcode,
}
/// Additional information for JTSequence instructions, left out of line to lower the size of the Inst
/// enum.
#[derive(Clone, Debug)]
pub struct JTSequenceInfo {
pub targets: Vec<BranchTarget>,
pub targets_for_term: Vec<MachLabel>, // needed for MachTerminator.
}
/// Instruction formats. /// Instruction formats.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Inst { pub enum Inst {
@@ -649,19 +679,11 @@ pub enum Inst {
/// code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit /// code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit
/// target. /// target.
Call { Call {
dest: Box<ExternalName>, info: Box<CallInfo>,
uses: Box<[Reg]>,
defs: Box<[Writable<Reg>]>,
loc: SourceLoc,
opcode: Opcode,
}, },
/// A machine indirect-call instruction. /// A machine indirect-call instruction.
CallInd { CallInd {
rn: Reg, info: Box<CallIndInfo>,
uses: Box<[Reg]>,
defs: Box<[Writable<Reg>]>,
loc: SourceLoc,
opcode: Opcode,
}, },
// ---- branches (exactly one must appear at end of BB) ---- // ---- branches (exactly one must appear at end of BB) ----
@@ -742,8 +764,7 @@ pub enum Inst {
/// Jump-table sequence, as one compound instruction (see note in lower.rs /// Jump-table sequence, as one compound instruction (see note in lower.rs
/// for rationale). /// for rationale).
JTSequence { JTSequence {
targets: Box<[BranchTarget]>, info: Box<JTSequenceInfo>,
targets_for_term: Box<[MachLabel]>, // needed for MachTerminator.
ridx: Reg, ridx: Reg,
rtmp1: Writable<Reg>, rtmp1: Writable<Reg>,
rtmp2: Writable<Reg>, rtmp2: Writable<Reg>,
@@ -758,7 +779,7 @@ pub enum Inst {
/// Load an inline symbol reference. /// Load an inline symbol reference.
LoadExtName { LoadExtName {
rd: Writable<Reg>, rd: Writable<Reg>,
name: ExternalName, name: Box<ExternalName>,
srcloc: SourceLoc, srcloc: SourceLoc,
offset: i64, offset: i64,
}, },
@@ -817,7 +838,7 @@ fn count_zero_half_words(mut value: u64) -> usize {
fn inst_size_test() { fn inst_size_test() {
// This test will help with unintentionally growing the size // This test will help with unintentionally growing the size
// of the Inst enum. // of the Inst enum.
assert_eq!(48, std::mem::size_of::<Inst>()); assert_eq!(32, std::mem::size_of::<Inst>());
} }
impl Inst { impl Inst {
@@ -1173,21 +1194,14 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
collector.add_use(rn); collector.add_use(rn);
} }
&Inst::Jump { .. } | &Inst::Ret | &Inst::EpiloguePlaceholder => {} &Inst::Jump { .. } | &Inst::Ret | &Inst::EpiloguePlaceholder => {}
&Inst::Call { &Inst::Call { ref info } => {
ref uses, ref defs, .. collector.add_uses(&*info.uses);
} => { collector.add_defs(&*info.defs);
collector.add_uses(&*uses);
collector.add_defs(&*defs);
} }
&Inst::CallInd { &Inst::CallInd { ref info } => {
ref uses, collector.add_uses(&*info.uses);
ref defs, collector.add_defs(&*info.defs);
rn, collector.add_use(info.rn);
..
} => {
collector.add_uses(&*uses);
collector.add_defs(&*defs);
collector.add_use(rn);
} }
&Inst::CondBr { ref kind, .. } | &Inst::OneWayCondBr { ref kind, .. } => match kind { &Inst::CondBr { ref kind, .. } | &Inst::OneWayCondBr { ref kind, .. } => match kind {
CondBrKind::Zero(rt) | CondBrKind::NotZero(rt) => { CondBrKind::Zero(rt) | CondBrKind::NotZero(rt) => {
@@ -1724,32 +1738,23 @@ fn aarch64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_use(mapper, rn); map_use(mapper, rn);
} }
&mut Inst::Jump { .. } => {} &mut Inst::Jump { .. } => {}
&mut Inst::Call { &mut Inst::Call { ref mut info } => {
ref mut uses, for r in info.uses.iter_mut() {
ref mut defs,
..
} => {
for r in uses.iter_mut() {
map_use(mapper, r); map_use(mapper, r);
} }
for r in defs.iter_mut() { for r in info.defs.iter_mut() {
map_def(mapper, r); map_def(mapper, r);
} }
} }
&mut Inst::Ret | &mut Inst::EpiloguePlaceholder => {} &mut Inst::Ret | &mut Inst::EpiloguePlaceholder => {}
&mut Inst::CallInd { &mut Inst::CallInd { ref mut info, .. } => {
ref mut uses, for r in info.uses.iter_mut() {
ref mut defs,
ref mut rn,
..
} => {
for r in uses.iter_mut() {
map_use(mapper, r); map_use(mapper, r);
} }
for r in defs.iter_mut() { for r in info.defs.iter_mut() {
map_def(mapper, r); map_def(mapper, r);
} }
map_use(mapper, rn); map_use(mapper, &mut info.rn);
} }
&mut Inst::CondBr { ref mut kind, .. } | &mut Inst::OneWayCondBr { ref mut kind, .. } => { &mut Inst::CondBr { ref mut kind, .. } | &mut Inst::OneWayCondBr { ref mut kind, .. } => {
map_br(mapper, kind); map_br(mapper, kind);
@@ -1833,10 +1838,9 @@ impl MachInst for Inst {
MachTerminator::None MachTerminator::None
} }
&Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]), &Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
&Inst::JTSequence { &Inst::JTSequence { ref info, .. } => {
ref targets_for_term, MachTerminator::Indirect(&info.targets_for_term[..])
.. }
} => MachTerminator::Indirect(&targets_for_term[..]),
_ => MachTerminator::None, _ => MachTerminator::None,
} }
} }
@@ -2554,9 +2558,9 @@ impl ShowWithRRU for Inst {
&Inst::Extend { .. } => { &Inst::Extend { .. } => {
panic!("Unsupported Extend case"); panic!("Unsupported Extend case");
} }
&Inst::Call { dest: _, .. } => format!("bl 0"), &Inst::Call { .. } => format!("bl 0"),
&Inst::CallInd { rn, .. } => { &Inst::CallInd { ref info, .. } => {
let rn = rn.show_rru(mb_rru); let rn = info.rn.show_rru(mb_rru);
format!("blr {}", rn) format!("blr {}", rn)
} }
&Inst::Ret => "ret".to_string(), &Inst::Ret => "ret".to_string(),
@@ -2620,7 +2624,7 @@ impl ShowWithRRU for Inst {
&Inst::Word4 { data } => format!("data.i32 {}", data), &Inst::Word4 { data } => format!("data.i32 {}", data),
&Inst::Word8 { data } => format!("data.i64 {}", data), &Inst::Word8 { data } => format!("data.i64 {}", data),
&Inst::JTSequence { &Inst::JTSequence {
ref targets, ref info,
ridx, ridx,
rtmp1, rtmp1,
rtmp2, rtmp2,
@@ -2637,7 +2641,7 @@ impl ShowWithRRU for Inst {
"br {} ; ", "br {} ; ",
"jt_entries {:?}" "jt_entries {:?}"
), ),
rtmp1, rtmp2, rtmp1, ridx, rtmp1, rtmp1, rtmp2, rtmp1, targets rtmp1, rtmp2, rtmp1, ridx, rtmp1, rtmp1, rtmp2, rtmp1, info.targets
) )
} }
&Inst::LoadConst64 { rd, const_data } => { &Inst::LoadConst64 { rd, const_data } => {

View File

@@ -14,6 +14,7 @@ use crate::isa::aarch64::inst::*;
use regalloc::RegClass; use regalloc::RegClass;
use alloc::boxed::Box;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::convert::TryFrom; use core::convert::TryFrom;
use smallvec::SmallVec; use smallvec::SmallVec;
@@ -1245,7 +1246,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let loc = ctx.srcloc(insn); let loc = ctx.srcloc(insn);
ctx.emit(Inst::LoadExtName { ctx.emit(Inst::LoadExtName {
rd, rd,
name: extname, name: Box::new(extname),
srcloc: loc, srcloc: loc,
offset: 0, offset: 0,
}); });
@@ -1262,7 +1263,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let loc = ctx.srcloc(insn); let loc = ctx.srcloc(insn);
ctx.emit(Inst::LoadExtName { ctx.emit(Inst::LoadExtName {
rd, rd,
name: extname, name: Box::new(extname),
srcloc: loc, srcloc: loc,
offset, offset,
}); });
@@ -2140,8 +2141,10 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
ridx, ridx,
rtmp1, rtmp1,
rtmp2, rtmp2,
targets: jt_targets.into_boxed_slice(), info: Box::new(JTSequenceInfo {
targets_for_term: targets_for_term.into_boxed_slice(), targets: jt_targets,
targets_for_term: targets_for_term,
}),
}); });
} }