summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2021-05-28 20:01:34 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-06-27 14:57:39 -0400
commit37472a10da1ab39d22f1ab25b08fd6ef799cd0a7 (patch)
tree8cd4bc5355c6b2a7ce7686cc47cbe8d0ca007a91
parenteee498bfce3cce03ba1017b65d559c79d5c2eb60 (diff)
downloadhaskell-37472a10da1ab39d22f1ab25b08fd6ef799cd0a7.tar.gz
WorkWrap: Make mkWWstr and mkWWcpr generate fewer let bindings
In https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5814#note_355144, Simon noted that `mkWWstr` and `mkWWcpr` could generate fewer let bindings and be implemented less indirectly by returning the rebuilt expressions directly, e.g. instead of ``` f :: (Int, Int) -> Int f (x, y) = x+y ==> f :: (Int, Int) -> Int f p = case p of (x, y) -> case x of I# x' -> case y of I# y' -> case $wf x' y' of r' -> let r = I# r' -- immediately returned in r f :: Int# -> Int# -> Int# $wf x' y' = let x = I# x' in -- only used in p let y = I# y' in -- only used in p let p = (x, y) in -- only used in the App below case (\(x,y) -> x+y) p of I# r' -> r' ``` we know generate ``` f :: (Int, Int) -> Int f p = case p of (x, y) -> case x of I# x' -> case y of I# y' -> case $wf x' y' of r' -> I# r' -- 1 fewer let f :: Int# -> Int# -> Int# $wf x' y' = case (\(x,y) -> x+y) (I# x, I# y) of I# r' -> -- 3 fewer lets r' ``` Which is much nicer and makes it easier to comprehend the output of worker-wrapper pre-Simplification as well as puts less strain on the Simplifier. I had to drop support for #18983, but we found that it's broken anyway. Simon is working on a patch that provides a bit more justification.
-rw-r--r--compiler/GHC/Core/Opt/WorkWrap.hs6
-rw-r--r--compiler/GHC/Core/Opt/WorkWrap/Utils.hs138
-rw-r--r--testsuite/tests/stranal/should_compile/T18982.stderr8
3 files changed, 73 insertions, 79 deletions
diff --git a/compiler/GHC/Core/Opt/WorkWrap.hs b/compiler/GHC/Core/Opt/WorkWrap.hs
index 219990d135..ffb8f5c889 100644
--- a/compiler/GHC/Core/Opt/WorkWrap.hs
+++ b/compiler/GHC/Core/Opt/WorkWrap.hs
@@ -966,9 +966,9 @@ splitThunk :: WwOpts -> RecFlag -> Var -> Expr Var -> UniqSM [(Var, Expr Var)]
splitThunk ww_opts is_rec x rhs
= assert (not (isJoinId x)) $
do { let x' = localiseId x -- See comment above
- ; (useful,_, wrap_fn, work_fn)
- <- mkWWstr ww_opts NotArgOfInlineableFun [x']
- ; let res = [ (x, Let (NonRec x' rhs) (wrap_fn (work_fn (Var x')))) ]
+ ; (useful,_, wrap_fn, fn_arg)
+ <- mkWWstr_one ww_opts NotArgOfInlineableFun x'
+ ; let res = [ (x, Let (NonRec x' rhs) (wrap_fn fn_arg)) ]
; if useful then assertPpr (isNonRec is_rec) (ppr x) -- The thunk must be non-recursive
return res
else return [(x, rhs)] }
diff --git a/compiler/GHC/Core/Opt/WorkWrap/Utils.hs b/compiler/GHC/Core/Opt/WorkWrap/Utils.hs
index 8994af8283..c3e708c60d 100644
--- a/compiler/GHC/Core/Opt/WorkWrap/Utils.hs
+++ b/compiler/GHC/Core/Opt/WorkWrap/Utils.hs
@@ -8,7 +8,7 @@ A library for the ``worker\/wrapper'' back-end to the strictness analyser
{-# LANGUAGE ViewPatterns #-}
module GHC.Core.Opt.WorkWrap.Utils
- ( WwOpts(..), initWwOpts, mkWwBodies, mkWWstr, mkWorkerArgs
+ ( WwOpts(..), initWwOpts, mkWwBodies, mkWWstr, mkWWstr_one, mkWorkerArgs
, DataConPatContext(..)
, UnboxingDecision(..), ArgOfInlineableFun(..), wantToUnboxArg
, findTypeShape, mkAbsentFiller
@@ -224,7 +224,7 @@ mkWwBodies opts fun_id arg_vars res_ty demands res_cpr
(subst, cloned_arg_vars) = cloneBndrs empty_subst uniq_supply zapped_arg_vars
res_ty' = GHC.Core.Subst.substTy subst res_ty
- ; (useful1, work_args, wrap_fn_str, work_fn_str)
+ ; (useful1, work_args, wrap_fn_str, fn_args)
<- mkWWstr opts inlineable_flag cloned_arg_vars
-- Do CPR w/w. See Note [Always do CPR w/w]
@@ -234,10 +234,10 @@ mkWwBodies opts fun_id arg_vars res_ty demands res_cpr
; let (work_lam_args, work_call_args) = mkWorkerArgs fun_id (wo_fun_to_thunk opts)
work_args cpr_res_ty
call_work work_fn = mkVarApps (Var work_fn) work_call_args
- call_rhs fn_rhs = mkVarAppsBeta fn_rhs cloned_arg_vars
+ call_rhs fn_rhs = mkAppsBeta fn_rhs fn_args
-- See Note [Join points and beta-redexes]
wrapper_body = mkLams cloned_arg_vars . wrap_fn_cpr . wrap_fn_str . call_work
- worker_body = mkLams work_lam_args . work_fn_str . work_fn_cpr . call_rhs
+ worker_body = mkLams work_lam_args . work_fn_cpr . call_rhs
worker_args_dmds = [idDemandInfo v | v <- work_call_args, isId v]
; if isWorkerSmallEnough (wo_max_worker_args opts) (length demands) work_args
@@ -285,12 +285,13 @@ mkWwBodies opts fun_id arg_vars res_ty demands res_cpr
| otherwise
= False
--- | Version of 'GHC.Core.mkVarApps' that does beta reduction on-the-fly.
--- PRECONDITION: The arg vars don't shadow each other or any of the free vars of
--- the function expression.
-mkVarAppsBeta :: CoreExpr -> [Var] -> CoreExpr
-mkVarAppsBeta (Lam b body) (v:vs) = bindNonRec b (varToCoreExpr v) $! mkVarAppsBeta body vs
-mkVarAppsBeta f vars = mkVarApps f vars
+-- | Version of 'GHC.Core.mkApps' that does beta reduction on-the-fly.
+-- PRECONDITION: The arg expressions are not free in any of the lambdas binders.
+mkAppsBeta :: CoreExpr -> [CoreArg] -> CoreExpr
+-- The precondition holds for our call site in mkWwBodies, because all the FVs
+-- of as are either cloned_arg_vars (and thus fresh) or fresh worker args.
+mkAppsBeta (Lam b body) (a:as) = bindNonRec b a $! mkAppsBeta body as
+mkAppsBeta f as = mkApps f as
-- See Note [Limit w/w arity]
isWorkerSmallEnough :: Int -> Int -> [Var] -> Bool
@@ -352,7 +353,7 @@ function for the worker:
in the meantime, so zap it.
We zap in mkWwBodies because we need the zapped variables both when binding them
-in mkWWstr (mk_absent_let, specifically) and in mkWorkerArgs, where we produce
+in mkWWstr (mkAbsentFiller, specifically) and in mkWorkerArgs, where we produce
the call to the fun body.
************************************************************************
@@ -897,34 +898,33 @@ mkWWstr :: WwOpts
CoreExpr -> CoreExpr, -- Wrapper body, lacking the worker call
-- and without its lambdas
-- This fn adds the unboxing
-
- CoreExpr -> CoreExpr) -- Worker body, lacking the original body of the function,
- -- and lacking its lambdas.
- -- This fn does the reboxing
+ [CoreExpr]) -- Reboxed args for the call to the
+ -- original RHS. Corresponds one-to-one
+ -- with the wrapper arg vars
mkWWstr opts inlineable_flag args
= go args
where
go_one arg = mkWWstr_one opts inlineable_flag arg
- go [] = return (False, [], nop_fn, nop_fn)
- go (arg : args) = do { (useful1, args1, wrap_fn1, work_fn1) <- go_one arg
- ; (useful2, args2, wrap_fn2, work_fn2) <- go args
+ go [] = return (False, [], nop_fn, [])
+ go (arg : args) = do { (useful1, args1, wrap_fn1, wrap_arg) <- go_one arg
+ ; (useful2, args2, wrap_fn2, wrap_args) <- go args
; return ( useful1 || useful2
, args1 ++ args2
, wrap_fn1 . wrap_fn2
- , work_fn1 . work_fn2) }
+ , wrap_arg:wrap_args ) }
----------------------
--- mkWWstr_one wrap_arg = (useful, work_args, wrap_fn, work_fn)
--- * wrap_fn assumes wrap_arg is in scope,
+-- mkWWstr_one wrap_var = (useful, work_args, wrap_fn, wrap_arg)
+-- * wrap_fn assumes wrap_var is in scope,
-- brings into scope work_args (via cases)
--- * work_fn assumes work_args are in scope, a
--- brings into scope wrap_arg (via lets)
+-- * wrap_arg assumes work_args are in scope, and builds a ConApp that
+-- reconstructs the RHS of wrap_var that we pass to the original RHS
-- See Note [Worker/wrapper for Strictness and Absence]
mkWWstr_one :: WwOpts
-> ArgOfInlineableFun -- See Note [Do not unpack class dictionaries]
-> Var
- -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
+ -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr)
mkWWstr_one opts inlineable_flag arg =
case wantToUnboxArg fam_envs inlineable_flag arg_ty arg_dmd of
_ | isTyVar arg -> do_nothing
@@ -933,8 +933,8 @@ mkWWstr_one opts inlineable_flag arg =
| Just absent_filler <- mkAbsentFiller opts arg
-- Absent case. We can't always handle absence for arbitrary
-- unlifted types, so we need to choose just the cases we can
- -- (that's what mk_absent_let does)
- -> return (True, [], nop_fn, bindNonRec arg absent_filler)
+ -- (that's what mkAbsentFiller does)
+ -> return (True, [], nop_fn, absent_filler)
Unbox dcpc cs -> unbox_one_arg opts arg cs dcpc
@@ -944,34 +944,33 @@ mkWWstr_one opts inlineable_flag arg =
fam_envs = wo_fam_envs opts
arg_ty = idType arg
arg_dmd = idDemandInfo arg
- do_nothing = return (False, [arg], nop_fn, nop_fn)
+ do_nothing = return (False, [arg], nop_fn, varToCoreExpr arg)
unbox_one_arg :: WwOpts
-> Var
-> [Demand]
-> DataConPatContext
- -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-unbox_one_arg opts arg cs
+ -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr)
+unbox_one_arg opts arg_var cs
DataConPatContext { dcpc_dc = dc, dcpc_tc_args = tc_args
, dcpc_co = co }
= do { pat_bndrs_uniqs <- getUniquesM
- ; let ex_name_fss = map getOccFS $ dataConExTyCoVars dc
+ ; let ex_name_fss = map getOccFS $ dataConExTyCoVars dc
(ex_tvs', arg_ids) =
- dataConRepFSInstPat (ex_name_fss ++ repeat ww_prefix) pat_bndrs_uniqs (idMult arg) dc tc_args
- arg_ids' = zipWithEqual "unbox_one_arg" setIdDemandInfo arg_ids cs
- unbox_fn = mkUnpackCase (Var arg) co (idMult arg)
- dc (ex_tvs' ++ arg_ids')
- rebox_fn = Let (NonRec arg con_app)
- con_app = mkConApp2 dc tc_args (ex_tvs' ++ arg_ids') `mkCast` mkSymCo co
- ; (_, worker_args, wrap_fn, work_fn) <- mkWWstr opts NotArgOfInlineableFun (ex_tvs' ++ arg_ids')
- ; return (True, worker_args, unbox_fn . wrap_fn, work_fn . rebox_fn) }
+ dataConRepFSInstPat (ex_name_fss ++ repeat ww_prefix) pat_bndrs_uniqs (idMult arg_var) dc tc_args
+ arg_ids' = zipWithEqual "unbox_one_arg" setIdDemandInfo arg_ids cs
+ unbox_fn = mkUnpackCase (Var arg_var) co (idMult arg_var)
+ dc (ex_tvs' ++ arg_ids')
+ ; (_, worker_args, wrap_fn, wrap_args) <- mkWWstr opts NotArgOfInlineableFun (ex_tvs' ++ arg_ids')
+ ; let wrap_arg = mkConApp dc (map Type tc_args ++ wrap_args) `mkCast` mkSymCo co
+ ; return (True, worker_args, unbox_fn . wrap_fn, wrap_arg) }
-- Don't pass the arg, rebox instead
--- | Tries to find a suitable dummy RHS to bind the given absent identifier to.
+-- | Tries to find a suitable absent filler to bind the given absent identifier
+-- to. See Note [Absent fillers].
--
--- If @mk_absent_let _ id == Just wrap@, then @wrap e@ will wrap a let binding
--- for @id@ with that RHS around @e@. Otherwise, there could no suitable RHS be
--- found.
+-- If @mkAbsentFiller _ id == Just e@, then @e@ is an absent filler with the
+-- same type as @id@. Otherwise, no suitable filler could be found.
mkAbsentFiller :: WwOpts -> Id -> Maybe CoreExpr
mkAbsentFiller opts arg
-- The lifted case: Bind 'absentError' for a nice panic message if we are
@@ -1298,17 +1297,16 @@ mkWWcpr_entry opts body_ty body_cpr
-- Part (1)
res_bndr <- mk_res_bndr body_ty
let bind_res_bndr body scope = mkDefaultCase body res_bndr scope
- deref_res_bndr = Var res_bndr
-- Part (2)
- (useful, fromOL -> transit_vars, wrap_build_res, work_unpack_res) <-
+ (useful, fromOL -> transit_vars, rebuilt_result, work_unpack_res) <-
mkWWcpr_one opts res_bndr body_cpr
-- Part (3)
let (unbox_transit_tup, transit_tup) = move_transit_vars transit_vars
-- Stacking unboxer (work_fn) and builder (wrap_fn) together
- let wrap_fn = unbox_transit_tup (wrap_build_res deref_res_bndr) -- 3 2 1
+ let wrap_fn = unbox_transit_tup rebuilt_result -- 3 2
work_fn body = bind_res_bndr body (work_unpack_res transit_tup) -- 1 2 3
work_body_ty = exprType transit_tup
return $ if not useful
@@ -1327,68 +1325,67 @@ mk_res_bndr body_ty = do
--
-- 1. A Bool capturing whether the transformation did anything useful.
-- 2. The list of transit variables (see the Note).
--- 3. The result builder expression for the wrapper. 'nop_fn' if not useful.
+-- 3. The result builder expression for the wrapper. The original case binder if not useful.
-- 4. The result unpacking expression for the worker. 'nop_fn' if not useful.
-type CprWwResult = (Bool, OrdList Var, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
+type CprWwResultOne = (Bool, OrdList Var, CoreExpr , CoreExpr -> CoreExpr)
+type CprWwResultMany = (Bool, OrdList Var, [CoreExpr], CoreExpr -> CoreExpr)
-mkWWcpr :: WwOpts -> [Id] -> [Cpr] -> UniqSM CprWwResult
+mkWWcpr :: WwOpts -> [Id] -> [Cpr] -> UniqSM CprWwResultMany
mkWWcpr _opts vars [] =
-- special case: No CPRs means all top (for example from FlatConCpr),
-- hence stop WW.
- return (False, toOL vars, nop_fn, nop_fn)
+ return (False, toOL vars, map varToCoreExpr vars, nop_fn)
mkWWcpr opts vars cprs = do
-- No existentials in 'vars'. 'wantToUnboxResult' should have checked that.
massertPpr (not (any isTyVar vars)) (ppr vars $$ ppr cprs)
massertPpr (equalLength vars cprs) (ppr vars $$ ppr cprs)
- (usefuls, varss, wrap_build_ress, work_unpack_ress) <-
+ (usefuls, varss, rebuilt_results, work_unpack_ress) <-
unzip4 <$> zipWithM (mkWWcpr_one opts) vars cprs
return ( or usefuls
, concatOL varss
- , foldl' (.) nop_fn wrap_build_ress
+ , rebuilt_results
, foldl' (.) nop_fn work_unpack_ress )
-mkWWcpr_one :: WwOpts -> Id -> Cpr -> UniqSM CprWwResult
+mkWWcpr_one :: WwOpts -> Id -> Cpr -> UniqSM CprWwResultOne
-- ^ See if we want to unbox the result and hand off to 'unbox_one_result'.
mkWWcpr_one opts res_bndr cpr
| assert (not (isTyVar res_bndr) ) True
, Unbox dcpc arg_cprs <- wantToUnboxResult (wo_fam_envs opts) (idType res_bndr) cpr
= unbox_one_result opts res_bndr arg_cprs dcpc
| otherwise
- = return (False, unitOL res_bndr, nop_fn, nop_fn)
+ = return (False, unitOL res_bndr, varToCoreExpr res_bndr, nop_fn)
unbox_one_result
- :: WwOpts -> Id -> [Cpr] -> DataConPatContext -> UniqSM CprWwResult
+ :: WwOpts -> Id -> [Cpr] -> DataConPatContext -> UniqSM CprWwResultOne
-- ^ Implements the main bits of part (2) of Note [Worker/wrapper for CPR]
unbox_one_result opts res_bndr arg_cprs
DataConPatContext { dcpc_dc = dc, dcpc_tc_args = tc_args
, dcpc_co = co } = do
- -- unboxer (free in `res_bndr`): | builder (binds `res_bndr`):
- -- ( case res_bndr of (i, j) -> ) | ( let j = I# b in )
- -- ( case i of I# a -> ) | ( let i = I# a in )
- -- ( case j of I# b -> ) | ( let res_bndr = (i, j) in )
- -- ( <hole> ) | ( <hole> )
+ -- unboxer (free in `res_bndr`): | builder (where <i> builds what was
+ -- ( case res_bndr of (i, j) -> ) | bound to i)
+ -- ( case i of I# a -> ) |
+ -- ( case j of I# b -> ) | ( (<i>, <j>) )
+ -- ( <hole> ) |
pat_bndrs_uniqs <- getUniquesM
let (_exs, arg_ids) =
dataConRepFSInstPat (repeat ww_prefix) pat_bndrs_uniqs cprCaseBndrMult dc tc_args
massert (null _exs) -- Should have been caught by wantToUnboxResult
- let -- con_app = (C a b |> sym co)
- con_app = mkConApp2 dc tc_args arg_ids `mkCast` mkSymCo co
- -- this_wrap_build_res body = (let res_bndr = C a b |> sym co in <body>[r])
- this_wrap_build_res = Let (NonRec res_bndr con_app)
+ (nested_useful, transit_vars, con_args, work_unbox_res) <-
+ mkWWcpr opts arg_ids arg_cprs
+
+ let -- rebuilt_result = (C a b |> sym co)
+ rebuilt_result = mkConApp dc (map Type tc_args ++ con_args) `mkCast` mkSymCo co
-- this_work_unbox_res alt = (case res_bndr |> co of C a b -> <alt>[a,b])
this_work_unbox_res = mkUnpackCase (Var res_bndr) co cprCaseBndrMult dc arg_ids
- (nested_useful, transit_vars, wrap_build_res, work_unbox_res) <-
- mkWWcpr opts arg_ids arg_cprs
-
-- Don't try to WW an unboxed tuple return type when there's nothing inside
-- to unbox further.
return $ if isUnboxedTupleDataCon dc && not nested_useful
- then ( False, unitOL res_bndr, nop_fn, nop_fn )
+ then ( False, unitOL res_bndr, Var res_bndr, nop_fn )
else ( True
, transit_vars
- , wrap_build_res . this_wrap_build_res
+ , rebuilt_result
, this_work_unbox_res . work_unbox_res
)
@@ -1449,10 +1446,7 @@ body `body` (i.e., `(Int, Int)`). Then `mkWWcpr_entry body_ty body_cpr` returns
* A result-building expression for the wrapper, with a hole for the worker call:
```
build wkr_call = ( case <wkr_call> of (# a, b #) -> ) -- (3)
- ( let j = I# b in ) -- (2)
- ( let i = I# a in ) -- (2)
- ( let r = (i, j) in ) -- (2)
- ( r ) -- (1)
+ ( (I# a, I# b) ) -- (2)
```
* The result type of the worker, e.g., `(# Int#, Int# #)` above.
diff --git a/testsuite/tests/stranal/should_compile/T18982.stderr b/testsuite/tests/stranal/should_compile/T18982.stderr
index 19f25be15c..9b1f852dda 100644
--- a/testsuite/tests/stranal/should_compile/T18982.stderr
+++ b/testsuite/tests/stranal/should_compile/T18982.stderr
@@ -216,7 +216,7 @@ T18982.$wi = \ (@a) (@e) (ww :: a GHC.Prim.~# Int) (ww1 :: e) (ww2 :: GHC.Prim.I
-- RHS size: {terms: 15, types: 22, coercions: 1, joins: 0/0}
i :: forall a. ExGADT a -> Int
-i = \ (@a) (w :: ExGADT a) -> case w of { ExGADT @e ww ww1 ww2 ww3 -> case ww3 of { GHC.Types.I# ww4 -> case T18982.$wi @a @e @~(ww :: a GHC.Prim.~# Int) ww2 ww4 of ww5 { __DEFAULT -> GHC.Types.I# ww5 } } }
+i = \ (@a) (ds :: ExGADT a) -> case ds of { ExGADT @e ww ww1 ww2 ww3 -> case ww3 of { GHC.Types.I# ww4 -> case T18982.$wi @a @e @~(ww :: a GHC.Prim.~# Int) ww2 ww4 of ww5 { __DEFAULT -> GHC.Types.I# ww5 } } }
-- RHS size: {terms: 6, types: 7, coercions: 0, joins: 0/0}
T18982.$wh :: forall {a}. (a GHC.Prim.~# Int) -> GHC.Prim.Int# -> GHC.Prim.Int#
@@ -224,7 +224,7 @@ T18982.$wh = \ (@a) (ww :: a GHC.Prim.~# Int) (ww1 :: GHC.Prim.Int#) -> GHC.Prim
-- RHS size: {terms: 14, types: 15, coercions: 1, joins: 0/0}
h :: forall a. GADT a -> Int
-h = \ (@a) (w :: GADT a) -> case w of { GADT ww ww1 -> case ww1 of { GHC.Types.I# ww2 -> case T18982.$wh @a @~(ww :: a GHC.Prim.~# Int) ww2 of ww3 { __DEFAULT -> GHC.Types.I# ww3 } } }
+h = \ (@a) (ds :: GADT a) -> case ds of { GADT ww ww1 -> case ww1 of { GHC.Types.I# ww2 -> case T18982.$wh @a @~(ww :: a GHC.Prim.~# Int) ww2 of ww3 { __DEFAULT -> GHC.Types.I# ww3 } } }
-- RHS size: {terms: 9, types: 4, coercions: 0, joins: 0/0}
T18982.$wg :: forall {e}. e -> GHC.Prim.Int# -> GHC.Prim.Int#
@@ -232,7 +232,7 @@ T18982.$wg = \ (@e) (ww :: e) (ww1 :: GHC.Prim.Int#) -> case ww of { __DEFAULT -
-- RHS size: {terms: 14, types: 11, coercions: 0, joins: 0/0}
g :: Ex Int -> Int
-g = \ (w :: Ex Int) -> case w of { Ex @e ww ww1 -> case ww1 of { GHC.Types.I# ww2 -> case T18982.$wg @e ww ww2 of ww3 { __DEFAULT -> GHC.Types.I# ww3 } } }
+g = \ (ds :: Ex Int) -> case ds of { Ex @e ww ww1 -> case ww1 of { GHC.Types.I# ww2 -> case T18982.$wg @e ww ww2 of ww3 { __DEFAULT -> GHC.Types.I# ww3 } } }
-- RHS size: {terms: 4, types: 1, coercions: 0, joins: 0/0}
T18982.$wf :: GHC.Prim.Int# -> GHC.Prim.Int#
@@ -240,7 +240,7 @@ T18982.$wf = \ (ww :: GHC.Prim.Int#) -> GHC.Prim.+# ww 1#
-- RHS size: {terms: 13, types: 8, coercions: 0, joins: 0/0}
f :: Box Int -> Int
-f = \ (w :: Box Int) -> case w of { Box ww -> case ww of { GHC.Types.I# ww1 -> case T18982.$wf ww1 of ww2 { __DEFAULT -> GHC.Types.I# ww2 } } }
+f = \ (ds :: Box Int) -> case ds of { Box ww -> case ww of { GHC.Types.I# ww1 -> case T18982.$wf ww1 of ww2 { __DEFAULT -> GHC.Types.I# ww2 } } }