Merge remote-tracking branch 'origin/trunk' into nullable-tags

This commit is contained in:
Folkert 2021-01-17 02:37:57 +01:00
commit 8cd744342b
54 changed files with 1208 additions and 724 deletions

View file

@ -578,9 +578,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
Eq | NotEq | And | Or | NumAdd | NumAddWrap | NumAddChecked | NumSub | NumSubWrap
| NumSubChecked | NumMul | NumMulWrap | NumMulChecked | NumGt | NumGte | NumLt | NumLte
| NumCompare | NumDivUnchecked | NumRemUnchecked | NumPow | NumPowInt | NumBitwiseAnd => {
arena.alloc_slice_copy(&[irrelevant, irrelevant])
}
| NumCompare | NumDivUnchecked | NumRemUnchecked | NumPow | NumPowInt | NumBitwiseAnd
| NumBitwiseXor => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor
| NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin => {

View file

@ -905,7 +905,10 @@ pub fn optimize_when<'a>(
let decision_tree = compile(patterns);
let decider = tree_to_decider(decision_tree);
let target_counts = count_targets(&decider);
// for each target (branch body), count in how many ways it can be reached
let mut target_counts = bumpalo::vec![in env.arena; 0; indexed_branches.len()];
count_targets(&mut target_counts, &decider);
let mut choices = MutMap::default();
let mut jumps = Vec::new();
@ -913,8 +916,9 @@ pub fn optimize_when<'a>(
for (index, branch) in indexed_branches.into_iter() {
let ((branch_index, choice), opt_jump) = create_choices(&target_counts, index, branch);
if let Some(jump) = opt_jump {
jumps.push(jump);
if let Some((index, body)) = opt_jump {
let id = JoinPointId(env.unique_symbol());
jumps.push((index, id, body));
}
choices.insert(branch_index, choice);
@ -922,7 +926,7 @@ pub fn optimize_when<'a>(
let choice_decider = insert_choices(&choices, decider);
decide_to_branching(
let mut stmt = decide_to_branching(
env,
procs,
layout_cache,
@ -931,7 +935,18 @@ pub fn optimize_when<'a>(
ret_layout,
choice_decider,
&jumps,
)
);
for (_, id, body) in jumps.into_iter() {
stmt = Stmt::Join {
id,
parameters: &[],
continuation: env.arena.alloc(body),
remainder: env.arena.alloc(stmt),
};
}
stmt
}
#[derive(Debug)]
@ -1383,7 +1398,7 @@ fn decide_to_branching<'a>(
cond_layout: Layout<'a>,
ret_layout: Layout<'a>,
decider: Decider<'a, Choice<'a>>,
jumps: &Vec<(u64, Stmt<'a>)>,
jumps: &Vec<(u64, JoinPointId, Stmt<'a>)>,
) -> Stmt<'a> {
use Choice::*;
use Decider::*;
@ -1392,12 +1407,11 @@ fn decide_to_branching<'a>(
match decider {
Leaf(Jump(label)) => {
// we currently inline the jumps: does fewer jumps but produces a larger artifact
let (_, expr) = jumps
.iter()
.find(|(l, _)| l == &label)
let index = jumps
.binary_search_by_key(&label, |ref r| r.0)
.expect("jump not in list of jumps");
expr.clone()
Stmt::Jump(jumps[index].1, &[])
}
Leaf(Inline(expr)) => expr,
Chain {
@ -1674,39 +1688,32 @@ fn to_chain<'a>(
/// If a target appears exactly once in a Decider, the corresponding expression
/// can be inlined. Whether things are inlined or jumps is called a "choice".
fn count_targets(decision_tree: &Decider<u64>) -> MutMap<u64, u64> {
let mut result = MutMap::default();
count_targets_help(decision_tree, &mut result);
result
}
fn count_targets_help(decision_tree: &Decider<u64>, targets: &mut MutMap<u64, u64>) {
fn count_targets(targets: &mut bumpalo::collections::Vec<u64>, initial: &Decider<u64>) {
use Decider::*;
match decision_tree {
Leaf(target) => match targets.get_mut(target) {
None => {
targets.insert(*target, 1);
let mut stack = vec![initial];
while let Some(decision_tree) = stack.pop() {
match decision_tree {
Leaf(target) => {
targets[*target as usize] += 1;
}
Some(current) => {
*current += 1;
Chain {
success, failure, ..
} => {
stack.push(success);
stack.push(failure);
}
},
Chain {
success, failure, ..
} => {
count_targets_help(success, targets);
count_targets_help(failure, targets);
}
FanOut {
tests, fallback, ..
} => {
stack.push(fallback);
FanOut {
tests, fallback, ..
} => {
count_targets_help(fallback, targets);
for (_, decider) in tests {
count_targets_help(decider, targets);
for (_, decider) in tests {
stack.push(decider);
}
}
}
}
@ -1714,11 +1721,11 @@ fn count_targets_help(decision_tree: &Decider<u64>, targets: &mut MutMap<u64, u6
#[allow(clippy::type_complexity)]
fn create_choices<'a>(
target_counts: &MutMap<u64, u64>,
target_counts: &bumpalo::collections::Vec<'a, u64>,
target: u64,
branch: Stmt<'a>,
) -> ((u64, Choice<'a>), Option<(u64, Stmt<'a>)>) {
match target_counts.get(&target) {
match target_counts.get(target as usize) {
None => unreachable!(
"this should never happen: {:?} not in {:?}",
target, target_counts