-vectVar :: CoreExpr -> Var -> VM (CoreExpr, CoreExpr)
-vectVar lc v = local v `orElseV` global v
- where
- local v = maybeV (readLEnv $ \env -> lookupVarEnv (local_vars env) v)
- global v = do
- vexpr <- maybeV (readGEnv $ \env -> lookupVarEnv (global_vars env) v)
- lexpr <- replicateP vexpr lc
- return (vexpr, lexpr)
-
-vectExpr :: CoreExpr -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr)
-vectExpr lc (_, AnnType ty)
- = do
- vty <- vectType ty
- return (Type vty, Type vty)
-vectExpr lc (_, AnnVar v) = vectVar lc v
-vectExpr lc (_, AnnLit lit)
- = do
- let vexpr = Lit lit
- lexpr <- replicateP vexpr lc
- return (vexpr, lexpr)
-vectExpr lc (_, AnnNote note expr)
- = do
- (vexpr, lexpr) <- vectExpr lc expr
- return (Note note vexpr, Note note lexpr)
-vectExpr lc (_, AnnApp fn arg)
- = do
- fn' <- vectExpr lc fn
- arg' <- vectExpr lc arg
- capply fn' arg'
-vectExpr lc (_, AnnCase expr bndr ty alts)
- = panic "vectExpr: case"
-vectExpr lc (_, AnnLet (AnnNonRec bndr rhs) body)
- = do
- (vrhs, lrhs) <- vectExpr lc rhs
- (vbndr, lbndr, (vbody, lbody)) <- vectBndrIn bndr (vectExpr lc body)
- return (Let (NonRec vbndr vrhs) vbody,
- Let (NonRec lbndr lrhs) lbody)
-vectExpr lc (_, AnnLet (AnnRec prs) body)
- = do
- (vbndrs, lbndrs, (vrhss, vbody, lrhss, lbody)) <- vectBndrsIn bndrs vect
- return (Let (Rec (zip vbndrs vrhss)) vbody,
- Let (Rec (zip lbndrs lrhss)) lbody)
- where
- (bndrs, rhss) = unzip prs
-
- vect = do
- (vrhss, lrhss) <- mapAndUnzipM (vectExpr lc) rhss
- (vbody, lbody) <- vectExpr lc body
- return (vrhss, vbody, lrhss, lbody)
-vectExpr lc (_, AnnLam bndr body)
- | isTyVar bndr
- = do
- r <- paDictArgType bndr
- (upd_env, add_lam) <- get_upd r
- (vbody, lbody) <- localV (upd_env >> vectExpr lc body)
- return (Lam bndr (add_lam vbody), Lam bndr (add_lam lbody))
+ ; (_, fam_inst_env) <- readGEnv global_fam_inst_env
+
+ -- dicts <- mapM buildPADict pa_insts
+ -- workers <- mapM vectDataConWorkers pa_insts
+
+ -- Vectorise all the top level bindings.
+ ; binds' <- mapM vectTopBind binds
+
+ ; return $ guts { mg_types = types'
+ , mg_binds = Rec tc_binds : binds'
+ , mg_fam_inst_env = fam_inst_env
+ , mg_fam_insts = fam_insts ++ new_fam_insts
+ }
+ }
+
+-- |Try to vectorise a top-level binding. If it doesn't vectorise then return it unharmed.
+--
+-- For example, for the binding
+--
+-- @
+-- foo :: Int -> Int
+-- foo = \x -> x + x
+-- @
+--
+-- we get
+-- @
+-- foo :: Int -> Int
+-- foo = \x -> vfoo $: x
+--
+-- v_foo :: Closure void vfoo lfoo
+-- v_foo = closure vfoo lfoo void
+--
+-- vfoo :: Void -> Int -> Int
+-- vfoo = ...
+--
+-- lfoo :: PData Void -> PData Int -> PData Int
+-- lfoo = ...
+-- @
+--
+-- @vfoo@ is the "vectorised", or scalar, version that does the same as the original
+-- function foo, but takes an explicit environment.
+--
+-- @lfoo@ is the "lifted" version that works on arrays.
+--
+-- @v_foo@ combines both of these into a `Closure` that also contains the
+-- environment.
+--
+-- The original binding @foo@ is rewritten to call the vectorised version
+-- present in the closure.
+--
+-- Vectorisation may be surpressed by annotating a binding with a 'NOVECTORISE' pragma. If this
+-- pragma is used in a group of mutually recursive bindings, either all or no binding must have
+-- the pragma. If only some bindings are annotated, a fatal error is being raised.
+-- FIXME: Once we support partial vectorisation, we may be able to vectorise parts of a group, or
+-- we may emit a warning and refrain from vectorising the entire group.
+--
+vectTopBind :: CoreBind -> VM CoreBind
+vectTopBind b@(NonRec var expr)
+ = unlessNoVectDecl $
+ do { -- Vectorise the right-hand side, create an appropriate top-level binding and add it
+ -- to the vectorisation map.
+ ; (inline, isScalar, expr') <- vectTopRhs [] var expr
+ ; var' <- vectTopBinder var inline expr'
+ ; when isScalar $
+ addGlobalScalar var
+
+ -- We replace the original top-level binding by a value projected from the vectorised
+ -- closure and add any newly created hoisted top-level bindings.
+ ; cexpr <- tryConvert var var' expr
+ ; hs <- takeHoisted
+ ; return . Rec $ (var, cexpr) : (var', expr') : hs
+ }
+ `orElseV`
+ return b