ghc-8.4.4: The GHC API

Safe HaskellNone




Vectorisation of expressions.


Vectorise right-hand sides of toplevel bindings

vectTopExpr :: Var -> CoreExpr -> VM (Maybe (Bool, Inline, CoreExpr)) Source #

Vectorise a polymorphic expression that forms a *non-recursive* binding.

Return Nothing if the expression is scalar; otherwise, the first component of the result (which is of type Bool) indicates whether the expression is parallel (i.e., whether it is tagged as VIParr).

We have got the non-recursive case as a special case as it doesn't require to compute vectorisation information twice.

vectTopExprs :: [(Var, CoreExpr)] -> VM (Maybe (Bool, [(Inline, CoreExpr)])) Source #

Vectorise a recursive group of top-level polymorphic expressions.

Return Nothing if the expression group is scalar; otherwise, the first component of the result (which is of type Bool) indicates whether the expressions are parallel (i.e., whether they are tagged as VIParr).

vectScalarFun :: CoreExpr -> VM VExpr Source #

Vectorise an expression of functional type, where all arguments and the result are of primitive types (i.e., Int, Float, Double etc., which have instances of the Scalar type class) and which does not contain any subcomputations that involve parallel arrays. Such functionals do not require the full blown vectorisation transformation; instead, they can be lifted by application of a member of the zipWith family (i.e., map, zipWith, zipWith3', etc.)

Dictionary functions are also scalar functions (as dictionaries themselves are not vectorised, instead they become dictionaries of vectorised methods). We treat them differently, though see "Note [Scalar dfuns]" in Vectorise.

vectScalarDFun Source #


:: Var

Original dfun

-> VM CoreExpr 

Vectorise a dictionary function that has a 'VECTORISE SCALAR instance' pragma.

In other words, all methods in that dictionary are scalar functions — to be vectorised with vectScalarFun. The dictionary "function" itself may be a constant, though.

NB: You may think that we could implement this function guided by the structure of the Core expression of the right-hand side of the dictionary function. We cannot proceed like this as vectScalarDFun must also work for *imported* dfuns, where we don't necessarily have access to the Core code of the unvectorised dfun.

Here an example — assume,

class Eq a where { (==) :: a -> a -> Bool }
instance (Eq a, Eq b) => Eq (a, b) where { (==) = ... }
{-# VECTORISE SCALAR instance Eq (a, b) }

The unvectorised dfun for the above instance has the following signature:

$dEqPair :: forall a b. Eq a -> Eq b -> Eq (a, b)

We generate the following (scalar) vectorised dfun (liberally using TH notation):

$v$dEqPair :: forall a b. V:Eq a -> V:Eq b -> V:Eq (a, b)
$v$dEqPair = /\a b -> \dEqa :: V:Eq a -> \dEqb :: V:Eq b ->
               D:V:Eq $(vectScalarFun True recFns
                        [| (==) @(a, b) ($dEqPair @a @b $(unVect dEqa) $(unVect dEqb)) |])

NB: * '(,)' vectorises to '(,)' — hence, the type constructor in the result type remains the same. * We share the '$(unVect di)' sub-expressions between the different selectors, but duplicate the application of the unvectorised dfun, to enable the dictionary selection rules to fire.