diff options
author | Manuel M T Chakravarty <chak@cse.unsw.edu.au> | 2011-11-25 22:57:40 +1100 |
---|---|---|
committer | Manuel M T Chakravarty <chak@cse.unsw.edu.au> | 2011-11-25 23:03:01 +1100 |
commit | 18aae18503442276e14a47eabf4786bc7210662e (patch) | |
tree | dfc556a1b047c0031342db4b8e8d429b5f230613 | |
parent | 498467cf44e871a6abdb1e16714f6e91c7b10a80 (diff) | |
download | haskell-18aae18503442276e14a47eabf4786bc7210662e.tar.gz |
Fix newtype wrapper for 'PData[s] (Wrap a)' and fix VECTORISE type and instance pragmas
* Correct usage of new type wrappers from MkId
* 'VECTORISE [SCALAR] type T = S' didn't work correctly across module boundaries
* Clean up 'VECTORISE SCALAR instance'
-rw-r--r-- | compiler/coreSyn/CoreFVs.lhs | 2 | ||||
-rw-r--r-- | compiler/coreSyn/CoreSubst.lhs | 2 | ||||
-rw-r--r-- | compiler/coreSyn/CoreSyn.lhs | 2 | ||||
-rw-r--r-- | compiler/coreSyn/PprCore.lhs | 3 | ||||
-rw-r--r-- | compiler/deSugar/Desugar.lhs | 13 | ||||
-rw-r--r-- | compiler/hsSyn/HsDecls.lhs | 26 | ||||
-rw-r--r-- | compiler/iface/TcIface.lhs | 101 | ||||
-rw-r--r-- | compiler/main/HscTypes.lhs | 3 | ||||
-rw-r--r-- | compiler/parser/Parser.y.pp | 7 | ||||
-rw-r--r-- | compiler/rename/RnSource.lhs | 6 | ||||
-rw-r--r-- | compiler/typecheck/TcBinds.lhs | 12 | ||||
-rw-r--r-- | compiler/typecheck/TcHsSyn.lhs | 6 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise.hs | 14 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise/Env.hs | 20 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise/Monad.hs | 20 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise/Monad/Global.hs | 6 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise/Type/Env.hs | 136 | ||||
-rw-r--r-- | compiler/vectorise/Vectorise/Utils/Base.hs | 4 |
18 files changed, 226 insertions, 157 deletions
diff --git a/compiler/coreSyn/CoreFVs.lhs b/compiler/coreSyn/CoreFVs.lhs index 2402a47e70..cbb3bd877f 100644 --- a/compiler/coreSyn/CoreFVs.lhs +++ b/compiler/coreSyn/CoreFVs.lhs @@ -333,7 +333,7 @@ vectsFreeVars = foldr (unionVarSet . vectFreeVars) emptyVarSet vectFreeVars (NoVect _) = noFVs vectFreeVars (VectType _ _ _) = noFVs vectFreeVars (VectClass _) = noFVs - vectFreeVars (VectInst _ _) = noFVs + vectFreeVars (VectInst _) = noFVs -- this function is only concerned with values, not types \end{code} diff --git a/compiler/coreSyn/CoreSubst.lhs b/compiler/coreSyn/CoreSubst.lhs index 741c48eac9..09f00c70b2 100644 --- a/compiler/coreSyn/CoreSubst.lhs +++ b/compiler/coreSyn/CoreSubst.lhs @@ -754,7 +754,7 @@ substVect subst (Vect v (Just rhs)) = Vect v (Just (simpleOptExprWith subst r substVect _subst vd@(NoVect _) = vd substVect _subst vd@(VectType _ _ _) = vd substVect _subst vd@(VectClass _) = vd -substVect _subst vd@(VectInst _ _) = vd +substVect _subst vd@(VectInst _) = vd ------------------ substVarSet :: Subst -> VarSet -> VarSet diff --git a/compiler/coreSyn/CoreSyn.lhs b/compiler/coreSyn/CoreSyn.lhs index 3258d3da3a..78c733d830 100644 --- a/compiler/coreSyn/CoreSyn.lhs +++ b/compiler/coreSyn/CoreSyn.lhs @@ -538,7 +538,7 @@ data CoreVect = Vect Id (Maybe CoreExpr) | NoVect Id | VectType Bool TyCon (Maybe TyCon) | VectClass TyCon -- class tycon - | VectInst Bool Id -- (1) whether SCALAR & (2) instance dfun + | VectInst Id -- instance dfun (always SCALAR) \end{code} diff --git a/compiler/coreSyn/PprCore.lhs b/compiler/coreSyn/PprCore.lhs index c575b68857..9def8e8ca7 100644 --- a/compiler/coreSyn/PprCore.lhs +++ b/compiler/coreSyn/PprCore.lhs @@ -510,6 +510,5 @@ instance Outputable CoreVect where ppr (VectType True var (Just tc)) = ptext (sLit "VECTORISE SCALAR type") <+> ppr var <+> char '=' <+> ppr tc ppr (VectClass tc) = ptext (sLit "VECTORISE class") <+> ppr tc - ppr (VectInst False var) = ptext (sLit "VECTORISE instance") <+> ppr var - ppr (VectInst True var) = ptext (sLit "VECTORISE SCALAR instance") <+> ppr var + ppr (VectInst var) = ptext (sLit "VECTORISE SCALAR instance") <+> ppr var \end{code} diff --git a/compiler/deSugar/Desugar.lhs b/compiler/deSugar/Desugar.lhs index e88b57e835..d0713bcf99 100644 --- a/compiler/deSugar/Desugar.lhs +++ b/compiler/deSugar/Desugar.lhs @@ -23,6 +23,7 @@ import TcRnTypes import MkIface import Id import Name +import Type import InstEnv import Class import Avail @@ -415,15 +416,19 @@ dsVect (L loc (HsVect (L _ v) rhs)) dsVect (L _loc (HsNoVect (L _ v))) = return $ NoVect v dsVect (L _loc (HsVectTypeOut isScalar tycon rhs_tycon)) - = return $ VectType isScalar tycon rhs_tycon + = return $ VectType isScalar tycon' rhs_tycon + where + tycon' | Just ty <- coreView $ mkTyConTy tycon + , (tycon', []) <- splitTyConApp ty = tycon' + | otherwise = tycon dsVect vd@(L _ (HsVectTypeIn _ _ _)) = pprPanic "Desugar.dsVect: unexpected 'HsVectTypeIn'" (ppr vd) dsVect (L _loc (HsVectClassOut cls)) = return $ VectClass (classTyCon cls) dsVect vc@(L _ (HsVectClassIn _)) = pprPanic "Desugar.dsVect: unexpected 'HsVectClassIn'" (ppr vc) -dsVect (L _loc (HsVectInstOut isScalar inst)) - = return $ VectInst isScalar (instanceDFunId inst) -dsVect vi@(L _ (HsVectInstIn _ _)) +dsVect (L _loc (HsVectInstOut inst)) + = return $ VectInst (instanceDFunId inst) +dsVect vi@(L _ (HsVectInstIn _)) = pprPanic "Desugar.dsVect: unexpected 'HsVectInstIn'" (ppr vi) \end{code} diff --git a/compiler/hsSyn/HsDecls.lhs b/compiler/hsSyn/HsDecls.lhs index ea34e7991c..d4463632af 100644 --- a/compiler/hsSyn/HsDecls.lhs +++ b/compiler/hsSyn/HsDecls.lhs @@ -1093,11 +1093,9 @@ data VectDecl name (Located name) | HsVectClassOut -- post type-checking Class - | HsVectInstIn -- pre type-checking - Bool -- 'TRUE' => SCALAR declaration + | HsVectInstIn -- pre type-checking (always SCALAR) (LHsType name) - | HsVectInstOut -- post type-checking - Bool -- 'TRUE' => SCALAR declaration + | HsVectInstOut -- post type-checking (always SCALAR) Instance deriving (Data, Typeable) @@ -1108,15 +1106,13 @@ lvectDeclName (L _ (HsVectTypeIn _ (L _ name) _)) = getName name lvectDeclName (L _ (HsVectTypeOut _ tycon _)) = getName tycon lvectDeclName (L _ (HsVectClassIn (L _ name))) = getName name lvectDeclName (L _ (HsVectClassOut cls)) = getName cls -lvectDeclName (L _ (HsVectInstIn _ _)) = panic "HsDecls.lvectDeclName: HsVectInstIn" -lvectDeclName (L _ (HsVectInstOut _ _)) = panic "HsDecls.lvectDeclName: HsVectInstOut" --- lvectDeclName (L _ (HsVectInstIn _ (L _ name))) = getName name --- lvectDeclName (L _ (HsVectInstOut _ inst)) = getName inst +lvectDeclName (L _ (HsVectInstIn _)) = panic "HsDecls.lvectDeclName: HsVectInstIn" +lvectDeclName (L _ (HsVectInstOut _)) = panic "HsDecls.lvectDeclName: HsVectInstOut" lvectInstDecl :: LVectDecl name -> Bool -lvectInstDecl (L _ (HsVectInstIn _ _)) = True -lvectInstDecl (L _ (HsVectInstOut _ _)) = True -lvectInstDecl _ = False +lvectInstDecl (L _ (HsVectInstIn _)) = True +lvectInstDecl (L _ (HsVectInstOut _)) = True +lvectInstDecl _ = False instance OutputableBndr name => Outputable (VectDecl name) where ppr (HsVect v Nothing) @@ -1147,13 +1143,9 @@ instance OutputableBndr name => Outputable (VectDecl name) where = sep [text "{-# VECTORISE class" <+> ppr c <+> text "#-}" ] ppr (HsVectClassOut c) = sep [text "{-# VECTORISE class" <+> ppr c <+> text "#-}" ] - ppr (HsVectInstIn False ty) - = sep [text "{-# VECTORISE instance" <+> ppr ty <+> text "#-}" ] - ppr (HsVectInstIn True ty) + ppr (HsVectInstIn ty) = sep [text "{-# VECTORISE SCALAR instance" <+> ppr ty <+> text "#-}" ] - ppr (HsVectInstOut False i) - = sep [text "{-# VECTORISE instance" <+> ppr i <+> text "#-}" ] - ppr (HsVectInstOut True i) + ppr (HsVectInstOut i) = sep [text "{-# VECTORISE SCALAR instance" <+> ppr i <+> text "#-}" ] \end{code} diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs index d17b90d7f3..8a279ca3a1 100644 --- a/compiler/iface/TcIface.lhs +++ b/compiler/iface/TcIface.lhs @@ -728,10 +728,11 @@ tcIfaceVectInfo mod typeEnv (IfaceVectInfo , ifaceVectInfoScalarTyCons = scalarTyCons }) = do { let scalarTyConsSet = mkNameSet scalarTyCons - ; vVars <- mapM vectVarMapping vars - ; tyConRes1 <- mapM vectTyConMapping tycons - ; tyConRes2 <- mapM (vectTyConReuseMapping scalarTyConsSet) tyconsReuse - ; vScalarVars <- mapM vectVar scalarVars + ; vVars <- mapM vectVarMapping vars + ; let varsSet = mkVarSet (map fst vVars) + ; tyConRes1 <- mapM (vectTyConVectMapping varsSet) tycons + ; tyConRes2 <- mapM (vectTyConReuseMapping varsSet) tyconsReuse + ; vScalarVars <- mapM vectVar scalarVars ; let (vTyCons, vDataCons) = unzip (tyConRes1 ++ tyConRes2) ; return $ VectInfo { vectInfoVar = mkVarEnv vVars @@ -757,69 +758,51 @@ tcIfaceVectInfo mod typeEnv (IfaceVectInfo = forkM (ptext (sLit "vect scalar var") <+> ppr name) $ tcIfaceExtId name - vectTyConMapping name + vectTyConVectMapping vars name = do { vName <- lookupOrig mod (mkLocalisedOccName mod mkVectTyConOcc name) + ; vectTyConMapping vars name vName + } + + vectTyConReuseMapping vars name + = vectTyConMapping vars name name + + vectTyConMapping vars name vName + = do { tycon <- lookupLocalOrExternal name + ; vTycon <- lookupLocalOrExternal vName + + -- map the data constructors of the original type constructor to those of the + -- vectorised type constructor /unless/ the type constructor was vectorised + -- abstractly; if it was vectorised abstractly, the workers of its data constructors + -- do not appear in the set of vectorised variables + ; let isAbstract | isClassTyCon tycon = False + | datacon:_ <- tyConDataCons tycon + = not $ dataConWrapId datacon `elemVarSet` vars + | otherwise = True + vDataCons | isAbstract = [] + | otherwise = [ (dataConName datacon, (datacon, vDatacon)) + | (datacon, vDatacon) <- zip (tyConDataCons tycon) + (tyConDataCons vTycon) + ] - -- we need a fully defined version of the type constructor to be able to extract - -- its data constructors etc. - ; tycon <- do { let mb_tycon = lookupTypeEnv typeEnv name - ; case mb_tycon of - -- tycon is local - Just (ATyCon tycon) -> return tycon - -- name is not a tycon => internal inconsistency - Just _ -> notATyConErr - -- tycon is external - Nothing -> tcIfaceTyCon (IfaceTc name) - } - ; vTycon <- forkM (text ("vect vTycon") <+> ppr vName) $ - tcIfaceTyCon (IfaceTc vName) - - -- we need to handle class type constructors differently due to the manner in which - -- the name for the dictionary data constructor is computed - ; vDataCons <- if isClassTyCon tycon - then vectClassDataConMapping vName (tyConSingleDataCon_maybe tycon) - else mapM vectDataConMapping (tyConDataCons tycon) ; return ( (name, (tycon, vTycon)) -- (T, T_v) , vDataCons -- list of (Ci, Ci_v) ) } where - notATyConErr = pprPanic "TcIface.tcIfaceVectInfo: not a tycon" (ppr name) - - vectTyConReuseMapping scalarNames name - = do { tycon <- forkM (text ("vect reuse tycon") <+> ppr name) $ - tcIfaceTyCon (IfaceTc name) -- somewhat naughty for wired in tycons, but ok - ; if name `elemNameSet` scalarNames - then do - { return ( (name, (tycon, tycon)) -- scalar type constructors expose no data.. - , [] -- ..constructors see.. - ) -- .."Note [Pragmas to vectorise tycons]".. - -- ..in 'Vectorise.Type.Env' - } else do - { let { vDataCons = [ (dataConName dc, (dc, dc)) - | dc <- tyConDataCons tycon] - } - ; return ( (name, (tycon, tycon)) -- (T, T) - , vDataCons -- list of (Ci, Ci) - ) - }} - - vectClassDataConMapping _vTyconName Nothing = panic "tcIfaceVectInfo: vectClassDataConMapping" - vectClassDataConMapping vTyconName (Just datacon) - = do { let name = dataConName datacon - ; vName <- lookupOrig mod (mkClassDataConOcc . nameOccName $ vTyconName) - ; vDataCon <- forkM (text ("vect class datacon") <+> ppr name) $ - tcIfaceDataCon vName - ; return [(name, (datacon, vDataCon))] - } + -- we need a fully defined version of the type constructor to be able to extract + -- its data constructors etc. + lookupLocalOrExternal name + = do { let mb_tycon = lookupTypeEnv typeEnv name + ; case mb_tycon of + -- tycon is local + Just (ATyCon tycon) -> return tycon + -- name is not a tycon => internal inconsistency + Just _ -> notATyConErr + -- tycon is external + Nothing -> tcIfaceTyCon (IfaceTc name) + } - vectDataConMapping datacon - = do { let name = dataConName datacon - ; vName <- lookupOrig mod (mkLocalisedOccName mod mkVectDataConOcc name) - ; vDataCon <- forkM (text ("vect datacon") <+> ppr name) $ - tcIfaceDataCon vName - ; return (name, (datacon, vDataCon)) - } + notATyConErr = pprPanic "TcIface.tcIfaceVectInfo: not a tycon" (ppr name) \end{code} %************************************************************************ diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs index 2424ddc989..6b389fd1b2 100644 --- a/compiler/main/HscTypes.lhs +++ b/compiler/main/HscTypes.lhs @@ -1948,6 +1948,9 @@ data VectInfo -- -- NB: The field 'ifaceVectInfoVar' explicitly contains the workers of data constructors as well as -- class selectors — i.e., their mappings are /not/ implicitly generated from the data types. +-- Moreover, whether the worker of a data constructor is in 'ifaceVectInfoVar' determines +-- whether that data constructor was vectorised (or is part of an abstractly vectorised type +-- constructor). -- data IfaceVectInfo = IfaceVectInfo diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp index a0ccf07a7c..de15f1cf2f 100644 --- a/compiler/parser/Parser.y.pp +++ b/compiler/parser/Parser.y.pp @@ -589,11 +589,12 @@ topdecl :: { OrdList (LHsDecl RdrName) } | '{-# VECTORISE' 'type' gtycon '=' gtycon '#-}' { unitOL $ LL $ VectD (HsVectTypeIn False $3 (Just $5)) } + | '{-# VECTORISE_SCALAR' 'type' gtycon '=' gtycon '#-}' + { unitOL $ LL $ + VectD (HsVectTypeIn True $3 (Just $5)) } | '{-# VECTORISE' 'class' gtycon '#-}' { unitOL $ LL $ VectD (HsVectClassIn $3) } - | '{-# VECTORISE' 'instance' type '#-}' - { unitOL $ LL $ VectD (HsVectInstIn False $3) } | '{-# VECTORISE_SCALAR' 'instance' type '#-}' - { unitOL $ LL $ VectD (HsVectInstIn True $3) } + { unitOL $ LL $ VectD (HsVectInstIn $3) } | annotation { unitOL $1 } | decl { unLoc $1 } diff --git a/compiler/rename/RnSource.lhs b/compiler/rename/RnSource.lhs index 7d8d1d5a89..d79dcb868e 100644 --- a/compiler/rename/RnSource.lhs +++ b/compiler/rename/RnSource.lhs @@ -672,11 +672,11 @@ rnHsVectDecl (HsVectClassIn cls) } rnHsVectDecl (HsVectClassOut _) = panic "RnSource.rnHsVectDecl: Unexpected 'HsVectClassOut'" -rnHsVectDecl (HsVectInstIn isScalar instTy) +rnHsVectDecl (HsVectInstIn instTy) = do { instTy' <- rnLHsInstType (text "In a VECTORISE pragma") instTy - ; return (HsVectInstIn isScalar instTy', emptyFVs) + ; return (HsVectInstIn instTy', emptyFVs) } -rnHsVectDecl (HsVectInstOut _ _) +rnHsVectDecl (HsVectInstOut _) = panic "RnSource.rnHsVectDecl: Unexpected 'HsVectInstOut'" \end{code} diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs index f12bad426d..072f77c2f2 100644 --- a/compiler/typecheck/TcBinds.lhs +++ b/compiler/typecheck/TcBinds.lhs @@ -694,7 +694,11 @@ tcVect (HsNoVect name) tcVect (HsVectTypeIn isScalar lname rhs_name) = addErrCtxt (vectCtxt lname) $ do { tycon <- tcLookupLocatedTyCon lname - ; checkTc (not isScalar || tyConArity tycon == 0) scalarTyConMustBeNullary + ; checkTc ( not isScalar -- either we have a non-SCALAR declaration + || isJust rhs_name -- or we explicitly provide a vectorised type + || tyConArity tycon == 0 -- otherwise the type constructor must be nullary + ) + scalarTyConMustBeNullary ; rhs_tycon <- fmapMaybeM (tcLookupTyCon . unLoc) rhs_name ; return $ HsVectTypeOut isScalar tycon rhs_tycon @@ -708,13 +712,13 @@ tcVect (HsVectClassIn lname) } tcVect (HsVectClassOut _) = panic "TcBinds.tcVect: Unexpected 'HsVectClassOut'" -tcVect (HsVectInstIn isScalar linstTy) +tcVect (HsVectInstIn linstTy) = addErrCtxt (vectCtxt linstTy) $ do { (cls, tys) <- tcHsVectInst linstTy ; inst <- tcLookupInstance cls tys - ; return $ HsVectInstOut isScalar inst + ; return $ HsVectInstOut inst } -tcVect (HsVectInstOut _ _) +tcVect (HsVectInstOut _) = panic "TcBinds.tcVect: Unexpected 'HsVectInstOut'" vectCtxt :: Outputable thing => thing -> SDoc diff --git a/compiler/typecheck/TcHsSyn.lhs b/compiler/typecheck/TcHsSyn.lhs index ce6b48c7fa..d349095114 100644 --- a/compiler/typecheck/TcHsSyn.lhs +++ b/compiler/typecheck/TcHsSyn.lhs @@ -1063,9 +1063,9 @@ zonkVect _ (HsVectTypeIn _ _ _) = panic "TcHsSyn.zonkVect: HsVectTypeIn" zonkVect _env (HsVectClassOut c) = return $ HsVectClassOut c zonkVect _ (HsVectClassIn _) = panic "TcHsSyn.zonkVect: HsVectClassIn" -zonkVect _env (HsVectInstOut s i) - = return $ HsVectInstOut s i -zonkVect _ (HsVectInstIn _ _) = panic "TcHsSyn.zonkVect: HsVectInstIn" +zonkVect _env (HsVectInstOut i) + = return $ HsVectInstOut i +zonkVect _ (HsVectInstIn _) = panic "TcHsSyn.zonkVect: HsVectInstIn" \end{code} %************************************************************************ diff --git a/compiler/vectorise/Vectorise.hs b/compiler/vectorise/Vectorise.hs index dc467f5187..cd87868081 100644 --- a/compiler/vectorise/Vectorise.hs +++ b/compiler/vectorise/Vectorise.hs @@ -87,8 +87,8 @@ vectModule guts@(ModGuts { mg_tcs = tycons -- Vectorise all the top level bindings and VECTORISE declarations on imported identifiers -- NB: Need to vectorise the imported bindings first (local bindings may depend on them). - ; let impBinds = [imp_id | Vect imp_id _ <- vect_decls, isGlobalId imp_id] ++ - [imp_id | VectInst True imp_id <- vect_decls, isGlobalId imp_id] + ; let impBinds = [imp_id | Vect imp_id _ <- vect_decls, isGlobalId imp_id] ++ + [imp_id | VectInst imp_id <- vect_decls, isGlobalId imp_id] ; binds_imp <- mapM vectImpBind impBinds ; binds_top <- mapM vectTopBind binds @@ -150,7 +150,7 @@ vectTopBind b@(NonRec var expr) ; (inline, isScalar, expr') <- vectTopRhs [] var expr ; var' <- vectTopBinder var inline expr' ; when isScalar $ - addGlobalScalar var + addGlobalScalarVar var -- We replace the original top-level binding by a value projected from the vectorised -- closure and add any newly created hoisted top-level bindings. @@ -182,7 +182,7 @@ vectTopBind b@(Rec bs) ; if and areScalars then -- (1) Entire recursive group is scalar -- => add all variables to the global set of scalars - do { mapM_ addGlobalScalar vars + do { mapM_ addGlobalScalarVar vars ; return (vars', inlines, exprs', hs) } else -- (2) At least one binding is not scalar @@ -226,7 +226,7 @@ vectImpBind var ; (inline, isScalar, expr') <- vectTopRhs [] var (Var var) ; var' <- vectTopBinder var inline expr' ; when isScalar $ - addGlobalScalar var + addGlobalScalarVar var -- We add any newly created hoisted top-level bindings. ; hs <- takeHoisted @@ -340,7 +340,7 @@ vectTopRhs :: [Var] -- ^ Names of all functions in the rec block , CoreExpr) -- (3) the vectorised right-hand side vectTopRhs recFs var expr = closedV - $ do { globalScalar <- isGlobalScalar var + $ do { globalScalar <- isGlobalScalarVar var ; vectDecl <- lookupVectDecl var ; let isDFun = isDFunId var @@ -385,7 +385,7 @@ tryConvert :: Var -- ^ Name of the original binding (eg @foo@) -> CoreExpr -- ^ The original body of the binding. -> VM CoreExpr tryConvert var vect_var rhs - = do { globalScalar <- isGlobalScalar var + = do { globalScalar <- isGlobalScalarVar var ; if globalScalar then return rhs diff --git a/compiler/vectorise/Vectorise/Env.hs b/compiler/vectorise/Vectorise/Env.hs index 64ab075cef..ffaf388b31 100644 --- a/compiler/vectorise/Vectorise/Env.hs +++ b/compiler/vectorise/Vectorise/Env.hs @@ -129,6 +129,10 @@ data GlobalEnv -- |Create an initial global environment. -- +-- We add scalar variables and type constructors identified by vectorisation pragmas already here +-- to the global table, so that we can query scalarness during vectorisation, and especially, when +-- vectorising the scalar entities' definitions themselves. +-- initGlobalEnv :: VectInfo -> [CoreVect] -> (InstEnv, InstEnv) -> FamInstEnvs -> GlobalEnv initGlobalEnv info vectDecls instEnvs famInstEnvs = GlobalEnv @@ -151,10 +155,16 @@ initGlobalEnv info vectDecls instEnvs famInstEnvs -- FIXME: we currently only allow RHSes consisting of a -- single variable to be able to obtain the type without -- inference — see also 'TcBinds.tcVect' - scalar_vars = [var | Vect var Nothing <- vectDecls] ++ - [var | VectInst True var <- vectDecls] - novects = [var | NoVect var <- vectDecls] - scalar_tycons = [tyConName tycon | VectType True tycon _ <- vectDecls] + scalar_vars = [var | Vect var Nothing <- vectDecls] ++ + [var | VectInst var <- vectDecls] + novects = [var | NoVect var <- vectDecls] + scalar_tycons = [tyConName tycon | VectType True tycon Nothing <- vectDecls] ++ + [tyConName tycon | VectType _ tycon (Just tycon') <- vectDecls + , tycon == tycon'] + -- - for 'VectType True tycon Nothing', we checked that the type does not + -- contain arrays (or type variables that could be instatiated to arrays) + -- - for 'VectType _ tycon (Just tycon')', where the two tycons are the same, + -- we also know that there can be no embedded arrays -- Operators on Global Environments ------------------------------------------- @@ -207,7 +217,7 @@ modVectInfo env mg_ids mg_tyCons vectDecls info } where vectIds = [id | Vect id _ <- vectDecls] ++ - [id | VectInst _ id <- vectDecls] + [id | VectInst id <- vectDecls] vectTypeTyCons = [tycon | VectType _ tycon _ <- vectDecls] ++ [tycon | VectClass tycon <- vectDecls] vectDataCons = concatMap tyConDataCons vectTypeTyCons diff --git a/compiler/vectorise/Vectorise/Monad.hs b/compiler/vectorise/Vectorise/Monad.hs index b9a1fdf046..0706e25f4f 100644 --- a/compiler/vectorise/Vectorise/Monad.hs +++ b/compiler/vectorise/Vectorise/Monad.hs @@ -14,7 +14,8 @@ module Vectorise.Monad ( -- * Variables lookupVar, lookupVar_maybe, - addGlobalScalar, + addGlobalScalarVar, + addGlobalScalarTyCon, ) where import Vectorise.Monad.Base @@ -32,6 +33,8 @@ import DynFlags import MonadUtils (liftIO) import InstEnv import Class +import TyCon +import NameSet import VarSet import VarEnv import Var @@ -174,8 +177,17 @@ dumpVar var -- |Mark the given variable as scalar — i.e., executing the associated code does not involve any -- parallel array computations. -- -addGlobalScalar :: Var -> VM () -addGlobalScalar var - = do { traceVt "addGlobalScalar" (ppr var) +addGlobalScalarVar :: Var -> VM () +addGlobalScalarVar var + = do { traceVt "addGlobalScalarVar" (ppr var) ; updGEnv $ \env -> env{global_scalar_vars = extendVarSet (global_scalar_vars env) var} } + +-- |Mark the given type constructor as scalar — i.e., its values cannot embed parallel arrays. +-- +addGlobalScalarTyCon :: TyCon -> VM () +addGlobalScalarTyCon tycon + = do { traceVt "addGlobalScalarTyCon" (ppr tycon) + ; updGEnv $ \env -> + env{global_scalar_tycons = addOneToNameSet (global_scalar_tycons env) (tyConName tycon)} + } diff --git a/compiler/vectorise/Vectorise/Monad/Global.hs b/compiler/vectorise/Vectorise/Monad/Global.hs index bc68a5012f..f393f01e92 100644 --- a/compiler/vectorise/Vectorise/Monad/Global.hs +++ b/compiler/vectorise/Vectorise/Monad/Global.hs @@ -12,7 +12,7 @@ module Vectorise.Monad.Global ( lookupVectDecl, noVectDecl, -- * Scalars - globalScalarVars, isGlobalScalar, globalScalarTyCons, + globalScalarVars, isGlobalScalarVar, globalScalarTyCons, -- * TyCons lookupTyCon, @@ -96,8 +96,8 @@ globalScalarVars = readGEnv global_scalar_vars -- |Check whether a given variable is in the set of global scalar variables. -- -isGlobalScalar :: Var -> VM Bool -isGlobalScalar var = readGEnv $ \env -> var `elemVarSet` global_scalar_vars env +isGlobalScalarVar :: Var -> VM Bool +isGlobalScalarVar var = readGEnv $ \env -> var `elemVarSet` global_scalar_vars env -- |Get the set of global scalar type constructors including both those scalar type constructors -- declared in an imported module and those declared in the current module. diff --git a/compiler/vectorise/Vectorise/Type/Env.hs b/compiler/vectorise/Vectorise/Type/Env.hs index 6b75ecace2..5d2213ac26 100644 --- a/compiler/vectorise/Vectorise/Type/Env.hs +++ b/compiler/vectorise/Vectorise/Type/Env.hs @@ -32,14 +32,18 @@ import Id import MkId import NameEnv import NameSet +import OccName import Util import Outputable import FastString import MonadUtils + import Control.Monad +import Data.Maybe import Data.List + -- Note [Pragmas to vectorise tycons] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- @@ -60,7 +64,20 @@ import Data.List -- Type constructors declared with {-# VECTORISE SCALAR type T #-} are treated in this manner. -- (The vectoriser never treats a type constructor automatically in this manner.) -- --- (2) Data type constructor 'T' that together with its constructors 'Cn' may be used in vectorised +-- (2) Data type constructor 'T' that may be used in vectorised code, where 'T' is represented by an +-- explicitly given 'Tv', but the representation of 'T' is opaque in vectorised code. +-- +-- An example is the treatment of '[::]'. '[::]'s can be used in vectorised code and is +-- vectorised to 'PArray'. However, the representation of '[::]' is not exposed in vectorised +-- code. Instead, computations involving the representation need to be confined to scalar code. +-- +-- 'PData' and 'PRepr' instances need to be explicitly supplied for 'T' (they are not generated +-- by the vectoriser). +-- +-- Type constructors declared with {-# VECTORISE SCALAR type T = T' #-} are treated in this +-- manner. (The vectoriser never treats a type constructor automatically in this manner.) +-- +-- (3) Data type constructor 'T' that together with its constructors 'Cn' may be used in vectorised -- code, where 'T' and the 'Cn' are automatically vectorised in the same manner as data types -- declared in a vectorised module. This includes the case where the vectoriser determines that -- the original representation of 'T' may be used in vectorised code (as it does not embed any @@ -74,13 +91,13 @@ import Data.List -- -- Type constructors declared with {-# VECTORISE type T #-} are treated in this manner. -- --- (3) Data type constructor 'T' that together with its constructors 'Cn' may be used in vectorised +-- (4) Data type constructor 'T' that together with its constructors 'Cn' may be used in vectorised -- code, where 'T' is represented by an explicitly given 'Tv' whose constructors 'Cvn' represent -- the original constructors in vectorised code. As a special case, we can have 'Tv = T' -- -- An example is the treatment of 'Bool', which is represented by itself in vectorised code -- (as it cannot embed any parallel arrays). However, we do not want any automatic generation --- of class and family instances, which is why Case (2) does not apply. +-- of class and family instances, which is why Case (3) does not apply. -- -- 'PData' and 'PRepr' instances need to be explicitly supplied for 'T' (they are not generated -- by the vectoriser). @@ -139,35 +156,37 @@ vectTypeEnv tycons vectTypeDecls vectClassDecls allScalarTyConNames ; let -- {-# VECTORISE SCALAR type T -#} (imported and local tycons) - localScalarTyCons = [tycon | VectType True tycon Nothing <- vectTypeDecls] + localAbstractTyCons = [tycon | VectType True tycon Nothing <- vectTypeDecls] -- {-# VECTORISE type T -#} (ONLY the imported tycons) impVectTyCons = ( [tycon | VectType False tycon Nothing <- vectTypeDecls] ++ [tycon | VectClass tycon <- vectClassDecls]) \\ tycons - -- {-# VECTORISE type T = ty -#} (imported and local tycons) - vectTyConsWithRHS = [ (tycon, rhs) - | VectType False tycon (Just rhs) <- vectTypeDecls] + -- {-# VECTORISE [SCALAR] type T = T' -#} (imported and local tycons) + vectTyConsWithRHS = [ (tycon, rhs, isAbstract) + | VectType isAbstract tycon (Just rhs) <- vectTypeDecls] -- filter VECTORISE SCALAR tycons and VECTORISE tycons with explicit rhses vectSpecialTyConNames = mkNameSet . map tyConName $ - localScalarTyCons ++ map fst vectTyConsWithRHS - notLocalScalarTyCon tc = not $ (tyConName tc) `elemNameSet` vectSpecialTyConNames + localAbstractTyCons ++ map fst3 vectTyConsWithRHS + notVectSpecialTyCon tc = not $ (tyConName tc) `elemNameSet` vectSpecialTyConNames -- Split the list of 'TyCons' into the ones (1) that we must vectorise and those (2) -- that we could, but don't need to vectorise. Type constructors that are not data -- type constructors or use non-Haskell98 features are being dropped. They may not -- appear in vectorised code. (We also drop the local type constructors appearing in a -- VECTORISE SCALAR pragma or a VECTORISE pragma with an explicit right-hand side, as - -- these are being handled separately.) + -- these are being handled separately. NB: Some type constructors may be marked SCALAR + -- /and/ have an explicit right-hand side.) + -- -- Furthermore, 'drop_tcs' are those type constructors that we cannot vectorise. - ; let maybeVectoriseTyCons = filter notLocalScalarTyCon tycons ++ impVectTyCons + ; let maybeVectoriseTyCons = filter notVectSpecialTyCon tycons ++ impVectTyCons (conv_tcs, keep_tcs, drop_tcs) = classifyTyCons vectTyConFlavour maybeVectoriseTyCons - ; traceVt " VECT SCALAR : " $ ppr localScalarTyCons + ; traceVt " VECT SCALAR : " $ ppr localAbstractTyCons ; traceVt " VECT [class] : " $ ppr impVectTyCons - ; traceVt " VECT with rhs : " $ ppr (map fst vectTyConsWithRHS) + ; traceVt " VECT with rhs : " $ ppr (map fst3 vectTyConsWithRHS) ; traceVt " -- after classification (local and VECT [class] tycons) --" empty ; traceVt " reuse : " $ ppr keep_tcs ; traceVt " convert : " $ ppr conv_tcs @@ -180,24 +199,22 @@ vectTypeEnv tycons vectTypeDecls vectClassDecls emitVt "Warning: cannot vectorise these type constructors:" $ pprQuotedList drop_tcs_nosyn $$ explanation - ; let defTyConDataCons origTyCon vectTyCon - = do { defTyCon origTyCon vectTyCon - ; MASSERT(length (tyConDataCons origTyCon) == length (tyConDataCons vectTyCon)) - ; zipWithM_ defDataCon (tyConDataCons origTyCon) (tyConDataCons vectTyCon) - } - - -- For the type constructors that we don't need to vectorise, we use the original - -- representation in both unvectorised and vectorised code. - ; zipWithM_ defTyConDataCons keep_tcs keep_tcs - - -- We do the same for type constructors declared VECTORISE SCALAR, while ignoring their - -- representation (data constructors) — see "Note [Pragmas to vectorise tycons]". - ; zipWithM_ defTyCon localScalarTyCons localScalarTyCons - - -- For type constructors declared VECTORISE with an explicit vectorised type, we use the - -- explicitly given type in vectorised code and map data constructors one for one — see - -- "Note [Pragmas to vectorise tycons]". - ; mapM_ (uncurry defTyConDataCons) vectTyConsWithRHS + ; mapM_ addGlobalScalarTyCon keep_tcs + + ; let mapping = + -- Type constructors that we don't need to vectorise, use the same + -- representation in both unvectorised and vectorised code; they are not + -- abstract. + [(tycon, tycon, False) | tycon <- keep_tcs] + -- We do the same for type constructors declared VECTORISE SCALAR /without/ + -- an explicit right-hand side, but ignore their representation (data + -- constructors) as they are abstract. + ++ [(tycon, tycon, True) | tycon <- localAbstractTyCons] + -- Type constructors declared VECTORISE /with/ an explicit vectorised type, + -- we map from the original to the given type; whether they are abstract depends + -- on whether the vectorisation declaration was SCALAR. + ++ vectTyConsWithRHS + ; syn_tcs <- catMaybes <$> mapM defTyConDataCons mapping -- Vectorise all the data type declarations that we can and must vectorise (enter the -- type and data constructors into the vectorisation map on-the-fly.) @@ -228,17 +245,19 @@ vectTypeEnv tycons vectTypeDecls vectClassDecls do { defTyConPAs (zipLazy vect_tcs dfuns) -- Query the 'PData' instance type constructors for type constructors that have a - -- VECTORISE pragma with an explicit right-hand side (this is Item (3) of + -- VECTORISE pragma with an explicit right-hand side (this is Item (4) of -- "Note [Pragmas to vectorise tycons]" above). - ; pdata_withRHS_tcs <- mapM pdataReprTyConExact (map fst vectTyConsWithRHS) + ; let (withRHS_non_abstract, vwithRHS_non_abstract) + = unzip [(tycon, vtycon) | (tycon, vtycon, False) <- vectTyConsWithRHS] + ; pdata_withRHS_tcs <- mapM pdataReprTyConExact withRHS_non_abstract - -- Build workers for all vectorised data constructors (except scalar ones) + -- Build workers for all vectorised data constructors (except abstract ones) ; sequence_ $ - zipWith3 vectDataConWorkers (orig_tcs ++ map fst vectTyConsWithRHS) - (vect_tcs ++ map snd vectTyConsWithRHS) + zipWith3 vectDataConWorkers (orig_tcs ++ withRHS_non_abstract) + (vect_tcs ++ vwithRHS_non_abstract) (pdata_tcs ++ pdata_withRHS_tcs) - -- Build a 'PA' dictionary for all type constructors (except scalar ones and those + -- Build a 'PA' dictionary for all type constructors (except abstract ones & those -- defined with an explicit right-hand side where the dictionary is user-supplied) ; dfuns <- sequence $ zipWith4 buildTyConPADict @@ -253,8 +272,49 @@ vectTypeEnv tycons vectTypeDecls vectClassDecls -- Return the vectorised variants of type constructors as well as the generated instance -- type constructors, family instances, and dfun bindings. - ; return (new_tcs ++ inst_tcs, fam_insts, binds) + ; return (new_tcs ++ inst_tcs ++ syn_tcs, fam_insts, binds) } + where + fst3 (a, _, _) = a + + -- Add a mapping from the original to vectorised type constructor to the vectorisation map. + -- Unless the type constructor is abstract, also mappings from the orignal's data constructors + -- to the vectorised type's data constructors. + -- + -- We have three cases: (1) original and vectorised type constructor are the same, (2) the + -- name of the vectorised type constructor is canonical (as prescribed by 'mkVectTyConOcc'), or + -- (3) the name is not canonical. In the third case, we additionally introduce a type synonym + -- with the canonical name that is set equal to the non-canonical name (so that we find the + -- right type constructor when reading vectorisation information from interface files). + -- + defTyConDataCons (origTyCon, vectTyCon, isAbstract) + = do { canonName <- mkLocalisedName mkVectTyConOcc origName + ; if origName == vectName -- Case (1) + || vectName == canonName -- Case (2) + then do + { defTyCon origTyCon vectTyCon -- T --> vT + ; defDataCons -- Ci --> vCi + ; return Nothing + } + else do -- Case (3) + { let synTyCon = mkSyn canonName (mkTyConTy vectTyCon) -- type S = vT + ; defTyCon origTyCon synTyCon -- T --> S + ; defDataCons -- Ci --> vCi + ; return $ Just synTyCon + } + } + where + origName = tyConName origTyCon + vectName = tyConName vectTyCon + + mkSyn canonName ty = mkSynTyCon canonName (typeKind ty) [] (SynonymTyCon ty) NoParentTyCon + + defDataCons + | isAbstract = return () + | otherwise + = do { MASSERT(length (tyConDataCons origTyCon) == length (tyConDataCons vectTyCon)) + ; zipWithM_ defDataCon (tyConDataCons origTyCon) (tyConDataCons vectTyCon) + } -- Helpers -------------------------------------------------------------------- diff --git a/compiler/vectorise/Vectorise/Utils/Base.hs b/compiler/vectorise/Vectorise/Utils/Base.hs index 6a576659f0..0c111f49c7 100644 --- a/compiler/vectorise/Vectorise/Utils/Base.hs +++ b/compiler/vectorise/Vectorise/Utils/Base.hs @@ -156,7 +156,7 @@ wrapNewTypeBodyOfPDataWrap :: CoreExpr -> Type -> VM CoreExpr wrapNewTypeBodyOfPDataWrap e ty = do { wrap_tc <- builtin wrapTyCon ; pwrap_tc <- pdataReprTyConExact wrap_tc - ; return $ wrapFamInstBody pwrap_tc [ty] (wrapNewTypeBody pwrap_tc [ty] e) + ; return $ wrapNewTypeBody pwrap_tc [ty] e } -- |Strip the constructor wrapper of the 'PData' /newtype/ instance of 'Wrap'. @@ -174,7 +174,7 @@ wrapNewTypeBodyOfPDatasWrap :: CoreExpr -> Type -> VM CoreExpr wrapNewTypeBodyOfPDatasWrap e ty = do { wrap_tc <- builtin wrapTyCon ; pwrap_tc <- pdatasReprTyConExact wrap_tc - ; return $ wrapFamInstBody pwrap_tc [ty] (wrapNewTypeBody pwrap_tc [ty] e) + ; return $ wrapNewTypeBody pwrap_tc [ty] e } -- |Strip the constructor wrapper of the 'PDatas' /newtype/ instance of 'Wrap'. |