Skip to content
This repository was archived by the owner on Oct 4, 2022. It is now read-only.

Add orig_insn_map: mapping from original to new insn indices. #50

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions lib/src/backtracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl SpillSlotAllocator {
self.slots.push(LogicalSpillSlot::Unavail);
}
// And now the new slot.
let dflt = RangeFragIx::new(0xFFFF_FFFF); // value is unimportant
let dflt = RangeFragIx::invalid_value();
let tree = AVLTree::<RangeFragIx>::new(dflt);
let res = self.slots.len() as u32;
self.slots.push(LogicalSpillSlot::InUse {
Expand Down Expand Up @@ -1108,12 +1108,11 @@ fn cmp_tree_entries_for_CommitmentMapFAST(
impl CommitmentMapFAST {
pub fn new() -> Self {
// The AVL tree constructor needs a default value for the elements. It
// will never be used. To be on the safe side, give it something that
// will show as obviously bogus if we ever try to "dereference" any part
// of it.
// will never be used. The not-present index value will show as
// obviously bogus if we ever try to "dereference" any part of it.
let dflt = FIxAndVLRIx::new(
RangeFragIx::new(0xFFFF_FFFF),
Some(VirtualRangeIx::new(0xFFFF_FFFF)),
RangeFragIx::invalid_value(),
Some(VirtualRangeIx::invalid_value()),
);
Self {
tree: AVLTree::<FIxAndVLRIx>::new(dflt),
Expand Down Expand Up @@ -1740,7 +1739,7 @@ fn frags_are_mergeable(frag1: &RangeFrag, frag2: &RangeFrag) -> bool {
false
}

const Z_INVALID_BLOCKIX: BlockIx = BlockIx::BlockIx(0xFFFF_FFFF);
const Z_INVALID_BLOCKIX: BlockIx = BlockIx::invalid_value();
const Z_INVALID_COUNT: u16 = 0xFFFF;

// Try and compress the fragments for each virtual range in `vlr_env`, adding
Expand Down Expand Up @@ -2803,7 +2802,7 @@ pub fn alloc_main<F: Function>(
// ======== BEGIN Create the RegAllocResult ========

match final_insns_and_targetmap__or_err {
Ok((ref final_insns, ref _targetmap)) => {
Ok((ref final_insns, ..)) => {
info!(
"alloc_main: out: VLRs: {} initially, {} processed",
num_vlrs_initial, num_vlrs_processed
Expand All @@ -2829,7 +2828,7 @@ pub fn alloc_main<F: Function>(
}
}

let (final_insns, target_map) = match final_insns_and_targetmap__or_err {
let (final_insns, target_map, orig_insn_map) = match final_insns_and_targetmap__or_err {
Err(e) => {
info!("alloc_main: fail");
return Err(e);
Expand Down Expand Up @@ -2891,6 +2890,7 @@ pub fn alloc_main<F: Function>(
let ra_res = RegAllocResult {
insns: final_insns,
target_map,
orig_insn_map,
clobbered_registers,
num_spill_slots: spill_slot_allocator.slots.len() as u32,
block_annotations,
Expand Down
35 changes: 31 additions & 4 deletions lib/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,61 +435,88 @@ macro_rules! generate_boilerplate {
#[allow(dead_code)]
#[inline(always)]
pub fn new(n: u32) -> Self {
debug_assert!(n != u32::max_value());
Self::$TypeIx(n)
}
#[allow(dead_code)]
#[inline(always)]
pub fn max_value() -> Self {
Self::$TypeIx(u32::max_value())
pub const fn max_value() -> Self {
Self::$TypeIx(u32::max_value() - 1)
}
#[allow(dead_code)]
#[inline(always)]
pub fn min_value() -> Self {
pub const fn min_value() -> Self {
Self::$TypeIx(u32::min_value())
}
#[allow(dead_code)]
#[inline(always)]
pub const fn invalid_value() -> Self {
Self::$TypeIx(u32::max_value())
}
#[allow(dead_code)]
#[inline(always)]
pub fn is_valid(self) -> bool {
self != Self::invalid_value()
}
#[allow(dead_code)]
#[inline(always)]
pub fn is_invalid(self) -> bool {
self == Self::invalid_value()
}
#[allow(dead_code)]
#[inline(always)]
pub fn get(self) -> u32 {
debug_assert!(self.is_valid());
match self {
$TypeIx::$TypeIx(n) => n,
}
}
#[allow(dead_code)]
#[inline(always)]
pub fn plus(self, delta: u32) -> $TypeIx {
debug_assert!(self.is_valid());
$TypeIx::$TypeIx(self.get() + delta)
}
#[allow(dead_code)]
#[inline(always)]
pub fn minus(self, delta: u32) -> $TypeIx {
debug_assert!(self.is_valid());
$TypeIx::$TypeIx(self.get() - delta)
}
#[allow(dead_code)]
pub fn dotdot(&self, last_plus1: $TypeIx) -> Range<$TypeIx> {
debug_assert!(self.is_valid());
let len = (last_plus1.get() - self.get()) as usize;
Range::new(*self, len)
}
}
impl fmt::Debug for $TypeIx {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}{}", $PrintingPrefix, &self.get())
if self.is_invalid() {
write!(fmt, "{}<NONE>", $PrintingPrefix)
} else {
write!(fmt, "{}{}", $PrintingPrefix, &self.get())
}
}
}
impl PlusOne for $TypeIx {
#[inline(always)]
fn plus_one(&self) -> Self {
debug_assert!(self.is_valid());
self.plus(1)
}
}
impl PlusN for $TypeIx {
#[inline(always)]
fn plus_n(&self, n: usize) -> Self {
debug_assert!(self.is_valid());
self.plus(n as u32)
}
}
impl Into<u32> for $TypeIx {
#[inline(always)]
fn into(self) -> u32 {
debug_assert!(self.is_valid());
self.get()
}
}
Expand Down
26 changes: 23 additions & 3 deletions lib/src/inst_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,14 @@ fn map_vregs_to_rregs<F: Function>(
fn add_spills_reloads_and_moves<F: Function>(
func: &mut F,
mut insts_to_add: Vec<InstToInsertAndPoint>,
) -> Result<(Vec<F::Inst>, TypedIxVec<BlockIx, InstIx>), String> {
) -> Result<
(
Vec<F::Inst>,
TypedIxVec<BlockIx, InstIx>,
TypedIxVec<InstIx, InstIx>,
),
String,
> {
// Construct the final code by interleaving the mapped code with the the
// spills, reloads and moves that we have been requested to insert. To do
// that requires having the latter sorted by InstPoint.
Expand All @@ -447,6 +454,9 @@ fn add_spills_reloads_and_moves<F: Function>(

let mut insns: Vec<F::Inst> = vec![];
let mut target_map: TypedIxVec<BlockIx, InstIx> = TypedIxVec::new();
let mut orig_insn_map: TypedIxVec<InstIx, InstIx> = TypedIxVec::new();
target_map.reserve(func.blocks().len());
orig_insn_map.reserve(func.insn_indices().len() + insts_to_add.len());

for iix in func.insn_indices() {
// Is `iix` the first instruction in a block? Meaning, are we
Expand All @@ -463,15 +473,18 @@ fn add_spills_reloads_and_moves<F: Function>(
&& insts_to_add[curITA].point == InstPoint::new_reload(iix)
{
insns.push(insts_to_add[curITA].inst.construct(func));
orig_insn_map.push(InstIx::invalid_value());
curITA += 1;
}
// Copy the inst at `iix` itself
orig_insn_map.push(iix);
insns.push(func.get_insn(iix).clone());
// And copy the extra insts that are to be placed at the spill point of
// `iix`.
while curITA < insts_to_add.len() && insts_to_add[curITA].point == InstPoint::new_spill(iix)
{
insns.push(insts_to_add[curITA].inst.construct(func));
orig_insn_map.push(InstIx::invalid_value());
curITA += 1;
}

Expand All @@ -485,7 +498,7 @@ fn add_spills_reloads_and_moves<F: Function>(
debug_assert!(curITA == insts_to_add.len());
debug_assert!(curB.get() == func.blocks().len() as u32);

Ok((insns, target_map))
Ok((insns, target_map, orig_insn_map))
}

//=============================================================================
Expand All @@ -501,7 +514,14 @@ pub(crate) fn edit_inst_stream<F: Function>(
reg_universe: &RealRegUniverse,
has_multiple_blocks_per_frag: bool,
use_checker: bool,
) -> Result<(Vec<F::Inst>, TypedIxVec<BlockIx, InstIx>), RegAllocError> {
) -> Result<
(
Vec<F::Inst>,
TypedIxVec<BlockIx, InstIx>,
TypedIxVec<InstIx, InstIx>,
),
RegAllocError,
> {
map_vregs_to_rregs(
func,
frag_map,
Expand Down
10 changes: 10 additions & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ pub struct RegAllocResult<F: Function> {
/// branch targets appropriately.
pub target_map: TypedIxVec<BlockIx, InstIx>,

/// Full mapping from new instruction indices to original instruction
/// indices. May be needed by the client to, for example, update metadata
/// such as debug/source-location info as the instructions are spliced
/// and reordered.
///
/// Each entry is an `InstIx`, but may be `InstIx::invalid_value()` if the
/// new instruction at this new index was inserted by the allocator
/// (i.e., if it is a load, spill or move instruction).
pub orig_insn_map: TypedIxVec</* new */ InstIx, /* orig */ InstIx>,

/// Which real registers were overwritten? This will contain all real regs
/// that appear as defs or modifies in register slots of the output
/// instruction list. This will only list registers that are available to
Expand Down
3 changes: 2 additions & 1 deletion lib/src/linear_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3251,7 +3251,7 @@ fn apply_registers<F: Function>(
use_checker,
);

let (final_insns, target_map) = match final_insns_and_targetmap_or_err {
let (final_insns, target_map, orig_insn_map) = match final_insns_and_targetmap_or_err {
Err(e) => return Err(e),
Ok(pair) => pair,
};
Expand Down Expand Up @@ -3295,6 +3295,7 @@ fn apply_registers<F: Function>(
let ra_res = RegAllocResult {
insns: final_insns,
target_map,
orig_insn_map,
clobbered_registers,
num_spill_slots,
block_annotations: None,
Expand Down