Calculate whether an inlining is safe

It's safe if all top level arguments are used at most once, meaning that
there's no risk of duplication.
This commit is contained in:
Edwin Brady 2021-05-11 00:12:23 +01:00
parent 251d77b92d
commit efaf290d88
6 changed files with 206 additions and 31 deletions

View File

@ -103,6 +103,7 @@ public export
($>) fa b = map (const b) fa
||| Run something for effects, throwing away the return value.
%inline
public export
ignore : Functor f => f a -> f ()
ignore = map (const ())

View File

@ -1,5 +1,6 @@
module TTImp.Elab.Case
import Core.CaseTree
import Core.Context
import Core.Context.Log
import Core.Core
@ -226,13 +227,6 @@ caseBlock {vars} rigc elabinfo fc nest env scr scrtm scrty caseRig alts expected
setFlag fc (Resolved cidx) (SetTotal PartialOK)
let caseRef : Term vars = Ref fc Func (Resolved cidx)
-- If there's no duplication of the scrutinee in the block,
-- inline it.
-- This will be the case either if the scrutinee is a variable, in
-- which case the duplication won't hurt, or if (TODO) none of the
-- case patterns in alts are just a variable
maybe (pure ()) (const (setFlag fc casen Inline)) splitOn
let applyEnv = applyToFull fc caseRef env
let appTm : Term vars
= maybe (App fc applyEnv scrtm)
@ -254,6 +248,17 @@ caseBlock {vars} rigc elabinfo fc nest env scr scrtm scrty caseRig alts expected
let olddelayed = delayedElab ust
put UST (record { delayedElab = [] } ust)
processDecl [InCase] nest' [] (IDef fc casen alts')
-- If there's no duplication of the scrutinee in the block,
-- flag it as inlinable.
-- This will be the case either if the scrutinee is a variable, in
-- which case the duplication won't hurt, or if there's no variable
-- duplicated in the body (what ghc calls W-safe)
-- We'll check that second condition later, after generating the
-- runtime (erased) case trees
let inlineOK = maybe False (const True) splitOn
when inlineOK $ setFlag fc casen Inline
ust <- get UST
put UST (record { delayedElab = olddelayed } ust)

View File

