Avoid cloning precessor lists to the heap.
This commit is contained in:
@@ -169,7 +169,7 @@ enum ZeroOneOrMore<T> {
|
|||||||
enum UseVarCases {
|
enum UseVarCases {
|
||||||
Unsealed(Value),
|
Unsealed(Value),
|
||||||
SealedOnePredecessor(Block),
|
SealedOnePredecessor(Block),
|
||||||
SealedMultiplePredecessors(Vec<(Block, Inst)>, Value, Ebb),
|
SealedMultiplePredecessors(Value, Ebb),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The following methods are the API of the SSA builder. Here is how it should be used when
|
/// The following methods are the API of the SSA builder. Here is how it should be used when
|
||||||
@@ -238,8 +238,7 @@ where
|
|||||||
UseVarCases::SealedOnePredecessor(data.predecessors[0].0)
|
UseVarCases::SealedOnePredecessor(data.predecessors[0].0)
|
||||||
} else {
|
} else {
|
||||||
let val = dfg.append_ebb_arg(data.ebb, ty);
|
let val = dfg.append_ebb_arg(data.ebb, ty);
|
||||||
let preds = data.predecessors.clone();
|
UseVarCases::SealedMultiplePredecessors(val, data.ebb)
|
||||||
UseVarCases::SealedMultiplePredecessors(preds, val, data.ebb)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let val = dfg.append_ebb_arg(data.ebb, ty);
|
let val = dfg.append_ebb_arg(data.ebb, ty);
|
||||||
@@ -264,11 +263,11 @@ where
|
|||||||
self.def_var(var, val, block);
|
self.def_var(var, val, block);
|
||||||
(val, SideEffects::new())
|
(val, SideEffects::new())
|
||||||
}
|
}
|
||||||
UseVarCases::SealedMultiplePredecessors(preds, val, ebb) => {
|
UseVarCases::SealedMultiplePredecessors(val, ebb) => {
|
||||||
// If multiple predecessor we look up a use_var in each of them:
|
// If multiple predecessor we look up a use_var in each of them:
|
||||||
// if they all yield the same value no need for an Ebb argument
|
// if they all yield the same value no need for an Ebb argument
|
||||||
self.def_var(var, val, block);
|
self.def_var(var, val, block);
|
||||||
self.predecessors_lookup(dfg, layout, jts, val, var, ebb, &preds)
|
self.predecessors_lookup(dfg, layout, jts, val, var, ebb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,10 +345,7 @@ where
|
|||||||
) -> SideEffects {
|
) -> SideEffects {
|
||||||
let block = self.header_block(ebb);
|
let block = self.header_block(ebb);
|
||||||
|
|
||||||
// TODO: find a way to not allocate vectors
|
let (undef_vars, ebb): (Vec<(Variable, Value)>, Ebb) = match self.blocks[block] {
|
||||||
let (predecessors, undef_vars, ebb): (Vec<(Block, Inst)>,
|
|
||||||
Vec<(Variable, Value)>,
|
|
||||||
Ebb) = match self.blocks[block] {
|
|
||||||
BlockData::EbbBody { .. } => panic!("this should not happen"),
|
BlockData::EbbBody { .. } => panic!("this should not happen"),
|
||||||
BlockData::EbbHeader(ref mut data) => {
|
BlockData::EbbHeader(ref mut data) => {
|
||||||
assert!(!data.sealed);
|
assert!(!data.sealed);
|
||||||
@@ -357,7 +353,7 @@ where
|
|||||||
// can iterate over it without borrowing the whole builder.
|
// can iterate over it without borrowing the whole builder.
|
||||||
let mut undef_variables = Vec::new();
|
let mut undef_variables = Vec::new();
|
||||||
mem::swap(&mut data.undef_variables, &mut undef_variables);
|
mem::swap(&mut data.undef_variables, &mut undef_variables);
|
||||||
(data.predecessors.clone(), undef_variables, data.ebb)
|
(undef_variables, data.ebb)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -366,7 +362,7 @@ where
|
|||||||
// only if necessary.
|
// only if necessary.
|
||||||
for (var, val) in undef_vars {
|
for (var, val) in undef_vars {
|
||||||
let (_, mut local_side_effects) =
|
let (_, mut local_side_effects) =
|
||||||
self.predecessors_lookup(dfg, layout, jts, val, var, ebb, &predecessors);
|
self.predecessors_lookup(dfg, layout, jts, val, var, ebb);
|
||||||
side_effects.split_ebbs_created.append(
|
side_effects.split_ebbs_created.append(
|
||||||
&mut local_side_effects
|
&mut local_side_effects
|
||||||
.split_ebbs_created,
|
.split_ebbs_created,
|
||||||
@@ -399,13 +395,18 @@ where
|
|||||||
temp_arg_val: Value,
|
temp_arg_val: Value,
|
||||||
temp_arg_var: Variable,
|
temp_arg_var: Variable,
|
||||||
dest_ebb: Ebb,
|
dest_ebb: Ebb,
|
||||||
preds: &[(Block, Inst)],
|
|
||||||
) -> (Value, SideEffects) {
|
) -> (Value, SideEffects) {
|
||||||
let mut pred_values: ZeroOneOrMore<Value> = ZeroOneOrMore::Zero();
|
let mut pred_values: ZeroOneOrMore<Value> = ZeroOneOrMore::Zero();
|
||||||
// TODO: find a way to not allocate a vector
|
// TODO: find a way to not allocate a vector
|
||||||
let mut jump_args_to_append: Vec<(Block, Inst, Value)> = Vec::new();
|
let mut jump_args_to_append: Vec<(Block, Inst, Value)> = Vec::new();
|
||||||
let ty = dfg.value_type(temp_arg_val);
|
let ty = dfg.value_type(temp_arg_val);
|
||||||
let mut side_effects = SideEffects::new();
|
let mut side_effects = SideEffects::new();
|
||||||
|
|
||||||
|
// Iterate over the predecessors. To avoid borrowing `self` for the whole loop,
|
||||||
|
// temporarily detach the predecessors list and replace it with an empty list.
|
||||||
|
// `use_var`'s traversal won't revisit these predecesors.
|
||||||
|
let mut preds = Vec::new();
|
||||||
|
mem::swap(&mut preds, &mut self.predecessors_mut(dest_ebb));
|
||||||
for &(pred, last_inst) in preds.iter() {
|
for &(pred, last_inst) in preds.iter() {
|
||||||
// For undef value and each predecessor we query what is the local SSA value
|
// For undef value and each predecessor we query what is the local SSA value
|
||||||
// corresponding to var and we put it as an argument of the branch instruction.
|
// corresponding to var and we put it as an argument of the branch instruction.
|
||||||
@@ -437,6 +438,10 @@ where
|
|||||||
&mut local_side_effects.instructions_added_to_ebbs,
|
&mut local_side_effects.instructions_added_to_ebbs,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Now that we're done iterating, move the predecessors list back.
|
||||||
|
debug_assert!(self.predecessors(dest_ebb).is_empty());
|
||||||
|
*self.predecessors_mut(dest_ebb) = preds;
|
||||||
|
|
||||||
match pred_values {
|
match pred_values {
|
||||||
ZeroOneOrMore::Zero() => {
|
ZeroOneOrMore::Zero() => {
|
||||||
// The variable is used but never defined before. This is an irregularity in the
|
// The variable is used but never defined before. This is an irregularity in the
|
||||||
@@ -560,6 +565,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as predecessors, but for &mut.
|
||||||
|
pub fn predecessors_mut(&mut self, ebb: Ebb) -> &mut Vec<(Block, Inst)> {
|
||||||
|
let block = self.header_block(ebb);
|
||||||
|
match self.blocks[block] {
|
||||||
|
BlockData::EbbBody { .. } => panic!("should not happen"),
|
||||||
|
BlockData::EbbHeader(ref mut data) => &mut data.predecessors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if and only if `seal_ebb_header_block` has been called on the argument.
|
/// Returns `true` if and only if `seal_ebb_header_block` has been called on the argument.
|
||||||
pub fn is_sealed(&self, ebb: Ebb) -> bool {
|
pub fn is_sealed(&self, ebb: Ebb) -> bool {
|
||||||
match self.blocks[self.header_block(ebb)] {
|
match self.blocks[self.header_block(ebb)] {
|
||||||
|
|||||||
Reference in New Issue
Block a user