Clarify some lowlevel code to make it clearer what to do when adding new ones

This commit is contained in:
Brian Carroll 2021-12-29 22:03:25 +00:00
parent 5ac12efbe5
commit 6b932f9743
4 changed files with 152 additions and 135 deletions

View File

@ -6,7 +6,7 @@ use bumpalo::{collections::Vec, Bump};
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
use roc_collections::all::{MutMap, MutSet};
use roc_module::ident::{ModuleName, TagName};
use roc_module::low_level::LowLevel;
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::ir::{
@ -260,8 +260,9 @@ trait Backend<'a> {
ret_layout,
..
} => {
// If this function is just a lowlevel wrapper, then inline it
if let Some(lowlevel) = LowLevel::from_inlined_wrapper(*func_sym) {
if let LowLevelWrapperType::CanBeReplacedBy(lowlevel) =
LowLevelWrapperType::from_symbol(*func_sym)
{
self.build_run_low_level(
sym,
&lowlevel,

View File

@ -4,7 +4,7 @@ use code_builder::Align;
use roc_builtins::bitcode::{self, IntWidth};
use roc_collections::all::MutMap;
use roc_module::ident::Ident;
use roc_module::low_level::LowLevel;
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
use roc_module::symbol::{Interns, Symbol};
use roc_mono::code_gen_help::{CodeGenHelp, REFCOUNT_MAX};
use roc_mono::ir::{
@ -591,7 +591,9 @@ impl<'a> WasmBackend<'a> {
}) => match call_type {
CallType::ByName { name: func_sym, .. } => {
// If this function is just a lowlevel wrapper, then inline it
if let Some(lowlevel) = LowLevel::from_inlined_wrapper(*func_sym) {
if let LowLevelWrapperType::CanBeReplacedBy(lowlevel) =
LowLevelWrapperType::from_symbol(*func_sym)
{
return self.build_low_level(
lowlevel,
arguments,

View File

@ -8,7 +8,7 @@ use bumpalo::{self, collections::Vec, Bump};
use roc_builtins::bitcode::IntWidth;
use roc_collections::all::{MutMap, MutSet};
use roc_module::low_level::LowLevel;
use roc_module::low_level::LowLevelWrapperType;
use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::ir::{Proc, ProcLayout};
@ -62,7 +62,10 @@ pub fn build_module_help<'a>(
// and filter out procs we're going to inline
let mut fn_index: u32 = 0;
for ((sym, layout), proc) in procedures.into_iter() {
if LowLevel::from_inlined_wrapper(sym).is_some() {
if matches!(
LowLevelWrapperType::from_symbol(sym),
LowLevelWrapperType::CanBeReplacedBy(_)
) {
continue;
}
procs.push(proc);

View File

@ -175,138 +175,149 @@ impl LowLevel {
_ => unreachable!(),
}
}
}
/// Used in dev backends to inline some lowlevel wrapper functions
/// For wrappers that contain logic, we return None to prevent inlining
/// (Mention each explicitly rather than using `_`, to show they have not been forgotten)
pub fn from_inlined_wrapper(symbol: Symbol) -> Option<LowLevel> {
/// Some wrapper functions can just be replaced by lowlevels in the backend for performance.
/// For example, Num.add should be an instruction, not a function call.
/// Variant names are chosen to help explain what to do when adding new lowlevels
pub enum LowLevelWrapperType {
/// This wrapper function contains no logic and we can remove it in code gen
CanBeReplacedBy(LowLevel),
/// This wrapper function contains important logic and we cannot remove it in code gen
WrapperIsRequired,
NotALowLevelWrapper,
}
impl LowLevelWrapperType {
pub fn from_symbol(symbol: Symbol) -> LowLevelWrapperType {
use LowLevel::*;
use LowLevelWrapperType::*;
match symbol {
Symbol::STR_CONCAT => Some(StrConcat),
Symbol::STR_JOIN_WITH => Some(StrJoinWith),
Symbol::STR_IS_EMPTY => Some(StrIsEmpty),
Symbol::STR_STARTS_WITH => Some(StrStartsWith),
Symbol::STR_STARTS_WITH_CODE_PT => Some(StrStartsWithCodePt),
Symbol::STR_ENDS_WITH => Some(StrEndsWith),
Symbol::STR_SPLIT => Some(StrSplit),
Symbol::STR_COUNT_GRAPHEMES => Some(StrCountGraphemes),
Symbol::STR_FROM_UTF8 => None,
Symbol::STR_FROM_UTF8_RANGE => None,
Symbol::STR_TO_UTF8 => Some(StrToUtf8),
Symbol::STR_REPEAT => Some(StrRepeat),
Symbol::STR_TRIM => Some(StrTrim),
Symbol::STR_TRIM_LEFT => Some(StrTrimLeft),
Symbol::STR_TRIM_RIGHT => Some(StrTrimRight),
Symbol::STR_TO_DEC => Some(StrToNum),
Symbol::STR_TO_F64 => Some(StrToNum),
Symbol::STR_TO_F32 => Some(StrToNum),
Symbol::STR_TO_NAT => Some(StrToNum),
Symbol::STR_TO_U128 => Some(StrToNum),
Symbol::STR_TO_I128 => Some(StrToNum),
Symbol::STR_TO_U64 => Some(StrToNum),
Symbol::STR_TO_I64 => Some(StrToNum),
Symbol::STR_TO_U32 => Some(StrToNum),
Symbol::STR_TO_I32 => Some(StrToNum),
Symbol::STR_TO_U16 => Some(StrToNum),
Symbol::STR_TO_I16 => Some(StrToNum),
Symbol::STR_TO_U8 => Some(StrToNum),
Symbol::STR_TO_I8 => Some(StrToNum),
Symbol::LIST_LEN => Some(ListLen),
Symbol::LIST_GET => None,
Symbol::LIST_SET => None,
Symbol::LIST_SINGLE => Some(ListSingle),
Symbol::LIST_REPEAT => Some(ListRepeat),
Symbol::LIST_REVERSE => Some(ListReverse),
Symbol::LIST_CONCAT => Some(ListConcat),
Symbol::LIST_CONTAINS => Some(ListContains),
Symbol::LIST_APPEND => Some(ListAppend),
Symbol::LIST_PREPEND => Some(ListPrepend),
Symbol::LIST_JOIN => Some(ListJoin),
Symbol::LIST_RANGE => Some(ListRange),
Symbol::LIST_MAP => Some(ListMap),
Symbol::LIST_MAP2 => Some(ListMap2),
Symbol::LIST_MAP3 => Some(ListMap3),
Symbol::LIST_MAP4 => Some(ListMap4),
Symbol::LIST_MAP_WITH_INDEX => Some(ListMapWithIndex),
Symbol::LIST_KEEP_IF => Some(ListKeepIf),
Symbol::LIST_WALK => Some(ListWalk),
Symbol::LIST_WALK_UNTIL => Some(ListWalkUntil),
Symbol::LIST_WALK_BACKWARDS => Some(ListWalkBackwards),
Symbol::LIST_KEEP_OKS => Some(ListKeepOks),
Symbol::LIST_KEEP_ERRS => Some(ListKeepErrs),
Symbol::LIST_SORT_WITH => Some(ListSortWith),
Symbol::LIST_SUBLIST => Some(ListSublist),
Symbol::LIST_DROP_AT => Some(ListDropAt),
Symbol::LIST_SWAP => Some(ListSwap),
Symbol::LIST_ANY => Some(ListAny),
Symbol::LIST_ALL => Some(ListAll),
Symbol::LIST_FIND => None,
Symbol::DICT_LEN => Some(DictSize),
Symbol::DICT_EMPTY => Some(DictEmpty),
Symbol::DICT_INSERT => Some(DictInsert),
Symbol::DICT_REMOVE => Some(DictRemove),
Symbol::DICT_CONTAINS => Some(DictContains),
Symbol::DICT_GET => None,
Symbol::DICT_KEYS => Some(DictKeys),
Symbol::DICT_VALUES => Some(DictValues),
Symbol::DICT_UNION => Some(DictUnion),
Symbol::DICT_INTERSECTION => Some(DictIntersection),
Symbol::DICT_DIFFERENCE => Some(DictDifference),
Symbol::DICT_WALK => Some(DictWalk),
Symbol::SET_FROM_LIST => Some(SetFromList),
Symbol::NUM_ADD => Some(NumAdd),
Symbol::NUM_ADD_WRAP => Some(NumAddWrap),
Symbol::NUM_ADD_CHECKED => None,
Symbol::NUM_SUB => Some(NumSub),
Symbol::NUM_SUB_WRAP => Some(NumSubWrap),
Symbol::NUM_SUB_CHECKED => None,
Symbol::NUM_MUL => Some(NumMul),
Symbol::NUM_MUL_WRAP => Some(NumMulWrap),
Symbol::NUM_MUL_CHECKED => None,
Symbol::NUM_GT => Some(NumGt),
Symbol::NUM_GTE => Some(NumGte),
Symbol::NUM_LT => Some(NumLt),
Symbol::NUM_LTE => Some(NumLte),
Symbol::NUM_COMPARE => Some(NumCompare),
Symbol::NUM_DIV_FLOAT => None,
Symbol::NUM_DIV_CEIL => None,
Symbol::NUM_REM => None,
Symbol::NUM_IS_MULTIPLE_OF => Some(NumIsMultipleOf),
Symbol::NUM_ABS => Some(NumAbs),
Symbol::NUM_NEG => Some(NumNeg),
Symbol::NUM_SIN => Some(NumSin),
Symbol::NUM_COS => Some(NumCos),
Symbol::NUM_SQRT => None,
Symbol::NUM_LOG => None,
Symbol::NUM_ROUND => Some(NumRound),
Symbol::NUM_TO_FLOAT => Some(NumToFloat),
Symbol::NUM_POW => Some(NumPow),
Symbol::NUM_CEILING => Some(NumCeiling),
Symbol::NUM_POW_INT => Some(NumPowInt),
Symbol::NUM_FLOOR => Some(NumFloor),
Symbol::NUM_TO_STR => Some(NumToStr),
// => Some(NumIsFinite),
Symbol::NUM_ATAN => Some(NumAtan),
Symbol::NUM_ACOS => Some(NumAcos),
Symbol::NUM_ASIN => Some(NumAsin),
Symbol::NUM_BYTES_TO_U16 => None,
Symbol::NUM_BYTES_TO_U32 => None,
Symbol::NUM_BITWISE_AND => Some(NumBitwiseAnd),
Symbol::NUM_BITWISE_XOR => Some(NumBitwiseXor),
Symbol::NUM_BITWISE_OR => Some(NumBitwiseOr),
Symbol::NUM_SHIFT_LEFT => Some(NumShiftLeftBy),
Symbol::NUM_SHIFT_RIGHT => Some(NumShiftRightBy),
Symbol::NUM_SHIFT_RIGHT_ZERO_FILL => Some(NumShiftRightZfBy),
Symbol::NUM_INT_CAST => Some(NumIntCast),
Symbol::BOOL_EQ => Some(Eq),
Symbol::BOOL_NEQ => Some(NotEq),
Symbol::BOOL_AND => Some(And),
Symbol::BOOL_OR => Some(Or),
Symbol::BOOL_NOT => Some(Not),
// => Some(Hash),
// => Some(ExpectTrue),
_ => None,
Symbol::STR_CONCAT => CanBeReplacedBy(StrConcat),
Symbol::STR_JOIN_WITH => CanBeReplacedBy(StrJoinWith),
Symbol::STR_IS_EMPTY => CanBeReplacedBy(StrIsEmpty),
Symbol::STR_STARTS_WITH => CanBeReplacedBy(StrStartsWith),
Symbol::STR_STARTS_WITH_CODE_PT => CanBeReplacedBy(StrStartsWithCodePt),
Symbol::STR_ENDS_WITH => CanBeReplacedBy(StrEndsWith),
Symbol::STR_SPLIT => CanBeReplacedBy(StrSplit),
Symbol::STR_COUNT_GRAPHEMES => CanBeReplacedBy(StrCountGraphemes),
Symbol::STR_FROM_UTF8 => WrapperIsRequired,
Symbol::STR_FROM_UTF8_RANGE => WrapperIsRequired,
Symbol::STR_TO_UTF8 => CanBeReplacedBy(StrToUtf8),
Symbol::STR_REPEAT => CanBeReplacedBy(StrRepeat),
Symbol::STR_TRIM => CanBeReplacedBy(StrTrim),
Symbol::STR_TRIM_LEFT => CanBeReplacedBy(StrTrimLeft),
Symbol::STR_TRIM_RIGHT => CanBeReplacedBy(StrTrimRight),
Symbol::STR_TO_DEC => WrapperIsRequired,
Symbol::STR_TO_F64 => WrapperIsRequired,
Symbol::STR_TO_F32 => WrapperIsRequired,
Symbol::STR_TO_NAT => WrapperIsRequired,
Symbol::STR_TO_U128 => WrapperIsRequired,
Symbol::STR_TO_I128 => WrapperIsRequired,
Symbol::STR_TO_U64 => WrapperIsRequired,
Symbol::STR_TO_I64 => WrapperIsRequired,
Symbol::STR_TO_U32 => WrapperIsRequired,
Symbol::STR_TO_I32 => WrapperIsRequired,
Symbol::STR_TO_U16 => WrapperIsRequired,
Symbol::STR_TO_I16 => WrapperIsRequired,
Symbol::STR_TO_U8 => WrapperIsRequired,
Symbol::STR_TO_I8 => WrapperIsRequired,
Symbol::LIST_LEN => CanBeReplacedBy(ListLen),
Symbol::LIST_GET => WrapperIsRequired,
Symbol::LIST_SET => WrapperIsRequired,
Symbol::LIST_SINGLE => CanBeReplacedBy(ListSingle),
Symbol::LIST_REPEAT => CanBeReplacedBy(ListRepeat),
Symbol::LIST_REVERSE => CanBeReplacedBy(ListReverse),
Symbol::LIST_CONCAT => CanBeReplacedBy(ListConcat),
Symbol::LIST_CONTAINS => CanBeReplacedBy(ListContains),
Symbol::LIST_APPEND => CanBeReplacedBy(ListAppend),
Symbol::LIST_PREPEND => CanBeReplacedBy(ListPrepend),
Symbol::LIST_JOIN => CanBeReplacedBy(ListJoin),
Symbol::LIST_RANGE => CanBeReplacedBy(ListRange),
Symbol::LIST_MAP => CanBeReplacedBy(ListMap),
Symbol::LIST_MAP2 => CanBeReplacedBy(ListMap2),
Symbol::LIST_MAP3 => CanBeReplacedBy(ListMap3),
Symbol::LIST_MAP4 => CanBeReplacedBy(ListMap4),
Symbol::LIST_MAP_WITH_INDEX => CanBeReplacedBy(ListMapWithIndex),
Symbol::LIST_KEEP_IF => CanBeReplacedBy(ListKeepIf),
Symbol::LIST_WALK => CanBeReplacedBy(ListWalk),
Symbol::LIST_WALK_UNTIL => CanBeReplacedBy(ListWalkUntil),
Symbol::LIST_WALK_BACKWARDS => CanBeReplacedBy(ListWalkBackwards),
Symbol::LIST_KEEP_OKS => CanBeReplacedBy(ListKeepOks),
Symbol::LIST_KEEP_ERRS => CanBeReplacedBy(ListKeepErrs),
Symbol::LIST_SORT_WITH => CanBeReplacedBy(ListSortWith),
Symbol::LIST_SUBLIST => CanBeReplacedBy(ListSublist),
Symbol::LIST_DROP_AT => CanBeReplacedBy(ListDropAt),
Symbol::LIST_SWAP => CanBeReplacedBy(ListSwap),
Symbol::LIST_ANY => CanBeReplacedBy(ListAny),
Symbol::LIST_ALL => CanBeReplacedBy(ListAll),
Symbol::LIST_FIND => WrapperIsRequired,
Symbol::DICT_LEN => CanBeReplacedBy(DictSize),
Symbol::DICT_EMPTY => CanBeReplacedBy(DictEmpty),
Symbol::DICT_INSERT => CanBeReplacedBy(DictInsert),
Symbol::DICT_REMOVE => CanBeReplacedBy(DictRemove),
Symbol::DICT_CONTAINS => CanBeReplacedBy(DictContains),
Symbol::DICT_GET => WrapperIsRequired,
Symbol::DICT_KEYS => CanBeReplacedBy(DictKeys),
Symbol::DICT_VALUES => CanBeReplacedBy(DictValues),
Symbol::DICT_UNION => CanBeReplacedBy(DictUnion),
Symbol::DICT_INTERSECTION => CanBeReplacedBy(DictIntersection),
Symbol::DICT_DIFFERENCE => CanBeReplacedBy(DictDifference),
Symbol::DICT_WALK => CanBeReplacedBy(DictWalk),
Symbol::SET_FROM_LIST => CanBeReplacedBy(SetFromList),
Symbol::NUM_ADD => CanBeReplacedBy(NumAdd),
Symbol::NUM_ADD_WRAP => CanBeReplacedBy(NumAddWrap),
Symbol::NUM_ADD_CHECKED => WrapperIsRequired,
Symbol::NUM_SUB => CanBeReplacedBy(NumSub),
Symbol::NUM_SUB_WRAP => CanBeReplacedBy(NumSubWrap),
Symbol::NUM_SUB_CHECKED => WrapperIsRequired,
Symbol::NUM_MUL => CanBeReplacedBy(NumMul),
Symbol::NUM_MUL_WRAP => CanBeReplacedBy(NumMulWrap),
Symbol::NUM_MUL_CHECKED => WrapperIsRequired,
Symbol::NUM_GT => CanBeReplacedBy(NumGt),
Symbol::NUM_GTE => CanBeReplacedBy(NumGte),
Symbol::NUM_LT => CanBeReplacedBy(NumLt),
Symbol::NUM_LTE => CanBeReplacedBy(NumLte),
Symbol::NUM_COMPARE => CanBeReplacedBy(NumCompare),
Symbol::NUM_DIV_FLOAT => WrapperIsRequired,
Symbol::NUM_DIV_CEIL => WrapperIsRequired,
Symbol::NUM_REM => WrapperIsRequired,
Symbol::NUM_IS_MULTIPLE_OF => CanBeReplacedBy(NumIsMultipleOf),
Symbol::NUM_ABS => CanBeReplacedBy(NumAbs),
Symbol::NUM_NEG => CanBeReplacedBy(NumNeg),
Symbol::NUM_SIN => CanBeReplacedBy(NumSin),
Symbol::NUM_COS => CanBeReplacedBy(NumCos),
Symbol::NUM_SQRT => WrapperIsRequired,
Symbol::NUM_LOG => WrapperIsRequired,
Symbol::NUM_ROUND => CanBeReplacedBy(NumRound),
Symbol::NUM_TO_FLOAT => CanBeReplacedBy(NumToFloat),
Symbol::NUM_POW => CanBeReplacedBy(NumPow),
Symbol::NUM_CEILING => CanBeReplacedBy(NumCeiling),
Symbol::NUM_POW_INT => CanBeReplacedBy(NumPowInt),
Symbol::NUM_FLOOR => CanBeReplacedBy(NumFloor),
Symbol::NUM_TO_STR => CanBeReplacedBy(NumToStr),
// => CanBeReplacedBy(NumIsFinite),
Symbol::NUM_ATAN => CanBeReplacedBy(NumAtan),
Symbol::NUM_ACOS => CanBeReplacedBy(NumAcos),
Symbol::NUM_ASIN => CanBeReplacedBy(NumAsin),
Symbol::NUM_BYTES_TO_U16 => WrapperIsRequired,
Symbol::NUM_BYTES_TO_U32 => WrapperIsRequired,
Symbol::NUM_BITWISE_AND => CanBeReplacedBy(NumBitwiseAnd),
Symbol::NUM_BITWISE_XOR => CanBeReplacedBy(NumBitwiseXor),
Symbol::NUM_BITWISE_OR => CanBeReplacedBy(NumBitwiseOr),
Symbol::NUM_SHIFT_LEFT => CanBeReplacedBy(NumShiftLeftBy),
Symbol::NUM_SHIFT_RIGHT => CanBeReplacedBy(NumShiftRightBy),
Symbol::NUM_SHIFT_RIGHT_ZERO_FILL => CanBeReplacedBy(NumShiftRightZfBy),
Symbol::NUM_INT_CAST => CanBeReplacedBy(NumIntCast),
Symbol::BOOL_EQ => CanBeReplacedBy(Eq),
Symbol::BOOL_NEQ => CanBeReplacedBy(NotEq),
Symbol::BOOL_AND => CanBeReplacedBy(And),
Symbol::BOOL_OR => CanBeReplacedBy(Or),
Symbol::BOOL_NOT => CanBeReplacedBy(Not),
// => CanBeReplacedBy(Hash),
// => CanBeReplacedBy(ExpectTrue),
_ => NotALowLevelWrapper,
}
}
}