@ -1,5 +1,6 @@
module TTImp.Elab.Utils
import Core.CaseTree
import Core.Context
import Core.Core
import Core.Env
@ -116,3 +117,169 @@ bindReq {vs = n :: _} fc (b :: env) (KeepCons p) ns tm
(Bind fc _ (Pi (binderLoc b) (multiplicity b) Explicit (binderType b')) tm)
bindReq fc (b :: env) (DropCons p) ns tm
= bindReq fc env p ns tm
-- This machinery is to calculate whether any top level argument is used
-- more than once in a case block, in which case inlining wouldn't be safe
-- since it might duplicate work.
data ArgUsed = Used1 -- been used
| Used0 -- not used
| LocalVar -- don't care if it's used
data Usage : List Name -> Type where
Nil : Usage []
(::) : ArgUsed -> Usage xs -> Usage (x :: xs)
initUsed : (xs : List Name) -> Usage xs
initUsed [] = []
initUsed (x :: xs) = Used0 :: initUsed xs
initUsedCase : (xs : List Name) -> Usage xs
initUsedCase [] = []
initUsedCase [x] = [Used0]
initUsedCase (x :: xs) = LocalVar :: initUsedCase xs
setUsedVar : {idx : _} ->
(0 _ : IsVar n idx xs) -> Usage xs -> Usage xs
setUsedVar First (Used0 :: us) = Used1 :: us
setUsedVar (Later p) (x :: us) = x :: setUsedVar p us
setUsedVar First us = us
isUsed : {idx : _} ->
(0 _ : IsVar n idx xs) -> Usage xs -> Bool
isUsed First (Used1 :: us) = True
isUsed First (_ :: us) = False
isUsed (Later p) (_ :: us) = isUsed p us
data Used : Type where
setUsed : {idx : _} ->
{auto u : Ref Used (Usage vars)} ->
(0 _ : IsVar n idx vars) -> Core ()
setUsed p
= do used <- get Used
put Used (setUsedVar p used)
extendUsed : ArgUsed -> (new : List Name) -> Usage vars -> Usage (new ++ vars)
extendUsed a [] x = x
extendUsed a (y :: xs) x = a :: extendUsed a xs x
dropUsed : (new : List Name) -> Usage (new ++ vars) -> Usage vars
dropUsed [] x = x
dropUsed (x :: xs) (u :: us) = dropUsed xs us
inExtended : ArgUsed -> (new : List Name) ->
{auto u : Ref Used (Usage vars)} ->
(Ref Used (Usage (new ++ vars)) -> Core a) ->
Core a
inExtended a new sc
= do used <- get Used
u' <- newRef Used (extendUsed a new used)
res <- sc u'
put Used (dropUsed new !(get Used @{u'}))
pure res
termInlineSafe : {vars : _} ->
{auto u : Ref Used (Usage vars)} ->
Term vars -> Core Bool
termInlineSafe (Local fc isLet idx p)
= if isUsed p !(get Used)
then pure False
else do setUsed p
pure True
termInlineSafe (Meta fc x y xs)
= allInlineSafe xs
where
allInlineSafe : List (Term vars) -> Core Bool
allInlineSafe [] = pure True
allInlineSafe (x :: xs)
= do xok <- termInlineSafe x
if xok
then allInlineSafe xs
else pure False
termInlineSafe (Bind fc x b scope)
= do bok <- binderInlineSafe b
if bok
then inExtended LocalVar [x] (\u' => termInlineSafe scope)
else pure False
where
binderInlineSafe : Binder (Term vars) -> Core Bool
binderInlineSafe (Let _ _ val _) = termInlineSafe val
binderInlineSafe _ = pure True
termInlineSafe (App fc fn arg)
= do fok <- termInlineSafe fn
if fok
then termInlineSafe arg
else pure False
termInlineSafe (As fc x as pat) = termInlineSafe pat
termInlineSafe (TDelayed fc x ty) = termInlineSafe ty
termInlineSafe (TDelay fc x ty arg) = termInlineSafe arg
termInlineSafe (TForce fc x val) = termInlineSafe val
termInlineSafe _ = pure True
mutual
caseInlineSafe : {vars : _} ->
{auto u : Ref Used (Usage vars)} ->
CaseTree vars -> Core Bool
caseInlineSafe (Case idx p scTy xs)
= if isUsed p !(get Used)
then pure False
else do setUsed p
altsSafe xs
where
altsSafe : List (CaseAlt vars) -> Core Bool
altsSafe [] = pure True
altsSafe (a :: as)
= do u <- get Used
aok <- caseAltInlineSafe a
if aok
then do -- We can reset the usage information, because we're
-- only going to use one alternative at a time
put Used u
altsSafe as
else pure False
caseInlineSafe (STerm x tm) = termInlineSafe tm
caseInlineSafe (Unmatched msg) = pure True
caseInlineSafe Impossible = pure True
caseAltInlineSafe : {vars : _} ->
{auto u : Ref Used (Usage vars)} ->
CaseAlt vars -> Core Bool
caseAltInlineSafe (ConCase x tag args sc)
= inExtended Used0 args (\u' => caseInlineSafe sc)
caseAltInlineSafe (DelayCase ty arg sc)
= inExtended Used0 [ty, arg] (\u' => caseInlineSafe sc)
caseAltInlineSafe (ConstCase x sc) = caseInlineSafe sc
caseAltInlineSafe (DefaultCase sc) = caseInlineSafe sc
-- An inlining is safe if no variable is used more than once in the tree,
-- which means that there's no risk of an input being evaluated more than
-- once after the definition is expanded.
export
inlineSafe : {vars : _} ->
CaseTree vars -> Core Bool
inlineSafe t
= do u <- newRef Used (initUsed vars)
caseInlineSafe t
export
canInlineDef : {auto c : Ref Ctxt Defs} ->
Name -> Core Bool
canInlineDef n
= do defs <- get Ctxt
Just (PMDef _ _ _ rtree _) <- lookupDefExact n (gamma defs)
| _ => pure False
inlineSafe rtree
-- This is a special case because the only argument we actually care about
-- is the last one, since the others are just variables passed through from
-- the environment, and duplicating a variable doesn't cost anything.
export
canInlineCaseBlock : {auto c : Ref Ctxt Defs} ->
Name -> Core Bool
canInlineCaseBlock n
= do defs <- get Ctxt
Just (PMDef _ vars _ rtree _) <- lookupDefExact n (gamma defs)
| _ => pure False
u <- newRef Used (initUsedCase vars)
caseInlineSafe rtree

View File

@ -750,7 +750,22 @@ mkRunTime fc n
ignore $ addDef n $
record { definition = PMDef r rargs tree_ct tree_rt pats
} gdef
-- If it's a case block, and not already set as inlinable,
-- check if it's safe to inline
when (caseName !(toFullNames n) && noInline (flags gdef)) $
do inl <- canInlineCaseBlock n
when inl $ setFlag fc n Inline
where
noInline : List DefFlag -> Bool
noInline (Inline :: _) = False
noInline (x :: xs) = noInline xs
noInline _ = True
caseName : Name -> Bool
caseName (CaseBlock _ _) = True
caseName (NS _ n) = caseName n
caseName _ = False
mkCrash : {vars : _} -> String -> Term vars
mkCrash msg
= apply fc (Ref fc Func (NS builtinNS (UN "idris_crash")))

View File

@ -5,10 +5,8 @@ prim__mul_Integer = [{arg:N}, {arg:N}]: (*Integer [!{arg:N}, !{arg:N}])
Main.plus = [{arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 0 !{arg:N})] Just (%let {e:N} (-Integer [!{arg:N}, 1]) (+Integer [1, (Main.plus [!{e:N}, !{arg:N}])])))
Main.main = [{ext:N}]: (Main.plus [(+Integer [1, 0]), (+Integer [1, (+Integer [1, 0])])])
Builtin.believe_me = [{ext:N}]: (believe_me [___, ___, !{ext:N}])
Prelude.Types.case block in prim__integerToNat = [{arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 (Builtin.believe_me [!{arg:N}])), (%constcase 0 0)] Nothing)
Prelude.Types.prim__integerToNat = [{arg:N}]: (Prelude.Types.case block in prim__integerToNat [!{arg:N}, (%case (<=Integer [0, !{arg:N}]) [(%constcase 0 0)] Just 1)])
PrimIO.case block in unsafePerformIO = [{arg:N}, {arg:N}]: (PrimIO.unsafeDestroyWorld [___, !{arg:N}])
PrimIO.unsafePerformIO = [{arg:N}]: (PrimIO.unsafeCreateWorld [(%lam w (PrimIO.case block in unsafePerformIO [!{arg:N}, (!{arg:N} [!w])]))])
Prelude.Types.prim__integerToNat = [{arg:N}]: (%case (%case (<=Integer [0, !{arg:N}]) [(%constcase 0 0)] Just 1) [(%constcase 1 (Builtin.believe_me [!{arg:N}])), (%constcase 0 0)] Nothing)
PrimIO.unsafePerformIO = [{arg:N}]: (PrimIO.unsafeCreateWorld [(%lam w (PrimIO.unsafeDestroyWorld [___, (!{arg:N} [!w])]))])
PrimIO.unsafeDestroyWorld = [{arg:N}, {arg:N}]: !{arg:N}
PrimIO.unsafeCreateWorld = [{arg:N}]: (!{arg:N} [%MkWorld])

View File

@ -8,31 +8,21 @@ Builtin.snd = [{arg:N}]: (%case !{arg:N} [(%concase [cons] Builtin.MkPair Just 0
Builtin.idris_crash = [{ext:N}]: (crash [___, !{ext:N}])
Builtin.fst = [{arg:N}]: (%case !{arg:N} [(%concase [cons] Builtin.MkPair Just 0 [{e:N}, {e:N}] !{e:N})] Nothing)
Builtin.believe_me = [{ext:N}]: (believe_me [___, ___, !{ext:N}])
Prelude.Types.case block in case block in rangeFromTo = [{arg:N}, {arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 (Prelude.Types.takeUntil [(%lam {arg:N} (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)), (Prelude.Types.countFrom [!{arg:N}, (%lam x (%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [!x]) [(%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] (!{e:N} [1]))] Nothing))] Nothing)]))] Nothing))])])), (%constcase 0 (%con [cons] Prelude.Types.:: Just 1 [!{arg:N}, (%con [nil] Prelude.Types.Nil Just 0 [])]))] Nothing)
Prelude.Types.case block in rangeFromTo = [{arg:N}, {arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 (Prelude.Types.takeUntil [(%lam {arg:N} (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)), (Prelude.Types.countFrom [!{arg:N}, (%lam {arg:N} (%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [(%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] (!{e:N} [1]))] Nothing))] Nothing)]))] Nothing))] Nothing))])])), (%constcase 0 (Prelude.Types.case block in case block in rangeFromTo [!{arg:N}, !{arg:N}, !{arg:N}, (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)]))] Nothing)
Prelude.Types.case block in takeUntil = [{arg:N}, {arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 (%con [cons] Prelude.Types.:: Just 1 [!{arg:N}, (%con [nil] Prelude.Types.Nil Just 0 [])])), (%constcase 0 (%con [cons] Prelude.Types.:: Just 1 [!{arg:N}, (Prelude.Types.takeUntil [!{arg:N}, (%force Inf !{arg:N})])]))] Nothing)
Prelude.Types.case block in prim__integerToNat = [{arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 (Builtin.believe_me [!{arg:N}])), (%constcase 0 0)] Nothing)
Prelude.Types.rangeFromTo = [{arg:N}, {arg:N}, {arg:N}]: (Prelude.Types.case block in rangeFromTo [!{arg:N}, !{arg:N}, !{arg:N}, (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)])
Prelude.Types.rangeFromTo = [{arg:N}, {arg:N}, {arg:N}]: (%case (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing) [(%constcase 1 (Prelude.Types.takeUntil [(%lam {arg:N} (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)), (Prelude.Types.countFrom [!{arg:N}, (%lam {arg:N} (%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [(%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] (!{e:N} [1]))] Nothing))] Nothing)]))] Nothing))] Nothing))])])), (%constcase 0 (%case (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing) [(%constcase 1 (Prelude.Types.takeUntil [(%lam {arg:N} (%case (Builtin.fst [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.EqOrd.MkOrd Just 0 [{e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}, {e:N}] ((!{e:N} [!{arg:N}]) [!{arg:N}]))] Nothing)), (Prelude.Types.countFrom [!{arg:N}, (%lam x (%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [!x]) [(%case (Builtin.snd [(Builtin.snd [!{arg:N}])]) [(%concase Prelude.Num.MkNeg Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] (!{e:N} [1]))] Nothing))] Nothing)]))] Nothing))])])), (%constcase 0 (%con [cons] Prelude.Types.:: Just 1 [!{arg:N}, (%con [nil] Prelude.Types.Nil Just 0 [])]))] Nothing))] Nothing)
Prelude.Types.null = [{arg:N}]: (%case !{arg:N} [(%concase [nil] Prelude.Types.Nil Just 0 [] (%delay Lazy 1)), (%concase [cons] Prelude.Types.:: Just 1 [{e:N}, {e:N}] (%delay Lazy 0))] Nothing)
Prelude.Types.foldr = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%concase [nil] Prelude.Types.Nil Just 0 [] !{arg:N}), (%concase [cons] Prelude.Types.:: Just 1 [{e:N}, {e:N}] ((!{arg:N} [!{e:N}]) [(Prelude.Types.foldr [!{arg:N}, !{arg:N}, !{e:N}])]))] Nothing)
Prelude.Types.foldl = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%concase [nil] Prelude.Types.Nil Just 0 [] !{arg:N}), (%concase [cons] Prelude.Types.:: Just 1 [{e:N}, {e:N}] (Prelude.Types.foldl [!{arg:N}, ((!{arg:N} [!{arg:N}]) [!{e:N}]), !{e:N}]))] Nothing)
Prelude.Types.foldlM = [{arg:N}, {arg:N}, {arg:N}, {ext:N}]: (Prelude.Types.foldl [(%lam ma (%lam b (%case !{arg:N} [(%concase Prelude.Interfaces.MkMonad Just 0 [{e:N}, {e:N}, {e:N}] ((((!{e:N} [___]) [___]) [!ma]) [(%lam {eta:N} (Prelude.Basics.flip [!{arg:N}, !b, !{eta:N}]))]))] Nothing))), (%case !{arg:N} [(%concase Prelude.Interfaces.MkMonad Just 0 [{e:N}, {e:N}, {e:N}] (%case !{e:N} [(%concase Prelude.Interfaces.MkApplicative Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [___]) [!{arg:N}]))] Nothing))] Nothing), !{ext:N}])
Prelude.Types.takeUntil = [{arg:N}, {arg:N}]: (%case !{arg:N} [(%concase [cons] Prelude.Types.Stream.:: Just 0 [{e:N}, {e:N}] (Prelude.Types.case block in takeUntil [!{e:N}, !{e:N}, !{arg:N}, (!{arg:N} [!{e:N}])]))] Nothing)
Prelude.Types.prim__integerToNat = [{arg:N}]: (Prelude.Types.case block in prim__integerToNat [!{arg:N}, (%case (<=Integer [0, !{arg:N}]) [(%constcase 0 0)] Just 1)])
Prelude.Types.takeUntil = [{arg:N}, {arg:N}]: (%case !{arg:N} [(%concase [cons] Prelude.Types.Stream.:: Just 0 [{e:N}, {e:N}] (%case (!{arg:N} [!{e:N}]) [(%constcase 1 (%con [cons] Prelude.Types.:: Just 1 [!{e:N}, (%con [nil] Prelude.Types.Nil Just 0 [])])), (%constcase 0 (%con [cons] Prelude.Types.:: Just 1 [!{e:N}, (Prelude.Types.takeUntil [!{arg:N}, (%force Inf !{e:N})])]))] Nothing))] Nothing)
Prelude.Types.prim__integerToNat = [{arg:N}]: (%case (%case (<=Integer [0, !{arg:N}]) [(%constcase 0 0)] Just 1) [(%constcase 1 (Builtin.believe_me [!{arg:N}])), (%constcase 0 0)] Nothing)
Prelude.Types.countFrom = [{arg:N}, {arg:N}]: (%con [cons] Prelude.Types.Stream.:: Just 0 [!{arg:N}, (%delay Inf (Prelude.Types.countFrom [(!{arg:N} [!{arg:N}]), !{arg:N}]))])
Prelude.Num.case block in mod = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 0 (%Int [!{arg:N}, !{arg:N}]))] Just (Builtin.idris_crash ["Unhandled input for Prelude.Num.case block in mod at Prelude/Num.idr:L:C--L:C"]))
Prelude.Num.case block in div = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 0 (/Int [!{arg:N}, !{arg:N}]))] Just (Builtin.idris_crash ["Unhandled input for Prelude.Num.case block in div at Prelude/Num.idr:L:C--L:C"]))
Prelude.Num.negate = [{arg:N}]: (-Int [0, !{arg:N}])
Prelude.Num.mod = [{arg:N}, {arg:N}]: (Prelude.Num.case block in mod [!{arg:N}, !{arg:N}, (Prelude.EqOrd.== [!{arg:N}, (cast-Integer-Int [0])])])
Prelude.Num.div = [{arg:N}, {arg:N}]: (Prelude.Num.case block in div [!{arg:N}, !{arg:N}, (Prelude.EqOrd.== [!{arg:N}, (cast-Integer-Int [0])])])
Prelude.Num.mod = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.== [!{arg:N}, (cast-Integer-Int [0])]) [(%constcase 0 (%Int [!{arg:N}, !{arg:N}]))] Just (Builtin.idris_crash ["Unhandled input for Prelude.Num.case block in mod at Prelude/Num.idr:L:C--L:C"]))
Prelude.Num.div = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.== [!{arg:N}, (cast-Integer-Int [0])]) [(%constcase 0 (/Int [!{arg:N}, !{arg:N}]))] Just (Builtin.idris_crash ["Unhandled input for Prelude.Num.case block in div at Prelude/Num.idr:L:C--L:C"]))
Prelude.Num.- = [{ext:N}, {ext:N}]: (-Int [!{ext:N}, !{ext:N}])
Prelude.EqOrd.case block in case block in compare = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 1), (%constcase 0 2)] Nothing)
Prelude.EqOrd.case block in compare = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 0), (%constcase 0 (Prelude.EqOrd.case block in case block in compare [!{arg:N}, !{arg:N}, (Prelude.EqOrd.== [!{arg:N}, !{arg:N}])]))] Nothing)
Prelude.EqOrd.case block in max = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 !{arg:N}), (%constcase 0 !{arg:N})] Nothing)
Prelude.EqOrd.case block in min = [{arg:N}, {arg:N}, {arg:N}]: (%case !{arg:N} [(%constcase 1 !{arg:N}), (%constcase 0 !{arg:N})] Nothing)
Prelude.EqOrd.min = [{arg:N}, {arg:N}]: (Prelude.EqOrd.case block in min [!{arg:N}, !{arg:N}, (Prelude.EqOrd.< [!{arg:N}, !{arg:N}])])
Prelude.EqOrd.max = [{arg:N}, {arg:N}]: (Prelude.EqOrd.case block in max [!{arg:N}, !{arg:N}, (Prelude.EqOrd.> [!{arg:N}, !{arg:N}])])
Prelude.EqOrd.compare = [{arg:N}, {arg:N}]: (Prelude.EqOrd.case block in compare [!{arg:N}, !{arg:N}, (Prelude.EqOrd.< [!{arg:N}, !{arg:N}])])
Prelude.EqOrd.min = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.< [!{arg:N}, !{arg:N}]) [(%constcase 1 !{arg:N}), (%constcase 0 !{arg:N})] Nothing)
Prelude.EqOrd.max = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.> [!{arg:N}, !{arg:N}]) [(%constcase 1 !{arg:N}), (%constcase 0 !{arg:N})] Nothing)
Prelude.EqOrd.compare = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.< [!{arg:N}, !{arg:N}]) [(%constcase 1 0), (%constcase 0 (%case (Prelude.EqOrd.== [!{arg:N}, !{arg:N}]) [(%constcase 1 1), (%constcase 0 2)] Nothing))] Nothing)
Prelude.EqOrd.> = [{arg:N}, {arg:N}]: (%case (>Int [!{arg:N}, !{arg:N}]) [(%constcase 0 0)] Just 1)
Prelude.EqOrd.>= = [{arg:N}, {arg:N}]: (%case (>=Int [!{arg:N}, !{arg:N}]) [(%constcase 0 0)] Just 1)
Prelude.EqOrd.== = [{arg:N}, {arg:N}]: (%case (==Int [!{arg:N}, !{arg:N}]) [(%constcase 0 0)] Just 1)
@ -40,8 +30,7 @@ Prelude.EqOrd.< = [{arg:N}, {arg:N}]: (%case (<Int [!{arg:N}, !{arg:N}]) [(%cons
Prelude.EqOrd.<= = [{arg:N}, {arg:N}]: (%case (<=Int [!{arg:N}, !{arg:N}]) [(%constcase 0 0)] Just 1)
Prelude.EqOrd./= = [{arg:N}, {arg:N}]: (%case (Prelude.EqOrd.== [!{arg:N}, !{arg:N}]) [(%constcase 1 0), (%constcase 0 1)] Nothing)
Prelude.Interfaces.sum = [{arg:N}, {ext:N}]: (%case (Builtin.fst [!{arg:N}]) [(%concase Prelude.Interfaces.MkFoldable Just 0 [{e:N}, {e:N}, {e:N}, {e:N}] (((((!{e:N} [___]) [___]) [(%lam {eta:N} (%lam {eta:N} (%case (Builtin.snd [!{arg:N}]) [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] ((!{e:N} [!{eta:N}]) [!{eta:N}]))] Nothing)))]) [(%case (Builtin.snd [!{arg:N}]) [(%concase Prelude.Num.MkNum Just 0 [{e:N}, {e:N}, {e:N}] (!{e:N} [0]))] Nothing)]) [!{ext:N}]))] Nothing)
PrimIO.case block in unsafePerformIO = [{arg:N}, {arg:N}]: (PrimIO.unsafeDestroyWorld [___, !{arg:N}])
PrimIO.unsafePerformIO = [{arg:N}]: (PrimIO.unsafeCreateWorld [(%lam w (PrimIO.case block in unsafePerformIO [!{arg:N}, (!{arg:N} [!w])]))])
PrimIO.unsafePerformIO = [{arg:N}]: (PrimIO.unsafeCreateWorld [(%lam w (PrimIO.unsafeDestroyWorld [___, (!{arg:N} [!w])]))])
PrimIO.unsafeDestroyWorld = [{arg:N}, {arg:N}]: !{arg:N}
PrimIO.unsafeCreateWorld = [{arg:N}]: (!{arg:N} [%MkWorld])