+++ /dev/null
--- $Id$
---
--- Copyright (c) [2001..2002] Manuel M T Chakravarty & Gabriele Keller
---
--- Vectorisation and lifting
---
---- DESCRIPTION ---------------------------------------------------------------
---
--- This module implements the vectorisation and function lifting
--- transformations of the flattening transformation.
---
---- DOCU ----------------------------------------------------------------------
---
--- Language: Haskell 98 with C preprocessor
---
--- Types:
--- the transformation on types has five purposes:
---
--- 1) for each type definition, derive the lifted version of this type
--- liftTypeef
--- 2) change the type annotations of functions & variables acc. to rep.
--- flattenType
--- 3) derive the type of a lifted function
--- liftType
--- 4) sumtypes:
--- this is the most fuzzy and complicated part. For each lifted
--- sumtype we need to generate function to access and combine the
--- component arrays
---
--- NOTE: the type information of variables and data constructors is *not*
--- changed to reflect it's representation. This has to be solved
--- somehow (???, FIXME) using type indexed types
---
--- Vectorisation:
--- is very naive at the moment. One of the most striking inefficiencies is
--- application vect (app e1 e2) -> app (fst (vect e1) (vect e2)) if e1 is a
--- lambda abstraction. The vectorisation produces a pair consisting of the
--- original and the lifted function, but the lifted version is discarded.
--- I'm also not sure how much of this would be thrown out by the simplifier
--- eventually
---
--- *) vectorise
---
--- Conventions:
---
---- TODO ----------------------------------------------------------------------
---
--- * look closer into the definition of type definition (TypeThing or so)
---
-
-module Flattening (
- flatten, flattenExpr,
-) where
-
-#include "HsVersions.h"
-
--- friends
-import NDPCoreUtils (tupleTyArgs, funTyArgs, parrElemTy, isDefault,
- isLit, mkPArrTy, mkTuple, isSimpleExpr, substIdEnv)
-import FlattenMonad (Flatten, runFlatten, mkBind, extendContext, packContext,
- liftVar, liftConst, intersectWithContext, mk'fst,
- mk'lengthP, mk'replicateP, mk'mapP, mk'bpermuteDftP,
- mk'indexOfP,mk'eq,mk'neq)
-
--- GHC
-import TcType ( tcIsForAllTy, tcView )
-import TypeRep ( Type(..) )
-import StaticFlags (opt_Flatten)
-import Panic (panic)
-import ErrUtils (dumpIfSet_dyn)
-import UniqSupply (mkSplitUniqSupply)
-import DynFlags (DynFlag(..))
-import Literal (Literal, literalType)
-import Var (Var(..), idType, isTyVar)
-import Id (setIdType)
-import DataCon (DataCon, dataConTag)
-import HscTypes ( ModGuts(..), ModGuts, HscEnv(..), hscEPS )
-import CoreFVs (exprFreeVars)
-import CoreSyn (Expr(..), Bind(..), Alt(..), AltCon(..), Note(..),
- CoreBndr, CoreExpr, CoreBind, mkLams, mkLets,
- mkApps, mkIntLitInt)
-import PprCore (pprCoreExpr)
-import CoreLint (showPass, endPass)
-
-import CoreUtils (exprType, applyTypeToArg, mkPiType)
-import VarEnv (zipVarEnv)
-import TysWiredIn (mkTupleTy)
-import BasicTypes (Boxity(..))
-import Outputable
-import FastString
-
-
--- FIXME: fro debugging - remove this
-import TRACE (trace)
-
--- standard
-import Monad (liftM, foldM)
-
--- toplevel transformation
--- -----------------------
-
--- entry point to the flattening transformation for the compiler driver when
--- compiling a complete module (EXPORTED)
---
-flatten :: HscEnv
- -> ModGuts
- -> IO ModGuts
-flatten hsc_env mod_impl@(ModGuts {mg_binds = binds})
- | not opt_Flatten = return mod_impl -- skip without -fflatten
- | otherwise =
- do
- let dflags = hsc_dflags hsc_env
-
- eps <- hscEPS hsc_env
- us <- mkSplitUniqSupply 'l' -- 'l' as in fLattening
- --
- -- announce vectorisation
- --
- showPass dflags "Flattening [first phase: vectorisation]"
- --
- -- vectorise all toplevel bindings
- --
- let binds' = runFlatten hsc_env eps us $ vectoriseTopLevelBinds binds
- --
- -- and dump the result if requested
- --
- endPass dflags "Flattening [first phase: vectorisation]"
- Opt_D_dump_vect binds'
- return $ mod_impl {mg_binds = binds'}
-
--- entry point to the flattening transformation for the compiler driver when
--- compiling a single expression in interactive mode (EXPORTED)
---
-flattenExpr :: HscEnv
- -> CoreExpr -- the expression to be flattened
- -> IO CoreExpr
-flattenExpr hsc_env expr
- | not opt_Flatten = return expr -- skip without -fflatten
- | otherwise =
- do
- let dflags = hsc_dflags hsc_env
- eps <- hscEPS hsc_env
-
- us <- mkSplitUniqSupply 'l' -- 'l' as in fLattening
- --
- -- announce vectorisation
- --
- showPass dflags "Flattening [first phase: vectorisation]"
- --
- -- vectorise the expression
- --
- let expr' = fst . runFlatten hsc_env eps us $ vectorise expr
- --
- -- and dump the result if requested
- --
- dumpIfSet_dyn dflags Opt_D_dump_vect "Vectorised expression"
- (pprCoreExpr expr')
- return expr'
-
-
--- vectorisation of bindings and expressions
--- -----------------------------------------
-
-
-vectoriseTopLevelBinds:: [CoreBind] -> Flatten [CoreBind]
-vectoriseTopLevelBinds binds =
- do
- vbinds <- mapM vectoriseBind binds
- return (adjustTypeBinds vbinds)
-
-adjustTypeBinds:: [CoreBind] -> [CoreBind]
-adjustTypeBinds vbinds =
- let
- ids = concat (map extIds vbinds)
- idEnv = zipVarEnv ids ids
- in map (substIdEnvBind idEnv) vbinds
- where
- -- FIXME replace by 'bindersOf'
- extIds (NonRec b expr) = [b]
- extIds (Rec bnds) = map fst bnds
- substIdEnvBind idEnv (NonRec b expr) = NonRec b (substIdEnv idEnv expr)
- substIdEnvBind idEnv (Rec bnds)
- = Rec (map (\ (b,e) -> (b, (substIdEnv idEnv e))) bnds)
-
--- vectorise a single core binder
---
-vectoriseBind :: CoreBind -> Flatten CoreBind
-vectoriseBind (NonRec b expr) =
- liftM (NonRec b) $ liftM fst $ vectorise expr
-vectoriseBind (Rec bindings) =
- liftM Rec $ mapM vectoriseOne bindings
- where
- vectoriseOne (b, expr) =
- do
- (vexpr, ty) <- vectorise expr
- return (setIdType b ty, vexpr)
-
-
--- Searches for function definitions and creates a lifted version for
--- each function.
--- We have only two interesting cases:
--- 1) function application (ex1) (ex2)
--- vectorise both subexpressions. The function will end up becoming a
--- pair (orig. fun, lifted fun), choose first component (in many cases,
--- this is pretty inefficient, since the lifted version is generated
--- although it is clear that it won't be used
---
--- 2) lambda abstraction
--- any function has to exist in two forms: it's original form and it's
--- lifted form. Therefore, every lambda abstraction is transformed into
--- a pair of functions: the original function and its lifted variant
---
---
--- FIXME: currently, I use 'exprType' all over the place - this is terribly
--- inefficient. It should be suffiecient to change 'vectorise' and 'lift' to
--- return the type of the result expression as well.
---
-vectorise:: CoreExpr -> Flatten (CoreExpr, Type)
-vectorise (Var id) =
- do
- let varTy = idType id
- let vecTy = vectoriseTy varTy
- return (Var (setIdType id vecTy), vecTy)
-
-vectorise (Lit lit) =
- return ((Lit lit), literalType lit)
-
-
-vectorise e@(App expr t@(Type _)) =
- do
- (vexpr, vexprTy) <- vectorise expr
- return ((App vexpr t), applyTypeToArg vexprTy t)
-
-vectorise (App (Lam b expr) arg) =
- do
- (varg, argTy) <- vectorise arg
- (vexpr, vexprTy) <- vectorise expr
- let vb = setIdType b argTy
- return ((App (Lam vb vexpr) varg),
- applyTypeToArg (mkPiType vb vexprTy) varg)
-
--- if vexpr expects a type as first argument
--- application stays just as it is
---
-vectorise (App expr arg) =
- do
- (vexpr, vexprTy) <- vectorise expr
- (varg, vargTy) <- vectorise arg
-
- if (tcIsForAllTy vexprTy)
- then do
- let resTy = applyTypeToArg vexprTy varg
- return (App vexpr varg, resTy)
- else do
- let [t1, t2] = tupleTyArgs vexprTy
- vexpr' <- mk'fst t1 t2 vexpr
- let resTy = applyTypeToArg t1 varg
- return ((App vexpr' varg), resTy) -- apply the first component of
- -- the vectorized function
-
-vectorise e@(Lam b expr)
- | isTyVar b
- = do
- (vexpr, vexprTy) <- vectorise expr -- don't vectorise 'b'!
- return ((Lam b vexpr), mkPiType b vexprTy)
- | otherwise =
- do
- (vexpr, vexprTy) <- vectorise expr
- let vb = setIdType b (vectoriseTy (idType b))
- let ve = Lam vb vexpr
- (lexpr, lexprTy) <- lift e
- let veTy = mkPiType vb vexprTy
- return $ (mkTuple [veTy, lexprTy] [ve, lexpr],
- mkTupleTy Boxed 2 [veTy, lexprTy])
-
-vectorise (Let bind body) =
- do
- vbind <- vectoriseBind bind
- (vbody, vbodyTy) <- vectorise body
- return ((Let vbind vbody), vbodyTy)
-
-vectorise (Case expr b ty alts) =
- do
- (vexpr, vexprTy) <- vectorise expr
- valts <- mapM vectorise' alts
- let res_ty = snd (head valts)
- return (Case vexpr (setIdType b vexprTy) res_ty (map fst valts), res_ty)
- where vectorise' (con, bs, expr) =
- do
- (vexpr, vexprTy) <- vectorise expr
- return ((con, bs, vexpr), vexprTy) -- FIXME: change type of con
- -- and bs
-
-
-
-vectorise (Note note expr) =
- do
- (vexpr, vexprTy) <- vectorise expr -- FIXME: is this ok or does it
- return ((Note note vexpr), vexprTy) -- change the validity of note?
-
-vectorise e@(Type t) =
- return (e, t) -- FIXME: panic instead of 't'???
-
-
-{-
-myShowTy (TyVarTy _) = "TyVar "
-myShowTy (AppTy t1 t2) =
- "AppTy (" ++ (myShowTy t1) ++ ", " ++ (myShowTy t2) ++ ")"
-myShowTy (TyConApp _ t) =
- "TyConApp TC (" ++ (myShowTy t) ++ ")"
--}
-
-vectoriseTy :: Type -> Type
-vectoriseTy ty | Just ty' <- tcView ty = vectoriseTy ty'
- -- Look through notes and synonyms
- -- NB: This will discard notes and synonyms, of course
- -- ToDo: retain somehow?
-vectoriseTy t@(TyVarTy v) = t
-vectoriseTy t@(AppTy t1 t2) =
- AppTy (vectoriseTy t1) (vectoriseTy t2)
-vectoriseTy t@(TyConApp tc ts) =
- TyConApp tc (map vectoriseTy ts)
-vectoriseTy t@(FunTy t1 t2) =
- mkTupleTy Boxed 2 [(FunTy (vectoriseTy t1) (vectoriseTy t2)),
- (liftTy t)]
-vectoriseTy t@(ForAllTy v ty) =
- ForAllTy v (vectoriseTy ty)
-vectoriseTy t = t
-
-
--- liftTy: wrap the type in an array but be careful with function types
--- on the *top level* (is this sufficient???)
-
-liftTy:: Type -> Type
-liftTy ty | Just ty' <- tcView ty = liftTy ty'
-liftTy (FunTy t1 t2) = FunTy (liftTy t1) (liftTy t2)
-liftTy (ForAllTy tv t) = ForAllTy tv (liftTy t)
-liftTy t = mkPArrTy t
-
-
--- lifting:
--- ----------
--- * liftType
--- * lift
-
-
--- liftBinderType: Converts a type 'a' stored in the binder to the
--- representation of '[:a:]' will therefore call liftType
---
--- lift type, don't change name (incl unique) nor IdInfo. IdInfo looks ok,
--- but I'm not entirely sure about some fields (e.g., strictness info)
-liftBinderType:: CoreBndr -> Flatten CoreBndr
-liftBinderType bndr = return $ setIdType bndr (liftTy (idType bndr))
-
--- lift: lifts an expression (a -> [:a:])
--- If the expression is a simple expression, it is treated like a constant
--- expression.
--- If the body of a lambda expression is a simple expression, it is
--- transformed into a mapP
-lift:: CoreExpr -> Flatten (CoreExpr, Type)
-lift cExpr@(Var id) =
- do
- lVar@(Var lId) <- liftVar id
- return (lVar, idType lId)
-
-lift cExpr@(Lit lit) =
- do
- lLit <- liftConst cExpr
- return (lLit, exprType lLit)
-
-
-lift (Lam b expr)
- | isSimpleExpr expr = liftSimpleFun b expr
- | isTyVar b =
- do
- (lexpr, lexprTy) <- lift expr -- don't lift b!
- return (Lam b lexpr, mkPiType b lexprTy)
- | otherwise =
- do
- lb <- liftBinderType b
- (lexpr, lexprTy) <- extendContext [lb] (lift expr)
- return ((Lam lb lexpr) , mkPiType lb lexprTy)
-
-lift (App expr1 expr2) =
- do
- (lexpr1, lexpr1Ty) <- lift expr1
- (lexpr2, _) <- lift expr2
- return ((App lexpr1 lexpr2), applyTypeToArg lexpr1Ty lexpr2)
-
-
-lift (Let (NonRec b expr1) expr2)
- |isSimpleExpr expr2 =
- do
- (lexpr1, _) <- lift expr1
- (lexpr2, lexpr2Ty) <- liftSimpleFun b expr2
- let (t1, t2) = funTyArgs lexpr2Ty
- liftM (\x -> (x, liftTy t2)) $ mk'mapP t1 t2 lexpr2 lexpr1
-
- | otherwise =
- do
- (lexpr1, _) <- lift expr1
- lb <- liftBinderType b
- (lexpr2, lexpr2Ty) <- extendContext [lb] (lift expr1)
- return ((Let (NonRec lb lexpr1) lexpr2), lexpr2Ty)
-
-lift (Let (Rec binds) expr2) =
- do
- let (bndVars, exprs) = unzip binds
- lBndVars <- mapM liftBinderType bndVars
- lexprs <- extendContext bndVars (mapM lift exprs)
- (lexpr2, lexpr2Ty) <- extendContext bndVars (lift expr2)
- return ((Let (Rec (zip lBndVars (map fst lexprs))) lexpr2), lexpr2Ty)
-
--- FIXME:
--- Assumption: alternatives can either be literals or data construtors.
--- Due to type restrictions, I don't think it is possible
--- that they are mixed.
--- The handling of literals and data constructors is completely
--- different
---
---
--- let b = expr in alts
---
--- I think I read somewhere that the default case (if present) is stored
--- in the head of the list. Assume for now this is true, have to check
---
--- (1) literals
--- (2) data constructors
---
--- FIXME: optimisation: first, filter out all simple expression and
--- loop (mapP & filter) over all the corresponding values in a single
--- traversal:
-
--- (1) splitAlts:: [Alt CoreBndr] -> ([Alt CoreBndr],[Alt CoreBndr])
--- simple alts reg alts
--- (2) if simpleAlts = [] then (just as before)
--- if regAlts = [] then (the whole thing is just a loop)
--- otherwise (a) compute index vector for simpleAlts (for def permute
--- later on
--- (b)
--- gaw 2004 FIX?
-lift cExpr@(Case expr b _ alts) =
- do
- (lExpr, _) <- lift expr
- lb <- liftBinderType b -- lift alt-expression
- lalts <- if isLit alts
- then extendContext [lb] (liftCaseLit b alts)
- else extendContext [lb] (liftCaseDataCon b alts)
- letWrapper lExpr b lalts
-
-lift (Note (Coerce t1 t2) expr) =
- do
- (lexpr, t) <- lift expr
- let lt1 = liftTy t1
- return ((Note (Coerce lt1 (liftTy t2)) lexpr), lt1)
-
-lift (Note note expr) =
- do
- (lexpr, t) <- lift expr
- return ((Note note lexpr), t)
-
-lift e@(Type t) = return (e, t)
-
-
--- auxilliary functions for lifting of case statements
---
-
-liftCaseDataCon:: CoreBndr -> [Alt CoreBndr] ->
- Flatten (([CoreBind], [CoreBind], [CoreBind]))
-liftCaseDataCon b [] =
- return ([], [], [])
-liftCaseDataCon b alls@(alt:alts)
- | isDefault alt =
- do
- (i, e, defAltBndrs) <- liftCaseDataConDefault b alt alts
- (is, es, altBndrs) <- liftCaseDataCon' b alts
- return (i:is, e:es, defAltBndrs ++ altBndrs)
- | otherwise =
- liftCaseDataCon' b alls
-
-liftCaseDataCon':: CoreBndr -> [Alt CoreBndr] ->
- Flatten ([CoreBind], [CoreBind], [CoreBind])
-liftCaseDataCon' _ [] =
- do
- return ([], [], [])
-
-
-liftCaseDataCon' b ((DataAlt dcon, bnds, expr): alts) =
- do
- (permBnd, exprBnd, packBnd) <- liftSingleDataCon b dcon bnds expr
- (permBnds, exprBnds, packBnds) <- liftCaseDataCon' b alts
- return (permBnd:permBnds, exprBnd:exprBnds, packBnd ++ packBnds)
-
-
--- FIXME: is is really necessary to return the binding to the permutation
--- array in the data constructor case, as the representation already
--- contains the extended flag vector
-liftSingleDataCon:: CoreBndr -> DataCon -> [CoreBndr] -> CoreExpr ->
- Flatten (CoreBind, CoreBind, [CoreBind])
-liftSingleDataCon b dcon bnds expr =
- do
- let dconId = dataConTag dcon
- indexExpr <- mkIndexOfExprDCon (idType b) b dconId
- (bb, bbind) <- mkBind FSLIT("is") indexExpr
- lbnds <- mapM liftBinderType bnds
- ((lExpr, _), bnds') <- packContext bb (extendContext lbnds (lift expr))
- (_, vbind) <- mkBind FSLIT("r") lExpr
- return (bbind, vbind, bnds')
-
--- FIXME: clean this up. the datacon and the literal case are so
--- similar that it would be easy to use the same function here
--- instead of duplicating all the code.
---
-liftCaseDataConDefault:: CoreBndr -> (Alt CoreBndr) -> [Alt CoreBndr]
- -> Flatten (CoreBind, CoreBind, [CoreBind])
-liftCaseDataConDefault b (_, _, def) alts =
- do
- let dconIds = map (\(DataAlt d, _, _) -> dataConTag d) alts
- indexExpr <- mkIndexOfExprDConDft (idType b) b dconIds
- (bb, bbind) <- mkBind FSLIT("is") indexExpr
- ((lDef, _), bnds) <- packContext bb (lift def)
- (_, vbind) <- mkBind FSLIT("r") lDef
- return (bbind, vbind, bnds)
-
--- liftCaseLit: checks if we have a default case and handles it
--- if necessary
-liftCaseLit:: CoreBndr -> [Alt CoreBndr] ->
- Flatten ([CoreBind], [CoreBind], [CoreBind])
-liftCaseLit b [] =
- return ([], [], []) --FIXME: a case with no cases at all???
-liftCaseLit b alls@(alt:alts)
- | isDefault alt =
- do
- (i, e, defAltBndrs) <- liftCaseLitDefault b alt alts
- (is, es, altBndrs) <- liftCaseLit' b alts
- return (i:is, e:es, defAltBndrs ++ altBndrs)
- | otherwise =
- do
- liftCaseLit' b alls
-
--- liftCaseLitDefault: looks at all the other alternatives which
--- contain a literal and filters all those elements from the
--- array which do not match any of the literals in the other
--- alternatives.
-liftCaseLitDefault:: CoreBndr -> (Alt CoreBndr) -> [Alt CoreBndr]
- -> Flatten (CoreBind, CoreBind, [CoreBind])
-liftCaseLitDefault b (_, _, def) alts =
- do
- let lits = map (\(LitAlt l, _, _) -> l) alts
- indexExpr <- mkIndexOfExprDft (idType b) b lits
- (bb, bbind) <- mkBind FSLIT("is") indexExpr
- ((lDef, _), bnds) <- packContext bb (lift def)
- (_, vbind) <- mkBind FSLIT("r") lDef
- return (bbind, vbind, bnds)
-
--- FIXME:
--- Assumption: in case of Lit, the list of binders of the alt is empty.
---
--- returns
--- a list of all vars bound to the expr in the body of the alternative
--- a list of (var, expr) pairs, where var has to be bound to expr
--- by letWrapper
-liftCaseLit':: CoreBndr -> [Alt CoreBndr] ->
- Flatten ([CoreBind], [CoreBind], [CoreBind])
-liftCaseLit' _ [] =
- do
- return ([], [], [])
-liftCaseLit' b ((LitAlt lit, [], expr):alts) =
- do
- (permBnd, exprBnd, packBnd) <- liftSingleCaseLit b lit expr
- (permBnds, exprBnds, packBnds) <- liftCaseLit' b alts
- return (permBnd:permBnds, exprBnd:exprBnds, packBnd ++ packBnds)
-
--- lift a single alternative of the form: case b of lit -> expr.
---
--- It returns the bindings:
--- (a) let b' = indexOfP (mapP (\x -> x == lit) b)
---
--- (b) lift expr in the packed context. Returns lexpr and the
--- list of binds (bnds) that describe the packed arrays
---
--- (c) create new var v' to bind lexpr to
---
--- (d) return (b' = indexOf...., v' = lexpr, bnds)
-liftSingleCaseLit:: CoreBndr -> Literal -> CoreExpr ->
- Flatten (CoreBind, CoreBind, [CoreBind])
-liftSingleCaseLit b lit expr =
- do
- indexExpr <- mkIndexOfExpr (idType b) b lit -- (a)
- (bb, bbind) <- mkBind FSLIT("is") indexExpr
- ((lExpr, t), bnds) <- packContext bb (lift expr) -- (b)
- (_, vbind) <- mkBind FSLIT("r") lExpr
- return (bbind, vbind, bnds)
-
--- letWrapper lExpr b ([indexbnd_i], [exprbnd_i], [pckbnd_ij])
---
--- let b = lExpr in
--- let index_bnd_1 in
--- let packbnd_11 in
--- ... packbnd_1m in
--- let exprbnd_1 in ....
--- ...
--- let nvar = replicate dummy (length <current context>)
--- nvar1 = bpermuteDftP index_bnd_1 ...
---
--- in bpermuteDftP index_bnd_n nvar_(n-1)
---
-letWrapper:: CoreExpr -> CoreBndr ->([CoreBind], [CoreBind], [CoreBind]) ->
- Flatten (CoreExpr, Type)
-letWrapper lExpr b (indBnds, exprBnds, pckBnds) =
- do
- (defBpBnds, ty) <- dftbpBinders indBnds exprBnds
- let resExpr = getExprOfBind (head defBpBnds)
- return ((mkLets (indBnds ++ pckBnds ++ exprBnds ++ defBpBnds) resExpr), ty)
-
--- dftbpBinders: return the list of binders necessary to construct the overall
--- result from the subresults computed in the different branches of the case
--- statement. The binding which contains the final result is in the *head*
--- of the result list.
---
--- dftbpBinders [ind_i = ...] [expr_i = ...] = [dn = ..., d_n-1 = .., d1 = ...]
---
--- let def = replicate (length of context) undefined
--- d1 = bpermuteDftP dft e1 i1
--- .....
---
-dftbpBinders:: [CoreBind] -> [CoreBind] -> Flatten ([CoreBind], Type)
-dftbpBinders indexBnds exprBnds =
- do
- let expr = getExprOfBind (head exprBnds)
- defVecExpr <- createDftArrayBind expr
- ((b, bnds), t) <- dftbpBinders' indexBnds exprBnds defVecExpr
- return ((b:bnds),t)
- where
- dftbpBinders' :: [CoreBind]
- -> [CoreBind]
- -> CoreBind
- -> Flatten ((CoreBind, [CoreBind]), Type)
- dftbpBinders' [] [] cBnd =
- return ((cBnd, []), panic "dftbpBinders: undefined type")
- dftbpBinders' (i:is) (e:es) cBind =
- do
- let iVar = getVarOfBind i
- let eVar = getVarOfBind e
- let cVar = getVarOfBind cBind
- let ty = idType eVar
- newBnd <- mkDftBackpermute ty iVar eVar cVar
- ((fBnd, restBnds), _) <- dftbpBinders' is es newBnd
- return ((fBnd, (newBnd:restBnds)), liftTy ty)
-
- dftbpBinders' _ _ _ =
- panic "Flattening.dftbpBinders: index and expression binder lists have different length!"
-
-getExprOfBind:: CoreBind -> CoreExpr
-getExprOfBind (NonRec _ expr) = expr
-
-getVarOfBind:: CoreBind -> Var
-getVarOfBind (NonRec b _) = b
-
-
-
--- Optimised Transformation
--- =========================
---
-
--- liftSimpleFun
--- if variables x_1 to x_i occur in the context *and* free in expr
--- then
--- (liftSimpleExpression expr) => mapP (\ (x1,..xn) -> expr) (x1,..xn)
---
-liftSimpleFun:: CoreBndr -> CoreExpr -> Flatten (CoreExpr, Type)
-liftSimpleFun b expr =
- do
- bndVars <- collectBoundVars expr
- let bndVars' = b:bndVars
- bndVarsTuple = mkTuple (map idType bndVars') (map Var bndVars')
- lamExpr = mkLams (b:bndVars) expr -- FIXME: should be tuple
- -- here
- let (t1, t2) = funTyArgs . exprType $ lamExpr
- mapExpr <- mk'mapP t1 t2 lamExpr bndVarsTuple
- let lexpr = mkApps mapExpr [bndVarsTuple]
- return (lexpr, undefined) -- FIXME!!!!!
-
-
-collectBoundVars:: CoreExpr -> Flatten [CoreBndr]
-collectBoundVars expr =
- intersectWithContext (exprFreeVars expr)
-
-
--- auxilliary routines
--- -------------------
-
--- mkIndexOfExpr b lit ->
--- indexOf (mapP (\x -> x == lit) b) b
---
-mkIndexOfExpr:: Type -> CoreBndr -> Literal -> Flatten CoreExpr
-mkIndexOfExpr idType b lit =
- do
- eqExpr <- mk'eq idType (Var b) (Lit lit)
- let lambdaExpr = (Lam b eqExpr)
- mk'indexOfP idType lambdaExpr (Var b)
-
--- there is FlattenMonad.mk'indexOfP as well as
--- CoreSyn.mkApps and CoreSyn.mkLam, all of which should help here
-
--- for case-distinction over data constructors:
--- let b = expr in
--- case b of
--- dcon args -> ....
--- dconId = dataConTag dcon
--- the call "mkIndexOfExprDCon b dconId" computes the core expression for
--- indexOfP (\x -> x == dconId) b)
---
-mkIndexOfExprDCon::Type -> CoreBndr -> Int -> Flatten CoreExpr
-mkIndexOfExprDCon idType b dId =
- do
- let intExpr = mkIntLitInt dId
- eqExpr <- mk'eq idType (Var b) intExpr
- let lambdaExpr = (Lam b intExpr)
- mk'indexOfP idType lambdaExpr (Var b)
-
-
-
--- there is FlattenMonad.mk'indexOfP as well as
--- CoreSyn.mkApps and CoreSyn.mkLam, all of which should help here
-
--- mk'IndexOfExprDConDft b dconIds : Generates the index expression for the
--- default case. "dconIds" is a list of all the data constructor idents which
--- are covered by the other cases.
--- indexOfP (\x -> x != dconId_1 && ....) b)
---
-mkIndexOfExprDConDft:: Type -> CoreBndr -> [Int] -> Flatten CoreExpr
-mkIndexOfExprDConDft idType b dId =
- do
- let intExprs = map mkIntLitInt dId
- bExpr <- foldM (mk'neq idType) (head intExprs) (tail intExprs)
- let lambdaExpr = (Lam b bExpr)
- mk'indexOfP idType (Var b) bExpr
-
-
--- mkIndexOfExprDef b [lit1, lit2,...] ->
--- indexOf (\x -> not (x == lit1 || x == lit2 ....) b
-mkIndexOfExprDft:: Type -> CoreBndr -> [Literal] -> Flatten CoreExpr
-mkIndexOfExprDft idType b lits =
- do
- let litExprs = map (\l-> Lit l) lits
- bExpr <- foldM (mk'neq idType) (head litExprs) (tail litExprs)
- let lambdaExpr = (Lam b bExpr)
- mk'indexOfP idType bExpr (Var b)
-
-
--- create a back-permute binder
---
--- * `mkDftBackpermute ty indexArrayVar srcArrayVar dftArrayVar' creates a
--- Core binding of the form
---
--- x = bpermuteDftP indexArrayVar srcArrayVar dftArrayVar
---
--- where `x' is a new local variable
---
-mkDftBackpermute :: Type -> Var -> Var -> Var -> Flatten CoreBind
-mkDftBackpermute ty idx src dft =
- do
- rhs <- mk'bpermuteDftP ty (Var idx) (Var src) (Var dft)
- liftM snd $ mkBind FSLIT("dbp") rhs
-
--- create a dummy array with elements of the given type, which can be used as
--- default array for the combination of the subresults of the lifted case
--- expression
---
-createDftArrayBind :: CoreExpr -> Flatten CoreBind
-createDftArrayBind e =
- panic "Flattening.createDftArrayBind: not implemented yet"
-{-
- do
- let ty = parrElemTy . exprType $ expr
- len <- mk'lengthP e
- rhs <- mk'replicateP ty len err??
- lift snd $ mkBind FSLIT("dft") rhs
-FIXME: nicht so einfach; man kann kein "error"-Wert nehmen, denn der w"urde
- beim bpermuteDftP sofort evaluiert, aber es ist auch schwer m"oglich einen
- generischen Wert f"ur jeden beliebigen Typ zu erfinden.
--}
-
-
-
-
--- show functions (the pretty print functions sometimes don't
--- show it the way I want....
-
--- shows just the structure
-showCoreExpr (Var _ ) = "Var "
-showCoreExpr (Lit _) = "Lit "
-showCoreExpr (App e1 e2) =
- "(App \n " ++ (showCoreExpr e1) ++ "\n " ++ (showCoreExpr e2) ++ ") "
-showCoreExpr (Lam b e) =
- "Lam b " ++ (showCoreExpr e)
-showCoreExpr (Let bnds expr) =
- "Let \n" ++ (showBinds bnds) ++ "in " ++ (showCoreExpr expr)
- where showBinds (NonRec b e) = showBind (b,e)
- showBinds (Rec bnds) = concat (map showBind bnds)
- showBind (b,e) = " b = " ++ (showCoreExpr e)++ "\n"
--- gaw 2004 FIX?
-showCoreExpr (Case ex b ty alts) =
- "Case b = " ++ (showCoreExpr ex) ++ " of \n" ++ (showAlts alts)
- where showAlts _ = ""
-showCoreExpr (Note _ ex) = "Note n " ++ (showCoreExpr ex)
-showCoreExpr (Type t) = "Type"