|
|
@ -20,7 +20,7 @@ use crate::machinst::{ |
|
|
|
LoweredBlock, MachLabel, Reg, VCode, VCodeBuilder, VCodeConstant, VCodeConstantData, |
|
|
|
VCodeConstants, VCodeInst, ValueRegs, Writable, |
|
|
|
}; |
|
|
|
use crate::CodegenResult; |
|
|
|
use crate::{trace, CodegenResult}; |
|
|
|
use alloc::boxed::Box; |
|
|
|
use alloc::vec::Vec; |
|
|
|
use core::convert::TryInto; |
|
|
@ -506,7 +506,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
if value_regs[param].is_invalid() { |
|
|
|
let regs = alloc_vregs(ty, &mut next_vreg, &mut vcode)?; |
|
|
|
value_regs[param] = regs; |
|
|
|
log::trace!("bb {} param {}: regs {:?}", bb, param, regs); |
|
|
|
trace!("bb {} param {}: regs {:?}", bb, param, regs); |
|
|
|
} |
|
|
|
} |
|
|
|
for inst in f.layout.block_insts(bb) { |
|
|
@ -515,7 +515,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
if value_regs[result].is_invalid() { |
|
|
|
let regs = alloc_vregs(ty, &mut next_vreg, &mut vcode)?; |
|
|
|
value_regs[result] = regs; |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"bb {} inst {} ({:?}): result {} regs {:?}", |
|
|
|
bb, |
|
|
|
inst, |
|
|
@ -543,7 +543,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
for ret in &vcode.abi().signature().returns.clone() { |
|
|
|
let regs = alloc_vregs(ret.value_type, &mut next_vreg, &mut vcode)?; |
|
|
|
retval_regs.push(regs); |
|
|
|
log::trace!("retval gets regs {:?}", regs); |
|
|
|
trace!("retval gets regs {:?}", regs); |
|
|
|
} |
|
|
|
|
|
|
|
// Compute instruction colors, find constant instructions, and find instructions with
|
|
|
@ -557,16 +557,16 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
for inst in f.layout.block_insts(bb) { |
|
|
|
let side_effect = has_lowering_side_effect(f, inst); |
|
|
|
|
|
|
|
log::trace!("bb {} inst {} has color {}", bb, inst, cur_color); |
|
|
|
trace!("bb {} inst {} has color {}", bb, inst, cur_color); |
|
|
|
if side_effect { |
|
|
|
side_effect_inst_entry_colors.insert(inst, InstColor::new(cur_color)); |
|
|
|
log::trace!(" -> side-effecting; incrementing color for next inst"); |
|
|
|
trace!(" -> side-effecting; incrementing color for next inst"); |
|
|
|
cur_color += 1; |
|
|
|
} |
|
|
|
|
|
|
|
// Determine if this is a constant; if so, add to the table.
|
|
|
|
if let Some(c) = is_constant_64bit(f, inst) { |
|
|
|
log::trace!(" -> constant: {}", c); |
|
|
|
trace!(" -> constant: {}", c); |
|
|
|
inst_constants.insert(inst, c); |
|
|
|
} |
|
|
|
} |
|
|
@ -627,7 +627,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
|
|
|
|
// Push args for a given inst onto the DFS stack.
|
|
|
|
let push_args_on_stack = |stack: &mut StackVec<'a>, value| { |
|
|
|
log::trace!(" -> pushing args for {} onto stack", value); |
|
|
|
trace!(" -> pushing args for {} onto stack", value); |
|
|
|
if let ValueDef::Result(src_inst, _) = f.dfg.value_def(value) { |
|
|
|
stack.push(f.dfg.inst_args(src_inst).iter()); |
|
|
|
} |
|
|
@ -640,7 +640,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
while let Some(iter) = stack.last_mut() { |
|
|
|
if let Some(&value) = iter.next() { |
|
|
|
let value = f.dfg.resolve_aliases(value); |
|
|
|
log::trace!(" -> DFS reaches {}", value); |
|
|
|
trace!(" -> DFS reaches {}", value); |
|
|
|
if value_ir_uses[value] == ValueUseState::Multiple { |
|
|
|
// Truncate DFS here: no need to go further,
|
|
|
|
// as whole subtree must already be Multiple.
|
|
|
@ -658,7 +658,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
continue; |
|
|
|
} |
|
|
|
value_ir_uses[value] = ValueUseState::Multiple; |
|
|
|
log::trace!(" -> became Multiple"); |
|
|
|
trace!(" -> became Multiple"); |
|
|
|
push_args_on_stack(stack, value); |
|
|
|
} else { |
|
|
|
// Empty iterator, discard.
|
|
|
@ -683,7 +683,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
let arg = f.dfg.resolve_aliases(arg); |
|
|
|
let old = value_ir_uses[arg]; |
|
|
|
if force_multiple { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"forcing arg {} to Multiple because of multiple results of user inst", |
|
|
|
arg |
|
|
|
); |
|
|
@ -692,7 +692,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
value_ir_uses[arg].inc(); |
|
|
|
} |
|
|
|
let new = value_ir_uses[arg]; |
|
|
|
log::trace!("arg {} used, old state {:?}, new {:?}", arg, old, new,); |
|
|
|
trace!("arg {} used, old state {:?}, new {:?}", arg, old, new,); |
|
|
|
// On transition to Multiple, do DFS.
|
|
|
|
if old != ValueUseState::Multiple && new == ValueUseState::Multiple { |
|
|
|
push_args_on_stack(&mut stack, arg); |
|
|
@ -706,7 +706,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
|
|
|
|
fn gen_arg_setup(&mut self) { |
|
|
|
if let Some(entry_bb) = self.f.layout.entry_block() { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"gen_arg_setup: entry BB {} args are:\n{:?}", |
|
|
|
entry_bb, |
|
|
|
self.f.dfg.block_params(entry_bb) |
|
|
@ -830,7 +830,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
} |
|
|
|
// Are any outputs used at least once?
|
|
|
|
let value_needed = self.is_any_inst_result_needed(inst); |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"lower_clif_block: block {} inst {} ({:?}) is_branch {} side_effect {} value_needed {}", |
|
|
|
block, |
|
|
|
inst, |
|
|
@ -860,7 +860,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
// Normal instruction: codegen if the instruction is side-effecting
|
|
|
|
// or any of its outputs its used.
|
|
|
|
if has_side_effect || value_needed { |
|
|
|
log::trace!("lowering: inst {}: {:?}", inst, self.f.dfg[inst]); |
|
|
|
trace!("lowering: inst {}: {:?}", inst, self.f.dfg[inst]); |
|
|
|
backend.lower(self, inst)?; |
|
|
|
} |
|
|
|
if data.opcode().is_return() { |
|
|
@ -905,7 +905,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
|
|
|
|
fn get_value_labels<'a>(&'a self, val: Value, depth: usize) -> Option<&'a [ValueLabelStart]> { |
|
|
|
if let Some(ref values_labels) = self.f.dfg.values_labels { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"get_value_labels: val {} -> {} -> {:?}", |
|
|
|
val, |
|
|
|
self.f.dfg.resolve_aliases(val), |
|
|
@ -937,7 +937,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
.map(|&ValueLabelStart { label, .. }| label) |
|
|
|
.collect::<FxHashSet<_>>(); |
|
|
|
for label in labels { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"value labeling: defines val {:?} -> reg {:?} -> label {:?}", |
|
|
|
val, |
|
|
|
reg, |
|
|
@ -953,7 +953,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"value labeling: srcloc {}: inst {}", |
|
|
|
self.srcloc(inst), |
|
|
|
inst |
|
|
@ -968,7 +968,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
log::trace!("value labeling: block {}", block); |
|
|
|
trace!("value labeling: block {}", block); |
|
|
|
for &arg in self.f.dfg.block_params(block) { |
|
|
|
self.emit_value_label_marks_for_value(arg); |
|
|
|
} |
|
|
@ -999,7 +999,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
branches: &SmallVec<[Inst; 2]>, |
|
|
|
targets: &SmallVec<[MachLabel; 2]>, |
|
|
|
) -> CodegenResult<()> { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"lower_clif_branches: block {} branches {:?} targets {:?}", |
|
|
|
block, |
|
|
|
branches, |
|
|
@ -1061,7 +1061,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
|
|
|
|
/// Lower the function.
|
|
|
|
pub fn lower<B: LowerBackend<MInst = I>>(mut self, backend: &B) -> CodegenResult<VCode<I>> { |
|
|
|
log::trace!("about to lower function: {:?}", self.f); |
|
|
|
trace!("about to lower function: {:?}", self.f); |
|
|
|
|
|
|
|
// Initialize the ABI object, giving it a temp if requested.
|
|
|
|
let maybe_tmp = if let Some(temp_ty) = self.vcode.abi().temp_needed() { |
|
|
@ -1152,7 +1152,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { |
|
|
|
// Now that we've emitted all instructions into the
|
|
|
|
// VCodeBuilder, let's build the VCode.
|
|
|
|
let vcode = self.vcode.build(); |
|
|
|
log::trace!("built vcode: {:?}", vcode); |
|
|
|
trace!("built vcode: {:?}", vcode); |
|
|
|
|
|
|
|
Ok(vcode) |
|
|
|
} |
|
|
@ -1287,7 +1287,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
} |
|
|
|
|
|
|
|
fn get_value_as_source_or_const(&self, val: Value) -> NonRegInput { |
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
"get_input_for_val: val {} at cur_inst {:?} cur_scan_entry_color {:?}", |
|
|
|
val, |
|
|
|
self.cur_inst, |
|
|
@ -1317,8 +1317,8 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
// prior to the sunk instruction) to sink.
|
|
|
|
ValueDef::Result(src_inst, result_idx) => { |
|
|
|
let src_side_effect = has_lowering_side_effect(self.f, src_inst); |
|
|
|
log::trace!(" -> src inst {}", src_inst); |
|
|
|
log::trace!(" -> has lowering side effect: {}", src_side_effect); |
|
|
|
trace!(" -> src inst {}", src_inst); |
|
|
|
trace!(" -> has lowering side effect: {}", src_side_effect); |
|
|
|
if !src_side_effect { |
|
|
|
// Pure instruction: always possible to
|
|
|
|
// sink. Let's determine whether we are the only
|
|
|
@ -1332,7 +1332,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
// Side-effect: test whether this is the only use of the
|
|
|
|
// only result of the instruction, and whether colors allow
|
|
|
|
// the code-motion.
|
|
|
|
log::trace!( |
|
|
|
trace!( |
|
|
|
" -> side-effecting op {} for val {}: use state {:?}", |
|
|
|
src_inst, |
|
|
|
val, |
|
|
@ -1369,7 +1369,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
|
|
|
|
fn put_value_in_regs(&mut self, val: Value) -> ValueRegs<Reg> { |
|
|
|
let val = self.f.dfg.resolve_aliases(val); |
|
|
|
log::trace!("put_value_in_regs: val {}", val); |
|
|
|
trace!("put_value_in_regs: val {}", val); |
|
|
|
|
|
|
|
// Assert that the value is not `iflags`/`fflags`-typed; these
|
|
|
|
// cannot be reified into normal registers. TODO(#3249)
|
|
|
@ -1387,7 +1387,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
.and_then(|inst| self.get_constant(inst)) |
|
|
|
{ |
|
|
|
let regs = self.alloc_tmp(ty); |
|
|
|
log::trace!(" -> regs {:?}", regs); |
|
|
|
trace!(" -> regs {:?}", regs); |
|
|
|
assert!(regs.is_valid()); |
|
|
|
|
|
|
|
let insts = I::gen_constant(regs, c.into(), ty, |ty| { |
|
|
@ -1400,7 +1400,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
} |
|
|
|
|
|
|
|
let mut regs = self.value_regs[val]; |
|
|
|
log::trace!(" -> regs {:?}", regs); |
|
|
|
trace!(" -> regs {:?}", regs); |
|
|
|
assert!(regs.is_valid()); |
|
|
|
|
|
|
|
self.value_lowered_uses[val] += 1; |
|
|
@ -1431,7 +1431,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
} |
|
|
|
|
|
|
|
fn emit(&mut self, mach_inst: I) { |
|
|
|
log::trace!("emit: {:?}", mach_inst); |
|
|
|
trace!("emit: {:?}", mach_inst); |
|
|
|
self.ir_insts.push(mach_inst); |
|
|
|
} |
|
|
|
|
|
|
@ -1492,7 +1492,7 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> { |
|
|
|
} |
|
|
|
|
|
|
|
fn set_vreg_alias(&mut self, from: Reg, to: Reg) { |
|
|
|
log::trace!("set vreg alias: from {:?} to {:?}", from, to); |
|
|
|
trace!("set vreg alias: from {:?} to {:?}", from, to); |
|
|
|
self.vcode.set_vreg_alias(from, to); |
|
|
|
} |
|
|
|
} |
|
|
|