- let vclo = Var mk_clo `mkTyApps` [arg_ty, res_ty, env_ty]
- `mkApps` [pa_dict, mono_vfn, mono_lfn, venv]
-
- lclo = Var mk_cloP `mkTyApps` [arg_ty, res_ty, env_ty]
- `mkApps` [pa_dict, mono_vfn, mono_lfn, lenv]
+vectScalarLam :: [Var] -> CoreExpr -> VM VExpr
+vectScalarLam args body
+ = do
+ scalars <- globalScalars
+ onlyIfV (all is_scalar_ty arg_tys
+ && is_scalar_ty res_ty
+ && is_scalar (extendVarSetList scalars args) body
+ && uses scalars body)
+ $ do
+ fn_var <- hoistExpr (fsLit "fn") (mkLams args body) DontInline
+ zipf <- zipScalars arg_tys res_ty
+ clo <- scalarClosure arg_tys res_ty (Var fn_var)
+ (zipf `App` Var fn_var)
+ clo_var <- hoistExpr (fsLit "clo") clo DontInline
+ lclo <- liftPD (Var clo_var)
+ return (Var clo_var, lclo)
+ where
+ arg_tys = map idType args
+ res_ty = exprType body
+
+ is_scalar_ty ty | Just (tycon, []) <- splitTyConApp_maybe ty
+ = tycon == intTyCon
+ || tycon == floatTyCon
+ || tycon == doubleTyCon
+
+ | otherwise = False
+
+ is_scalar vs (Var v) = v `elemVarSet` vs
+ is_scalar _ e@(Lit _) = is_scalar_ty $ exprType e
+ is_scalar vs (App e1 e2) = is_scalar vs e1 && is_scalar vs e2
+ is_scalar _ _ = False
+
+ -- A scalar function has to actually compute something. Without the check,
+ -- we would treat (\(x :: Int) -> x) as a scalar function and lift it to
+ -- (map (\x -> x)) which is very bad. Normal lifting transforms it to
+ -- (\n# x -> x) which is what we want.
+ uses funs (Var v) = v `elemVarSet` funs
+ uses funs (App e1 e2) = uses funs e1 || uses funs e2
+ uses _ _ = False
+
+vectLam :: Bool -> Bool -> VarSet -> [Var] -> CoreExprWithFVs -> VM VExpr
+vectLam inline loop_breaker fvs bs body
+ = do
+ tyvars <- localTyVars
+ (vs, vvs) <- readLEnv $ \env ->
+ unzip [(var, vv) | var <- varSetElems fvs
+ , Just vv <- [lookupVarEnv (local_vars env) var]]
+
+ arg_tys <- mapM (vectType . idType) bs
+ res_ty <- vectType (exprType $ deAnnotate body)
+
+ buildClosures tyvars vvs arg_tys res_ty
+ . hoistPolyVExpr tyvars (maybe_inline (length vs + length bs))
+ $ do
+ lc <- builtin liftingContext
+ (vbndrs, vbody) <- vectBndrsIn (vs ++ bs)
+ (vectExpr body)
+ vbody' <- break_loop lc res_ty vbody
+ return $ vLams lc vbndrs vbody'
+ where
+ maybe_inline n | inline = Inline n
+ | otherwise = DontInline