[regalloc] Transform the program_input_abi function into a Context method;
It was implemented this way before to avoid borrow-checking issues, where self would be both mutably borrowed (because of the solver) and immutably borrowed (because of the ABI parameters list). This is worked around by adding a local AbiParams struct which contains a summary of the information that's needed by program_input_abi, allowing to retrieve the ABI params within the method's body itself.
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
|
||||
use crate::cursor::{Cursor, EncCursor};
|
||||
use crate::dominator_tree::DominatorTree;
|
||||
use crate::ir::{AbiParam, ArgumentLoc, InstBuilder, ValueDef};
|
||||
use crate::ir::{ArgumentLoc, InstBuilder, ValueDef};
|
||||
use crate::ir::{Ebb, Function, Inst, InstructionData, Layout, Opcode, SigRef, Value, ValueLoc};
|
||||
use crate::isa::{regs_overlap, RegClass, RegInfo, RegUnit};
|
||||
use crate::isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa};
|
||||
@@ -68,6 +68,12 @@ pub struct Coloring {
|
||||
solver: Solver,
|
||||
}
|
||||
|
||||
/// Kinds of ABI parameters.
|
||||
enum AbiParams {
|
||||
Parameters(SigRef),
|
||||
Returns,
|
||||
}
|
||||
|
||||
/// Bundle of references that the coloring algorithm needs.
|
||||
///
|
||||
/// Some of the needed mutable references are passed around as explicit function arguments so we
|
||||
@@ -285,6 +291,36 @@ impl<'a> Context<'a> {
|
||||
regs
|
||||
}
|
||||
|
||||
/// Program the input-side ABI constraints for `inst` into the constraint solver.
|
||||
///
|
||||
/// ABI constraints are the fixed register assignments useds for calls and returns.
|
||||
fn program_input_abi(&mut self, inst: Inst, abi_params: AbiParams) {
|
||||
let abi_types = match abi_params {
|
||||
AbiParams::Parameters(sig) => &self.cur.func.dfg.signatures[sig].params,
|
||||
AbiParams::Returns => &self.cur.func.signature.returns,
|
||||
};
|
||||
|
||||
for (abi, &value) in abi_types
|
||||
.iter()
|
||||
.zip(self.cur.func.dfg.inst_variable_args(inst))
|
||||
{
|
||||
if let ArgumentLoc::Reg(reg) = abi.location {
|
||||
if let Affinity::Reg(rci) = self
|
||||
.liveness
|
||||
.get(value)
|
||||
.expect("ABI register must have live range")
|
||||
.affinity
|
||||
{
|
||||
let rc = self.reginfo.rc(rci);
|
||||
let cur_reg = self.divert.reg(value, &self.cur.func.locations);
|
||||
self.solver.reassign_in(value, rc, cur_reg, reg);
|
||||
} else {
|
||||
panic!("ABI argument {} should be in a register", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Color the values defined by `inst` and insert any necessary shuffle code to satisfy
|
||||
/// instruction constraints.
|
||||
///
|
||||
@@ -316,25 +352,9 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
let call_sig = self.cur.func.dfg.call_signature(inst);
|
||||
if let Some(sig) = call_sig {
|
||||
program_input_abi(
|
||||
&mut self.solver,
|
||||
inst,
|
||||
&self.cur.func.dfg.signatures[sig].params,
|
||||
&self.cur.func,
|
||||
&self.liveness,
|
||||
&self.reginfo,
|
||||
&self.divert,
|
||||
);
|
||||
self.program_input_abi(inst, AbiParams::Parameters(sig));
|
||||
} else if self.cur.func.dfg[inst].opcode().is_return() {
|
||||
program_input_abi(
|
||||
&mut self.solver,
|
||||
inst,
|
||||
&self.cur.func.signature.returns,
|
||||
&self.cur.func,
|
||||
&self.liveness,
|
||||
&self.reginfo,
|
||||
&self.divert,
|
||||
);
|
||||
self.program_input_abi(inst, AbiParams::Returns);
|
||||
} else if self.cur.func.dfg[inst].opcode().is_branch() {
|
||||
// This is a branch, so we need to make sure that globally live values are in their
|
||||
// global registers. For EBBs that take arguments, we also need to place the argument
|
||||
@@ -1104,35 +1124,6 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Program the input-side ABI constraints for `inst` into the constraint solver.
|
||||
///
|
||||
/// ABI constraints are the fixed register assignments used for calls and returns.
|
||||
fn program_input_abi(
|
||||
solver: &mut Solver,
|
||||
inst: Inst,
|
||||
abi_types: &[AbiParam],
|
||||
func: &Function,
|
||||
liveness: &Liveness,
|
||||
reginfo: &RegInfo,
|
||||
divert: &RegDiversions,
|
||||
) {
|
||||
for (abi, &value) in abi_types.iter().zip(func.dfg.inst_variable_args(inst)) {
|
||||
if let ArgumentLoc::Reg(reg) = abi.location {
|
||||
if let Affinity::Reg(rci) = liveness
|
||||
.get(value)
|
||||
.expect("ABI register must have live range")
|
||||
.affinity
|
||||
{
|
||||
let rc = reginfo.rc(rci);
|
||||
let cur_reg = divert.reg(value, &func.locations);
|
||||
solver.reassign_in(value, rc, cur_reg, reg);
|
||||
} else {
|
||||
panic!("ABI argument {} should be in a register", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep track of the set of available registers in two interference domains: all registers
|
||||
/// considering diversions and global registers not considering diversions.
|
||||
struct AvailableRegs {
|
||||
|
||||
Reference in New Issue
Block a user