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