Fixes #1240: Add a new accessor to indicate that an opcode requires spilling all registers;
This commit is contained in:
@@ -134,6 +134,8 @@ pub(crate) struct InstructionContent {
|
|||||||
pub other_side_effects: bool,
|
pub other_side_effects: bool,
|
||||||
/// Does this instruction write to CPU flags?
|
/// Does this instruction write to CPU flags?
|
||||||
pub writes_cpu_flags: bool,
|
pub writes_cpu_flags: bool,
|
||||||
|
/// Should this opcode be considered to clobber all live registers, during regalloc?
|
||||||
|
pub clobbers_all_regs: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionContent {
|
impl InstructionContent {
|
||||||
@@ -214,6 +216,7 @@ pub(crate) struct InstructionBuilder {
|
|||||||
can_store: bool,
|
can_store: bool,
|
||||||
can_trap: bool,
|
can_trap: bool,
|
||||||
other_side_effects: bool,
|
other_side_effects: bool,
|
||||||
|
clobbers_all_regs: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionBuilder {
|
impl InstructionBuilder {
|
||||||
@@ -236,6 +239,7 @@ impl InstructionBuilder {
|
|||||||
can_store: false,
|
can_store: false,
|
||||||
can_trap: false,
|
can_trap: false,
|
||||||
other_side_effects: false,
|
other_side_effects: false,
|
||||||
|
clobbers_all_regs: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,6 +317,11 @@ impl InstructionBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clobbers_all_regs(mut self, val: bool) -> Self {
|
||||||
|
self.clobbers_all_regs = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn build(self, opcode_number: OpcodeNumber) -> Instruction {
|
fn build(self, opcode_number: OpcodeNumber) -> Instruction {
|
||||||
let operands_in = self.operands_in.unwrap_or_else(Vec::new);
|
let operands_in = self.operands_in.unwrap_or_else(Vec::new);
|
||||||
let operands_out = self.operands_out.unwrap_or_else(Vec::new);
|
let operands_out = self.operands_out.unwrap_or_else(Vec::new);
|
||||||
@@ -369,6 +378,7 @@ impl InstructionBuilder {
|
|||||||
can_trap: self.can_trap,
|
can_trap: self.can_trap,
|
||||||
other_side_effects: self.other_side_effects,
|
other_side_effects: self.other_side_effects,
|
||||||
writes_cpu_flags,
|
writes_cpu_flags,
|
||||||
|
clobbers_all_regs: self.clobbers_all_regs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -523,6 +523,13 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
|||||||
"Does this instruction write to CPU flags?",
|
"Does this instruction write to CPU flags?",
|
||||||
fmt,
|
fmt,
|
||||||
);
|
);
|
||||||
|
gen_bool_accessor(
|
||||||
|
all_inst,
|
||||||
|
|inst| inst.clobbers_all_regs,
|
||||||
|
"clobbers_all_regs",
|
||||||
|
"Should this opcode be considered to clobber all the registers, during regalloc?",
|
||||||
|
fmt,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
fmt.line("}");
|
fmt.line("}");
|
||||||
fmt.empty_line();
|
fmt.empty_line();
|
||||||
|
|||||||
@@ -562,6 +562,10 @@ pub(crate) fn define(
|
|||||||
"#,
|
"#,
|
||||||
&formats.unary_global_value,
|
&formats.unary_global_value,
|
||||||
)
|
)
|
||||||
|
// This is a bit overly broad to mark as clobbering *all* the registers, because it should
|
||||||
|
// only preserve caller-saved registers. There's no way to indicate this to register
|
||||||
|
// allocation yet, though, so mark as clobbering all registers instead.
|
||||||
|
.clobbers_all_regs(true)
|
||||||
.operands_in(vec![GV])
|
.operands_in(vec![GV])
|
||||||
.operands_out(vec![addr]),
|
.operands_out(vec![addr]),
|
||||||
);
|
);
|
||||||
@@ -574,6 +578,8 @@ pub(crate) fn define(
|
|||||||
"#,
|
"#,
|
||||||
&formats.unary_global_value,
|
&formats.unary_global_value,
|
||||||
)
|
)
|
||||||
|
// See above comment for x86_elf_tls_get_addr.
|
||||||
|
.clobbers_all_regs(true)
|
||||||
.operands_in(vec![GV])
|
.operands_in(vec![GV])
|
||||||
.operands_out(vec![addr]),
|
.operands_out(vec![addr]),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -268,10 +268,7 @@ impl<'a> Context<'a> {
|
|||||||
// This means that we don't currently take advantage of callee-saved registers.
|
// This means that we don't currently take advantage of callee-saved registers.
|
||||||
// TODO: Be more sophisticated.
|
// TODO: Be more sophisticated.
|
||||||
let opcode = self.cur.func.dfg[inst].opcode();
|
let opcode = self.cur.func.dfg[inst].opcode();
|
||||||
if call_sig.is_some()
|
if call_sig.is_some() || opcode.clobbers_all_regs() {
|
||||||
|| opcode == crate::ir::Opcode::X86ElfTlsGetAddr
|
|
||||||
|| opcode == crate::ir::Opcode::X86MachoTlsGetAddr
|
|
||||||
{
|
|
||||||
for lv in throughs {
|
for lv in throughs {
|
||||||
if lv.affinity.is_reg() && !self.spills.contains(&lv.value) {
|
if lv.affinity.is_reg() && !self.spills.contains(&lv.value) {
|
||||||
self.spill_reg(lv.value);
|
self.spill_reg(lv.value);
|
||||||
|
|||||||
Reference in New Issue
Block a user