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