machinst: fix the pinned reg hack;
The pinned register hack didn't work because the GetPinnedReg is marked as having side-effects, so that GVN wouldn't try to common it out. This commit tweaks the function used during lowering to vcode, so that the GetPinnedReg opcode is specially handled. It's a bit lame, but it makes the hack work again. Also, use_input needs to be a no-op for real registers.
This commit is contained in:
@@ -41,9 +41,11 @@ pub fn has_side_effect(func: &Function, inst: Inst) -> bool {
|
|||||||
trivially_has_side_effects(opcode) || is_load_with_defined_trapping(opcode, data)
|
trivially_has_side_effects(opcode) || is_load_with_defined_trapping(opcode, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does the given instruction have any side-effect as per [has_side_effect], or else is a load?
|
/// Does the given instruction have any side-effect as per [has_side_effect], or else is a load,
|
||||||
pub fn has_side_effect_or_load(func: &Function, inst: Inst) -> bool {
|
/// but not the get_pinned_reg opcode?
|
||||||
has_side_effect(func, inst) || func.dfg[inst].opcode().can_load()
|
pub fn has_side_effect_or_load_not_get_pinned_reg(func: &Function, inst: Inst) -> bool {
|
||||||
|
let op = func.dfg[inst].opcode();
|
||||||
|
op != Opcode::GetPinnedReg && (has_side_effect(func, inst) || op.can_load())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the given instruction a constant value (`iconst`, `fconst`, `bconst`) that can be
|
/// Is the given instruction a constant value (`iconst`, `fconst`, `bconst`) that can be
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use crate::entity::SecondaryMap;
|
use crate::entity::SecondaryMap;
|
||||||
use crate::fx::{FxHashMap, FxHashSet};
|
use crate::fx::{FxHashMap, FxHashSet};
|
||||||
use crate::inst_predicates::{has_side_effect_or_load, is_constant_64bit};
|
use crate::inst_predicates::{has_side_effect_or_load_not_get_pinned_reg, is_constant_64bit};
|
||||||
use crate::ir::instructions::BranchInfo;
|
use crate::ir::instructions::BranchInfo;
|
||||||
use crate::ir::types::I64;
|
use crate::ir::types::I64;
|
||||||
use crate::ir::{
|
use crate::ir::{
|
||||||
@@ -372,7 +372,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
|||||||
for bb in f.layout.blocks() {
|
for bb in f.layout.blocks() {
|
||||||
cur_color += 1;
|
cur_color += 1;
|
||||||
for inst in f.layout.block_insts(bb) {
|
for inst in f.layout.block_insts(bb) {
|
||||||
let side_effect = has_side_effect_or_load(f, inst);
|
let side_effect = has_side_effect_or_load_not_get_pinned_reg(f, inst);
|
||||||
|
|
||||||
// Assign colors. A new color is chosen *after* any side-effecting instruction.
|
// Assign colors. A new color is chosen *after* any side-effecting instruction.
|
||||||
inst_colors[inst] = InstColor::new(cur_color);
|
inst_colors[inst] = InstColor::new(cur_color);
|
||||||
@@ -800,14 +800,14 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
|||||||
debug!(" -> src inst {}", src_inst);
|
debug!(" -> src inst {}", src_inst);
|
||||||
debug!(
|
debug!(
|
||||||
" -> has side effect: {}",
|
" -> has side effect: {}",
|
||||||
has_side_effect_or_load(self.f, src_inst)
|
has_side_effect_or_load_not_get_pinned_reg(self.f, src_inst)
|
||||||
);
|
);
|
||||||
debug!(
|
debug!(
|
||||||
" -> our color is {:?}, src inst is {:?}",
|
" -> our color is {:?}, src inst is {:?}",
|
||||||
self.inst_color(at_inst),
|
self.inst_color(at_inst),
|
||||||
self.inst_color(src_inst)
|
self.inst_color(src_inst)
|
||||||
);
|
);
|
||||||
if !has_side_effect_or_load(self.f, src_inst)
|
if !has_side_effect_or_load_not_get_pinned_reg(self.f, src_inst)
|
||||||
|| self.inst_color(at_inst) == self.inst_color(src_inst)
|
|| self.inst_color(at_inst) == self.inst_color(src_inst)
|
||||||
{
|
{
|
||||||
Some((src_inst, result_idx))
|
Some((src_inst, result_idx))
|
||||||
@@ -989,8 +989,10 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> {
|
|||||||
|
|
||||||
fn use_input_reg(&mut self, input: LowerInput) {
|
fn use_input_reg(&mut self, input: LowerInput) {
|
||||||
debug!("use_input_reg: vreg {:?} is needed", input.reg);
|
debug!("use_input_reg: vreg {:?} is needed", input.reg);
|
||||||
|
if input.reg.is_virtual() {
|
||||||
self.vreg_needed[input.reg.get_index()] = true;
|
self.vreg_needed[input.reg.get_index()] = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_reg_needed(&self, ir_inst: Inst, reg: Reg) -> bool {
|
fn is_reg_needed(&self, ir_inst: Inst, reg: Reg) -> bool {
|
||||||
self.inst_needed[ir_inst] || self.vreg_needed[reg.get_index()]
|
self.inst_needed[ir_inst] || self.vreg_needed[reg.get_index()]
|
||||||
|
|||||||
Reference in New Issue
Block a user