Some structure packing: Use now fits in three u32s.
This commit is contained in:
115
src/ion/mod.rs
115
src/ion/mod.rs
@@ -164,8 +164,37 @@ impl LiveRange {
|
|||||||
struct Use {
|
struct Use {
|
||||||
operand: Operand,
|
operand: Operand,
|
||||||
pos: ProgPoint,
|
pos: ProgPoint,
|
||||||
next_use: UseIndex,
|
next_use_and_slot: u32,
|
||||||
slot: u8,
|
}
|
||||||
|
|
||||||
|
impl Use {
|
||||||
|
#[inline(always)]
|
||||||
|
fn new(operand: Operand, pos: ProgPoint, next_use: UseIndex, slot: u8) -> Self {
|
||||||
|
debug_assert!(next_use.is_invalid() || next_use.index() < ((1 << 24) - 1));
|
||||||
|
let next_use = next_use.0 & 0x00ff_ffff;
|
||||||
|
Self {
|
||||||
|
operand,
|
||||||
|
pos,
|
||||||
|
next_use_and_slot: next_use | ((slot as u32) << 24),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn next_use(&self) -> UseIndex {
|
||||||
|
let val = self.next_use_and_slot & 0x00ff_ffff;
|
||||||
|
// Sign-extend 0x00ff_ffff to INVALID (0xffff_ffff).
|
||||||
|
let val = ((val as i32) << 8) >> 8;
|
||||||
|
UseIndex(val as u32)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn slot(&self) -> u8 {
|
||||||
|
(self.next_use_and_slot >> 24) as u8
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn set_next_use(&mut self, u: UseIndex) {
|
||||||
|
debug_assert!(u.is_invalid() || u.index() < ((1 << 24) - 1));
|
||||||
|
let u = u.0 & 0x00ff_ffff;
|
||||||
|
self.next_use_and_slot = (self.next_use_and_slot & 0xff00_0000) | u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SLOT_NONE: u8 = u8::MAX;
|
const SLOT_NONE: u8 = u8::MAX;
|
||||||
@@ -968,9 +997,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// If this use is within the range of `into`, move it over.
|
// If this use is within the range of `into`, move it over.
|
||||||
if into_range.contains_point(usedata.pos) {
|
if into_range.contains_point(usedata.pos) {
|
||||||
log::debug!(" -> moving {:?}", iter);
|
log::debug!(" -> moving {:?}", iter);
|
||||||
let next = usedata.next_use;
|
let next = usedata.next_use();
|
||||||
if prev.is_valid() {
|
if prev.is_valid() {
|
||||||
self.uses[prev.index()].next_use = next;
|
self.uses[prev.index()].set_next_use(next);
|
||||||
} else {
|
} else {
|
||||||
self.ranges[from.index()].first_use = next;
|
self.ranges[from.index()].first_use = next;
|
||||||
}
|
}
|
||||||
@@ -986,7 +1015,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
iter = next;
|
iter = next;
|
||||||
} else {
|
} else {
|
||||||
prev = iter;
|
prev = iter;
|
||||||
iter = usedata.next_use;
|
iter = usedata.next_use();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ranges[from.index()].merged_into = into;
|
self.ranges[from.index()].merged_into = into;
|
||||||
@@ -1013,7 +1042,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
fn insert_use_into_liverange_and_update_stats(&mut self, into: LiveRangeIndex, u: UseIndex) {
|
fn insert_use_into_liverange_and_update_stats(&mut self, into: LiveRangeIndex, u: UseIndex) {
|
||||||
let insert_pos = self.uses[u.index()].pos;
|
let insert_pos = self.uses[u.index()].pos;
|
||||||
let first = self.ranges[into.index()].first_use;
|
let first = self.ranges[into.index()].first_use;
|
||||||
self.uses[u.index()].next_use = UseIndex::invalid();
|
self.uses[u.index()].set_next_use(UseIndex::invalid());
|
||||||
if first.is_invalid() {
|
if first.is_invalid() {
|
||||||
// Empty list.
|
// Empty list.
|
||||||
self.ranges[into.index()].first_use = u;
|
self.ranges[into.index()].first_use = u;
|
||||||
@@ -1021,7 +1050,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
} else if insert_pos > self.uses[self.ranges[into.index()].last_use.index()].pos {
|
} else if insert_pos > self.uses[self.ranges[into.index()].last_use.index()].pos {
|
||||||
// After tail.
|
// After tail.
|
||||||
let tail = self.ranges[into.index()].last_use;
|
let tail = self.ranges[into.index()].last_use;
|
||||||
self.uses[tail.index()].next_use = u;
|
self.uses[tail.index()].set_next_use(u);
|
||||||
self.ranges[into.index()].last_use = u;
|
self.ranges[into.index()].last_use = u;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, scan linearly to find insertion position.
|
// Otherwise, scan linearly to find insertion position.
|
||||||
@@ -1032,11 +1061,11 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev = iter;
|
prev = iter;
|
||||||
iter = self.uses[iter.index()].next_use;
|
iter = self.uses[iter.index()].next_use();
|
||||||
}
|
}
|
||||||
self.uses[u.index()].next_use = iter;
|
self.uses[u.index()].set_next_use(iter);
|
||||||
if prev.is_valid() {
|
if prev.is_valid() {
|
||||||
self.uses[prev.index()].next_use = u;
|
self.uses[prev.index()].set_next_use(u);
|
||||||
} else {
|
} else {
|
||||||
self.ranges[into.index()].first_use = u;
|
self.ranges[into.index()].first_use = u;
|
||||||
}
|
}
|
||||||
@@ -1333,12 +1362,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
OperandPos::After => ProgPoint::after(inst),
|
OperandPos::After => ProgPoint::after(inst),
|
||||||
};
|
};
|
||||||
let u = UseIndex(self.uses.len() as u32);
|
let u = UseIndex(self.uses.len() as u32);
|
||||||
self.uses.push(Use {
|
self.uses
|
||||||
operand,
|
.push(Use::new(operand, pos, UseIndex::invalid(), i as u8));
|
||||||
pos,
|
|
||||||
slot: i as u8,
|
|
||||||
next_use: UseIndex::invalid(),
|
|
||||||
});
|
|
||||||
|
|
||||||
log::debug!("Def of {} at {:?}", operand.vreg(), pos);
|
log::debug!("Def of {} at {:?}", operand.vreg(), pos);
|
||||||
|
|
||||||
@@ -1399,12 +1424,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
// Create the actual use object.
|
// Create the actual use object.
|
||||||
let u = UseIndex(self.uses.len() as u32);
|
let u = UseIndex(self.uses.len() as u32);
|
||||||
self.uses.push(Use {
|
self.uses
|
||||||
operand,
|
.push(Use::new(operand, pos, UseIndex::invalid(), i as u8));
|
||||||
pos,
|
|
||||||
slot: i as u8,
|
|
||||||
next_use: UseIndex::invalid(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create/extend the LiveRange and add the use to the range.
|
// Create/extend the LiveRange and add the use to the range.
|
||||||
let range = CodeRange {
|
let range = CodeRange {
|
||||||
@@ -1493,12 +1514,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
|
|
||||||
// Create the actual use object.
|
// Create the actual use object.
|
||||||
let u = UseIndex(self.uses.len() as u32);
|
let u = UseIndex(self.uses.len() as u32);
|
||||||
self.uses.push(Use {
|
self.uses
|
||||||
operand,
|
.push(Use::new(operand, pos, UseIndex::invalid(), SLOT_NONE));
|
||||||
pos,
|
|
||||||
slot: SLOT_NONE,
|
|
||||||
next_use: UseIndex::invalid(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create/extend the LiveRange and add the use to the range.
|
// Create/extend the LiveRange and add the use to the range.
|
||||||
let range = CodeRange {
|
let range = CodeRange {
|
||||||
@@ -1604,14 +1621,14 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let mut use_iter = self.ranges[iter.index()].first_use;
|
let mut use_iter = self.ranges[iter.index()].first_use;
|
||||||
while use_iter.is_valid() {
|
while use_iter.is_valid() {
|
||||||
let pos = self.uses[use_iter.index()].pos;
|
let pos = self.uses[use_iter.index()].pos;
|
||||||
let slot = self.uses[use_iter.index()].slot as usize;
|
let slot = self.uses[use_iter.index()].slot() as usize;
|
||||||
fixup_multi_fixed_vregs(
|
fixup_multi_fixed_vregs(
|
||||||
pos,
|
pos,
|
||||||
slot,
|
slot,
|
||||||
&mut self.uses[use_iter.index()].operand,
|
&mut self.uses[use_iter.index()].operand,
|
||||||
&mut self.multi_fixed_reg_fixups,
|
&mut self.multi_fixed_reg_fixups,
|
||||||
);
|
);
|
||||||
use_iter = self.uses[use_iter.index()].next_use;
|
use_iter = self.uses[use_iter.index()].next_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (clobber, inst) in extra_clobbers {
|
for (clobber, inst) in extra_clobbers {
|
||||||
@@ -1928,11 +1945,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
to_vreg.index(),
|
to_vreg.index(),
|
||||||
from_vreg.index()
|
from_vreg.index()
|
||||||
);
|
);
|
||||||
let to_bundle =
|
let to_bundle = self.ranges[self.vregs[to_vreg.index()].first_range.index()].bundle;
|
||||||
self.ranges[self.vregs[to_vreg.index()].first_range.index()].bundle;
|
|
||||||
assert!(to_bundle.is_valid());
|
assert!(to_bundle.is_valid());
|
||||||
let from_bundle =
|
let from_bundle = self.ranges[self.vregs[from_vreg.index()].first_range.index()].bundle;
|
||||||
self.ranges[self.vregs[from_vreg.index()].first_range.index()].bundle;
|
|
||||||
assert!(from_bundle.is_valid());
|
assert!(from_bundle.is_valid());
|
||||||
log::debug!(
|
log::debug!(
|
||||||
" -> from bundle{} to bundle{}",
|
" -> from bundle{} to bundle{}",
|
||||||
@@ -2112,8 +2127,8 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
i,
|
i,
|
||||||
u.operand,
|
u.operand,
|
||||||
u.pos,
|
u.pos,
|
||||||
u.slot,
|
u.slot(),
|
||||||
u.next_use,
|
u.next_use(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2145,7 +2160,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
log::debug!(" -> use {:?} op {:?} req {:?}", use_iter, use_op, use_req);
|
log::debug!(" -> use {:?} op {:?} req {:?}", use_iter, use_op, use_req);
|
||||||
needed = needed.merge(use_req)?;
|
needed = needed.merge(use_req)?;
|
||||||
log::debug!(" -> needed {:?}", needed);
|
log::debug!(" -> needed {:?}", needed);
|
||||||
use_iter = usedata.next_use;
|
use_iter = usedata.next_use();
|
||||||
}
|
}
|
||||||
iter = range.next_in_bundle;
|
iter = range.next_in_bundle;
|
||||||
}
|
}
|
||||||
@@ -2199,10 +2214,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
{
|
{
|
||||||
log::debug!(" -> btree contains range {:?} that overlaps", preg_range);
|
log::debug!(" -> btree contains range {:?} that overlaps", preg_range);
|
||||||
if self.ranges[preg_range.index()].vreg.is_valid() {
|
if self.ranges[preg_range.index()].vreg.is_valid() {
|
||||||
log::debug!(
|
log::debug!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg);
|
||||||
" -> from vreg {:?}",
|
|
||||||
self.ranges[preg_range.index()].vreg
|
|
||||||
);
|
|
||||||
// range from an allocated bundle: find the bundle and add to
|
// range from an allocated bundle: find the bundle and add to
|
||||||
// conflicts list.
|
// conflicts list.
|
||||||
let conflict_bundle = self.ranges[preg_range.index()].bundle;
|
let conflict_bundle = self.ranges[preg_range.index()].bundle;
|
||||||
@@ -2324,7 +2336,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
fixed = true;
|
fixed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
use_iter = use_data.next_use;
|
use_iter = use_data.next_use();
|
||||||
}
|
}
|
||||||
// Minimal if this is the only range in the bundle, and if
|
// Minimal if this is the only range in the bundle, and if
|
||||||
// the range covers only one instruction. Note that it
|
// the range covers only one instruction. Note that it
|
||||||
@@ -2536,7 +2548,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let use_data = &self.uses[use_idx.index()];
|
let use_data = &self.uses[use_idx.index()];
|
||||||
log::debug!(" -> range has use at {:?}", use_data.pos);
|
log::debug!(" -> range has use at {:?}", use_data.pos);
|
||||||
update_with_pos(use_data.pos);
|
update_with_pos(use_data.pos);
|
||||||
use_idx = use_data.next_use;
|
use_idx = use_data.next_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
our_iter = self.ranges[our_iter.index()].next_in_bundle;
|
our_iter = self.ranges[our_iter.index()].next_in_bundle;
|
||||||
@@ -2624,7 +2636,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
splits.push(before_use_inst);
|
splits.push(before_use_inst);
|
||||||
}
|
}
|
||||||
splits.push(after_use_inst);
|
splits.push(after_use_inst);
|
||||||
use_idx = use_data.next_use;
|
use_idx = use_data.next_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = rangedata.next_in_bundle;
|
iter = rangedata.next_in_bundle;
|
||||||
@@ -2793,8 +2805,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
// tail-pointer so we do not need to update that.)
|
// tail-pointer so we do not need to update that.)
|
||||||
let rest_lr = self.create_liverange(rest_range);
|
let rest_lr = self.create_liverange(rest_range);
|
||||||
self.ranges[rest_lr.index()].vreg = self.ranges[iter.index()].vreg;
|
self.ranges[rest_lr.index()].vreg = self.ranges[iter.index()].vreg;
|
||||||
self.ranges[rest_lr.index()].next_in_reg =
|
self.ranges[rest_lr.index()].next_in_reg = self.ranges[iter.index()].next_in_reg;
|
||||||
self.ranges[iter.index()].next_in_reg;
|
|
||||||
self.ranges[iter.index()].next_in_reg = rest_lr;
|
self.ranges[iter.index()].next_in_reg = rest_lr;
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@@ -2822,7 +2833,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
uses_spill_weight += spill_weight_from_policy(policy);
|
uses_spill_weight += spill_weight_from_policy(policy);
|
||||||
log::debug!(" -> use {:?} remains in orig", use_iter);
|
log::debug!(" -> use {:?} remains in orig", use_iter);
|
||||||
use_iter = self.uses[use_iter.index()].next_use;
|
use_iter = self.uses[use_iter.index()].next_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move over `rest`'s uses and update stats on first
|
// Move over `rest`'s uses and update stats on first
|
||||||
@@ -2833,12 +2844,12 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
use_iter
|
use_iter
|
||||||
);
|
);
|
||||||
self.ranges[rest_lr.index()].first_use = use_iter;
|
self.ranges[rest_lr.index()].first_use = use_iter;
|
||||||
self.ranges[rest_lr.index()].last_use =
|
self.ranges[rest_lr.index()].last_use = self.ranges[iter.index()].last_use;
|
||||||
self.ranges[iter.index()].last_use;
|
|
||||||
|
|
||||||
self.ranges[iter.index()].last_use = last_use_in_first_range;
|
self.ranges[iter.index()].last_use = last_use_in_first_range;
|
||||||
if last_use_in_first_range.is_valid() {
|
if last_use_in_first_range.is_valid() {
|
||||||
self.uses[last_use_in_first_range.index()].next_use = UseIndex::invalid();
|
self.uses[last_use_in_first_range.index()]
|
||||||
|
.set_next_use(UseIndex::invalid());
|
||||||
} else {
|
} else {
|
||||||
self.ranges[iter.index()].first_use = UseIndex::invalid();
|
self.ranges[iter.index()].first_use = UseIndex::invalid();
|
||||||
}
|
}
|
||||||
@@ -3734,7 +3745,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
let usedata = &self.uses[use_iter.index()];
|
let usedata = &self.uses[use_iter.index()];
|
||||||
debug_assert!(range.contains_point(usedata.pos));
|
debug_assert!(range.contains_point(usedata.pos));
|
||||||
let inst = usedata.pos.inst();
|
let inst = usedata.pos.inst();
|
||||||
let slot = usedata.slot;
|
let slot = usedata.slot();
|
||||||
let operand = usedata.operand;
|
let operand = usedata.operand;
|
||||||
// Safepoints add virtual uses with no slots;
|
// Safepoints add virtual uses with no slots;
|
||||||
// avoid these.
|
// avoid these.
|
||||||
@@ -3744,7 +3755,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if let OperandPolicy::Reuse(_) = operand.policy() {
|
if let OperandPolicy::Reuse(_) = operand.policy() {
|
||||||
reuse_input_insts.push(inst);
|
reuse_input_insts.push(inst);
|
||||||
}
|
}
|
||||||
use_iter = self.uses[use_iter.index()].next_use;
|
use_iter = self.uses[use_iter.index()].next_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan over program move srcs/dsts to fill in allocations.
|
// Scan over program move srcs/dsts to fill in allocations.
|
||||||
|
|||||||
Reference in New Issue
Block a user