Use PackedOption<Ebb> in the Layout implementation.

The doubly linked lists are terminated with None.

Remove NO_EBB and the Default impl for Ebb.
This commit is contained in:
Jakob Stoklund Olesen
2017-01-19 13:59:57 -08:00
parent 5fc222348d
commit 52db486500
3 changed files with 49 additions and 47 deletions

View File

@@ -72,15 +72,6 @@ impl Ebb {
}
}
/// A guaranteed invalid EBB reference.
pub const NO_EBB: Ebb = Ebb(u32::MAX);
impl Default for Ebb {
fn default() -> Ebb {
NO_EBB
}
}
/// An opaque reference to an instruction in a function.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub struct Inst(u32);

View File

@@ -6,7 +6,8 @@
use std::cmp;
use std::iter::{Iterator, IntoIterator};
use entity_map::{EntityMap, EntityRef};
use ir::entities::{Ebb, NO_EBB, Inst, NO_INST};
use packed_option::PackedOption;
use ir::entities::{Ebb, Inst, NO_INST};
use ir::progpoint::{ProgramOrder, ExpandedProgramPoint};
/// The `Layout` struct determines the layout of EBBs and instructions in a function. It does not
@@ -25,7 +26,7 @@ use ir::progpoint::{ProgramOrder, ExpandedProgramPoint};
#[derive(Clone)]
pub struct Layout {
// Linked list nodes for the layout order of EBBs Forms a doubly linked list, terminated in
// both ends by NO_EBB.
// both ends by `None`.
ebbs: EntityMap<Ebb, EbbNode>,
// Linked list nodes for the layout order of instructions. Forms a double linked list per EBB,
@@ -130,13 +131,12 @@ impl Layout {
assert!(self.is_ebb_inserted(ebb));
// Get the sequence number immediately before `ebb`, or 0.
let prev_seq =
self.ebbs[ebb].prev.wrap().map(|prev_ebb| self.last_ebb_seq(prev_ebb)).unwrap_or(0);
let prev_seq = self.ebbs[ebb].prev.map(|prev_ebb| self.last_ebb_seq(prev_ebb)).unwrap_or(0);
// Get the sequence number immediately following `ebb`.
let next_seq = if let Some(inst) = self.ebbs[ebb].first_inst.wrap() {
self.insts[inst].seq
} else if let Some(next_ebb) = self.ebbs[ebb].next.wrap() {
} else if let Some(next_ebb) = self.ebbs[ebb].next.expand() {
self.ebbs[next_ebb].seq
} else {
// There is nothing after `ebb`. We can just use a major stride.
@@ -167,7 +167,7 @@ impl Layout {
// Get the sequence number immediately following `inst`.
let next_seq = if let Some(next_inst) = self.insts[inst].next.wrap() {
self.insts[next_inst].seq
} else if let Some(next_ebb) = self.ebbs[ebb].next.wrap() {
} else if let Some(next_ebb) = self.ebbs[ebb].next.expand() {
self.ebbs[next_ebb].seq
} else {
// There is nothing after `inst`. We can just use a major stride.
@@ -229,7 +229,7 @@ impl Layout {
}
// Advance to the next EBB.
ebb = match self.ebbs[ebb].next.wrap() {
ebb = match self.ebbs[ebb].next.expand() {
Some(next) => next,
None => return,
};
@@ -248,7 +248,7 @@ impl Layout {
fn renumber_from_inst(&mut self, inst: Inst, first_seq: SequenceNumber) {
if let Some(seq) = self.renumber_insts(inst, first_seq) {
// Renumbering spills over into next EBB.
if let Some(next_ebb) = self.ebbs[self.inst_ebb(inst).unwrap()].next.wrap() {
if let Some(next_ebb) = self.ebbs[self.inst_ebb(inst).unwrap()].next.expand() {
self.renumber_from_ebb(next_ebb, seq + MINOR_STRIDE);
}
}
@@ -267,7 +267,7 @@ impl Layout {
impl Layout {
/// Is `ebb` currently part of the layout?
pub fn is_ebb_inserted(&self, ebb: Ebb) -> bool {
Some(ebb) == self.first_ebb || (self.ebbs.is_valid(ebb) && self.ebbs[ebb].prev != NO_EBB)
Some(ebb) == self.first_ebb || (self.ebbs.is_valid(ebb) && self.ebbs[ebb].prev.is_some())
}
/// Insert `ebb` as the last EBB in the layout.
@@ -277,11 +277,11 @@ impl Layout {
{
let node = self.ebbs.ensure(ebb);
assert!(node.first_inst == NO_INST && node.last_inst == NO_INST);
node.prev = self.last_ebb.unwrap_or_default();
node.next = NO_EBB;
node.prev = self.last_ebb.into();
node.next = None.into();
}
if let Some(last) = self.last_ebb {
self.ebbs[last].next = ebb;
self.ebbs[last].next = ebb.into();
} else {
self.first_ebb = Some(ebb);
}
@@ -298,14 +298,13 @@ impl Layout {
let after = self.ebbs[before].prev;
{
let node = self.ebbs.ensure(ebb);
node.next = before;
node.next = before.into();
node.prev = after;
}
self.ebbs[before].prev = ebb;
if after == NO_EBB {
self.first_ebb = Some(ebb);
} else {
self.ebbs[after].next = ebb;
self.ebbs[before].prev = ebb.into();
match after.expand() {
None => self.first_ebb = Some(ebb),
Some(a) => self.ebbs[a].next = ebb.into(),
}
self.assign_ebb_seq(ebb);
}
@@ -320,13 +319,12 @@ impl Layout {
{
let node = self.ebbs.ensure(ebb);
node.next = before;
node.prev = after;
node.prev = after.into();
}
self.ebbs[after].next = ebb;
if before == NO_EBB {
self.last_ebb = Some(ebb);
} else {
self.ebbs[before].prev = ebb;
self.ebbs[after].next = ebb.into();
match before.expand() {
None => self.last_ebb = Some(ebb),
Some(b) => self.ebbs[b].prev = ebb.into(),
}
self.assign_ebb_seq(ebb);
}
@@ -348,8 +346,8 @@ impl Layout {
#[derive(Clone, Debug, Default)]
struct EbbNode {
prev: Ebb,
next: Ebb,
prev: PackedOption<Ebb>,
next: PackedOption<Ebb>,
first_inst: Inst,
last_inst: Inst,
seq: SequenceNumber,
@@ -367,7 +365,7 @@ impl<'f> Iterator for Ebbs<'f> {
fn next(&mut self) -> Option<Ebb> {
match self.next {
Some(ebb) => {
self.next = self.layout.ebbs[ebb].next.wrap();
self.next = self.layout.ebbs[ebb].next.expand();
Some(ebb)
}
None => None,
@@ -393,7 +391,7 @@ impl Layout {
/// Get the EBB containing `inst`, or `None` if `inst` is not inserted in the layout.
pub fn inst_ebb(&self, inst: Inst) -> Option<Ebb> {
if self.insts.is_valid(inst) {
self.insts[inst].ebb.wrap()
self.insts[inst].ebb.into()
} else {
None
}
@@ -408,7 +406,7 @@ impl Layout {
let ebb_node = &mut self.ebbs[ebb];
{
let inst_node = self.insts.ensure(inst);
inst_node.ebb = ebb;
inst_node.ebb = ebb.into();
inst_node.prev = ebb_node.last_inst;
assert_eq!(inst_node.next, NO_INST);
}
@@ -435,7 +433,7 @@ impl Layout {
let after = self.insts[before].prev;
{
let inst_node = self.insts.ensure(inst);
inst_node.ebb = ebb;
inst_node.ebb = ebb.into();
inst_node.next = before;
inst_node.prev = after;
}
@@ -489,18 +487,18 @@ impl Layout {
let last_inst = self.ebbs[old_ebb].last_inst;
{
let node = self.ebbs.ensure(new_ebb);
node.prev = old_ebb;
node.prev = old_ebb.into();
node.next = next_ebb;
node.first_inst = before;
node.last_inst = last_inst;
}
self.ebbs[old_ebb].next = new_ebb;
self.ebbs[old_ebb].next = new_ebb.into();
// Fix backwards link.
if Some(old_ebb) == self.last_ebb {
self.last_ebb = Some(new_ebb);
} else {
self.ebbs[next_ebb].prev = new_ebb;
self.ebbs[next_ebb.unwrap()].prev = new_ebb.into();
}
// Disconnect the instruction links.
@@ -516,8 +514,8 @@ impl Layout {
// Fix the instruction -> ebb pointers.
let mut i = before;
while i != NO_INST {
debug_assert_eq!(self.insts[i].ebb, old_ebb);
self.insts[i].ebb = new_ebb;
debug_assert_eq!(self.insts[i].ebb.expand(), Some(old_ebb));
self.insts[i].ebb = new_ebb.into();
i = self.insts[i].next;
}
@@ -527,7 +525,8 @@ impl Layout {
#[derive(Clone, Debug, Default)]
struct InstNode {
ebb: Ebb,
// The Ebb containing this instruction, or `None` if the instruction is not yet inserted.
ebb: PackedOption<Ebb>,
prev: Inst,
next: Inst,
seq: SequenceNumber,
@@ -686,7 +685,7 @@ impl<'f> Cursor<'f> {
/// ```
pub fn next_ebb(&mut self) -> Option<Ebb> {
let next = if let Some(ebb) = self.current_ebb() {
self.layout.ebbs[ebb].next.wrap()
self.layout.ebbs[ebb].next.expand()
} else {
self.layout.first_ebb
};
@@ -719,7 +718,7 @@ impl<'f> Cursor<'f> {
/// ```
pub fn prev_ebb(&mut self) -> Option<Ebb> {
let prev = if let Some(ebb) = self.current_ebb() {
self.layout.ebbs[ebb].prev.wrap()
self.layout.ebbs[ebb].prev.expand()
} else {
self.layout.last_ebb
};

View File

@@ -34,6 +34,18 @@ impl<T: ReservedValue> PackedOption<T> {
pub fn expand(self) -> Option<T> {
if self.is_none() { None } else { Some(self.0) }
}
/// Maps a `PackedOption<T>` to `Option<U>` by applying a function to a contained value.
pub fn map<U, F>(self, f: F) -> Option<U>
where F: FnOnce(T) -> U
{
self.expand().map(f)
}
/// Unwrap a packed `Some` value or panic.
pub fn unwrap(self) -> T {
self.expand().unwrap()
}
}
impl<T: ReservedValue> Default for PackedOption<T> {