Add a function to seal all the blocks at once.

This commit is contained in:
Dan Gohman
2017-11-01 13:09:20 -07:00
parent c6d39dea5d
commit 1cbf921d9d
2 changed files with 58 additions and 6 deletions

View File

@@ -300,6 +300,17 @@ where
self.handle_ssa_side_effects(side_effects);
}
/// Effectively calls seal_block on all blocks in the function.
///
/// It's more efficient to seal `Ebb`s as soon as possible, during
/// translation, but for frontends where this is impractical to do, this
/// function can be used at the end of translating all blocks to ensure
/// that everything is sealed.
pub fn seal_all_blocks(&mut self) {
let side_effects = self.builder.ssa.seal_all_ebb_header_blocks(self.func);
self.handle_ssa_side_effects(side_effects);
}
/// In order to use a variable in a `use_var`, you need to declare its type with this method.
pub fn declare_var(&mut self, var: Variable, ty: Type) {
self.builder.types[var] = ty;
@@ -679,8 +690,7 @@ mod tests {
}
}
#[test]
fn sample_function() {
fn sample_function(lazy_seal: bool) {
let mut sig = Signature::new(CallConv::Native);
sig.returns.push(AbiParam::new(I32));
sig.params.push(AbiParam::new(I32));
@@ -701,7 +711,9 @@ mod tests {
builder.declare_var(z, I32);
builder.switch_to_block(block0, &[]);
builder.seal_block(block0);
if !lazy_seal {
builder.seal_block(block0);
}
{
let tmp = builder.param_value(0);
builder.def_var(x, tmp);
@@ -741,7 +753,9 @@ mod tests {
}
builder.switch_to_block(block2, &[]);
builder.seal_block(block2);
if !lazy_seal {
builder.seal_block(block2);
}
{
let arg1 = builder.use_var(y);
@@ -750,7 +764,13 @@ mod tests {
builder.def_var(y, tmp);
}
builder.ins().jump(block1, &[]);
builder.seal_block(block1);
if !lazy_seal {
builder.seal_block(block1);
}
if lazy_seal {
builder.seal_all_blocks();
}
}
let flags = settings::Flags::new(&settings::builder());
@@ -761,4 +781,14 @@ mod tests {
Err(err) => panic!("{}{}", func.display(None), err),
}
}
#[test]
fn sample() {
sample_function(false)
}
#[test]
fn sample_with_lazy_seal() {
sample_function(true)
}
}

View File

@@ -409,6 +409,29 @@ where
///
/// Returns the list of newly created ebbs for critical edge splitting.
pub fn seal_ebb_header_block(&mut self, ebb: Ebb, func: &mut Function) -> SideEffects {
self.seal_one_ebb_header_block(ebb, func);
mem::replace(&mut self.side_effects, SideEffects::new())
}
/// Completes the global value numbering for all `Ebb`s in `func`.
///
/// It's more efficient to seal `Ebb`s as soon as possible, during
/// translation, but for frontends where this is impractical to do, this
/// function can be used at the end of translating all blocks to ensure
/// that everything is sealed.
pub fn seal_all_ebb_header_blocks(&mut self, func: &mut Function) -> SideEffects {
// Seal all `Ebb`s currently in the function. This can entail splitting
// and creation of new blocks, however such new blocks are sealed on
// the fly, so we don't need to accout for them here.
for ebb in self.ebb_headers.keys() {
self.seal_one_ebb_header_block(ebb, func);
}
mem::replace(&mut self.side_effects, SideEffects::new())
}
/// Helper function for `seal_ebb_header_block` and
/// `seal_all_ebb_header_blocks`.
fn seal_one_ebb_header_block(&mut self, ebb: Ebb, func: &mut Function) {
let block = self.header_block(ebb);
let (undef_vars, ebb): (Vec<(Variable, Value)>, Ebb) = match self.blocks[block] {
@@ -429,7 +452,6 @@ where
self.predecessors_lookup(func, val, var, ty, ebb);
}
self.mark_ebb_header_block_sealed(block);
mem::replace(&mut self.side_effects, SideEffects::new())
}
/// Set the `sealed` flag for `block`.