Vectorise.Exp

ghc-8.4.4: The GHC API

Safe Haskell | None
Language | Haskell2010

Vectorise.Exp

Contents

- Vectorise right-hand sides of toplevel bindings

Description

Vectorisation of expressions.

Synopsis

- vectTopExpr :: Var -> CoreExpr -> VM (Maybe (Bool, Inline, CoreExpr))
- vectTopExprs :: [(Var, CoreExpr)] -> VM (Maybe (Bool, [(Inline, CoreExpr)]))
- vectScalarFun :: CoreExpr -> VM VExpr
- vectScalarDFun :: Var -> VM CoreExpr

# Vectorise right-hand sides of toplevel bindings

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

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)])) #

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 #

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 #

Arguments

:: 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.