-vectTopRhs
- :: Var -- ^ Name of the binding.
- -> CoreExpr -- ^ Body of the binding.
- -> VM (Inline, CoreExpr)
-
-vectTopRhs var expr
- = dtrace (vcat [text "vectTopRhs", ppr expr])
- $ closedV
- $ do (inline, vexpr) <- inBind var
- $ vectPolyExpr (isLoopBreaker $ idOccInfo var)
- (freeVars expr)
- return (inline, vectorised vexpr)
-
+--
+-- We need to distinguish three cases:
+--
+-- (1) We have a (non-scalar) vectorisation declaration for the variable (which explicitly provides
+-- vectorised code implemented by the user)
+-- => no automatic vectorisation & instead use the user-supplied code
+--
+-- (2) We have a scalar vectorisation declaration for the variable
+-- => generate vectorised code that uses a scalar 'map'/'zipWith' to lift the computation
+--
+-- (3) There is no vectorisation declaration for the variable
+-- => perform automatic vectorisation of the RHS
+--
+vectTopRhs :: [Var] -- ^ Names of all functions in the rec block
+ -> Var -- ^ Name of the binding.
+ -> CoreExpr -- ^ Body of the binding.
+ -> VM ( Inline -- (1) inline specification for the binding
+ , Bool -- (2) whether the right-hand side is a scalar computation
+ , CoreExpr) -- (3) the vectorised right-hand side
+vectTopRhs recFs var expr
+ = closedV
+ $ do { traceVt ("vectTopRhs of " ++ show var) $ ppr expr
+
+ ; globalScalar <- isGlobalScalar var
+ ; vectDecl <- lookupVectDecl var
+ ; rhs globalScalar vectDecl
+ }
+ where
+ rhs _globalScalar (Just (_, expr')) -- Case (1)
+ = return (inlineMe, False, expr')
+ rhs True Nothing -- Case (2)
+ = do { expr' <- vectScalarFun True recFs expr
+ ; return (inlineMe, True, vectorised expr')
+ }
+ rhs False Nothing -- Case (3)
+ = do { let fvs = freeVars expr
+ ; (inline, isScalar, vexpr) <- inBind var $
+ vectPolyExpr (isLoopBreaker $ idOccInfo var) recFs fvs
+ ; return (inline, isScalar, vectorised vexpr)
+ }