Add a function to seal all the blocks at once.
This commit is contained in:
@@ -300,6 +300,17 @@ where
|
|||||||
self.handle_ssa_side_effects(side_effects);
|
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.
|
/// 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) {
|
pub fn declare_var(&mut self, var: Variable, ty: Type) {
|
||||||
self.builder.types[var] = ty;
|
self.builder.types[var] = ty;
|
||||||
@@ -679,8 +690,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn sample_function(lazy_seal: bool) {
|
||||||
fn sample_function() {
|
|
||||||
let mut sig = Signature::new(CallConv::Native);
|
let mut sig = Signature::new(CallConv::Native);
|
||||||
sig.returns.push(AbiParam::new(I32));
|
sig.returns.push(AbiParam::new(I32));
|
||||||
sig.params.push(AbiParam::new(I32));
|
sig.params.push(AbiParam::new(I32));
|
||||||
@@ -701,7 +711,9 @@ mod tests {
|
|||||||
builder.declare_var(z, I32);
|
builder.declare_var(z, I32);
|
||||||
|
|
||||||
builder.switch_to_block(block0, &[]);
|
builder.switch_to_block(block0, &[]);
|
||||||
builder.seal_block(block0);
|
if !lazy_seal {
|
||||||
|
builder.seal_block(block0);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
let tmp = builder.param_value(0);
|
let tmp = builder.param_value(0);
|
||||||
builder.def_var(x, tmp);
|
builder.def_var(x, tmp);
|
||||||
@@ -741,7 +753,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.switch_to_block(block2, &[]);
|
builder.switch_to_block(block2, &[]);
|
||||||
builder.seal_block(block2);
|
if !lazy_seal {
|
||||||
|
builder.seal_block(block2);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let arg1 = builder.use_var(y);
|
let arg1 = builder.use_var(y);
|
||||||
@@ -750,7 +764,13 @@ mod tests {
|
|||||||
builder.def_var(y, tmp);
|
builder.def_var(y, tmp);
|
||||||
}
|
}
|
||||||
builder.ins().jump(block1, &[]);
|
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());
|
let flags = settings::Flags::new(&settings::builder());
|
||||||
@@ -761,4 +781,14 @@ mod tests {
|
|||||||
Err(err) => panic!("{}{}", func.display(None), err),
|
Err(err) => panic!("{}{}", func.display(None), err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample() {
|
||||||
|
sample_function(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_with_lazy_seal() {
|
||||||
|
sample_function(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,29 @@ where
|
|||||||
///
|
///
|
||||||
/// Returns the list of newly created ebbs for critical edge splitting.
|
/// 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 {
|
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 block = self.header_block(ebb);
|
||||||
|
|
||||||
let (undef_vars, ebb): (Vec<(Variable, Value)>, Ebb) = match self.blocks[block] {
|
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.predecessors_lookup(func, val, var, ty, ebb);
|
||||||
}
|
}
|
||||||
self.mark_ebb_header_block_sealed(block);
|
self.mark_ebb_header_block_sealed(block);
|
||||||
mem::replace(&mut self.side_effects, SideEffects::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the `sealed` flag for `block`.
|
/// Set the `sealed` flag for `block`.
|
||||||
|
|||||||
Reference in New Issue
Block a user