Remove the need for count_operands by restructuring emit in s390x (#5164)
Remove the need for count_operands by restructuring emit in the s390x backend to instead take the AllocationConsumer as an argument.
This commit is contained in:
@@ -5,7 +5,6 @@ use crate::ir::{MemFlags, RelSourceLoc, TrapCode};
|
|||||||
use crate::isa::s390x::abi::S390xMachineDeps;
|
use crate::isa::s390x::abi::S390xMachineDeps;
|
||||||
use crate::isa::s390x::inst::*;
|
use crate::isa::s390x::inst::*;
|
||||||
use crate::isa::s390x::settings as s390x_settings;
|
use crate::isa::s390x::settings as s390x_settings;
|
||||||
use crate::machinst::reg::count_operands;
|
|
||||||
use crate::machinst::{Reg, RegClass};
|
use crate::machinst::{Reg, RegClass};
|
||||||
use crate::trace;
|
use crate::trace;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
@@ -1396,7 +1395,23 @@ impl MachInstEmit for Inst {
|
|||||||
state: &mut EmitState,
|
state: &mut EmitState,
|
||||||
) {
|
) {
|
||||||
let mut allocs = AllocationConsumer::new(allocs);
|
let mut allocs = AllocationConsumer::new(allocs);
|
||||||
|
self.emit_with_alloc_consumer(&mut allocs, sink, emit_info, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pretty_print_inst(&self, allocs: &[Allocation], state: &mut EmitState) -> String {
|
||||||
|
let mut allocs = AllocationConsumer::new(allocs);
|
||||||
|
self.print_with_state(state, &mut allocs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Inst {
|
||||||
|
fn emit_with_alloc_consumer(
|
||||||
|
&self,
|
||||||
|
allocs: &mut AllocationConsumer<'_>,
|
||||||
|
sink: &mut MachBuffer<Inst>,
|
||||||
|
emit_info: &EmitInfo,
|
||||||
|
state: &mut EmitState,
|
||||||
|
) {
|
||||||
// Verify that we can emit this Inst in the current ISA
|
// Verify that we can emit this Inst in the current ISA
|
||||||
let matches_isa_flags = |iset_requirement: &InstructionSet| -> bool {
|
let matches_isa_flags = |iset_requirement: &InstructionSet| -> bool {
|
||||||
match iset_requirement {
|
match iset_requirement {
|
||||||
@@ -1541,7 +1556,7 @@ impl MachInstEmit for Inst {
|
|||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let ri = allocs.next(ri);
|
let ri = allocs.next(ri);
|
||||||
debug_assert_eq!(rd.to_reg(), ri);
|
debug_assert_eq!(rd.to_reg(), ri);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_rx, opcode_rxy) = match alu_op {
|
let (opcode_rx, opcode_rxy) = match alu_op {
|
||||||
ALUOp::Add32 => (Some(0x5a), Some(0xe35a)), // A(Y)
|
ALUOp::Add32 => (Some(0x5a), Some(0xe35a)), // A(Y)
|
||||||
@@ -1960,7 +1975,7 @@ impl MachInstEmit for Inst {
|
|||||||
}
|
}
|
||||||
&Inst::CmpRX { op, rn, ref mem } => {
|
&Inst::CmpRX { op, rn, ref mem } => {
|
||||||
let rn = allocs.next(rn);
|
let rn = allocs.next(rn);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_rx, opcode_rxy, opcode_ril) = match op {
|
let (opcode_rx, opcode_rxy, opcode_ril) = match op {
|
||||||
CmpOp::CmpS32 => (Some(0x59), Some(0xe359), Some(0xc6d)), // C(Y), CRL
|
CmpOp::CmpS32 => (Some(0x59), Some(0xe359), Some(0xc6d)), // C(Y), CRL
|
||||||
@@ -2076,7 +2091,7 @@ impl MachInstEmit for Inst {
|
|||||||
} => {
|
} => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let rn = allocs.next(rn);
|
let rn = allocs.next(rn);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode = match alu_op {
|
let opcode = match alu_op {
|
||||||
ALUOp::Add32 => 0xebf8, // LAA
|
ALUOp::Add32 => 0xebf8, // LAA
|
||||||
@@ -2115,8 +2130,6 @@ impl MachInstEmit for Inst {
|
|||||||
sink.bind_label(loop_label);
|
sink.bind_label(loop_label);
|
||||||
|
|
||||||
for inst in (&body).into_iter() {
|
for inst in (&body).into_iter() {
|
||||||
let op_count = count_operands(inst);
|
|
||||||
let sub_allocs = allocs.next_n(op_count);
|
|
||||||
match &inst {
|
match &inst {
|
||||||
// Replace a CondBreak with a branch to done_label.
|
// Replace a CondBreak with a branch to done_label.
|
||||||
&Inst::CondBreak { cond } => {
|
&Inst::CondBreak { cond } => {
|
||||||
@@ -2124,9 +2137,9 @@ impl MachInstEmit for Inst {
|
|||||||
target: done_label,
|
target: done_label,
|
||||||
cond: *cond,
|
cond: *cond,
|
||||||
};
|
};
|
||||||
inst.emit(&sub_allocs[..], sink, emit_info, state);
|
inst.emit_with_alloc_consumer(allocs, sink, emit_info, state);
|
||||||
}
|
}
|
||||||
_ => inst.emit(&sub_allocs[..], sink, emit_info, state),
|
_ => inst.emit_with_alloc_consumer(allocs, sink, emit_info, state),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2156,7 +2169,7 @@ impl MachInstEmit for Inst {
|
|||||||
let ri = allocs.next(ri);
|
let ri = allocs.next(ri);
|
||||||
debug_assert_eq!(rd.to_reg(), ri);
|
debug_assert_eq!(rd.to_reg(), ri);
|
||||||
let rn = allocs.next(rn);
|
let rn = allocs.next(rn);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_rs, opcode_rsy) = match self {
|
let (opcode_rs, opcode_rsy) = match self {
|
||||||
&Inst::AtomicCas32 { .. } => (Some(0xba), Some(0xeb14)), // CS(Y)
|
&Inst::AtomicCas32 { .. } => (Some(0xba), Some(0xeb14)), // CS(Y)
|
||||||
@@ -2189,7 +2202,7 @@ impl MachInstEmit for Inst {
|
|||||||
| &Inst::LoadRev32 { rd, ref mem }
|
| &Inst::LoadRev32 { rd, ref mem }
|
||||||
| &Inst::LoadRev64 { rd, ref mem } => {
|
| &Inst::LoadRev64 { rd, ref mem } => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
||||||
&Inst::Load32 { .. } => (Some(0x58), Some(0xe358), Some(0xc4d)), // L(Y), LRL
|
&Inst::Load32 { .. } => (Some(0x58), Some(0xe358), Some(0xc4d)), // L(Y), LRL
|
||||||
@@ -2223,7 +2236,7 @@ impl MachInstEmit for Inst {
|
|||||||
| &Inst::StoreRev32 { rd, ref mem }
|
| &Inst::StoreRev32 { rd, ref mem }
|
||||||
| &Inst::StoreRev64 { rd, ref mem } => {
|
| &Inst::StoreRev64 { rd, ref mem } => {
|
||||||
let rd = allocs.next(rd);
|
let rd = allocs.next(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
let (opcode_rx, opcode_rxy, opcode_ril) = match self {
|
||||||
&Inst::Store8 { .. } => (Some(0x42), Some(0xe372), None), // STC(Y)
|
&Inst::Store8 { .. } => (Some(0x42), Some(0xe372), None), // STC(Y)
|
||||||
@@ -2240,7 +2253,7 @@ impl MachInstEmit for Inst {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
&Inst::StoreImm8 { imm, ref mem } => {
|
&Inst::StoreImm8 { imm, ref mem } => {
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode_si = 0x92; // MVI
|
let opcode_si = 0x92; // MVI
|
||||||
let opcode_siy = 0xeb52; // MVIY
|
let opcode_siy = 0xeb52; // MVIY
|
||||||
@@ -2251,7 +2264,7 @@ impl MachInstEmit for Inst {
|
|||||||
&Inst::StoreImm16 { imm, ref mem }
|
&Inst::StoreImm16 { imm, ref mem }
|
||||||
| &Inst::StoreImm32SExt16 { imm, ref mem }
|
| &Inst::StoreImm32SExt16 { imm, ref mem }
|
||||||
| &Inst::StoreImm64SExt16 { imm, ref mem } => {
|
| &Inst::StoreImm64SExt16 { imm, ref mem } => {
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode = match self {
|
let opcode = match self {
|
||||||
&Inst::StoreImm16 { .. } => 0xe544, // MVHHI
|
&Inst::StoreImm16 { .. } => 0xe544, // MVHHI
|
||||||
@@ -2266,14 +2279,14 @@ impl MachInstEmit for Inst {
|
|||||||
ref src,
|
ref src,
|
||||||
len_minus_one,
|
len_minus_one,
|
||||||
} => {
|
} => {
|
||||||
let dst = dst.with_allocs(&mut allocs);
|
let dst = dst.with_allocs(allocs);
|
||||||
let src = src.with_allocs(&mut allocs);
|
let src = src.with_allocs(allocs);
|
||||||
let opcode = 0xd2; // MVC
|
let opcode = 0xd2; // MVC
|
||||||
mem_mem_emit(&dst, &src, len_minus_one, opcode, true, sink, state);
|
mem_mem_emit(&dst, &src, len_minus_one, opcode, true, sink, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
&Inst::LoadMultiple64 { rt, rt2, ref mem } => {
|
&Inst::LoadMultiple64 { rt, rt2, ref mem } => {
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode = 0xeb04; // LMG
|
let opcode = 0xeb04; // LMG
|
||||||
let rt = rt.to_reg();
|
let rt = rt.to_reg();
|
||||||
@@ -2291,7 +2304,7 @@ impl MachInstEmit for Inst {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
&Inst::StoreMultiple64 { rt, rt2, ref mem } => {
|
&Inst::StoreMultiple64 { rt, rt2, ref mem } => {
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode = 0xeb24; // STMG
|
let opcode = 0xeb24; // STMG
|
||||||
mem_rs_emit(
|
mem_rs_emit(
|
||||||
@@ -2309,7 +2322,7 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
&Inst::LoadAddr { rd, ref mem } => {
|
&Inst::LoadAddr { rd, ref mem } => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode_rx = Some(0x41); // LA
|
let opcode_rx = Some(0x41); // LA
|
||||||
let opcode_rxy = Some(0xe371); // LAY
|
let opcode_rxy = Some(0xe371); // LAY
|
||||||
@@ -3055,7 +3068,7 @@ impl MachInstEmit for Inst {
|
|||||||
| &Inst::VecLoadElt32Rev { rd, ref mem }
|
| &Inst::VecLoadElt32Rev { rd, ref mem }
|
||||||
| &Inst::VecLoadElt64Rev { rd, ref mem } => {
|
| &Inst::VecLoadElt64Rev { rd, ref mem } => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode, m3) = match self {
|
let (opcode, m3) = match self {
|
||||||
&Inst::VecLoad { .. } => (0xe706, 0), // VL
|
&Inst::VecLoad { .. } => (0xe706, 0), // VL
|
||||||
@@ -3079,7 +3092,7 @@ impl MachInstEmit for Inst {
|
|||||||
| &Inst::VecStoreElt32Rev { rd, ref mem }
|
| &Inst::VecStoreElt32Rev { rd, ref mem }
|
||||||
| &Inst::VecStoreElt64Rev { rd, ref mem } => {
|
| &Inst::VecStoreElt64Rev { rd, ref mem } => {
|
||||||
let rd = allocs.next(rd);
|
let rd = allocs.next(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode, m3) = match self {
|
let (opcode, m3) = match self {
|
||||||
&Inst::VecStore { .. } => (0xe70e, 0), // VST
|
&Inst::VecStore { .. } => (0xe70e, 0), // VST
|
||||||
@@ -3097,7 +3110,7 @@ impl MachInstEmit for Inst {
|
|||||||
&Inst::VecLoadReplicate { size, rd, ref mem }
|
&Inst::VecLoadReplicate { size, rd, ref mem }
|
||||||
| &Inst::VecLoadReplicateRev { size, rd, ref mem } => {
|
| &Inst::VecLoadReplicateRev { size, rd, ref mem } => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode, m3) = match (self, size) {
|
let (opcode, m3) = match (self, size) {
|
||||||
(&Inst::VecLoadReplicate { .. }, 8) => (0xe705, 0), // VLREPB
|
(&Inst::VecLoadReplicate { .. }, 8) => (0xe705, 0), // VLREPB
|
||||||
@@ -3225,7 +3238,7 @@ impl MachInstEmit for Inst {
|
|||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let ri = allocs.next(ri);
|
let ri = allocs.next(ri);
|
||||||
debug_assert_eq!(rd.to_reg(), ri);
|
debug_assert_eq!(rd.to_reg(), ri);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let opcode_vrx = match (self, size) {
|
let opcode_vrx = match (self, size) {
|
||||||
(&Inst::VecLoadLane { .. }, 8) => 0xe700, // VLEB
|
(&Inst::VecLoadLane { .. }, 8) => 0xe700, // VLEB
|
||||||
@@ -3263,7 +3276,7 @@ impl MachInstEmit for Inst {
|
|||||||
lane_imm,
|
lane_imm,
|
||||||
} => {
|
} => {
|
||||||
let rd = allocs.next_writable(rd);
|
let rd = allocs.next_writable(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
|
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
|
||||||
(&Inst::VecLoadLaneUndef { .. }, 8) => (0xe700, None, None), // VLEB
|
(&Inst::VecLoadLaneUndef { .. }, 8) => (0xe700, None, None), // VLEB
|
||||||
@@ -3307,7 +3320,7 @@ impl MachInstEmit for Inst {
|
|||||||
lane_imm,
|
lane_imm,
|
||||||
} => {
|
} => {
|
||||||
let rd = allocs.next(rd);
|
let rd = allocs.next(rd);
|
||||||
let mem = mem.with_allocs(&mut allocs);
|
let mem = mem.with_allocs(allocs);
|
||||||
|
|
||||||
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
|
let (opcode_vrx, opcode_rx, opcode_rxy) = match (self, size) {
|
||||||
(&Inst::VecStoreLane { .. }, 8) => (0xe708, None, None), // VSTEB
|
(&Inst::VecStoreLane { .. }, 8) => (0xe708, None, None), // VSTEB
|
||||||
@@ -3653,9 +3666,4 @@ impl MachInstEmit for Inst {
|
|||||||
|
|
||||||
state.clear_post_insn();
|
state.clear_post_insn();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pretty_print_inst(&self, allocs: &[Allocation], state: &mut EmitState) -> String {
|
|
||||||
let mut allocs = AllocationConsumer::new(allocs);
|
|
||||||
self.print_with_state(state, &mut allocs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@
|
|||||||
//! interface over the register allocator so that we can more easily
|
//! interface over the register allocator so that we can more easily
|
||||||
//! swap it out or shim it when necessary.
|
//! swap it out or shim it when necessary.
|
||||||
|
|
||||||
use crate::machinst::MachInst;
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use core::{fmt::Debug, hash::Hash};
|
use core::{fmt::Debug, hash::Hash};
|
||||||
use regalloc2::{Allocation, Operand, PReg, PRegSet, VReg};
|
use regalloc2::{Allocation, Operand, PReg, PRegSet, VReg};
|
||||||
use smallvec::{smallvec, SmallVec};
|
|
||||||
|
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -399,16 +397,6 @@ impl<'a, F: Fn(VReg) -> VReg> OperandCollector<'a, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use an OperandCollector to count the number of operands on an instruction.
|
|
||||||
pub fn count_operands<I: MachInst>(inst: &I) -> usize {
|
|
||||||
let mut ops = vec![];
|
|
||||||
let mut coll = OperandCollector::new(&mut ops, |vreg| vreg);
|
|
||||||
inst.get_operands(&mut coll);
|
|
||||||
let ((start, end), _) = coll.finish();
|
|
||||||
debug_assert_eq!(0, start);
|
|
||||||
end as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pretty-print part of a disassembly, with knowledge of
|
/// Pretty-print part of a disassembly, with knowledge of
|
||||||
/// operand/instruction size, and optionally with regalloc
|
/// operand/instruction size, and optionally with regalloc
|
||||||
/// results. This can be used, for example, to print either `rax` or
|
/// results. This can be used, for example, to print either `rax` or
|
||||||
@@ -470,18 +458,6 @@ impl<'a> AllocationConsumer<'a> {
|
|||||||
pub fn next_writable(&mut self, pre_regalloc_reg: Writable<Reg>) -> Writable<Reg> {
|
pub fn next_writable(&mut self, pre_regalloc_reg: Writable<Reg>) -> Writable<Reg> {
|
||||||
Writable::from_reg(self.next(pre_regalloc_reg.to_reg()))
|
Writable::from_reg(self.next(pre_regalloc_reg.to_reg()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_n(&mut self, count: usize) -> SmallVec<[Allocation; 4]> {
|
|
||||||
let mut allocs = smallvec![];
|
|
||||||
for _ in 0..count {
|
|
||||||
if let Some(next) = self.allocs.next() {
|
|
||||||
allocs.push(*next);
|
|
||||||
} else {
|
|
||||||
return allocs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allocs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::default::Default for AllocationConsumer<'a> {
|
impl<'a> std::default::Default for AllocationConsumer<'a> {
|
||||||
|
|||||||
Reference in New Issue
Block a user