Comments and formatting to vectoriser, and split out varish stuff into own module
[ghc-hetmet.git] / compiler / vectorise / Vectorise.hs
1 {-# OPTIONS -fno-warn-missing-signatures #-}
2
3 module Vectorise( vectorise )
4 where
5
6 import VectMonad
7 import VectUtils
8 import VectVar
9 import VectType
10 import VectCore
11
12 import HscTypes hiding      ( MonadThings(..) )
13
14 import Module               ( PackageId )
15 import CoreSyn
16 import CoreUtils
17 import CoreUnfold           ( mkInlineRule )
18 import MkCore               ( mkWildCase )
19 import CoreFVs
20 import CoreMonad            ( CoreM, getHscEnv )
21 import DataCon
22 import TyCon
23 import Type
24 import FamInstEnv           ( extendFamInstEnvList )
25 import Var
26 import VarEnv
27 import VarSet
28 import Id
29 import OccName
30 import BasicTypes           ( isLoopBreaker )
31
32 import Literal
33 import TysWiredIn
34 import TysPrim              ( intPrimTy )
35
36 import Outputable
37 import FastString
38 import Util                 ( zipLazy )
39 import Control.Monad
40 import Data.List            ( sortBy, unzip4 )
41
42
43 debug           = False
44 dtrace s x      = if debug then pprTrace "Vectorise" s x else x
45
46 -- | Vectorise a single module.
47 --   Takes the package containing the DPH backend we're using. Eg either dph-par or dph-seq.
48 vectorise :: PackageId -> ModGuts -> CoreM ModGuts
49 vectorise backend guts 
50  = do hsc_env <- getHscEnv
51       liftIO $ vectoriseIO backend hsc_env guts
52
53
54 -- | Vectorise a single monad, given its HscEnv (code gen environment).
55 vectoriseIO :: PackageId -> HscEnv -> ModGuts -> IO ModGuts
56 vectoriseIO backend hsc_env guts
57  = do -- Get information about currently loaded external packages.
58       eps <- hscEPS hsc_env
59
60       -- Combine vectorisation info from the current module, and external ones.
61       let info = hptVectInfo hsc_env `plusVectInfo` eps_vect_info eps
62
63       -- Run the main VM computation.
64       Just (info', guts') <- initV backend hsc_env guts info (vectModule guts)
65       return (guts' { mg_vect_info = info' })
66
67
68 -- | Vectorise a single module, in the VM monad.
69 vectModule :: ModGuts -> VM ModGuts
70 vectModule guts
71  = do -- Vectorise the type environment.
72       -- This may add new TyCons and DataCons.
73       -- TODO: What new binds do we get back here?
74       (types', fam_insts, tc_binds) <- vectTypeEnv (mg_types guts)
75
76       -- TODO: What is this?
77       let fam_inst_env' = extendFamInstEnvList (mg_fam_inst_env guts) fam_insts
78       updGEnv (setFamInstEnv fam_inst_env')
79
80       -- dicts   <- mapM buildPADict pa_insts
81       -- workers <- mapM vectDataConWorkers pa_insts
82
83       -- Vectorise all the top level bindings.
84       binds'  <- mapM vectTopBind (mg_binds guts)
85
86       return $ guts { mg_types        = types'
87                     , mg_binds        = Rec tc_binds : binds'
88                     , mg_fam_inst_env = fam_inst_env'
89                     , mg_fam_insts    = mg_fam_insts guts ++ fam_insts
90                     }
91
92
93 -- | Try to vectorise a top-level binding.
94 --   If it doesn't vectorise then return it unharmed.
95 --
96 --   For example, for the binding 
97 --
98 --   @  
99 --      foo :: Int -> Int
100 --      foo = \x -> x + x
101 --   @
102 --  
103 --   we get
104 --   @
105 --      foo  :: Int -> Int
106 --      foo  = \x -> vfoo $: x                  
107 -- 
108 --      v_foo :: Closure void vfoo lfoo
109 --      v_foo = closure vfoo lfoo void        
110 -- 
111 --      vfoo :: Void -> Int -> Int
112 --      vfoo = ...
113 --
114 --      lfoo :: PData Void -> PData Int -> PData Int
115 --      lfoo = ...
116 --   @ 
117 --
118 --   @vfoo@ is the "vectorised", or scalar, version that does the same as the original
119 --   function foo, but takes an explicit environment.
120 -- 
121 --   @lfoo@ is the "lifted" version that works on arrays.
122 --
123 --   @v_foo@ combines both of these into a `Closure` that also contains the
124 --   environment.
125 --
126 --   The original binding @foo@ is rewritten to call the vectorised version
127 --   present in the closure.
128 --
129 vectTopBind :: CoreBind -> VM CoreBind
130 vectTopBind b@(NonRec var expr)
131  = do
132       (inline, expr')   <- vectTopRhs var expr
133       var'              <- vectTopBinder var inline expr'
134
135       -- Vectorising the body may create other top-level bindings.
136       hs        <- takeHoisted
137
138       -- To get the same functionality as the original body we project
139       -- out its vectorised version from the closure.
140       cexpr     <- tryConvert var var' expr
141
142       return . Rec $ (var, cexpr) : (var', expr') : hs
143   `orElseV`
144     return b
145
146 vectTopBind b@(Rec bs)
147  = do
148       (vars', _, exprs') 
149         <- fixV $ \ ~(_, inlines, rhss) ->
150             do vars' <- sequence [vectTopBinder var inline rhs
151                                       | (var, ~(inline, rhs)) <- zipLazy vars (zip inlines rhss)]
152                (inlines', exprs') 
153                      <- mapAndUnzipM (uncurry vectTopRhs) bs
154
155                return (vars', inlines', exprs')
156
157       hs     <- takeHoisted
158       cexprs <- sequence $ zipWith3 tryConvert vars vars' exprs
159       return . Rec $ zip vars cexprs ++ zip vars' exprs' ++ hs
160   `orElseV`
161     return b
162   where
163     (vars, exprs) = unzip bs
164
165
166 -- | Make the vectorised version of this top level binder, and add the mapping
167 --   between it and the original to the state. For some binder @foo@ the vectorised
168 --   version is @$v_foo@
169 --
170 --   NOTE: vectTopBinder *MUST* be lazy in inline and expr because of how it is
171 --   used inside of fixV in vectTopBind
172 vectTopBinder 
173         :: Var          -- ^ Name of the binding.
174         -> Inline       -- ^ Whether it should be inlined, used to annotate it.
175         -> CoreExpr     -- ^ RHS of the binding, used to set the `Unfolding` of the returned `Var`.
176         -> VM Var       -- ^ Name of the vectorised binding.
177
178 vectTopBinder var inline expr
179  = do
180       -- Vectorise the type attached to the var.
181       vty  <- vectType (idType var)
182
183       -- Make the vectorised version of binding's name, and set the unfolding used for inlining.
184       var' <- liftM (`setIdUnfolding` unfolding) 
185            $  cloneId mkVectOcc var vty
186
187       -- Add the mapping between the plain and vectorised name to the state.
188       defGlobalVar var var'
189
190       return var'
191   where
192     unfolding = case inline of
193                   Inline arity -> mkInlineRule expr (Just arity)
194                   DontInline   -> noUnfolding
195
196
197 -- | Vectorise the RHS of a top-level binding, in an empty local environment.
198 vectTopRhs 
199         :: Var          -- ^ Name of the binding.
200         -> CoreExpr     -- ^ Body of the binding.
201         -> VM (Inline, CoreExpr)
202
203 vectTopRhs var expr
204  = dtrace (vcat [text "vectTopRhs", ppr expr])
205  $ closedV
206  $ do (inline, vexpr) <- inBind var
207                       $ vectPolyExpr (isLoopBreaker $ idOccInfo var)
208                                       (freeVars expr)
209       return (inline, vectorised vexpr)
210
211
212 -- | Project out the vectorised version of a binding from some closure,
213 --      or return the original body if that doesn't work.       
214 tryConvert 
215         :: Var          -- ^ Name of the original binding (eg @foo@)
216         -> Var          -- ^ Name of vectorised version of binding (eg @$vfoo@)
217         -> CoreExpr     -- ^ The original body of the binding.
218         -> VM CoreExpr
219
220 tryConvert var vect_var rhs
221   = fromVect (idType var) (Var vect_var) `orElseV` return rhs
222
223
224 -- ----------------------------------------------------------------------------
225 -- Expressions
226
227
228 -- | Vectorise a polymorphic expression
229 vectPolyExpr 
230         :: Bool                 -- ^ When vectorising the RHS of a binding, whether that
231                                 --   binding is a loop breaker.
232         -> CoreExprWithFVs
233         -> VM (Inline, VExpr)
234
235 vectPolyExpr loop_breaker (_, AnnNote note expr)
236  = do (inline, expr') <- vectPolyExpr loop_breaker expr
237       return (inline, vNote note expr')
238
239 vectPolyExpr loop_breaker expr
240  = dtrace (vcat [text "vectPolyExpr", ppr (deAnnotate expr)])
241  $ do
242       arity <- polyArity tvs
243       polyAbstract tvs $ \args ->
244         do
245           (inline, mono') <- vectFnExpr False loop_breaker mono
246           return (addInlineArity inline arity,
247                   mapVect (mkLams $ tvs ++ args) mono')
248   where
249     (tvs, mono) = collectAnnTypeBinders expr
250
251
252 -- | Vectorise a core expression.
253 vectExpr :: CoreExprWithFVs -> VM VExpr
254 vectExpr (_, AnnType ty)
255   = liftM vType (vectType ty)
256
257 vectExpr (_, AnnVar v) 
258   = vectVar v
259
260 vectExpr (_, AnnLit lit) 
261   = vectLiteral lit
262
263 vectExpr (_, AnnNote note expr)
264   = liftM (vNote note) (vectExpr expr)
265
266 vectExpr e@(_, AnnApp _ arg)
267   | isAnnTypeArg arg
268   = vectTyAppExpr fn tys
269   where
270     (fn, tys) = collectAnnTypeArgs e
271
272 vectExpr (_, AnnApp (_, AnnVar v) (_, AnnLit lit))
273   | Just con <- isDataConId_maybe v
274   , is_special_con con
275   = do
276       let vexpr = App (Var v) (Lit lit)
277       lexpr <- liftPD vexpr
278       return (vexpr, lexpr)
279   where
280     is_special_con con = con `elem` [intDataCon, floatDataCon, doubleDataCon]
281
282
283 -- TODO: Avoid using closure application for dictionaries.
284 -- vectExpr (_, AnnApp fn arg)
285 --  | if is application of dictionary 
286 --    just use regular app instead of closure app.
287
288 -- for lifted version. 
289 --      do liftPD (sub a dNumber)
290 --      lift the result of the selection, not sub and dNumber seprately. 
291
292 vectExpr (_, AnnApp fn arg)
293  = dtrace (text "AnnApp" <+> ppr (deAnnotate fn) <+> ppr (deAnnotate arg))
294  $ do
295       arg_ty' <- vectType arg_ty
296       res_ty' <- vectType res_ty
297
298       dtrace (text "vectorising fn " <> ppr (deAnnotate fn))  $ return ()
299       fn'     <- vectExpr fn
300       dtrace (text "fn' = "       <> ppr fn') $ return ()
301
302       arg'    <- vectExpr arg
303
304       mkClosureApp arg_ty' res_ty' fn' arg'
305   where
306     (arg_ty, res_ty) = splitFunTy . exprType $ deAnnotate fn
307
308 vectExpr (_, AnnCase scrut bndr ty alts)
309   | Just (tycon, ty_args) <- splitTyConApp_maybe scrut_ty
310   , isAlgTyCon tycon
311   = vectAlgCase tycon ty_args scrut bndr ty alts
312   where
313     scrut_ty = exprType (deAnnotate scrut)
314
315 vectExpr (_, AnnLet (AnnNonRec bndr rhs) body)
316   = do
317       vrhs <- localV . inBind bndr . liftM snd $ vectPolyExpr False rhs
318       (vbndr, vbody) <- vectBndrIn bndr (vectExpr body)
319       return $ vLet (vNonRec vbndr vrhs) vbody
320
321 vectExpr (_, AnnLet (AnnRec bs) body)
322   = do
323       (vbndrs, (vrhss, vbody)) <- vectBndrsIn bndrs
324                                 $ liftM2 (,)
325                                   (zipWithM vect_rhs bndrs rhss)
326                                   (vectExpr body)
327       return $ vLet (vRec vbndrs vrhss) vbody
328   where
329     (bndrs, rhss) = unzip bs
330
331     vect_rhs bndr rhs = localV
332                       . inBind bndr
333                       . liftM snd
334                       $ vectPolyExpr (isLoopBreaker $ idOccInfo bndr) rhs
335
336 vectExpr e@(_, AnnLam bndr _)
337   | isId bndr = liftM snd $ vectFnExpr True False e
338 {-
339 onlyIfV (isEmptyVarSet fvs) (vectScalarLam bs $ deAnnotate body)
340                 `orElseV` vectLam True fvs bs body
341   where
342     (bs,body) = collectAnnValBinders e
343 -}
344
345 vectExpr e = cantVectorise "Can't vectorise expression" (ppr $ deAnnotate e)
346
347
348 -- | Vectorise an expression with an outer lambda abstraction.
349 vectFnExpr 
350         :: Bool                 -- ^ When the RHS of a binding, whether that binding should be inlined.
351         -> Bool                 -- ^ Whether the binding is a loop breaker.
352         -> CoreExprWithFVs      -- ^ Expression to vectorise. Must have an outer `AnnLam`.
353         -> VM (Inline, VExpr)
354
355 vectFnExpr inline loop_breaker e@(fvs, AnnLam bndr _)
356   | isId bndr = onlyIfV (isEmptyVarSet fvs)
357                         (mark DontInline . vectScalarLam bs $ deAnnotate body)
358                 `orElseV` mark inlineMe (vectLam inline loop_breaker fvs bs body)
359   where
360     (bs,body) = collectAnnValBinders e
361
362 vectFnExpr _ _ e = mark DontInline $ vectExpr e
363
364 mark :: Inline -> VM a -> VM (Inline, a)
365 mark b p = do { x <- p; return (b,x) }
366
367
368 -- | Vectorise a function where are the args have scalar type, that is Int, Float or Double.
369 vectScalarLam 
370         :: [Var]        -- ^ Bound variables of function.
371         -> CoreExpr     -- ^ Function body.
372         -> VM VExpr
373 vectScalarLam args body
374  = dtrace (vcat [text "vectScalarLam ", ppr args, ppr body])
375  $ do scalars <- globalScalars
376       onlyIfV (all is_scalar_ty arg_tys
377                && is_scalar_ty res_ty
378                && is_scalar (extendVarSetList scalars args) body
379                && uses scalars body)
380         $ do
381             fn_var  <- hoistExpr (fsLit "fn") (mkLams args body) DontInline
382             zipf    <- zipScalars arg_tys res_ty
383             clo     <- scalarClosure arg_tys res_ty (Var fn_var)
384                                                 (zipf `App` Var fn_var)
385             clo_var <- hoistExpr (fsLit "clo") clo DontInline
386             lclo    <- liftPD (Var clo_var)
387             return (Var clo_var, lclo)
388   where
389     arg_tys = map idType args
390     res_ty  = exprType body
391
392     is_scalar_ty ty 
393         | Just (tycon, [])   <- splitTyConApp_maybe ty
394         =    tycon == intTyCon
395           || tycon == floatTyCon
396           || tycon == doubleTyCon
397
398         | otherwise = False
399
400     is_scalar vs (Var v)     = v `elemVarSet` vs
401     is_scalar _ e@(Lit _)    = is_scalar_ty $ exprType e
402     is_scalar vs (App e1 e2) = is_scalar vs e1 && is_scalar vs e2
403     is_scalar _ _            = False
404
405     -- A scalar function has to actually compute something. Without the check,
406     -- we would treat (\(x :: Int) -> x) as a scalar function and lift it to
407     -- (map (\x -> x)) which is very bad. Normal lifting transforms it to
408     -- (\n# x -> x) which is what we want.
409     uses funs (Var v)     = v `elemVarSet` funs 
410     uses funs (App e1 e2) = uses funs e1 || uses funs e2
411     uses _ _              = False
412
413
414 vectLam 
415         :: Bool                 -- ^ When the RHS of a binding, whether that binding should be inlined.
416         -> Bool                 -- ^ Whether the binding is a loop breaker.
417         -> VarSet               -- ^ The free variables in the body.
418         -> [Var]                -- 
419         -> CoreExprWithFVs
420         -> VM VExpr
421
422 vectLam inline loop_breaker fvs bs body
423  = dtrace (vcat [ text "vectLam "
424                 , text "free vars    = " <> ppr fvs
425                 , text "binding vars = " <> ppr bs
426                 , text "body         = " <> ppr (deAnnotate body)])
427
428  $ do tyvars    <- localTyVars
429       (vs, vvs) <- readLEnv $ \env ->
430                    unzip [(var, vv) | var <- varSetElems fvs
431                                     , Just vv <- [lookupVarEnv (local_vars env) var]]
432
433       arg_tys   <- mapM (vectType . idType) bs
434
435       dtrace (text "arg_tys = " <> ppr arg_tys) $ return ()
436
437       res_ty    <- vectType (exprType $ deAnnotate body)
438
439       dtrace (text "res_ty = " <> ppr res_ty) $ return ()
440
441       buildClosures tyvars vvs arg_tys res_ty
442         . hoistPolyVExpr tyvars (maybe_inline (length vs + length bs))
443         $ do
444             lc              <- builtin liftingContext
445             (vbndrs, vbody) <- vectBndrsIn (vs ++ bs) (vectExpr body)
446
447             dtrace (text "vbody = " <> ppr vbody) $ return ()
448
449             vbody' <- break_loop lc res_ty vbody
450             return $ vLams lc vbndrs vbody'
451   where
452     maybe_inline n | inline    = Inline n
453                    | otherwise = DontInline
454
455     break_loop lc ty (ve, le)
456       | loop_breaker
457       = do
458           empty <- emptyPD ty
459           lty <- mkPDataType ty
460           return (ve, mkWildCase (Var lc) intPrimTy lty
461                         [(DEFAULT, [], le),
462                          (LitAlt (mkMachInt 0), [], empty)])
463
464       | otherwise = return (ve, le)
465  
466
467 vectTyAppExpr :: CoreExprWithFVs -> [Type] -> VM VExpr
468 vectTyAppExpr (_, AnnVar v) tys = vectPolyVar v tys
469 vectTyAppExpr e tys = cantVectorise "Can't vectorise expression"
470                         (ppr $ deAnnotate e `mkTyApps` tys)
471
472 -- We convert
473 --
474 --   case e :: t of v { ... }
475 --
476 -- to
477 --
478 --   V:    let v' = e in case v' of _ { ... }
479 --   L:    let v' = e in case v' `cast` ... of _ { ... }
480 --
481 -- When lifting, we have to do it this way because v must have the type
482 -- [:V(T):] but the scrutinee must be cast to the representation type. We also
483 -- have to handle the case where v is a wild var correctly.
484 --
485
486 -- FIXME: this is too lazy
487 vectAlgCase :: TyCon -> [Type] -> CoreExprWithFVs -> Var -> Type
488             -> [(AltCon, [Var], CoreExprWithFVs)]
489             -> VM VExpr
490 vectAlgCase _tycon _ty_args scrut bndr ty [(DEFAULT, [], body)]
491   = do
492       vscrut         <- vectExpr scrut
493       (vty, lty)     <- vectAndLiftType ty
494       (vbndr, vbody) <- vectBndrIn bndr (vectExpr body)
495       return $ vCaseDEFAULT vscrut vbndr vty lty vbody
496
497 vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt _, [], body)]
498   = do
499       vscrut         <- vectExpr scrut
500       (vty, lty)     <- vectAndLiftType ty
501       (vbndr, vbody) <- vectBndrIn bndr (vectExpr body)
502       return $ vCaseDEFAULT vscrut vbndr vty lty vbody
503
504 vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt dc, bndrs, body)]
505   = do
506       (vty, lty) <- vectAndLiftType ty
507       vexpr      <- vectExpr scrut
508       (vbndr, (vbndrs, (vect_body, lift_body)))
509          <- vect_scrut_bndr
510           . vectBndrsIn bndrs
511           $ vectExpr body
512       let (vect_bndrs, lift_bndrs) = unzip vbndrs
513       (vscrut, lscrut, pdata_tc, _arg_tys) <- mkVScrut (vVar vbndr)
514       vect_dc <- maybeV (lookupDataCon dc)
515       let [pdata_dc] = tyConDataCons pdata_tc
516
517       let vcase = mk_wild_case vscrut vty vect_dc  vect_bndrs vect_body
518           lcase = mk_wild_case lscrut lty pdata_dc lift_bndrs lift_body
519
520       return $ vLet (vNonRec vbndr vexpr) (vcase, lcase)
521   where
522     vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut")
523                     | otherwise         = vectBndrIn bndr
524
525     mk_wild_case expr ty dc bndrs body
526       = mkWildCase expr (exprType expr) ty [(DataAlt dc, bndrs, body)]
527
528 vectAlgCase tycon _ty_args scrut bndr ty alts
529   = do
530       vect_tc     <- maybeV (lookupTyCon tycon)
531       (vty, lty)  <- vectAndLiftType ty
532
533       let arity = length (tyConDataCons vect_tc)
534       sel_ty <- builtin (selTy arity)
535       sel_bndr <- newLocalVar (fsLit "sel") sel_ty
536       let sel = Var sel_bndr
537
538       (vbndr, valts) <- vect_scrut_bndr
539                       $ mapM (proc_alt arity sel vty lty) alts'
540       let (vect_dcs, vect_bndrss, lift_bndrss, vbodies) = unzip4 valts
541
542       vexpr <- vectExpr scrut
543       (vect_scrut, lift_scrut, pdata_tc, _arg_tys) <- mkVScrut (vVar vbndr)
544       let [pdata_dc] = tyConDataCons pdata_tc
545
546       let (vect_bodies, lift_bodies) = unzip vbodies
547
548       vdummy <- newDummyVar (exprType vect_scrut)
549       ldummy <- newDummyVar (exprType lift_scrut)
550       let vect_case = Case vect_scrut vdummy vty
551                            (zipWith3 mk_vect_alt vect_dcs vect_bndrss vect_bodies)
552
553       lc <- builtin liftingContext
554       lbody <- combinePD vty (Var lc) sel lift_bodies
555       let lift_case = Case lift_scrut ldummy lty
556                            [(DataAlt pdata_dc, sel_bndr : concat lift_bndrss,
557                              lbody)]
558
559       return . vLet (vNonRec vbndr vexpr)
560              $ (vect_case, lift_case)
561   where
562     vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut")
563                     | otherwise         = vectBndrIn bndr
564
565     alts' = sortBy (\(alt1, _, _) (alt2, _, _) -> cmp alt1 alt2) alts
566
567     cmp (DataAlt dc1) (DataAlt dc2) = dataConTag dc1 `compare` dataConTag dc2
568     cmp DEFAULT       DEFAULT       = EQ
569     cmp DEFAULT       _             = LT
570     cmp _             DEFAULT       = GT
571     cmp _             _             = panic "vectAlgCase/cmp"
572
573     proc_alt arity sel _ lty (DataAlt dc, bndrs, body)
574       = do
575           vect_dc <- maybeV (lookupDataCon dc)
576           let ntag = dataConTagZ vect_dc
577               tag  = mkDataConTag vect_dc
578               fvs  = freeVarsOf body `delVarSetList` bndrs
579
580           sel_tags  <- liftM (`App` sel) (builtin (selTags arity))
581           lc        <- builtin liftingContext
582           elems     <- builtin (selElements arity ntag)
583
584           (vbndrs, vbody)
585             <- vectBndrsIn bndrs
586              . localV
587              $ do
588                  binds    <- mapM (pack_var (Var lc) sel_tags tag)
589                            . filter isLocalId
590                            $ varSetElems fvs
591                  (ve, le) <- vectExpr body
592                  return (ve, Case (elems `App` sel) lc lty
593                              [(DEFAULT, [], (mkLets (concat binds) le))])
594                  -- empty    <- emptyPD vty
595                  -- return (ve, Case (elems `App` sel) lc lty
596                  --             [(DEFAULT, [], Let (NonRec flags_var flags_expr)
597                  --                             $ mkLets (concat binds) le),
598                  --               (LitAlt (mkMachInt 0), [], empty)])
599           let (vect_bndrs, lift_bndrs) = unzip vbndrs
600           return (vect_dc, vect_bndrs, lift_bndrs, vbody)
601
602     proc_alt _ _ _ _ _ = panic "vectAlgCase/proc_alt"
603
604     mk_vect_alt vect_dc bndrs body = (DataAlt vect_dc, bndrs, body)
605
606     pack_var len tags t v
607       = do
608           r <- lookupVar v
609           case r of
610             Local (vv, lv) ->
611               do
612                 lv'  <- cloneVar lv
613                 expr <- packByTagPD (idType vv) (Var lv) len tags t
614                 updLEnv (\env -> env { local_vars = extendVarEnv
615                                                 (local_vars env) v (vv, lv') })
616                 return [(NonRec lv' expr)]
617
618             _ -> return []
619