Simon Peyton Jones pushed to branch wip/T27737 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Core/Opt/Simplify/Env.hs
    ... ... @@ -40,7 +40,7 @@ module GHC.Core.Opt.Simplify.Env (
    40 40
             SimplFloats(..), emptyFloats, isEmptyFloats, mkRecFloats,
    
    41 41
             mkFloatBind, addLetFloat, addLetFloats, addCaseFloat,
    
    42 42
             addJoinFloats, addFloats, addFloatBindsF,
    
    43
    -        extendFloats, isEmptyJoinFloats,
    
    43
    +        isEmptyJoinFloats,
    
    44 44
             doFloatFromRhs, getTopFloatBinds,
    
    45 45
     
    
    46 46
             FloatEnable(..), mapLetFloats,
    
    ... ... @@ -443,7 +443,7 @@ instance Outputable SimplFloats where
    443 443
     
    
    444 444
     emptyFloats :: SimplEnvIS -> SimplFloats
    
    445 445
     emptyFloats env
    
    446
    -  = SimplFloats { sfBinds   = nilOL
    
    446
    +  = SimplFloats { sfBinds   = emptyFloatBinds
    
    447 447
                     , sfJoins   = emptyJoinFloats
    
    448 448
                     , sfInScope = seInScope env }
    
    449 449
     
    
    ... ... @@ -962,14 +962,17 @@ addLetFloat :: SimplFloats -> OutBind -> SimplFloats
    962 962
     -- makes a FloatCase.
    
    963 963
     -- See Note [Using FloatBinds in SimplFloats]
    
    964 964
     addLetFloat floats bind
    
    965
    +  = assert (all (not . isJoinId) (bindersOf bind)) $
    
    966
    +    add_float floats (mkLetFloat bind)
    
    967
    +
    
    968
    +mkLetFloat :: OutBind -> FloatBind
    
    969
    +mkLetFloat bind
    
    965 970
       | NonRec bndr rhs <- bind
    
    966 971
       , needsCaseBinding (idType bndr) rhs
    
    967 972
       = -- This should never happen, but currently does because of #27910
    
    968
    -    add_float floats (FloatCase rhs bndr DEFAULT [])
    
    969
    -
    
    973
    +    FloatCase rhs bndr DEFAULT []
    
    970 974
       | otherwise
    
    971
    -  = assert (all (not . isJoinId) (bindersOf bind)) $
    
    972
    -    add_float floats (FloatLet bind)
    
    975
    +  = FloatLet bind
    
    973 976
     
    
    974 977
     addCaseFloat :: SimplFloats -> OutExpr -> OutId -> AltCon -> [OutVar] -> SimplFloats
    
    975 978
     -- Add a single-alternative case float
    
    ... ... @@ -1002,21 +1005,21 @@ mkFloatBind :: SimplEnv -> OutBind -> (SimplFloats, SimplEnv)
    1002 1005
     -- extend the incoming SimplEnv's in-scope set with its binders
    
    1003 1006
     -- These binders may already be in the in-scope set,
    
    1004 1007
     -- but may have by now been augmented with more IdInfo
    
    1008
    +-- Works for join-points as well as ordinary let-bindings
    
    1005 1009
     mkFloatBind env bind
    
    1006
    -  = (floats, env { seInScope = sfInScope floats })
    
    1010
    +  = (floats, env { seInScope = in_scope' })
    
    1007 1011
       where
    
    1012
    +    in_scope  = seInScope env
    
    1013
    +    in_scope' = in_scope `extendInScopeSetBind` bind
    
    1008 1014
         -- See Note [Bangs in the Simplifier]
    
    1009
    -    !floats = emptyFloats env `extendFloats` bind
    
    1010
    -
    
    1011
    -extendFloats :: SimplFloats -> OutBind -> SimplFloats
    
    1012
    --- Add this binding (join point or not) to the floats,
    
    1013
    --- and extend the in-scope env too
    
    1014
    -extendFloats floats@(SimplFloats { sfJoins = jfloats, sfInScope = in_scope }) bind
    
    1015
    -  | isJoinBind bind
    
    1016
    -  = floats { sfJoins = jfloats `addJoinFlts` unitJoinFloat bind
    
    1017
    -           , sfInScope    = in_scope `extendInScopeSetBind` bind }
    
    1018
    -  | otherwise
    
    1019
    -  = floats `addLetFloat` bind
    
    1015
    +    !floats | isJoinBind bind
    
    1016
    +            = SimplFloats { sfBinds   = emptyFloatBinds
    
    1017
    +                          , sfJoins   = unitJoinFloat bind
    
    1018
    +                          , sfInScope = in_scope' }
    
    1019
    +            | otherwise
    
    1020
    +            = SimplFloats { sfBinds   = unitOL (mkLetFloat bind)
    
    1021
    +                          , sfJoins   = emptyJoinFloats
    
    1022
    +                          , sfInScope = in_scope' }
    
    1020 1023
     
    
    1021 1024
     addLetFloats :: SimplFloats -> OrdList OutBind -> SimplFloats
    
    1022 1025
     -- Add the let-bindings /inside/ the existing floats,
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -36,6 +36,7 @@ import GHC.Core.Ppr ( pprCoreExpr )
    36 36
     import GHC.Core.Unfold
    
    37 37
     import GHC.Core.Unfold.Make
    
    38 38
     import GHC.Core.Utils
    
    39
    +import GHC.Core.Stats ( exprSize )
    
    39 40
     import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe
    
    40 41
                               , pushCoTyArg, pushCoValArg, exprIsDeadEnd
    
    41 42
                               , typeArity, arityTypeArity, etaExpandAT )
    
    ... ... @@ -600,6 +601,7 @@ tryCastWorkerWrapper :: SimplEnv -> BindContext
    600 601
                          -> InId -> OutId -> OutExpr
    
    601 602
                          -> SimplM (SimplFloats, SimplEnv)
    
    602 603
     -- See Note [Cast worker/wrapper]
    
    604
    +-- Binder /can/ be a JoinId
    
    603 605
     tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
    
    604 606
       | BC_Let top_lvl is_rec <- bind_cxt  -- Not join points
    
    605 607
       , not (isDFunId bndr) -- nor DFuns; cast w/w is no help, and we can't transform
    
    ... ... @@ -636,7 +638,7 @@ tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
    636 638
               else do { wrap_unf <- mkLetUnfolding env top_lvl VanillaSrc bndr False triv_rhs
    
    637 639
                       ; let bndr' = bndr `setInlinePragma` mkCastWrapperInlinePrag (idInlinePragma bndr)
    
    638 640
                                     `setIdUnfolding`  wrap_unf
    
    639
    -                        floats' = floats `extendFloats` NonRec bndr' triv_rhs
    
    641
    +                        floats' = floats `addLetFloat` NonRec bndr' triv_rhs
    
    640 642
                       ; return ( floats', setInScopeFromF env floats' ) } }
    
    641 643
       where
    
    642 644
         -- Force the occ_fs so that the old Id is not retained in the new Id.
    
    ... ... @@ -1655,6 +1657,10 @@ rebuildWithFloats :: SimplEnv -> SimplFloats -> OutExpr -> SimplCont
    1655 1657
                       -> SimplM (SimplFloats, OutExpr)
    
    1656 1658
     -- (rebuildWithFloats env floats expr cont) rebuilds (let floats in expr)
    
    1657 1659
     -- with continuation `cont`.  Used only when seCaseCase is off.
    
    1660
    +-- The only reason it differs from wrapFloats-then-rebuild is when
    
    1661
    +-- we can do case-of-known-constructor:
    
    1662
    +--     case (let <binds> in Just e) of Just x -> rhs
    
    1663
    +--     --> let <binds> in let x=e in rhs
    
    1658 1664
     -- See (COC3) in Note [sm_case_case: switching off case continuations]
    
    1659 1665
     rebuildWithFloats env floats expr cont
    
    1660 1666
       | Select { sc_bndr = bndr, sc_alts = alts, sc_env = se, sc_cont = cont' } <- cont
    
    ... ... @@ -2409,11 +2415,53 @@ simplOutExpr :: HasDebugCallStack
    2409 2415
     --
    
    2410 2416
     -- What if expr = (K x y) and cont is `Select`?  That is handled by rebuild.
    
    2411 2417
     --   (Why?  That's a bit inconsistent with beta.)
    
    2412
    -simplOutExpr env expr cont
    
    2418
    +simplOutExpr env _expr _cont
    
    2413 2419
       | assertPpr (checkSimplEnvIS env) (pprBadSimplEnvIS env) $
    
    2414 2420
         False  -- Just checks the assertion!
    
    2415 2421
       = panic "simplOutExpr"
    
    2416 2422
     
    
    2423
    +simplOutExpr env expr cont
    
    2424
    +  | contIsStop cont
    
    2425
    +  = rebuild_go env expr cont
    
    2426
    +
    
    2427
    +simplOutExpr env expr@(Var v) cont
    
    2428
    +  | isDataConWorkId v = rebuild_go env expr cont
    
    2429
    +  | otherwise         = simplOutId env v cont
    
    2430
    +simplOutExpr env (App fun (Type ty)) cont
    
    2431
    +  = simplOutExpr env fun (ApplyToTy { sc_arg_ty = ty, sc_hole_ty = exprType fun, sc_cont = cont })
    
    2432
    +simplOutExpr env (App fun arg) cont
    
    2433
    +  = simplOutExpr env fun (ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup, sc_cast = MRefl
    
    2434
    +                                 , sc_hole_ty = exprType fun, sc_cont = cont })
    
    2435
    +simplOutExpr env (Cast e co) cont
    
    2436
    +  = do { cont' <- pushCast env co cont; simplOutExpr env e cont' }
    
    2437
    +simplOutExpr env expr@(Lam {}) cont
    
    2438
    +  | hasArgs cont = reSimplifyOutExpr env expr cont  -- Beta-reduce
    
    2439
    +  | otherwise    = rebuild_go env expr cont
    
    2440
    +
    
    2441
    +simplOutExpr env expr@(Case {}) cont
    
    2442
    +  -- `cont` is not a Stop (first equation), so pushing it into the
    
    2443
    +  -- alternatives now saves leaving a case-of-case, or a (case ...) arg
    
    2444
    +  -- redex, for the next iteration.  But only for small expressions:
    
    2445
    +  -- see (RSO2) in Note [Re-simplifying an OutExpr]
    
    2446
    +  | exprSize expr <= reSimplifyThreshold = reSimplifyOutExpr env expr cont
    
    2447
    +  | otherwise                            = rebuild_go env expr cont
    
    2448
    +
    
    2449
    +simplOutExpr env expr@(Let {}) cont
    
    2450
    +  = -- For now just give up, but we could probably do better
    
    2451
    +    rebuild_go env expr cont
    
    2452
    +
    
    2453
    +simplOutExpr env expr@(Tick {}) cont
    
    2454
    +  = rebuild_go env expr cont
    
    2455
    +simplOutExpr env expr@(Coercion {}) cont
    
    2456
    +  = rebuild_go env expr cont
    
    2457
    +simplOutExpr env expr@(Lit {}) cont
    
    2458
    +  = rebuild_go env expr cont
    
    2459
    +
    
    2460
    +simplOutExpr _env expr@(Type {}) cont
    
    2461
    +  = pprPanic "simplOutExpr:Type" (ppr expr $$ ppr cont)
    
    2462
    +
    
    2463
    +
    
    2464
    +{-
    
    2417 2465
       | Lam {} <- expr
    
    2418 2466
       , cont_has_args
    
    2419 2467
       = simplLam env (occurAnalyseExpr expr) cont
    
    ... ... @@ -2440,6 +2488,80 @@ simplOutExpr env expr cont
    2440 2488
       = rebuild_go env expr cont
    
    2441 2489
       where
    
    2442 2490
         cont_has_args = hasArgs cont
    
    2491
    +-}
    
    2492
    +
    
    2493
    +reSimplifyOutExpr :: SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    2494
    +-- See Note [Re-simplifying an OutExpr]
    
    2495
    +reSimplifyOutExpr env expr cont
    
    2496
    +  = simplExprF env (occurAnalyseExpr expr) cont
    
    2497
    +
    
    2498
    +reSimplifyThreshold :: Int
    
    2499
    +-- See (RSO2) in Note [Re-simplifying an OutExpr]
    
    2500
    +reSimplifyThreshold = 100
    
    2501
    +
    
    2502
    +{- Note [Re-simplifying an OutExpr]
    
    2503
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    2504
    +simplOutExpr is given an already-simplified expression `expr` (an OutExpr,
    
    2505
    +typically from a `DoneEx` in the substitution) and a continuation `cont`.
    
    2506
    +If `expr` is a lambda and `cont` has arguments, or if `expr` is a `case` and
    
    2507
    +`cont` is not a Stop, we want to push `cont` into `expr`: beta-reduce, do
    
    2508
    +case-of-case, apply the arguments in each alternative, and so on.  Otherwise
    
    2509
    +the next Simplifier iteration would have to do it, and extra iterations are
    
    2510
    +expensive (T13056).
    
    2511
    +
    
    2512
    +We do this by simply running the Simplifier over `expr` again, with the
    
    2513
    +substitution-free environment `env` (a SimplEnvIS).  That re-simplification
    
    2514
    +is mostly a renaming pass, but it is essential: we must NOT treat the binders
    
    2515
    +inside `expr` as if they were already simplified (e.g. by building a `Select`
    
    2516
    +with `sc_env = Simplified`, so that the alternatives go through the SAF_Out
    
    2517
    +route and `simplAltBinders` neither clones nor records the alternative binders).
    
    2518
    +Here is why:
    
    2519
    +
    
    2520
    +* The binders inside an OutExpr are not in the in-scope set at the point where
    
    2521
    +  `expr` is used.  (The in-scope set records only binders that scope over the
    
    2522
    +  current point, not binders nested inside expressions in the substitution.)
    
    2523
    +
    
    2524
    +* Fresh uniques come from `uniqAway`, which deterministically picks the next
    
    2525
    +  unique above the largest in the in-scope set.  So a binder created while
    
    2526
    +  simplifying `expr` (at its original binding site) and a binder created later
    
    2527
    +  elsewhere, from an in-scope set that does not contain the former, can share
    
    2528
    +  a unique.
    
    2529
    +
    
    2530
    +* So if we pushed `cont` into the alternatives without cloning the alternative
    
    2531
    +  binders against the current in-scope set, free variables of `cont` could be
    
    2532
    +  captured; and any Core operation that relies on the in-scope set, such as
    
    2533
    +  `exprIsConApp_maybe`, may crash (T9630: lookupIdSubst panic).
    
    2534
    +
    
    2535
    +Re-simplifying with an empty substitution cures all this: `simplBinders`
    
    2536
    +clones every binder whose unique is in scope and extends the in-scope set
    
    2537
    +with every binder.  (This is also what happens when an unfolding is inlined.)
    
    2538
    +
    
    2539
    +Two further points:
    
    2540
    +
    
    2541
    +(RSO1) We occurrence-analyse `expr` first because its occurrence info may be
    
    2542
    +  stale: the Simplifier may have duplicated occurrences of binders inside
    
    2543
    +  `expr` (by case-of-case, say) without updating the binders' OccInfo.
    
    2544
    +  Compare Note [Occurrence-analyse after rule firing].
    
    2545
    +
    
    2546
    +(RSO2) The cost of re-simplifying is proportional to the size of `expr`, and
    
    2547
    +  that can go quadratic.  In T15630 we get a chain
    
    2548
    +      f1 = case f0 of {...};  f2 = case f1 of {...};  f3 = case f2 of {...}; ...
    
    2549
    +  where each `fi` is bound by knownCon (so its RHS is already an OutExpr and
    
    2550
    +  preInlineUnconditionally never sees it), occurs once, and so becomes a
    
    2551
    +  `DoneEx` via postInlineUnconditionally.  Its one occurrence is scrutinised
    
    2552
    +  by a case, so we arrive here with a `Select` continuation, and the
    
    2553
    +  re-simplified result of level i is contained in `expr` at level i+1.
    
    2554
    +  Re-simplifying at every level costs O(n^2) in the length of the chain,
    
    2555
    +  whereas simply rebuilding leaves case-of-case redexes that the next
    
    2556
    +  iteration deals with in one linear pass.
    
    2557
    +
    
    2558
    +  So we re-simplify only if `expr` is smaller than `reSimplifyThreshold`.
    
    2559
    +  That keeps the win on T13056 (whose re-simplified expressions all have
    
    2560
    +  size < 60, and where it saves a Simplifier iteration) and avoids the
    
    2561
    +  quadratic cost on T15630 and T15630a (chain members of size 100-320).
    
    2562
    +  A lambda applied to arguments is always re-simplified: beta-reduction is
    
    2563
    +  too good to miss.
    
    2564
    +-}
    
    2443 2565
     
    
    2444 2566
     ---------------------------------------------------------
    
    2445 2567
     simplOutId :: SimplEnvIS -> OutId -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    ... ... @@ -4369,11 +4491,36 @@ mkDupableContWithDmds env dmds
    4369 4491
             ; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
    
    4370 4492
             ; let env' = env `setInScopeFromF` floats1
    
    4371 4493
             ; arg' <- simplArg env' Nothing hole_ty se arg arg_mco
    
    4372
    -        ; (let_floats2, triv_arg) <- makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
    
    4494
    +        ; (let_floats2, dup_arg)
    
    4495
    +             <- if small_enough_to_dup dmd arg'
    
    4496
    +                then return (nilOL, arg')  -- See Note [Duplicating small arguments]
    
    4497
    +                else makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
    
    4373 4498
             ; let all_floats = floats1 `addLetFloats` let_floats2
    
    4374 4499
             ; return ( all_floats
    
    4375
    -                 , ApplyToVal { sc_arg = triv_arg, sc_env = Simplified OkDup
    
    4500
    +                 , ApplyToVal { sc_arg = dup_arg, sc_env = Simplified OkDup
    
    4376 4501
                                   , sc_cast = MRefl, sc_cont = cont', sc_hole_ty = hole_ty }) }
    
    4502
    +  where
    
    4503
    +    -- See Note [Duplicating small arguments]
    
    4504
    +    small_enough_to_dup dmd arg
    
    4505
    +      = not (isStrUsedDmd dmd) && exprIsDupable (sePlatform env) arg
    
    4506
    +
    
    4507
    +{- Note [Duplicating small arguments]
    
    4508
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    4509
    +When mkDupableCont makes an (ApplyToVal arg) continuation duplicable, it
    
    4510
    +let-binds the argument,  karg = arg, and duplicates (ApplyToVal karg).  So
    
    4511
    +     (case x of { A -> f; B -> g }) arg
    
    4512
    +     ==>  let karg = arg in case x of { A -> f karg; B -> g karg }
    
    4513
    +But if `arg` is small, the very next Simplifier iteration will inline karg into
    
    4514
    +both branches (postInlineUnconditionally: lazy, one occurrence per branch, and
    
    4515
    +smallEnoughToInline), costing an entire extra iteration for nothing (T13056).
    
    4516
    +So we duplicate such an argument straight away if it is not strictly demanded
    
    4517
    +(a strict one costs no allocation, so there is nothing to gain by duplicating
    
    4518
    +it) and it is `exprIsDupable`.  That is not quite postInlineUnconditionally's
    
    4519
    +criterion (`smallEnoughToInline`), but it is much cheaper than building an
    
    4520
    +unfolding just to measure it, and getting it slightly wrong is harmless:
    
    4521
    +if we fail to duplicate, karg is inlined in the next iteration as before.
    
    4522
    +Duplication is work-safe because only one alternative is executed.
    
    4523
    +-}
    
    4377 4524
     
    
    4378 4525
     mkDupableContWithDmds env _
    
    4379 4526
         (Select { sc_bndr = case_bndr, sc_alts = alts, sc_env = se, sc_cont = cont })
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -2999,6 +2999,7 @@ simplWrapFloats :: SimplMode -> SimplFloats
    2999 2999
                     -> SimplM OutExpr
    
    3000 3000
     -- Wrap the floats around the body, using mkCase for case-floats
    
    3001 3001
     -- See Note [Wrapping case-floats with mkCase]
    
    3002
    +-- Monadic only because of the `mkCase`
    
    3002 3003
     simplWrapFloats mode (SimplFloats { sfBinds = lfs, sfJoins = jbs }) body body_ty
    
    3003 3004
       = go (fromOL lfs)
    
    3004 3005
       where
    

  • testsuite/tests/simplCore/should_compile/T26903.stderr
    1 1
     
    
    2 2
     ==================== Tidy Core ====================
    
    3 3
     Result size of Tidy Core
    
    4
    -  = {terms: 127, types: 130, coercions: 24, joins: 0/0}
    
    4
    +  = {terms: 127, types: 130, coercions: 48, joins: 0/0}
    
    5 5
     
    
    6 6
     $dmop
    
    7
    -  = \ @a $dC $dOrd xs ys ->
    
    8
    -      case $fOrdList_$ccompare $dOrd xs ys of {
    
    9
    -        __DEFAULT ->
    
    10
    -          (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
    
    11
    -          `cast` <Co:3>;
    
    12
    -        GT ->
    
    13
    -          (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
    
    14
    -          `cast` <Co:3>
    
    15
    -      }
    
    7
    +  = (\ @a _ $dOrd xs ys ->
    
    8
    +       case $fOrdList_$ccompare $dOrd xs ys of {
    
    9
    +         __DEFAULT ->
    
    10
    +           reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
    
    11
    +         GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
    
    12
    +       })
    
    13
    +    `cast` <Co:20> :: ...
    
    16 14
     
    
    17 15
     $fCInt_$cop
    
    18
    -  = \ xs ys ->
    
    19
    -      case $fOrdList_$s$ccompare xs ys of {
    
    20
    -        __DEFAULT ->
    
    21
    -          (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
    
    22
    -          `cast` <Co:3>;
    
    23
    -        GT ->
    
    24
    -          (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
    
    25
    -          `cast` <Co:3>
    
    26
    -      }
    
    16
    +  = (\ xs ys ->
    
    17
    +       case $fOrdList_$s$ccompare xs ys of {
    
    18
    +         __DEFAULT ->
    
    19
    +           reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
    
    20
    +         GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
    
    21
    +       })
    
    22
    +    `cast` <Co:11> :: ...
    
    27 23
     
    
    28 24
     $fCInt1
    
    29 25
       = \ xs ys ->
    
    30 26
           case $fOrdList_$s$ccompare xs ys of {
    
    31 27
             __DEFAULT ->
    
    32
    -          (reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [])
    
    33
    -          `cast` <Co:3>;
    
    34
    -        GT ->
    
    35
    -          (reverse1 (reverse1 (reverse1 (reverse xs) []) []) [])
    
    36
    -          `cast` <Co:3>
    
    28
    +          reverse1 (reverse1 (reverse1 (reverse1 (++ xs ys) []) []) []) [];
    
    29
    +        GT -> reverse1 (reverse1 (reverse1 (reverse xs) []) []) []
    
    37 30
           }
    
    38 31
     
    
    39
    -$fCInt = C:C $fCInt1
    
    32
    +$fCInt = C:C ($fCInt1 `cast` <Co:11> :: ...)
    
    40 33
     
    
    41 34
     test4 = reverse1 [] []
    
    42 35
     
    
    ... ... @@ -51,8 +44,8 @@ test
    51 44
           case $fOrdList_$s$ccompare [] xs of {
    
    52 45
             __DEFAULT ->
    
    53 46
               (reverse1 (reverse1 (reverse1 (reverse1 (++ [] xs) []) []) []) [])
    
    54
    -          `cast` <Co:3>;
    
    55
    -        GT -> test1 `cast` <Co:3>
    
    47
    +          `cast` <Co:3> :: ...;
    
    48
    +        GT -> test1 `cast` <Co:3> :: ...
    
    56 49
           }
    
    57 50
     
    
    58 51