further optimizations

This commit is contained in:
Folkert 2021-08-13 13:25:05 +02:00
parent df83bf0d48
commit 24ddc4b1e8
4 changed files with 90 additions and 17 deletions

View file

@ -60,6 +60,22 @@ impl Constraint {
true
}
pub fn contains_save_the_environment(&self) -> bool {
match self {
Constraint::Eq(_, _, _, _) => false,
Constraint::Store(_, _, _, _) => false,
Constraint::Lookup(_, _, _) => false,
Constraint::Pattern(_, _, _, _) => false,
Constraint::True => false,
Constraint::SaveTheEnvironment => true,
Constraint::Let(boxed) => {
boxed.ret_constraint.contains_save_the_environment()
|| boxed.defs_constraint.contains_save_the_environment()
}
Constraint::And(cs) => cs.iter().any(|c| c.contains_save_the_environment()),
}
}
}
fn subtract(declared: &Declared, detail: &VariableDetail, accum: &mut VariableDetail) {

View file

@ -1121,7 +1121,7 @@ pub fn constrain_decls(home: ModuleId, decls: &[Declaration]) -> Constraint {
}
// this assert make the "root" of the constraint wasn't dropped
debug_assert!(format!("{:?}", &constraint).contains("SaveTheEnvironment"));
debug_assert!(constraint.contains_save_the_environment());
constraint
}

View file

@ -1,7 +1,7 @@
use crate::ir::Parens;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_collections::all::{default_hasher, MutMap, MutSet};
use roc_collections::all::{default_hasher, MutMap};
use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::{Interns, Symbol};
use roc_types::subs::{
@ -368,7 +368,7 @@ impl<'a> LambdaSet<'a> {
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
for (tag_name, variables) in tags.iter() {
@ -488,7 +488,7 @@ pub enum Builtin<'a> {
pub struct Env<'a, 'b> {
arena: &'a Bump,
seen: MutSet<Variable>,
seen: Vec<'a, Variable>,
subs: &'b Subs,
}
@ -496,19 +496,24 @@ impl<'a, 'b> Env<'a, 'b> {
fn is_seen(&self, var: Variable) -> bool {
let var = self.subs.get_root_key_without_compacting(var);
self.seen.contains(&var)
self.seen.iter().rev().any(|x| x == &var)
}
fn insert_seen(&mut self, var: Variable) -> bool {
fn insert_seen(&mut self, var: Variable) {
let var = self.subs.get_root_key_without_compacting(var);
self.seen.insert(var)
self.seen.push(var);
}
fn remove_seen(&mut self, var: Variable) -> bool {
let var = self.subs.get_root_key_without_compacting(var);
self.seen.remove(&var)
if let Some(index) = self.seen.iter().rposition(|x| x == &var) {
self.seen.remove(index);
true
} else {
false
}
}
}
@ -886,7 +891,7 @@ impl<'a> LayoutCache<'a> {
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
let result = Layout::from_var(&mut env, var);
@ -929,7 +934,7 @@ impl<'a> LayoutCache<'a> {
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
Layout::from_var(&mut env, var).map(|l| match l {
@ -1377,7 +1382,7 @@ pub fn sort_record_fields<'a>(
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
let (it, _) = gather_fields_unsorted_iter(subs, RecordFields::empty(), var);
@ -1606,7 +1611,7 @@ fn union_sorted_tags_help_new<'a>(
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
match tags_vec.len() {
@ -1822,7 +1827,7 @@ pub fn union_sorted_tags_help<'a>(
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
seen: Vec::new_in(arena),
};
match tags_vec.len() {
@ -2039,9 +2044,50 @@ fn cheap_sort_tags<'a, 'b>(
tags_vec
}
pub fn layout_from_tag_union<'a>(arena: &'a Bump, tags: UnionTags, subs: &Subs) -> Layout<'a> {
fn layout_from_newtype<'a>(arena: &'a Bump, tags: UnionTags, subs: &Subs) -> Layout<'a> {
debug_assert!(tags.is_newtype_wrapper(subs));
let slice_index = tags.variables().into_iter().next().unwrap();
let slice = subs[slice_index];
let var_index = slice.into_iter().next().unwrap();
let var = subs[var_index];
let tag_name_index = tags.tag_names().into_iter().next().unwrap();
let tag_name = &subs[tag_name_index];
if tag_name == &TagName::Private(Symbol::NUM_AT_NUM) {
unwrap_num_tag(subs, var).expect("invalid Num argument")
} else {
let mut env = Env {
arena,
subs,
seen: Vec::new_in(arena),
};
match Layout::from_var(&mut env, var) {
Ok(layout) => layout,
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
// If we encounter an unbound type var (e.g. `Ok *`)
// then it's zero-sized; In the future we may drop this argument
// completely, but for now we represent it with the empty struct
Layout::Struct(&[])
}
Err(LayoutProblem::Erroneous) => {
// An erroneous type var will code gen to a runtime
// error, so we don't need to store any data for it.
todo!()
}
}
}
}
fn layout_from_tag_union<'a>(arena: &'a Bump, tags: UnionTags, subs: &Subs) -> Layout<'a> {
use UnionVariant::*;
if tags.is_newtype_wrapper(subs) {
return layout_from_newtype(arena, tags, subs);
}
let tags_vec = cheap_sort_tags(arena, tags, subs);
match tags_vec.get(0) {
@ -2066,11 +2112,13 @@ pub fn layout_from_tag_union<'a>(arena: &'a Bump, tags: UnionTags, subs: &Subs)
arguments: field_layouts,
..
} => {
if field_layouts.len() == 1 {
let answer1 = if field_layouts.len() == 1 {
field_layouts[0]
} else {
Layout::Struct(field_layouts.into_bump_slice())
}
};
answer1
}
Wrapped(variant) => {
use WrappedVariant::*;

View file

@ -1423,6 +1423,15 @@ pub struct UnionTags {
}
impl UnionTags {
pub fn is_newtype_wrapper(&self, subs: &Subs) -> bool {
if self.length != 1 {
return false;
}
let slice = subs.variable_slices[self.variables_start as usize].slice;
slice.length == 1
}
pub fn from_tag_name_index(index: SubsIndex<TagName>) -> Self {
Self::from_slices(
SubsSlice::new(index.start, 1),
@ -1440,7 +1449,7 @@ impl UnionTags {
}
}
const fn tag_names(&self) -> SubsSlice<TagName> {
pub const fn tag_names(&self) -> SubsSlice<TagName> {
SubsSlice::new(self.tag_names_start, self.length)
}