Use PackedOption<Inst> in the Layout implementation.

This also revealed that the last_inst() method should return an Option.
This commit is contained in:
Jakob Stoklund Olesen
2017-01-19 14:26:47 -08:00
parent 52db486500
commit 3fc0f80223
2 changed files with 42 additions and 45 deletions

View File

@@ -5,9 +5,9 @@
use std::cmp;
use std::iter::{Iterator, IntoIterator};
use entity_map::{EntityMap, EntityRef};
use entity_map::EntityMap;
use packed_option::PackedOption;
use ir::entities::{Ebb, Inst, NO_INST};
use ir::entities::{Ebb, Inst};
use ir::progpoint::{ProgramOrder, ExpandedProgramPoint};
/// The `Layout` struct determines the layout of EBBs and instructions in a function. It does not
@@ -30,7 +30,7 @@ pub struct Layout {
ebbs: EntityMap<Ebb, EbbNode>,
// Linked list nodes for the layout order of instructions. Forms a double linked list per EBB,
// terminated in both ends by NO_INST.
// terminated in both ends by `None`.
insts: EntityMap<Inst, InstNode>,
// First EBB in the layout order, or `None` when no EBBs have been laid out.
@@ -120,7 +120,6 @@ impl Layout {
// Get the seq of the last instruction if it exists, otherwise use the EBB header seq.
self.ebbs[ebb]
.last_inst
.wrap()
.map(|inst| self.insts[inst].seq)
.unwrap_or(self.ebbs[ebb].seq)
}
@@ -134,7 +133,7 @@ impl Layout {
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() {
let next_seq = if let Some(inst) = self.ebbs[ebb].first_inst.expand() {
self.insts[inst].seq
} else if let Some(next_ebb) = self.ebbs[ebb].next.expand() {
self.ebbs[next_ebb].seq
@@ -159,13 +158,13 @@ impl Layout {
let ebb = self.inst_ebb(inst).expect("inst must be inserted before assigning an seq");
// Get the sequence number immediately before `inst`.
let prev_seq = match self.insts[inst].prev.wrap() {
let prev_seq = match self.insts[inst].prev.expand() {
Some(prev_inst) => self.insts[prev_inst].seq,
None => self.ebbs[ebb].seq,
};
// 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.expand() {
self.insts[next_inst].seq
} else if let Some(next_ebb) = self.ebbs[ebb].next.expand() {
self.ebbs[next_ebb].seq
@@ -197,7 +196,7 @@ impl Layout {
self.insts[inst].seq = seq;
// Next instruction.
inst = match self.insts[inst].next.wrap() {
inst = match self.insts[inst].next.expand() {
None => return Some(seq),
Some(next) => next,
};
@@ -221,7 +220,7 @@ impl Layout {
self.ebbs[ebb].seq = seq;
// Renumber instructions in `ebb`. Stop when the numbers catch up.
if let Some(inst) = self.ebbs[ebb].first_inst.wrap() {
if let Some(inst) = self.ebbs[ebb].first_inst.expand() {
seq = match self.renumber_insts(inst, seq + MINOR_STRIDE) {
Some(s) => s,
None => return,
@@ -276,7 +275,7 @@ impl Layout {
"Cannot append EBB that is already in the layout");
{
let node = self.ebbs.ensure(ebb);
assert!(node.first_inst == NO_INST && node.last_inst == NO_INST);
assert!(node.first_inst.is_none() && node.last_inst.is_none());
node.prev = self.last_ebb.into();
node.next = None.into();
}
@@ -348,8 +347,8 @@ impl Layout {
struct EbbNode {
prev: PackedOption<Ebb>,
next: PackedOption<Ebb>,
first_inst: Inst,
last_inst: Inst,
first_inst: PackedOption<Inst>,
last_inst: PackedOption<Inst>,
seq: SequenceNumber,
}
@@ -408,21 +407,21 @@ impl Layout {
let inst_node = self.insts.ensure(inst);
inst_node.ebb = ebb.into();
inst_node.prev = ebb_node.last_inst;
assert_eq!(inst_node.next, NO_INST);
assert!(inst_node.next.is_none());
}
if ebb_node.first_inst == NO_INST {
ebb_node.first_inst = inst;
if ebb_node.first_inst.is_none() {
ebb_node.first_inst = inst.into();
} else {
self.insts[ebb_node.last_inst].next = inst;
self.insts[ebb_node.last_inst.unwrap()].next = inst.into();
}
ebb_node.last_inst = inst;
ebb_node.last_inst = inst.into();
}
self.assign_inst_seq(inst);
}
/// Fetch an ebb's last instruction.
pub fn last_inst(&self, ebb: Ebb) -> Inst {
self.ebbs[ebb].last_inst
pub fn last_inst(&self, ebb: Ebb) -> Option<Inst> {
self.ebbs[ebb].last_inst.into()
}
/// Insert `inst` before the instruction `before` in the same EBB.
@@ -434,14 +433,13 @@ impl Layout {
{
let inst_node = self.insts.ensure(inst);
inst_node.ebb = ebb.into();
inst_node.next = before;
inst_node.next = before.into();
inst_node.prev = after;
}
self.insts[before].prev = inst;
if after == NO_INST {
self.ebbs[ebb].first_inst = inst;
} else {
self.insts[after].next = inst;
self.insts[before].prev = inst.into();
match after.expand() {
None => self.ebbs[ebb].first_inst = inst.into(),
Some(a) => self.insts[a].next = inst.into(),
}
self.assign_inst_seq(inst);
}
@@ -450,8 +448,8 @@ impl Layout {
pub fn ebb_insts<'f>(&'f self, ebb: Ebb) -> Insts<'f> {
Insts {
layout: self,
head: self.ebbs[ebb].first_inst.wrap(),
tail: self.ebbs[ebb].last_inst.wrap(),
head: self.ebbs[ebb].first_inst.into(),
tail: self.ebbs[ebb].last_inst.into(),
}
}
@@ -489,7 +487,7 @@ impl Layout {
let node = self.ebbs.ensure(new_ebb);
node.prev = old_ebb.into();
node.next = next_ebb;
node.first_inst = before;
node.first_inst = before.into();
node.last_inst = last_inst;
}
self.ebbs[old_ebb].next = new_ebb.into();
@@ -503,20 +501,19 @@ impl Layout {
// Disconnect the instruction links.
let prev_inst = self.insts[before].prev;
self.insts[before].prev = NO_INST;
self.insts[before].prev = None.into();
self.ebbs[old_ebb].last_inst = prev_inst;
if prev_inst == NO_INST {
self.ebbs[old_ebb].first_inst = NO_INST;
} else {
self.insts[prev_inst].next = NO_INST;
match prev_inst.expand() {
None => self.ebbs[old_ebb].first_inst = None.into(),
Some(pi) => self.insts[pi].next = None.into(),
}
// Fix the instruction -> ebb pointers.
let mut i = before;
while i != NO_INST {
let mut opt_i = Some(before);
while let Some(i) = opt_i {
debug_assert_eq!(self.insts[i].ebb.expand(), Some(old_ebb));
self.insts[i].ebb = new_ebb.into();
i = self.insts[i].next;
opt_i = self.insts[i].next.into();
}
self.assign_ebb_seq(new_ebb);
@@ -527,8 +524,8 @@ impl Layout {
struct InstNode {
// The Ebb containing this instruction, or `None` if the instruction is not yet inserted.
ebb: PackedOption<Ebb>,
prev: Inst,
next: Inst,
prev: PackedOption<Inst>,
next: PackedOption<Inst>,
seq: SequenceNumber,
}
@@ -549,7 +546,7 @@ impl<'f> Iterator for Insts<'f> {
self.head = None;
self.tail = None;
} else {
self.head = Some(self.layout.insts[inst].next);
self.head = self.layout.insts[inst].next.into();
}
}
rval
@@ -564,7 +561,7 @@ impl<'f> DoubleEndedIterator for Insts<'f> {
self.head = None;
self.tail = None;
} else {
self.tail = Some(self.layout.insts[inst].prev);
self.tail = self.layout.insts[inst].prev.into();
}
}
rval
@@ -775,7 +772,7 @@ impl<'f> Cursor<'f> {
match self.pos {
Nowhere | After(..) => None,
At(inst) => {
if let Some(next) = self.layout.insts[inst].next.wrap() {
if let Some(next) = self.layout.insts[inst].next.expand() {
self.pos = At(next);
Some(next)
} else {
@@ -785,7 +782,7 @@ impl<'f> Cursor<'f> {
}
}
Before(ebb) => {
if let Some(next) = self.layout.ebbs[ebb].first_inst.wrap() {
if let Some(next) = self.layout.ebbs[ebb].first_inst.expand() {
self.pos = At(next);
Some(next)
} else {
@@ -826,7 +823,7 @@ impl<'f> Cursor<'f> {
match self.pos {
Nowhere | Before(..) => None,
At(inst) => {
if let Some(prev) = self.layout.insts[inst].prev.wrap() {
if let Some(prev) = self.layout.insts[inst].prev.expand() {
self.pos = At(prev);
Some(prev)
} else {
@@ -836,7 +833,7 @@ impl<'f> Cursor<'f> {
}
}
After(ebb) => {
if let Some(prev) = self.layout.ebbs[ebb].last_inst.wrap() {
if let Some(prev) = self.layout.ebbs[ebb].last_inst.expand() {
self.pos = At(prev);
Some(prev)
} else {

View File

@@ -110,7 +110,7 @@ impl<'a> Verifier<'a> {
fn ebb_integrity(&self, ebb: Ebb, inst: Inst) -> Result<()> {
let is_terminator = self.func.dfg[inst].opcode().is_terminator();
let is_last_inst = self.func.layout.last_inst(ebb) == inst;
let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst);
if is_terminator && !is_last_inst {
// Terminating instructions only occur at the end of blocks.