futhark 0.19.7 → 0.20.1
raw patch · 227 files changed
+12429/−7920 lines, 227 filesdep +base16-bytestringdep +cryptohash-md5dep +githashdep −gitrevdep −hashabledep −utf8-stringdep ~file-embeddep ~futhark-datadep ~mainland-prettyPVP ok
version bump matches the API change (PVP)
Dependencies added: base16-bytestring, cryptohash-md5, githash, half
Dependencies removed: gitrev, hashable, utf8-string
Dependency ranges changed: file-embed, futhark-data, mainland-pretty
API changes (from Hackage documentation)
- Futhark.Analysis.Rephrase: rephrasePattern :: Monad m => (from -> m to) -> PatternT from -> m (PatternT to)
- Futhark.Binder: class ASTRep rep => BinderOps rep
- Futhark.Binder: data BinderT rep m a
- Futhark.Binder: instance (Futhark.IR.Prop.ASTRep rep, Futhark.MonadFreshNames.MonadFreshNames m, Futhark.Binder.BinderOps rep) => Futhark.Binder.Class.MonadBinder (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance (Futhark.IR.Prop.ASTRep rep, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance (Futhark.IR.Prop.ASTRep rep, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance Control.Monad.Trans.Class.MonadTrans (Futhark.Binder.BinderT rep)
- Futhark.Binder: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance Futhark.MonadFreshNames.MonadFreshNames m => Futhark.MonadFreshNames.MonadFreshNames (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance GHC.Base.Monad m => GHC.Base.Applicative (Futhark.Binder.BinderT rep m)
- Futhark.Binder: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.Binder.BinderT rep m)
- Futhark.Binder: mkBodyB :: (BinderOps rep, MonadBinder m, Bindable rep) => Stms rep -> Result -> m (Body rep)
- Futhark.Binder: mkExpDecB :: (BinderOps rep, MonadBinder m, Bindable rep) => Pattern rep -> Exp rep -> m (ExpDec rep)
- Futhark.Binder: mkLetNamesB :: (BinderOps rep, MonadBinder m, Rep m ~ rep, Bindable rep) => [VName] -> Exp rep -> m (Stm rep)
- Futhark.Binder: runBinder :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep a -> m (a, Stms rep)
- Futhark.Binder: runBinderT :: MonadFreshNames m => BinderT rep m a -> Scope rep -> m (a, Stms rep)
- Futhark.Binder: runBinderT' :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => BinderT rep m a -> m (a, Stms rep)
- Futhark.Binder: runBinderT'_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => BinderT rep m a -> m (Stms rep)
- Futhark.Binder: runBinderT_ :: MonadFreshNames m => BinderT rep m () -> Scope rep -> m (Stms rep)
- Futhark.Binder: runBinder_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep a -> m (Stms rep)
- Futhark.Binder: runBodyBinder :: (Bindable rep, MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep (Body rep) -> m (Body rep)
- Futhark.Binder: type Binder rep = BinderT rep (State VNameSource)
- Futhark.Binder.Class: addStm :: MonadBinder m => Stm (Rep m) -> m ()
- Futhark.Binder.Class: addStms :: MonadBinder m => Stms (Rep m) -> m ()
- Futhark.Binder.Class: attributing :: MonadBinder m => Attrs -> m a -> m a
- Futhark.Binder.Class: auxing :: MonadBinder m => StmAux anyrep -> m a -> m a
- Futhark.Binder.Class: bodyBind :: MonadBinder m => Body (Rep m) -> m [SubExp]
- Futhark.Binder.Class: certifying :: MonadBinder m => Certificates -> m a -> m a
- Futhark.Binder.Class: class (ASTRep rep, FParamInfo rep ~ DeclType, LParamInfo rep ~ Type, RetType rep ~ DeclExtType, BranchType rep ~ ExtType, SetType (LetDec rep)) => Bindable rep
- Futhark.Binder.Class: class (ASTRep (Rep m), MonadFreshNames m, Applicative m, Monad m, LocalScope (Rep m) m) => MonadBinder m where {
- Futhark.Binder.Class: collectStms :: MonadBinder m => m a -> m (a, Stms (Rep m))
- Futhark.Binder.Class: collectStms_ :: MonadBinder m => m a -> m (Stms (Rep m))
- Futhark.Binder.Class: insertStm :: Bindable rep => Stm rep -> Body rep -> Body rep
- Futhark.Binder.Class: insertStms :: Bindable rep => Stms rep -> Body rep -> Body rep
- Futhark.Binder.Class: letBind :: MonadBinder m => Pattern (Rep m) -> Exp (Rep m) -> m ()
- Futhark.Binder.Class: letBindNames :: MonadBinder m => [VName] -> Exp (Rep m) -> m ()
- Futhark.Binder.Class: mkBody :: Bindable rep => Stms rep -> Result -> Body rep
- Futhark.Binder.Class: mkBodyM :: MonadBinder m => Stms (Rep m) -> Result -> m (Body (Rep m))
- Futhark.Binder.Class: mkExpDec :: Bindable rep => Pattern rep -> Exp rep -> ExpDec rep
- Futhark.Binder.Class: mkExpDecM :: MonadBinder m => Pattern (Rep m) -> Exp (Rep m) -> m (ExpDec (Rep m))
- Futhark.Binder.Class: mkExpPat :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Pattern rep
- Futhark.Binder.Class: mkLet :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Stm rep
- Futhark.Binder.Class: mkLet' :: Bindable rep => [Ident] -> [Ident] -> StmAux a -> Exp rep -> Stm rep
- Futhark.Binder.Class: mkLetNames :: (Bindable rep, MonadFreshNames m, HasScope rep m) => [VName] -> Exp rep -> m (Stm rep)
- Futhark.Binder.Class: mkLetNamesM :: MonadBinder m => [VName] -> Exp (Rep m) -> m (Stm (Rep m))
- Futhark.Binder.Class: type family Rep m :: Type;
- Futhark.Binder.Class: }
- Futhark.CodeGen.Backends.GenericC: compilePrimValue :: PrimValue -> Exp
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyFunctions :: String
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyPanic :: String
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyServer :: String
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyTuning :: String
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyUtility :: String
- Futhark.CodeGen.Backends.GenericPython.Definitions: pyValues :: String
- Futhark.CodeGen.Backends.PyOpenCL.Boilerplate: openClPrelude :: String
- Futhark.CodeGen.Backends.SimpleRep: cFloat32Funs :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: cFloat32Ops :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: cFloat64Funs :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: cFloat64Ops :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: cFloatConvOps :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: cIntOps :: [Definition]
- Futhark.CodeGen.Backends.SimpleRep: signedPrimTypeToCType :: Signedness -> PrimType -> Type
- Futhark.CodeGen.ImpCode: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.GPU: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.GPU: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Multicore: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Multicore: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.OpenCL: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.OpenCL: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Sequential: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Sequential: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpGen: MemLocation :: VName -> [DimSize] -> IxFun (TExp Int64) -> MemLocation
- Futhark.CodeGen.ImpGen: [entryArrayLocation] :: ArrayEntry -> MemLocation
- Futhark.CodeGen.ImpGen: [memLocationIxFun] :: MemLocation -> IxFun (TExp Int64)
- Futhark.CodeGen.ImpGen: [memLocationName] :: MemLocation -> VName
- Futhark.CodeGen.ImpGen: [memLocationShape] :: MemLocation -> [DimSize]
- Futhark.CodeGen.ImpGen: data MemLocation
- Futhark.CodeGen.ImpGen: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.MemLocation
- Futhark.CodeGen.ImpGen: instance GHC.Show.Show Futhark.CodeGen.ImpGen.Destination
- Futhark.CodeGen.ImpGen: instance GHC.Show.Show Futhark.CodeGen.ImpGen.MemLocation
- Futhark.Construct: eWriteArray :: (MonadBinder m, BranchType (Rep m) ~ ExtType) => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.IR.Aliases: addAliasesToPattern :: (ASTRep rep, CanBeAliased (Op rep), Typed dec) => PatternT dec -> Exp (Aliases rep) -> PatternT (VarAliases, dec)
- Futhark.IR.Aliases: instance (Futhark.Binder.Class.Bindable rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.Binder.Class.Bindable (Futhark.IR.Aliases.Aliases rep)
- Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTRep (Futhark.IR.Aliases.Aliases rep), Futhark.Binder.Class.Bindable (Futhark.IR.Aliases.Aliases rep)) => Futhark.Binder.BinderOps (Futhark.IR.Aliases.Aliases rep)
- Futhark.IR.Aliases: mkPatternAliases :: (Aliased rep, Typed dec) => PatternT dec -> Exp rep -> ([PatElemT (VarAliases, dec)], [PatElemT (VarAliases, dec)])
- Futhark.IR.Aliases: removePatternAliases :: PatternT (AliasDec, a) -> PatternT a
- Futhark.IR.GPU: instance Futhark.Binder.BinderOps Futhark.IR.GPU.GPU
- Futhark.IR.GPU: instance Futhark.Binder.Class.Bindable Futhark.IR.GPU.GPU
- Futhark.IR.GPU.Kernel: CalcNumGroups :: SubExp -> Name -> SubExp -> SizeOp
- Futhark.IR.GPU.Kernel: CmpSizeLe :: Name -> SizeClass -> SubExp -> SizeOp
- Futhark.IR.GPU.Kernel: GetSize :: Name -> SizeClass -> SizeOp
- Futhark.IR.GPU.Kernel: GetSizeMax :: SizeClass -> SizeOp
- Futhark.IR.GPU.Kernel: OtherOp :: op -> HostOp rep op
- Futhark.IR.GPU.Kernel: SegGroup :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
- Futhark.IR.GPU.Kernel: SegOp :: SegOp SegLevel rep -> HostOp rep op
- Futhark.IR.GPU.Kernel: SegThread :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
- Futhark.IR.GPU.Kernel: SizeOp :: SizeOp -> HostOp rep op
- Futhark.IR.GPU.Kernel: SplitSpace :: SplitOrdering -> SubExp -> SubExp -> SubExp -> SizeOp
- Futhark.IR.GPU.Kernel: [segGroupSize] :: SegLevel -> Count GroupSize SubExp
- Futhark.IR.GPU.Kernel: [segNumGroups] :: SegLevel -> Count NumGroups SubExp
- Futhark.IR.GPU.Kernel: [segVirt] :: SegLevel -> SegVirt
- Futhark.IR.GPU.Kernel: data HostOp rep op
- Futhark.IR.GPU.Kernel: data SegLevel
- Futhark.IR.GPU.Kernel: data SizeOp
- Futhark.IR.GPU.Kernel: instance (Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Rep.Op rep), Futhark.Analysis.Metrics.OpMetrics op) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Pretty.PrettyRep rep, Text.PrettyPrint.Mainland.Class.Pretty op) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Analysis.SymbolTable.IndexOp op) => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.IsOp op) => Futhark.IR.Prop.IsOp (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Names.FreeIn op) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Rename.Rename op) => Futhark.Transform.Rename.Rename (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Substitute.Substitute op) => Futhark.Transform.Substitute.Substitute (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.Aliases.Aliased rep, Futhark.IR.Prop.Aliases.AliasedOp op, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep), Futhark.IR.Prop.Aliases.CanBeAliased op, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Eq op) => GHC.Classes.Eq (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Ord op) => GHC.Classes.Ord (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.IR.Rep.RepTypes rep, GHC.Show.Show op) => GHC.Show.Show (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance (Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep), Futhark.Optimise.Simplify.Rep.CanBeWise op, Futhark.IR.Prop.ASTRep rep) => Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance Futhark.Analysis.Metrics.OpMetrics Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.Aliases.AliasedOp Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.IsOp Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.TypeOf.TypedOp Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.IR.Prop.TypeOf.TypedOp op => Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.IR.GPU.Kernel: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance Futhark.Transform.Rename.Rename Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance Futhark.Transform.Rename.Rename Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Futhark.Transform.Substitute.Substitute Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance Futhark.Transform.Substitute.Substitute Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance GHC.Classes.Eq Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance GHC.Classes.Eq Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance GHC.Classes.Ord Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance GHC.Classes.Ord Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance GHC.Show.Show Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance GHC.Show.Show Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.GPU.Kernel.SegLevel
- Futhark.IR.GPU.Kernel: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.GPU.Kernel.SizeOp
- Futhark.IR.GPU.Kernel: typeCheckHostOp :: Checkable rep => (SegLevel -> OpWithAliases (Op rep) -> TypeM rep ()) -> Maybe SegLevel -> (op -> TypeM rep ()) -> HostOp (Aliases rep) op -> TypeM rep ()
- Futhark.IR.GPU.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPU.GPU)
- Futhark.IR.GPUMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPUMem.GPUMem)
- Futhark.IR.GPUMem: instance Futhark.Binder.BinderOps Futhark.IR.GPUMem.GPUMem
- Futhark.IR.GPUMem: instance Futhark.IR.Mem.OpReturns Futhark.IR.GPUMem.GPUMem
- Futhark.IR.MC: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MC.MC)
- Futhark.IR.MC: instance Futhark.Binder.BinderOps Futhark.IR.MC.MC
- Futhark.IR.MC: instance Futhark.Binder.Class.Bindable Futhark.IR.MC.MC
- Futhark.IR.MCMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MCMem.MCMem)
- Futhark.IR.MCMem: instance Futhark.Binder.BinderOps Futhark.IR.MCMem.MCMem
- Futhark.IR.MCMem: instance Futhark.IR.Mem.OpReturns Futhark.IR.MCMem.MCMem
- Futhark.IR.Mem: allocOp :: AllocOp op => SubExp -> Space -> op
- Futhark.IR.Mem: bodyReturnsFromPattern :: PatternT (MemBound NoUniqueness) -> ([(VName, BodyReturns)], [(VName, BodyReturns)])
- Futhark.IR.Mem: class AllocOp op
- Futhark.IR.Mem: instance Futhark.IR.Mem.AllocOp (Futhark.IR.Mem.MemOp inner)
- Futhark.IR.Mem: matchPatternToExp :: (Mem rep, Checkable rep) => Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
- Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Core.PatElemT dec) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Prop: expExtTypesFromPattern :: Typed dec => PatternT dec -> [ExtType]
- Futhark.IR.Prop: expTypesFromPattern :: (ASTRep rep, HasScope rep m, Monad m) => Pattern rep -> m [BranchType rep]
- Futhark.IR.Prop.Aliases: patternAliases :: AliasesOf dec => PatternT dec -> [Names]
- Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn dec => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Prop.Patterns: basicPattern :: [Ident] -> [Ident] -> PatternT Type
- Futhark.IR.Prop.Patterns: patternContextIdents :: Typed dec => PatternT dec -> [Ident]
- Futhark.IR.Prop.Patterns: patternContextNames :: PatternT dec -> [VName]
- Futhark.IR.Prop.Patterns: patternElements :: PatternT dec -> [PatElemT dec]
- Futhark.IR.Prop.Patterns: patternIdents :: Typed dec => PatternT dec -> [Ident]
- Futhark.IR.Prop.Patterns: patternNames :: PatternT dec -> [VName]
- Futhark.IR.Prop.Patterns: patternSize :: PatternT dec -> Int
- Futhark.IR.Prop.Patterns: patternTypes :: Typed dec => PatternT dec -> [Type]
- Futhark.IR.Prop.Patterns: patternValueIdents :: Typed dec => PatternT dec -> [Ident]
- Futhark.IR.Prop.Patterns: patternValueNames :: PatternT dec -> [VName]
- Futhark.IR.Prop.Patterns: patternValueTypes :: Typed dec => PatternT dec -> [Type]
- Futhark.IR.Prop.Scope: scopeOfPattern :: LetDec rep ~ dec => PatternT dec -> Scope rep
- Futhark.IR.Prop.TypeOf: primOpType :: HasScope rep m => BasicOp -> m [Type]
- Futhark.IR.SOACS: Certificates :: [VName] -> Certificates
- Futhark.IR.SOACS: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.IR.SOACS: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.IR.SOACS: Pattern :: [PatElemT dec] -> [PatElemT dec] -> PatternT dec
- Futhark.IR.SOACS: [unCertificates] :: Certificates -> [VName]
- Futhark.IR.SOACS: data PatternT dec
- Futhark.IR.SOACS: instance Futhark.Binder.BinderOps Futhark.IR.SOACS.SOACS
- Futhark.IR.SOACS: instance Futhark.Binder.Class.Bindable Futhark.IR.SOACS.SOACS
- Futhark.IR.SOACS: newtype Certificates
- Futhark.IR.SOACS: pattern Let :: () => Pattern rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
- Futhark.IR.SOACS: stmPattern :: Stm rep -> Pattern rep
- Futhark.IR.SOACS: type Pattern = Pattern SOACS
- Futhark.IR.SOACS: type Slice d = [DimIndex d]
- Futhark.IR.SOACS.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SOACS.SOACS)
- Futhark.IR.Seq: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.Seq.Seq)
- Futhark.IR.Seq: instance Futhark.Binder.BinderOps Futhark.IR.Seq.Seq
- Futhark.IR.Seq: instance Futhark.Binder.Class.Bindable Futhark.IR.Seq.Seq
- Futhark.IR.SeqMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SeqMem.SeqMem)
- Futhark.IR.SeqMem: instance Futhark.Binder.BinderOps Futhark.IR.SeqMem.SeqMem
- Futhark.IR.SeqMem: instance Futhark.IR.Mem.OpReturns Futhark.IR.SeqMem.SeqMem
- Futhark.IR.Syntax: Pattern :: [PatElemT dec] -> [PatElemT dec] -> PatternT dec
- Futhark.IR.Syntax: [patternContextElements] :: PatternT dec -> [PatElemT dec]
- Futhark.IR.Syntax: [patternValueElements] :: PatternT dec -> [PatElemT dec]
- Futhark.IR.Syntax: [stmPattern] :: Stm rep -> Pattern rep
- Futhark.IR.Syntax: data PatternT dec
- Futhark.IR.Syntax: instance Data.Foldable.Foldable Futhark.IR.Syntax.PatternT
- Futhark.IR.Syntax: instance Data.Traversable.Traversable Futhark.IR.Syntax.PatternT
- Futhark.IR.Syntax: instance GHC.Base.Functor Futhark.IR.Syntax.PatternT
- Futhark.IR.Syntax: instance GHC.Base.Monoid (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Syntax: instance GHC.Base.Semigroup (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Syntax: instance GHC.Classes.Eq dec => GHC.Classes.Eq (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Syntax: instance GHC.Classes.Ord dec => GHC.Classes.Ord (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Syntax: instance GHC.Show.Show dec => GHC.Show.Show (Futhark.IR.Syntax.PatternT dec)
- Futhark.IR.Syntax: type Pattern rep = PatternT (LetDec rep)
- Futhark.IR.Syntax.Core: Certificates :: [VName] -> Certificates
- Futhark.IR.Syntax.Core: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.IR.Syntax.Core: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.IR.Syntax.Core: [unCertificates] :: Certificates -> [VName]
- Futhark.IR.Syntax.Core: instance GHC.Base.Monoid Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Syntax.Core: instance GHC.Base.Semigroup Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Syntax.Core: instance GHC.Classes.Eq Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Syntax.Core: instance GHC.Classes.Ord Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Syntax.Core: instance GHC.Show.Show Futhark.IR.Syntax.Core.Certificates
- Futhark.IR.Syntax.Core: newtype Certificates
- Futhark.IR.Syntax.Core: type Slice d = [DimIndex d]
- Futhark.Internalise.Bindings: stmPattern :: Pattern -> [Type] -> ([VName] -> InternaliseM a) -> InternaliseM a
- Futhark.Internalise.FreeVars: member :: VName -> NameSet -> Bool
- Futhark.Internalise.FreeVars: patternVars :: Pattern -> NameSet
- Futhark.Internalise.Monad: instance Futhark.Binder.Class.MonadBinder Futhark.Internalise.Monad.InternaliseM
- Futhark.Internalise.Monad: type VarSubstitutions = Map VName [SubExp]
- Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.Aliased rep, Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Rep.Op rep), Futhark.Optimise.CSE.CSEInOp op) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: [updateCertificates] :: DesiredUpdate dec -> Certificates
- Futhark.Optimise.InliningDeadFun: inlineFunctions :: Pass SOACS SOACS
- Futhark.Optimise.Simplify.Engine: instance Control.Monad.State.Class.MonadState (Futhark.FreshNames.VNameSource, GHC.Types.Bool, Futhark.IR.Syntax.Core.Certificates) (Futhark.Optimise.Simplify.Engine.SimpleM rep)
- Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.Syntax.Core.Certificates
- Futhark.Optimise.Simplify.Rep: addWisdomToPattern :: (ASTRep rep, CanBeWise (Op rep)) => Pattern rep -> Exp (Wise rep) -> Pattern (Wise rep)
- Futhark.Optimise.Simplify.Rep: instance (Futhark.Binder.Class.Bindable rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.Binder.Class.Bindable (Futhark.Optimise.Simplify.Rep.Wise rep)
- Futhark.Optimise.Simplify.Rep: removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a
- Futhark.Optimise.Simplify.Rule: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Binder.BinderOps rep) => Futhark.Binder.Class.MonadBinder (Futhark.Optimise.Simplify.Rule.RuleM rep)
- Futhark.Pass.ExplicitAllocations: addAllocStm :: (Allocator rep m, Allocable fromrep rep, m ~ AllocM fromrep rep) => AllocStm -> m ()
- Futhark.Pass.ExplicitAllocations: askConsts :: Allocator rep m => m (Set VName)
- Futhark.Pass.ExplicitAllocations: askDefaultSpace :: Allocator rep m => m Space
- Futhark.Pass.ExplicitAllocations: class (MonadFreshNames m, LocalScope rep m, Mem rep) => Allocator rep m
- Futhark.Pass.ExplicitAllocations: expHints :: Allocator rep m => Exp rep -> m [ExpHint]
- Futhark.Pass.ExplicitAllocations: instance (Futhark.Pass.ExplicitAllocations.Allocable fromrep torep, Futhark.Pass.ExplicitAllocations.Allocator torep (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)) => Futhark.Binder.Class.MonadBinder (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
- Futhark.Pass.ExplicitAllocations: instance Control.Monad.Writer.Class.MonadWriter [Futhark.Pass.ExplicitAllocations.AllocStm] (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Mem.Mem rep => Futhark.Pass.ExplicitAllocations.Allocator rep (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Rep.RepTypes rep => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Rep.RepTypes rep => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance Futhark.Pass.ExplicitAllocations.Allocable fromrep torep => Futhark.Pass.ExplicitAllocations.Allocator torep (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Applicative (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Functor (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Monad (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
- Futhark.Pass.ExplicitAllocations: instance GHC.Classes.Eq Futhark.Pass.ExplicitAllocations.AllocStm
- Futhark.Pass.ExplicitAllocations: instance GHC.Classes.Ord Futhark.Pass.ExplicitAllocations.AllocStm
- Futhark.Pass.ExplicitAllocations: instance GHC.Show.Show Futhark.Pass.ExplicitAllocations.AllocStm
- Futhark.Pass.ExplicitAllocations.GPU: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.GPU.Kernel.HostOp rep op)
- Futhark.Pass.ExtractKernels.Distribution: [loopNestingPattern] :: LoopNesting -> PatternT Type
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Rename Futhark.IR.Syntax.Core.Certificates
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Rename dec => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.PatternT dec)
- Futhark.Transform.Rename: renamePattern :: (Rename dec, MonadFreshNames m) => PatternT dec -> m (PatternT dec)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute Futhark.IR.Syntax.Core.Certificates
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute dec => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.PatternT dec)
- Futhark.TypeCheck: DupPatternError :: VName -> ErrorCase rep
- Futhark.TypeCheck: InvalidPatternError :: Pattern (Aliases rep) -> [ExtType] -> Maybe String -> ErrorCase rep
- Futhark.TypeCheck: matchExtPattern :: Checkable rep => Pattern (Aliases rep) -> [ExtType] -> TypeM rep ()
- Futhark.TypeCheck: matchPattern :: Checkable rep => Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
- Futhark.Util: hashIntText :: Int -> Text
- Futhark.Util.Console: inGreen :: String -> String
- Language.Futhark: type Pattern = PatternBase Info VName
- Language.Futhark.Parser: QUALUNOP :: [Name] -> Name -> Token
- Language.Futhark.Parser: UNOP :: Name -> Token
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Text.PrettyPrint.Mainland.Class.Pretty (Language.Futhark.Syntax.PatternBase f vn)
- Language.Futhark.Prop: patternIdents :: (Functor f, Ord vn) => PatternBase f vn -> Set (IdentBase f vn)
- Language.Futhark.Prop: patternNames :: (Functor f, Ord vn) => PatternBase f vn -> Set vn
- Language.Futhark.Prop: primByteSize :: Num a => PrimType -> a
- Language.Futhark.Prop: type UncheckedPattern = PatternBase NoInfo Name
- Language.Futhark.Syntax: PatternAscription :: PatternBase f vn -> TypeDeclBase f vn -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: PatternConstr :: Name -> f PatternType -> [PatternBase f vn] -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: PatternLit :: PatLit -> f PatternType -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: PatternParens :: PatternBase f vn -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: RecordPattern :: [(Name, PatternBase f vn)] -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: TuplePattern :: [PatternBase f vn] -> SrcLoc -> PatternBase f vn
- Language.Futhark.Syntax: data PatternBase f vn
- Language.Futhark.Syntax: instance Data.Loc.Located (Language.Futhark.Syntax.PatternBase f vn)
- Language.Futhark.Syntax: instance GHC.Classes.Eq (Language.Futhark.Syntax.PatternBase Language.Futhark.Syntax.NoInfo Language.Futhark.Core.VName)
- Language.Futhark.Syntax: instance GHC.Classes.Ord (Language.Futhark.Syntax.PatternBase Language.Futhark.Syntax.NoInfo Language.Futhark.Core.VName)
- Language.Futhark.Syntax: instance Language.Futhark.Syntax.Showable f vn => GHC.Show.Show (Language.Futhark.Syntax.PatternBase f vn)
- Language.Futhark.Syntax: type PatternType = TypeBase (DimDecl VName) Aliasing
- Language.Futhark.Syntax: unifyShapes :: ArrayDim dim => ShapeDecl dim -> ShapeDecl dim -> Maybe (ShapeDecl dim)
- Language.Futhark.Traversals: [mapOnPatternType] :: ASTMapper m -> PatternType -> m PatternType
- Language.Futhark.Traversals: instance Language.Futhark.Traversals.ASTMappable (Language.Futhark.Syntax.PatternBase Language.Futhark.Syntax.Info Language.Futhark.Core.VName)
- Language.Futhark.Traversals: instance Language.Futhark.Traversals.ASTMappable Language.Futhark.Syntax.PatternType
- Language.Futhark.TypeChecker.Terms: instance Text.PrettyPrint.Mainland.Class.Pretty (Language.Futhark.TypeChecker.Terms.Unmatched (Language.Futhark.Syntax.PatternBase Language.Futhark.Syntax.Info Language.Futhark.Core.VName))
- Language.Futhark.TypeChecker.Types: instance Language.Futhark.TypeChecker.Types.Substitutable Language.Futhark.Pattern
- Language.Futhark.TypeChecker.Types: unionSubs :: TypeSubs -> TypeSubs -> TypeSubs
- Language.Futhark.TypeChecker.Unify: normPatternType :: MonadUnify m => PatternType -> m PatternType
+ Futhark.Actions: callGraphAction :: Action SOACS
+ Futhark.Actions: compileCtoWASMAction :: FutharkConfig -> CompilerMode -> FilePath -> Action SeqMem
+ Futhark.Actions: compileMulticoreToWASMAction :: FutharkConfig -> CompilerMode -> FilePath -> Action MCMem
+ Futhark.Analysis.CallGraph: instance GHC.Base.Monoid Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: instance GHC.Base.Semigroup Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: instance GHC.Classes.Eq Futhark.Analysis.CallGraph.CallGraph
+ Futhark.Analysis.CallGraph: instance GHC.Classes.Eq Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: instance GHC.Classes.Ord Futhark.Analysis.CallGraph.CallGraph
+ Futhark.Analysis.CallGraph: instance GHC.Classes.Ord Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: instance GHC.Show.Show Futhark.Analysis.CallGraph.CallGraph
+ Futhark.Analysis.CallGraph: instance GHC.Show.Show Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Analysis.CallGraph.CallGraph
+ Futhark.Analysis.CallGraph: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Analysis.CallGraph.FunCalls
+ Futhark.Analysis.CallGraph: numOccurences :: CallGraph -> Map Name Int
+ Futhark.Analysis.PrimExp: instance Futhark.Analysis.PrimExp.FloatExp Numeric.Half.Internal.Half
+ Futhark.Analysis.PrimExp: instance Futhark.Analysis.PrimExp.NumExp Numeric.Half.Internal.Half
+ Futhark.Analysis.PrimExp: instance Text.PrettyPrint.Mainland.Class.Pretty v => GHC.Float.Floating (Futhark.Analysis.PrimExp.TPrimExp Numeric.Half.Internal.Half v)
+ Futhark.Analysis.PrimExp: isF16 :: PrimExp v -> TPrimExp Half v
+ Futhark.Analysis.Rephrase: rephrasePat :: Monad m => (from -> m to) -> PatT from -> m (PatT to)
+ Futhark.Builder: class ASTRep rep => BuilderOps rep
+ Futhark.Builder: data BuilderT rep m a
+ Futhark.Builder: instance (Futhark.IR.Prop.ASTRep rep, Futhark.MonadFreshNames.MonadFreshNames m, Futhark.Builder.BuilderOps rep) => Futhark.Builder.Class.MonadBuilder (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance (Futhark.IR.Prop.ASTRep rep, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance (Futhark.IR.Prop.ASTRep rep, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance Control.Monad.Trans.Class.MonadTrans (Futhark.Builder.BuilderT rep)
+ Futhark.Builder: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance Futhark.MonadFreshNames.MonadFreshNames m => Futhark.MonadFreshNames.MonadFreshNames (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance GHC.Base.Monad m => GHC.Base.Applicative (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.Builder.BuilderT rep m)
+ Futhark.Builder: mkBodyB :: (BuilderOps rep, MonadBuilder m, Buildable rep) => Stms rep -> Result -> m (Body rep)
+ Futhark.Builder: mkExpDecB :: (BuilderOps rep, MonadBuilder m, Buildable rep) => Pat rep -> Exp rep -> m (ExpDec rep)
+ Futhark.Builder: mkLetNamesB :: (BuilderOps rep, MonadBuilder m, Rep m ~ rep, Buildable rep) => [VName] -> Exp rep -> m (Stm rep)
+ Futhark.Builder: runBodyBuilder :: (Buildable rep, MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Builder rep (Body rep) -> m (Body rep)
+ Futhark.Builder: runBuilder :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Builder rep a -> m (a, Stms rep)
+ Futhark.Builder: runBuilderT :: MonadFreshNames m => BuilderT rep m a -> Scope rep -> m (a, Stms rep)
+ Futhark.Builder: runBuilderT' :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => BuilderT rep m a -> m (a, Stms rep)
+ Futhark.Builder: runBuilderT'_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => BuilderT rep m a -> m (Stms rep)
+ Futhark.Builder: runBuilderT_ :: MonadFreshNames m => BuilderT rep m () -> Scope rep -> m (Stms rep)
+ Futhark.Builder: runBuilder_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Builder rep a -> m (Stms rep)
+ Futhark.Builder: type Builder rep = BuilderT rep (State VNameSource)
+ Futhark.Builder.Class: addStm :: MonadBuilder m => Stm (Rep m) -> m ()
+ Futhark.Builder.Class: addStms :: MonadBuilder m => Stms (Rep m) -> m ()
+ Futhark.Builder.Class: attributing :: MonadBuilder m => Attrs -> m a -> m a
+ Futhark.Builder.Class: auxing :: MonadBuilder m => StmAux anyrep -> m a -> m a
+ Futhark.Builder.Class: bodyBind :: MonadBuilder m => Body (Rep m) -> m Result
+ Futhark.Builder.Class: certifying :: MonadBuilder m => Certs -> m a -> m a
+ Futhark.Builder.Class: class (ASTRep rep, FParamInfo rep ~ DeclType, LParamInfo rep ~ Type, RetType rep ~ DeclExtType, BranchType rep ~ ExtType, SetType (LetDec rep)) => Buildable rep
+ Futhark.Builder.Class: class (ASTRep (Rep m), MonadFreshNames m, Applicative m, Monad m, LocalScope (Rep m) m) => MonadBuilder m where {
+ Futhark.Builder.Class: collectStms :: MonadBuilder m => m a -> m (a, Stms (Rep m))
+ Futhark.Builder.Class: collectStms_ :: MonadBuilder m => m a -> m (Stms (Rep m))
+ Futhark.Builder.Class: insertStm :: Buildable rep => Stm rep -> Body rep -> Body rep
+ Futhark.Builder.Class: insertStms :: Buildable rep => Stms rep -> Body rep -> Body rep
+ Futhark.Builder.Class: letBind :: MonadBuilder m => Pat (Rep m) -> Exp (Rep m) -> m ()
+ Futhark.Builder.Class: letBindNames :: MonadBuilder m => [VName] -> Exp (Rep m) -> m ()
+ Futhark.Builder.Class: mkBody :: Buildable rep => Stms rep -> Result -> Body rep
+ Futhark.Builder.Class: mkBodyM :: MonadBuilder m => Stms (Rep m) -> Result -> m (Body (Rep m))
+ Futhark.Builder.Class: mkExpDec :: Buildable rep => Pat rep -> Exp rep -> ExpDec rep
+ Futhark.Builder.Class: mkExpDecM :: MonadBuilder m => Pat (Rep m) -> Exp (Rep m) -> m (ExpDec (Rep m))
+ Futhark.Builder.Class: mkExpPat :: Buildable rep => [Ident] -> Exp rep -> Pat rep
+ Futhark.Builder.Class: mkLet :: Buildable rep => [Ident] -> Exp rep -> Stm rep
+ Futhark.Builder.Class: mkLet' :: Buildable rep => [Ident] -> StmAux a -> Exp rep -> Stm rep
+ Futhark.Builder.Class: mkLetNames :: (Buildable rep, MonadFreshNames m, HasScope rep m) => [VName] -> Exp rep -> m (Stm rep)
+ Futhark.Builder.Class: mkLetNamesM :: MonadBuilder m => [VName] -> Exp (Rep m) -> m (Stm (Rep m))
+ Futhark.Builder.Class: type family Rep m :: Type;
+ Futhark.Builder.Class: }
+ Futhark.CLI.Dataset: instance System.Random.PCG.Class.Variate Numeric.Half.Internal.Half
+ Futhark.CLI.MulticoreWASM: main :: String -> [String] -> IO ()
+ Futhark.CLI.WASM: main :: String -> [String] -> IO ()
+ Futhark.CodeGen.Backends.GenericPython: fromStorage :: PrimType -> PyExp -> PyExp
+ Futhark.CodeGen.Backends.GenericPython: toStorage :: PrimType -> PyExp -> PyExp
+ Futhark.CodeGen.Backends.GenericWASM: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
+ Futhark.CodeGen.Backends.GenericWASM: JSEntryPoint :: String -> [EntryPointType] -> [EntryPointType] -> JSEntryPoint
+ Futhark.CodeGen.Backends.GenericWASM: [cCLI] :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: [cHeader] :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: [cLib] :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: [cServer] :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: [cUtils] :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: [name] :: JSEntryPoint -> String
+ Futhark.CodeGen.Backends.GenericWASM: [parameters] :: JSEntryPoint -> [EntryPointType]
+ Futhark.CodeGen.Backends.GenericWASM: [ret] :: JSEntryPoint -> [EntryPointType]
+ Futhark.CodeGen.Backends.GenericWASM: asExecutable :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: asLibrary :: CParts -> (Text, Text)
+ Futhark.CodeGen.Backends.GenericWASM: asServer :: CParts -> Text
+ Futhark.CodeGen.Backends.GenericWASM: data CParts
+ Futhark.CodeGen.Backends.GenericWASM: data JSEntryPoint
+ Futhark.CodeGen.Backends.GenericWASM: emccExportNames :: [JSEntryPoint] -> [String]
+ Futhark.CodeGen.Backends.GenericWASM: extToString :: ExternalValue -> String
+ Futhark.CodeGen.Backends.GenericWASM: javascriptWrapper :: [JSEntryPoint] -> Text
+ Futhark.CodeGen.Backends.GenericWASM: libraryExports :: Text
+ Futhark.CodeGen.Backends.GenericWASM: runServer :: Text
+ Futhark.CodeGen.Backends.MulticoreC: cliOptions :: [Option]
+ Futhark.CodeGen.Backends.MulticoreC: generateContext :: CompilerM op () ()
+ Futhark.CodeGen.Backends.MulticoreC: operations :: Operations Multicore ()
+ Futhark.CodeGen.Backends.MulticoreWASM: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
+ Futhark.CodeGen.Backends.MulticoreWASM: [cCLI] :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: [cHeader] :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: [cLib] :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: [cServer] :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: [cUtils] :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: asExecutable :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: asLibrary :: CParts -> (Text, Text)
+ Futhark.CodeGen.Backends.MulticoreWASM: asServer :: CParts -> Text
+ Futhark.CodeGen.Backends.MulticoreWASM: compileProg :: MonadFreshNames m => Prog MCMem -> m (Warnings, (CParts, Text, [String]))
+ Futhark.CodeGen.Backends.MulticoreWASM: data CParts
+ Futhark.CodeGen.Backends.MulticoreWASM: libraryExports :: Text
+ Futhark.CodeGen.Backends.MulticoreWASM: runServer :: Text
+ Futhark.CodeGen.Backends.SequentialWASM: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
+ Futhark.CodeGen.Backends.SequentialWASM: [cCLI] :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: [cHeader] :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: [cLib] :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: [cServer] :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: [cUtils] :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: asExecutable :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: asLibrary :: CParts -> (Text, Text)
+ Futhark.CodeGen.Backends.SequentialWASM: asServer :: CParts -> Text
+ Futhark.CodeGen.Backends.SequentialWASM: compileProg :: MonadFreshNames m => Prog SeqMem -> m (Warnings, (CParts, Text, [String]))
+ Futhark.CodeGen.Backends.SequentialWASM: data CParts
+ Futhark.CodeGen.Backends.SequentialWASM: libraryExports :: Text
+ Futhark.CodeGen.Backends.SequentialWASM: runServer :: Text
+ Futhark.CodeGen.Backends.SimpleRep: cScalarDefs :: Text
+ Futhark.CodeGen.Backends.SimpleRep: fromStorage :: PrimType -> Exp -> Exp
+ Futhark.CodeGen.Backends.SimpleRep: primAPIType :: Signedness -> PrimType -> Type
+ Futhark.CodeGen.Backends.SimpleRep: primStorageType :: PrimType -> Type
+ Futhark.CodeGen.Backends.SimpleRep: toStorage :: PrimType -> Exp -> Exp
+ Futhark.CodeGen.ImpCode: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode: TracePrint :: ErrorMsg Exp -> Code a
+ Futhark.CodeGen.ImpCode: instance GHC.Base.Functor Futhark.CodeGen.ImpCode.Constants
+ Futhark.CodeGen.ImpCode: instance GHC.Base.Functor Futhark.CodeGen.ImpCode.Definitions
+ Futhark.CodeGen.ImpCode.GPU: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.GPU: Float16 :: FloatType
+ Futhark.CodeGen.ImpCode.GPU: Float16Value :: !Half -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: data Half
+ Futhark.CodeGen.ImpCode.GPU: isF16 :: PrimExp v -> TPrimExp Half v
+ Futhark.CodeGen.ImpCode.GPU: pattern TracePrint :: () => ErrorMsg Exp -> Code a
+ Futhark.CodeGen.ImpCode.Multicore: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.Multicore: Float16 :: FloatType
+ Futhark.CodeGen.ImpCode.Multicore: Float16Value :: !Half -> FloatValue
+ Futhark.CodeGen.ImpCode.Multicore: data Half
+ Futhark.CodeGen.ImpCode.Multicore: isF16 :: PrimExp v -> TPrimExp Half v
+ Futhark.CodeGen.ImpCode.Multicore: pattern TracePrint :: () => ErrorMsg Exp -> Code a
+ Futhark.CodeGen.ImpCode.OpenCL: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.OpenCL: Float16 :: FloatType
+ Futhark.CodeGen.ImpCode.OpenCL: Float16Value :: !Half -> FloatValue
+ Futhark.CodeGen.ImpCode.OpenCL: data Half
+ Futhark.CodeGen.ImpCode.OpenCL: isF16 :: PrimExp v -> TPrimExp Half v
+ Futhark.CodeGen.ImpCode.OpenCL: pattern TracePrint :: () => ErrorMsg Exp -> Code a
+ Futhark.CodeGen.ImpCode.Sequential: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.Sequential: Float16 :: FloatType
+ Futhark.CodeGen.ImpCode.Sequential: Float16Value :: !Half -> FloatValue
+ Futhark.CodeGen.ImpCode.Sequential: data Half
+ Futhark.CodeGen.ImpCode.Sequential: isF16 :: PrimExp v -> TPrimExp Half v
+ Futhark.CodeGen.ImpCode.Sequential: pattern TracePrint :: () => ErrorMsg Exp -> Code a
+ Futhark.CodeGen.ImpGen: MemLoc :: VName -> [DimSize] -> IxFun (TExp Int64) -> MemLoc
+ Futhark.CodeGen.ImpGen: [entryArrayLoc] :: ArrayEntry -> MemLoc
+ Futhark.CodeGen.ImpGen: [memLocIxFun] :: MemLoc -> IxFun (TExp Int64)
+ Futhark.CodeGen.ImpGen: [memLocName] :: MemLoc -> VName
+ Futhark.CodeGen.ImpGen: [memLocShape] :: MemLoc -> [DimSize]
+ Futhark.CodeGen.ImpGen: dIndexSpace' :: String -> [TExp Int64] -> TExp Int64 -> ImpM rep r op [TExp Int64]
+ Futhark.CodeGen.ImpGen: data MemLoc
+ Futhark.CodeGen.ImpGen: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.MemLoc
+ Futhark.CodeGen.ImpGen: instance GHC.Show.Show Futhark.CodeGen.ImpGen.MemLoc
+ Futhark.CodeGen.ImpGen: sliceMemLoc :: MemLoc -> Slice (TExp Int64) -> MemLoc
+ Futhark.CodeGen.RTS.C: atomicsH :: Text
+ Futhark.CodeGen.RTS.C: chaselevH :: Text
+ Futhark.CodeGen.RTS.C: cudaH :: Text
+ Futhark.CodeGen.RTS.C: freeListH :: Text
+ Futhark.CodeGen.RTS.C: halfH :: Text
+ Futhark.CodeGen.RTS.C: lockH :: Text
+ Futhark.CodeGen.RTS.C: openclH :: Text
+ Futhark.CodeGen.RTS.C: scalarF16H :: Text
+ Futhark.CodeGen.RTS.C: scalarH :: Text
+ Futhark.CodeGen.RTS.C: schedulerH :: Text
+ Futhark.CodeGen.RTS.C: serverH :: Text
+ Futhark.CodeGen.RTS.C: timingH :: Text
+ Futhark.CodeGen.RTS.C: tuningH :: Text
+ Futhark.CodeGen.RTS.C: utilH :: Text
+ Futhark.CodeGen.RTS.C: valuesH :: Text
+ Futhark.CodeGen.RTS.JavaScript: serverJs :: Text
+ Futhark.CodeGen.RTS.JavaScript: valuesJs :: Text
+ Futhark.CodeGen.RTS.JavaScript: wrapperclassesJs :: Text
+ Futhark.CodeGen.RTS.Python: memoryPy :: Text
+ Futhark.CodeGen.RTS.Python: openclPy :: Text
+ Futhark.CodeGen.RTS.Python: panicPy :: Text
+ Futhark.CodeGen.RTS.Python: scalarPy :: Text
+ Futhark.CodeGen.RTS.Python: serverPy :: Text
+ Futhark.CodeGen.RTS.Python: tuningPy :: Text
+ Futhark.CodeGen.RTS.Python: valuesPy :: Text
+ Futhark.CodeGen.SetDefaultSpace: setDefaultCodeSpace :: Space -> Code op -> Code op
+ Futhark.Construct: eParam :: MonadBuilder m => Param t -> m (Exp (Rep m))
+ Futhark.IR.Aliases: addAliasesToPat :: (ASTRep rep, CanBeAliased (Op rep), Typed dec) => PatT dec -> Exp (Aliases rep) -> PatT (VarAliases, dec)
+ Futhark.IR.Aliases: instance (Futhark.Builder.Class.Buildable rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.Builder.Class.Buildable (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTRep (Futhark.IR.Aliases.Aliases rep), Futhark.Builder.Class.Buildable (Futhark.IR.Aliases.Aliases rep)) => Futhark.Builder.BuilderOps (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.Aliases: mkPatAliases :: (Aliased rep, Typed dec) => PatT dec -> Exp rep -> [PatElemT (VarAliases, dec)]
+ Futhark.IR.Aliases: removePatAliases :: PatT (AliasDec, a) -> PatT a
+ Futhark.IR.GPU: instance Futhark.Builder.BuilderOps Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.Builder.Class.Buildable Futhark.IR.GPU.GPU
+ Futhark.IR.GPU.Op: CalcNumGroups :: SubExp -> Name -> SubExp -> SizeOp
+ Futhark.IR.GPU.Op: CmpSizeLe :: Name -> SizeClass -> SubExp -> SizeOp
+ Futhark.IR.GPU.Op: GetSize :: Name -> SizeClass -> SizeOp
+ Futhark.IR.GPU.Op: GetSizeMax :: SizeClass -> SizeOp
+ Futhark.IR.GPU.Op: OtherOp :: op -> HostOp rep op
+ Futhark.IR.GPU.Op: SegGroup :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
+ Futhark.IR.GPU.Op: SegOp :: SegOp SegLevel rep -> HostOp rep op
+ Futhark.IR.GPU.Op: SegThread :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
+ Futhark.IR.GPU.Op: SizeOp :: SizeOp -> HostOp rep op
+ Futhark.IR.GPU.Op: SplitSpace :: SplitOrdering -> SubExp -> SubExp -> SubExp -> SizeOp
+ Futhark.IR.GPU.Op: [segGroupSize] :: SegLevel -> Count GroupSize SubExp
+ Futhark.IR.GPU.Op: [segNumGroups] :: SegLevel -> Count NumGroups SubExp
+ Futhark.IR.GPU.Op: [segVirt] :: SegLevel -> SegVirt
+ Futhark.IR.GPU.Op: data HostOp rep op
+ Futhark.IR.GPU.Op: data SegLevel
+ Futhark.IR.GPU.Op: data SizeOp
+ Futhark.IR.GPU.Op: instance (Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Rep.Op rep), Futhark.Analysis.Metrics.OpMetrics op) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Pretty.PrettyRep rep, Text.PrettyPrint.Mainland.Class.Pretty op) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Analysis.SymbolTable.IndexOp op) => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.IsOp op) => Futhark.IR.Prop.IsOp (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Names.FreeIn op) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Rename.Rename op) => Futhark.Transform.Rename.Rename (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Substitute.Substitute op) => Futhark.Transform.Substitute.Substitute (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.Aliases.Aliased rep, Futhark.IR.Prop.Aliases.AliasedOp op, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep), Futhark.IR.Prop.Aliases.CanBeAliased op, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Eq op) => GHC.Classes.Eq (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Ord op) => GHC.Classes.Ord (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Show.Show op) => GHC.Show.Show (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance (Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep), Futhark.Optimise.Simplify.Rep.CanBeWise op, Futhark.IR.Prop.ASTRep rep) => Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance Futhark.Analysis.Metrics.OpMetrics Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.Aliases.AliasedOp Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.IsOp Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.TypeOf.TypedOp Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.IR.Prop.TypeOf.TypedOp op => Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.IR.GPU.Op: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance Futhark.Transform.Rename.Rename Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance Futhark.Transform.Rename.Rename Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Futhark.Transform.Substitute.Substitute Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance Futhark.Transform.Substitute.Substitute Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance GHC.Classes.Eq Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance GHC.Classes.Eq Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance GHC.Classes.Ord Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance GHC.Classes.Ord Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance GHC.Show.Show Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance GHC.Show.Show Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.GPU.Op.SegLevel
+ Futhark.IR.GPU.Op: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.GPU.Op.SizeOp
+ Futhark.IR.GPU.Op: typeCheckHostOp :: Checkable rep => (SegLevel -> OpWithAliases (Op rep) -> TypeM rep ()) -> Maybe SegLevel -> (op -> TypeM rep ()) -> HostOp (Aliases rep) op -> TypeM rep ()
+ Futhark.IR.GPU.Simplify: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPU.GPU)
+ Futhark.IR.GPUMem: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPUMem.GPUMem)
+ Futhark.IR.GPUMem: instance Futhark.Builder.BuilderOps Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: instance Futhark.IR.Mem.OpReturns (Futhark.IR.GPU.Op.HostOp (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPUMem.GPUMem) ())
+ Futhark.IR.GPUMem: instance Futhark.IR.Mem.OpReturns (Futhark.IR.GPU.Op.HostOp Futhark.IR.GPUMem.GPUMem ())
+ Futhark.IR.MC: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MC.MC)
+ Futhark.IR.MC: instance Futhark.Builder.BuilderOps Futhark.IR.MC.MC
+ Futhark.IR.MC: instance Futhark.Builder.Class.Buildable Futhark.IR.MC.MC
+ Futhark.IR.MCMem: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MCMem.MCMem)
+ Futhark.IR.MCMem: instance Futhark.Builder.BuilderOps Futhark.IR.MCMem.MCMem
+ Futhark.IR.MCMem: instance Futhark.IR.Mem.OpReturns (Futhark.IR.MC.Op.MCOp (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MCMem.MCMem) ())
+ Futhark.IR.MCMem: instance Futhark.IR.Mem.OpReturns (Futhark.IR.MC.Op.MCOp Futhark.IR.MCMem.MCMem ())
+ Futhark.IR.Mem: bodyReturnsFromPat :: PatT (MemBound NoUniqueness) -> [(VName, BodyReturns)]
+ Futhark.IR.Mem: class HasLetDecMem t
+ Futhark.IR.Mem: instance Futhark.IR.Mem.HasLetDecMem Futhark.IR.Mem.LetDecMem
+ Futhark.IR.Mem: instance Futhark.IR.Mem.HasLetDecMem b => Futhark.IR.Mem.HasLetDecMem (a, b)
+ Futhark.IR.Mem: instance Futhark.IR.Mem.OpReturns ()
+ Futhark.IR.Mem: instance Futhark.IR.Mem.OpReturns inner => Futhark.IR.Mem.OpReturns (Futhark.IR.Mem.MemOp inner)
+ Futhark.IR.Mem: letDecMem :: HasLetDecMem t => t -> LetDecMem
+ Futhark.IR.Mem: matchPatToExp :: (Mem rep inner, LetDec rep ~ LetDecMem, Checkable rep) => Pat (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
+ Futhark.IR.Mem.IxFun: flatSlice :: (Eq num, IntegralExp num) => IxFun num -> FlatSlice num -> IxFun num
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Core.PatElemT dec) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Syntax.Attrs
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Syntax.SubExpRes
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty a => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Core.FlatSlice a)
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty a => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Core.Slice a)
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty d => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.IR.Primitive: Float16 :: FloatType
+ Futhark.IR.Primitive: Float16Value :: !Half -> FloatValue
+ Futhark.IR.Primitive: data Half
+ Futhark.IR.Prop: expExtTypesFromPat :: Typed dec => PatT dec -> [ExtType]
+ Futhark.IR.Prop: expTypesFromPat :: (ASTRep rep, HasScope rep m, Monad m) => Pat rep -> m [BranchType rep]
+ Futhark.IR.Prop.Aliases: patAliases :: AliasesOf dec => PatT dec -> [Names]
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.Syntax.SubExpRes
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn d => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn d => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Core.FlatSlice d)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn d => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn dec => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Prop.Patterns: basicPat :: [Ident] -> PatT Type
+ Futhark.IR.Prop.Patterns: patIdents :: Typed dec => PatT dec -> [Ident]
+ Futhark.IR.Prop.Patterns: patNames :: PatT dec -> [VName]
+ Futhark.IR.Prop.Patterns: patSize :: PatT dec -> Int
+ Futhark.IR.Prop.Patterns: patTypes :: Typed dec => PatT dec -> [Type]
+ Futhark.IR.Prop.Scope: scopeOfPat :: LetDec rep ~ dec => PatT dec -> Scope rep
+ Futhark.IR.Prop.TypeOf: basicOpType :: HasScope rep m => BasicOp -> m [Type]
+ Futhark.IR.Prop.TypeOf: subExpResType :: HasScope t m => SubExpRes -> m Type
+ Futhark.IR.SOACS: Certs :: [VName] -> Certs
+ Futhark.IR.SOACS: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.IR.SOACS: FlatDimIndex :: d -> d -> FlatDimIndex d
+ Futhark.IR.SOACS: FlatIndex :: VName -> FlatSlice SubExp -> BasicOp
+ Futhark.IR.SOACS: FlatSlice :: d -> [FlatDimIndex d] -> FlatSlice d
+ Futhark.IR.SOACS: FlatUpdate :: VName -> FlatSlice SubExp -> VName -> BasicOp
+ Futhark.IR.SOACS: Float16 :: FloatType
+ Futhark.IR.SOACS: Float16Value :: !Half -> FloatValue
+ Futhark.IR.SOACS: OpaqueNil :: OpaqueOp
+ Futhark.IR.SOACS: OpaqueTrace :: String -> OpaqueOp
+ Futhark.IR.SOACS: Pat :: [PatElemT dec] -> PatT dec
+ Futhark.IR.SOACS: Slice :: [DimIndex d] -> Slice d
+ Futhark.IR.SOACS: SubExpRes :: Certs -> SubExp -> SubExpRes
+ Futhark.IR.SOACS: [resCerts] :: SubExpRes -> Certs
+ Futhark.IR.SOACS: [resSubExp] :: SubExpRes -> SubExp
+ Futhark.IR.SOACS: [unCerts] :: Certs -> [VName]
+ Futhark.IR.SOACS: [unSlice] :: Slice d -> [DimIndex d]
+ Futhark.IR.SOACS: data FlatDimIndex d
+ Futhark.IR.SOACS: data FlatSlice d
+ Futhark.IR.SOACS: data Half
+ Futhark.IR.SOACS: data OpaqueOp
+ Futhark.IR.SOACS: data PatT dec
+ Futhark.IR.SOACS: data SubExpRes
+ Futhark.IR.SOACS: flatSliceDims :: FlatSlice d -> [d]
+ Futhark.IR.SOACS: flatSliceStrides :: FlatSlice d -> [d]
+ Futhark.IR.SOACS: instance Futhark.Builder.BuilderOps Futhark.IR.SOACS.SOACS
+ Futhark.IR.SOACS: instance Futhark.Builder.Class.Buildable Futhark.IR.SOACS.SOACS
+ Futhark.IR.SOACS: newtype Certs
+ Futhark.IR.SOACS: newtype PatT dec
+ Futhark.IR.SOACS: newtype Slice d
+ Futhark.IR.SOACS: pattern Let :: () => Pat rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
+ Futhark.IR.SOACS: stmPat :: Stm rep -> Pat rep
+ Futhark.IR.SOACS: subExpRes :: SubExp -> SubExpRes
+ Futhark.IR.SOACS: subExpsRes :: [SubExp] -> Result
+ Futhark.IR.SOACS: type Pat = Pat SOACS
+ Futhark.IR.SOACS: varRes :: VName -> SubExpRes
+ Futhark.IR.SOACS: varsRes :: [VName] -> Result
+ Futhark.IR.SOACS.Simplify: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SOACS.SOACS)
+ Futhark.IR.SegOp: kernelResultCerts :: KernelResult -> Certs
+ Futhark.IR.Seq: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.Seq.Seq)
+ Futhark.IR.Seq: instance Futhark.Builder.BuilderOps Futhark.IR.Seq.Seq
+ Futhark.IR.Seq: instance Futhark.Builder.Class.Buildable Futhark.IR.Seq.Seq
+ Futhark.IR.SeqMem: instance Futhark.Builder.BuilderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SeqMem.SeqMem)
+ Futhark.IR.SeqMem: instance Futhark.Builder.BuilderOps Futhark.IR.SeqMem.SeqMem
+ Futhark.IR.Syntax: FlatIndex :: VName -> FlatSlice SubExp -> BasicOp
+ Futhark.IR.Syntax: FlatUpdate :: VName -> FlatSlice SubExp -> VName -> BasicOp
+ Futhark.IR.Syntax: OpaqueNil :: OpaqueOp
+ Futhark.IR.Syntax: OpaqueTrace :: String -> OpaqueOp
+ Futhark.IR.Syntax: Pat :: [PatElemT dec] -> PatT dec
+ Futhark.IR.Syntax: SubExpRes :: Certs -> SubExp -> SubExpRes
+ Futhark.IR.Syntax: [patElems] :: PatT dec -> [PatElemT dec]
+ Futhark.IR.Syntax: [resCerts] :: SubExpRes -> Certs
+ Futhark.IR.Syntax: [resSubExp] :: SubExpRes -> SubExp
+ Futhark.IR.Syntax: [stmPat] :: Stm rep -> Pat rep
+ Futhark.IR.Syntax: data OpaqueOp
+ Futhark.IR.Syntax: data SubExpRes
+ Futhark.IR.Syntax: instance Data.Foldable.Foldable Futhark.IR.Syntax.PatT
+ Futhark.IR.Syntax: instance Data.Traversable.Traversable Futhark.IR.Syntax.PatT
+ Futhark.IR.Syntax: instance GHC.Base.Functor Futhark.IR.Syntax.PatT
+ Futhark.IR.Syntax: instance GHC.Base.Monoid (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Syntax: instance GHC.Base.Semigroup (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Syntax: instance GHC.Classes.Eq Futhark.IR.Syntax.OpaqueOp
+ Futhark.IR.Syntax: instance GHC.Classes.Eq Futhark.IR.Syntax.SubExpRes
+ Futhark.IR.Syntax: instance GHC.Classes.Eq dec => GHC.Classes.Eq (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Syntax: instance GHC.Classes.Ord Futhark.IR.Syntax.OpaqueOp
+ Futhark.IR.Syntax: instance GHC.Classes.Ord Futhark.IR.Syntax.SubExpRes
+ Futhark.IR.Syntax: instance GHC.Classes.Ord dec => GHC.Classes.Ord (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Syntax: instance GHC.Show.Show Futhark.IR.Syntax.OpaqueOp
+ Futhark.IR.Syntax: instance GHC.Show.Show Futhark.IR.Syntax.SubExpRes
+ Futhark.IR.Syntax: instance GHC.Show.Show dec => GHC.Show.Show (Futhark.IR.Syntax.PatT dec)
+ Futhark.IR.Syntax: newtype PatT dec
+ Futhark.IR.Syntax: subExpRes :: SubExp -> SubExpRes
+ Futhark.IR.Syntax: subExpsRes :: [SubExp] -> Result
+ Futhark.IR.Syntax: type Pat rep = PatT (LetDec rep)
+ Futhark.IR.Syntax: varRes :: VName -> SubExpRes
+ Futhark.IR.Syntax: varsRes :: [VName] -> Result
+ Futhark.IR.Syntax.Core: Certs :: [VName] -> Certs
+ Futhark.IR.Syntax.Core: ErrorVal :: PrimType -> a -> ErrorMsgPart a
+ Futhark.IR.Syntax.Core: FlatDimIndex :: d -> d -> FlatDimIndex d
+ Futhark.IR.Syntax.Core: FlatSlice :: d -> [FlatDimIndex d] -> FlatSlice d
+ Futhark.IR.Syntax.Core: Slice :: [DimIndex d] -> Slice d
+ Futhark.IR.Syntax.Core: [unCerts] :: Certs -> [VName]
+ Futhark.IR.Syntax.Core: [unSlice] :: Slice d -> [DimIndex d]
+ Futhark.IR.Syntax.Core: data FlatDimIndex d
+ Futhark.IR.Syntax.Core: data FlatSlice d
+ Futhark.IR.Syntax.Core: flatSliceDims :: FlatSlice d -> [d]
+ Futhark.IR.Syntax.Core: flatSliceStrides :: FlatSlice d -> [d]
+ Futhark.IR.Syntax.Core: instance Data.Foldable.Foldable Futhark.IR.Syntax.Core.FlatDimIndex
+ Futhark.IR.Syntax.Core: instance Data.Foldable.Foldable Futhark.IR.Syntax.Core.FlatSlice
+ Futhark.IR.Syntax.Core: instance Data.Foldable.Foldable Futhark.IR.Syntax.Core.Slice
+ Futhark.IR.Syntax.Core: instance Data.Traversable.Traversable Futhark.IR.Syntax.Core.FlatDimIndex
+ Futhark.IR.Syntax.Core: instance Data.Traversable.Traversable Futhark.IR.Syntax.Core.FlatSlice
+ Futhark.IR.Syntax.Core: instance Data.Traversable.Traversable Futhark.IR.Syntax.Core.Slice
+ Futhark.IR.Syntax.Core: instance GHC.Base.Functor Futhark.IR.Syntax.Core.FlatDimIndex
+ Futhark.IR.Syntax.Core: instance GHC.Base.Functor Futhark.IR.Syntax.Core.FlatSlice
+ Futhark.IR.Syntax.Core: instance GHC.Base.Functor Futhark.IR.Syntax.Core.Slice
+ Futhark.IR.Syntax.Core: instance GHC.Base.Monoid Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Syntax.Core: instance GHC.Base.Semigroup Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Eq Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Eq d => GHC.Classes.Eq (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Eq d => GHC.Classes.Eq (Futhark.IR.Syntax.Core.FlatSlice d)
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Eq d => GHC.Classes.Eq (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Ord Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Ord d => GHC.Classes.Ord (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Ord d => GHC.Classes.Ord (Futhark.IR.Syntax.Core.FlatSlice d)
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Ord d => GHC.Classes.Ord (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.IR.Syntax.Core: instance GHC.Show.Show Futhark.IR.Syntax.Core.Certs
+ Futhark.IR.Syntax.Core: instance GHC.Show.Show d => GHC.Show.Show (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.IR.Syntax.Core: instance GHC.Show.Show d => GHC.Show.Show (Futhark.IR.Syntax.Core.FlatSlice d)
+ Futhark.IR.Syntax.Core: instance GHC.Show.Show d => GHC.Show.Show (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.IR.Syntax.Core: newtype Certs
+ Futhark.IR.Syntax.Core: newtype Slice d
+ Futhark.Internalise.Bindings: stmPat :: Pat -> [Type] -> ([VName] -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.FreeVars: patVars :: Pat -> NameSet
+ Futhark.Internalise.Monad: instance Futhark.Builder.Class.MonadBuilder Futhark.Internalise.Monad.InternaliseM
+ Futhark.Internalise.Monad: type VarSubsts = Map VName [SubExp]
+ Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.Aliased rep, Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Rep.Op rep), Futhark.Optimise.CSE.CSEInOp op) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: [updateCerts] :: DesiredUpdate dec -> Certs
+ Futhark.Optimise.InliningDeadFun: inlineAggressively :: Pass SOACS SOACS
+ Futhark.Optimise.InliningDeadFun: inlineConservatively :: Pass SOACS SOACS
+ Futhark.Optimise.Simplify.Engine: instance Control.Monad.State.Class.MonadState (Futhark.FreshNames.VNameSource, GHC.Types.Bool, Futhark.IR.Syntax.Core.Certs) (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.Syntax.Core.Certs
+ Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.Syntax.SubExpRes
+ Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.Simplifiable d => Futhark.Optimise.Simplify.Engine.Simplifiable (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.Optimise.Simplify.Rep: addWisdomToPat :: (ASTRep rep, CanBeWise (Op rep)) => Pat rep -> Exp (Wise rep) -> Pat (Wise rep)
+ Futhark.Optimise.Simplify.Rep: instance (Futhark.Builder.Class.Buildable rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.Builder.Class.Buildable (Futhark.Optimise.Simplify.Rep.Wise rep)
+ Futhark.Optimise.Simplify.Rep: removePatWisdom :: PatT (VarWisdom, a) -> PatT a
+ Futhark.Optimise.Simplify.Rule: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Builder.BuilderOps rep) => Futhark.Builder.Class.MonadBuilder (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Pass.ExplicitAllocations: instance Futhark.Pass.ExplicitAllocations.Allocable fromrep torep inner => Futhark.Builder.Class.MonadBuilder (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
+ Futhark.Pass.ExplicitAllocations: type ChunkMap = Map VName SubExp
+ Futhark.Pass.ExplicitAllocations.GPU: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.GPU.Op.HostOp rep op)
+ Futhark.Pass.ExtractKernels.Distribution: [loopNestingPat] :: LoopNesting -> PatT Type
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Rename Futhark.IR.Syntax.Core.Certs
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Rename Futhark.IR.Syntax.SubExpRes
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Rename dec => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.PatT dec)
+ Futhark.Transform.Rename: renamePat :: (Rename dec, MonadFreshNames m) => PatT dec -> m (PatT dec)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute Futhark.IR.Syntax.Core.Certs
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute Futhark.IR.Syntax.SubExpRes
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute d => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Core.FlatDimIndex d)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute d => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Core.FlatSlice d)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute d => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Core.Slice d)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute dec => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.PatT dec)
+ Futhark.TypeCheck: DupPatError :: VName -> ErrorCase rep
+ Futhark.TypeCheck: InvalidPatError :: Pat (Aliases rep) -> [ExtType] -> Maybe String -> ErrorCase rep
+ Futhark.TypeCheck: checkCerts :: Checkable rep => Certs -> TypeM rep ()
+ Futhark.TypeCheck: matchExtPat :: Checkable rep => Pat (Aliases rep) -> [ExtType] -> TypeM rep ()
+ Futhark.TypeCheck: matchPat :: Checkable rep => Pat (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
+ Futhark.Util: convFloat :: (RealFloat from, RealFloat to) => from -> to
+ Futhark.Util: hashText :: Text -> Text
+ Futhark.Util.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Numeric.Half.Internal.Half
+ Language.Futhark: type Pat = PatBase Info VName
+ Language.Futhark.Core: data Half
+ Language.Futhark.Parser: BANG :: Token
+ Language.Futhark.Parser: F16LIT :: Half -> Token
+ Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Text.PrettyPrint.Mainland.Class.Pretty (Language.Futhark.Syntax.PatBase f vn)
+ Language.Futhark.Prop: patIdents :: (Functor f, Ord vn) => PatBase f vn -> Set (IdentBase f vn)
+ Language.Futhark.Prop: patNames :: (Functor f, Ord vn) => PatBase f vn -> Set vn
+ Language.Futhark.Prop: type UncheckedPat = PatBase NoInfo Name
+ Language.Futhark.Syntax: Float16 :: FloatType
+ Language.Futhark.Syntax: Float16Value :: !Half -> FloatValue
+ Language.Futhark.Syntax: Not :: ExpBase f vn -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: PatAscription :: PatBase f vn -> TypeDeclBase f vn -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: PatConstr :: Name -> f PatType -> [PatBase f vn] -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: PatLit :: PatLit -> f PatType -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: PatParens :: PatBase f vn -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: RecordPat :: [(Name, PatBase f vn)] -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: TuplePat :: [PatBase f vn] -> SrcLoc -> PatBase f vn
+ Language.Futhark.Syntax: data PatBase f vn
+ Language.Futhark.Syntax: instance Data.Loc.Located (Language.Futhark.Syntax.PatBase f vn)
+ Language.Futhark.Syntax: instance GHC.Classes.Eq (Language.Futhark.Syntax.PatBase Language.Futhark.Syntax.NoInfo Language.Futhark.Core.VName)
+ Language.Futhark.Syntax: instance GHC.Classes.Ord (Language.Futhark.Syntax.PatBase Language.Futhark.Syntax.NoInfo Language.Futhark.Core.VName)
+ Language.Futhark.Syntax: instance Language.Futhark.Syntax.Showable f vn => GHC.Show.Show (Language.Futhark.Syntax.PatBase f vn)
+ Language.Futhark.Syntax: type PatType = TypeBase (DimDecl VName) Aliasing
+ Language.Futhark.Traversals: [mapOnPatType] :: ASTMapper m -> PatType -> m PatType
+ Language.Futhark.Traversals: instance Language.Futhark.Traversals.ASTMappable (Language.Futhark.Syntax.PatBase Language.Futhark.Syntax.Info Language.Futhark.Core.VName)
+ Language.Futhark.Traversals: instance Language.Futhark.Traversals.ASTMappable Language.Futhark.Syntax.PatType
+ Language.Futhark.TypeChecker.Monad: anyIntType :: [PrimType]
+ Language.Futhark.TypeChecker.Terms: instance Text.PrettyPrint.Mainland.Class.Pretty (Language.Futhark.TypeChecker.Terms.Unmatched (Language.Futhark.Syntax.PatBase Language.Futhark.Syntax.Info Language.Futhark.Core.VName))
+ Language.Futhark.TypeChecker.Types: instance Language.Futhark.TypeChecker.Types.Substitutable Language.Futhark.Pat
+ Language.Futhark.TypeChecker.Unify: normPatType :: MonadUnify m => PatType -> m PatType
- Futhark.Analysis.HORep.MapNest: fromSOAC :: (Bindable rep, MonadFreshNames m, LocalScope rep m, Op rep ~ SOAC rep) => SOAC rep -> m (Maybe (MapNest rep))
+ Futhark.Analysis.HORep.MapNest: fromSOAC :: (Buildable rep, MonadFreshNames m, LocalScope rep m, Op rep ~ SOAC rep) => SOAC rep -> m (Maybe (MapNest rep))
- Futhark.Analysis.HORep.MapNest: toSOAC :: (MonadFreshNames m, HasScope rep m, Bindable rep, BinderOps rep, Op rep ~ SOAC rep) => MapNest rep -> m (SOAC rep)
+ Futhark.Analysis.HORep.MapNest: toSOAC :: (MonadFreshNames m, HasScope rep m, Buildable rep, BuilderOps rep, Op rep ~ SOAC rep) => MapNest rep -> m (SOAC rep)
- Futhark.Analysis.HORep.SOAC: Rearrange :: Certificates -> [Int] -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Rearrange :: Certs -> [Int] -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: Replicate :: Certificates -> Shape -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Replicate :: Certs -> Shape -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: Reshape :: Certificates -> ShapeChange SubExp -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Reshape :: Certs -> ShapeChange SubExp -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: ReshapeInner :: Certificates -> ShapeChange SubExp -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: ReshapeInner :: Certs -> ShapeChange SubExp -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: ReshapeOuter :: Certificates -> ShapeChange SubExp -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: ReshapeOuter :: Certs -> ShapeChange SubExp -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: soacToStream :: (MonadFreshNames m, Bindable rep, Op rep ~ SOAC rep) => SOAC rep -> m (SOAC rep, [Ident])
+ Futhark.Analysis.HORep.SOAC: soacToStream :: (MonadFreshNames m, Buildable rep, Op rep ~ SOAC rep) => SOAC rep -> m (SOAC rep, [Ident])
- Futhark.Analysis.HORep.SOAC: toExp :: (MonadBinder m, Op (Rep m) ~ SOAC (Rep m)) => SOAC (Rep m) -> m (Exp (Rep m))
+ Futhark.Analysis.HORep.SOAC: toExp :: (MonadBuilder m, Op (Rep m) ~ SOAC (Rep m)) => SOAC (Rep m) -> m (Exp (Rep m))
- Futhark.Analysis.HORep.SOAC: toSOAC :: MonadBinder m => SOAC (Rep m) -> m (SOAC (Rep m))
+ Futhark.Analysis.HORep.SOAC: toSOAC :: MonadBuilder m => SOAC (Rep m) -> m (SOAC (Rep m))
- Futhark.Analysis.HORep.SOAC: transformFromExp :: Certificates -> Exp rep -> Maybe (VName, ArrayTransform)
+ Futhark.Analysis.HORep.SOAC: transformFromExp :: Certs -> Exp rep -> Maybe (VName, ArrayTransform)
- Futhark.Analysis.PrimExp.Convert: subExpSlice :: MonadBinder m => Slice (TPrimExp Int64 VName) -> m (Slice SubExp)
+ Futhark.Analysis.PrimExp.Convert: subExpSlice :: MonadBuilder m => Slice (TPrimExp Int64 VName) -> m (Slice SubExp)
- Futhark.Analysis.SymbolTable: Indexed :: Certificates -> PrimExp VName -> Indexed
+ Futhark.Analysis.SymbolTable: Indexed :: Certs -> PrimExp VName -> Indexed
- Futhark.Analysis.SymbolTable: IndexedArray :: Certificates -> VName -> [TPrimExp Int64 VName] -> Indexed
+ Futhark.Analysis.SymbolTable: IndexedArray :: Certs -> VName -> [TPrimExp Int64 VName] -> Indexed
- Futhark.Analysis.SymbolTable: indexedAddCerts :: Certificates -> Indexed -> Indexed
+ Futhark.Analysis.SymbolTable: indexedAddCerts :: Certs -> Indexed -> Indexed
- Futhark.Analysis.SymbolTable: insertLoopMerge :: ASTRep rep => [(FParam rep, SubExp, SubExp)] -> SymbolTable rep -> SymbolTable rep
+ Futhark.Analysis.SymbolTable: insertLoopMerge :: ASTRep rep => [(FParam rep, SubExp, SubExpRes)] -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certificates)
+ Futhark.Analysis.SymbolTable: lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certs)
- Futhark.Analysis.SymbolTable: lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certificates)
+ Futhark.Analysis.SymbolTable: lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certs)
- Futhark.Analysis.SymbolTable: lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certificates)
+ Futhark.Analysis.SymbolTable: lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certs)
- Futhark.CodeGen.Backends.CCUDA: CParts :: String -> String -> String -> String -> String -> CParts
+ Futhark.CodeGen.Backends.CCUDA: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
- Futhark.CodeGen.Backends.CCUDA: [cCLI] :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: [cCLI] :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: [cHeader] :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: [cHeader] :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: [cLib] :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: [cLib] :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: [cServer] :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: [cServer] :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: [cUtils] :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: [cUtils] :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: asExecutable :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: asExecutable :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA: asLibrary :: CParts -> (String, String)
+ Futhark.CodeGen.Backends.CCUDA: asLibrary :: CParts -> (Text, Text)
- Futhark.CodeGen.Backends.CCUDA: asServer :: CParts -> String
+ Futhark.CodeGen.Backends.CCUDA: asServer :: CParts -> Text
- Futhark.CodeGen.Backends.CCUDA.Boilerplate: generateBoilerplate :: String -> String -> [Name] -> Map KernelName KernelSafety -> Map Name SizeClass -> [FailureMsg] -> CompilerM OpenCL () ()
+ Futhark.CodeGen.Backends.CCUDA.Boilerplate: generateBoilerplate :: Text -> Text -> [Name] -> Map KernelName KernelSafety -> Map Name SizeClass -> [FailureMsg] -> CompilerM OpenCL () ()
- Futhark.CodeGen.Backends.COpenCL: CParts :: String -> String -> String -> String -> String -> CParts
+ Futhark.CodeGen.Backends.COpenCL: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
- Futhark.CodeGen.Backends.COpenCL: [cCLI] :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: [cCLI] :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: [cHeader] :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: [cHeader] :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: [cLib] :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: [cLib] :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: [cServer] :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: [cServer] :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: [cUtils] :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: [cUtils] :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: asExecutable :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: asExecutable :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL: asLibrary :: CParts -> (String, String)
+ Futhark.CodeGen.Backends.COpenCL: asLibrary :: CParts -> (Text, Text)
- Futhark.CodeGen.Backends.COpenCL: asServer :: CParts -> String
+ Futhark.CodeGen.Backends.COpenCL: asServer :: CParts -> Text
- Futhark.CodeGen.Backends.COpenCL.Boilerplate: generateBoilerplate :: String -> String -> [Name] -> Map KernelName KernelSafety -> [PrimType] -> Map Name SizeClass -> [FailureMsg] -> CompilerM OpenCL () ()
+ Futhark.CodeGen.Backends.COpenCL.Boilerplate: generateBoilerplate :: Text -> Text -> [Name] -> Map KernelName KernelSafety -> [PrimType] -> Map Name SizeClass -> [FailureMsg] -> CompilerM OpenCL () ()
- Futhark.CodeGen.Backends.GenericC: CParts :: String -> String -> String -> String -> String -> CParts
+ Futhark.CodeGen.Backends.GenericC: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
- Futhark.CodeGen.Backends.GenericC: [cCLI] :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: [cCLI] :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: [cHeader] :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: [cHeader] :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: [cLib] :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: [cLib] :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: [cServer] :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: [cServer] :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: [cUtils] :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: [cUtils] :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: asExecutable :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: asExecutable :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: asLibrary :: CParts -> (String, String)
+ Futhark.CodeGen.Backends.GenericC: asLibrary :: CParts -> (Text, Text)
- Futhark.CodeGen.Backends.GenericC: asServer :: CParts -> String
+ Futhark.CodeGen.Backends.GenericC: asServer :: CParts -> Text
- Futhark.CodeGen.Backends.GenericC: compileProg :: MonadFreshNames m => String -> Operations op () -> CompilerM op () () -> String -> [Space] -> [Option] -> Definitions op -> m CParts
+ Futhark.CodeGen.Backends.GenericC: compileProg :: MonadFreshNames m => Text -> Operations op () -> CompilerM op () () -> Text -> [Space] -> [Option] -> Definitions op -> m CParts
- Futhark.CodeGen.Backends.GenericC.CLI: cliDefs :: [Option] -> Functions a -> [Definition]
+ Futhark.CodeGen.Backends.GenericC.CLI: cliDefs :: [Option] -> Functions a -> Text
- Futhark.CodeGen.Backends.GenericC.Server: serverDefs :: [Option] -> Functions a -> [Definition]
+ Futhark.CodeGen.Backends.GenericC.Server: serverDefs :: [Option] -> Functions a -> Text
- Futhark.CodeGen.Backends.GenericPython: compileProg :: MonadFreshNames m => CompilerMode -> String -> Constructor -> [PyStmt] -> [PyStmt] -> Operations op s -> s -> [PyStmt] -> [Option] -> Definitions op -> m String
+ Futhark.CodeGen.Backends.GenericPython: compileProg :: MonadFreshNames m => CompilerMode -> String -> Constructor -> [PyStmt] -> [PyStmt] -> Operations op s -> s -> [PyStmt] -> [Option] -> Definitions op -> m Text
- Futhark.CodeGen.Backends.GenericPython.AST: Escape :: String -> PyStmt
+ Futhark.CodeGen.Backends.GenericPython.AST: Escape :: Text -> PyStmt
- Futhark.CodeGen.Backends.GenericPython.AST: RawStringLiteral :: String -> PyExp
+ Futhark.CodeGen.Backends.GenericPython.AST: RawStringLiteral :: Text -> PyExp
- Futhark.CodeGen.Backends.MulticoreC: CParts :: String -> String -> String -> String -> String -> CParts
+ Futhark.CodeGen.Backends.MulticoreC: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
- Futhark.CodeGen.Backends.MulticoreC: [cCLI] :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: [cCLI] :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: [cHeader] :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: [cHeader] :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: [cLib] :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: [cLib] :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: [cServer] :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: [cServer] :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: [cUtils] :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: [cUtils] :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: asExecutable :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: asExecutable :: CParts -> Text
- Futhark.CodeGen.Backends.MulticoreC: asLibrary :: CParts -> (String, String)
+ Futhark.CodeGen.Backends.MulticoreC: asLibrary :: CParts -> (Text, Text)
- Futhark.CodeGen.Backends.MulticoreC: asServer :: CParts -> String
+ Futhark.CodeGen.Backends.MulticoreC: asServer :: CParts -> Text
- Futhark.CodeGen.Backends.PyOpenCL: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog GPUMem -> m (Warnings, String)
+ Futhark.CodeGen.Backends.PyOpenCL: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog GPUMem -> m (Warnings, Text)
- Futhark.CodeGen.Backends.PyOpenCL.Boilerplate: openClInit :: [PrimType] -> String -> Map Name SizeClass -> [FailureMsg] -> String
+ Futhark.CodeGen.Backends.PyOpenCL.Boilerplate: openClInit :: [PrimType] -> String -> Map Name SizeClass -> [FailureMsg] -> Text
- Futhark.CodeGen.Backends.SequentialC: CParts :: String -> String -> String -> String -> String -> CParts
+ Futhark.CodeGen.Backends.SequentialC: CParts :: Text -> Text -> Text -> Text -> Text -> CParts
- Futhark.CodeGen.Backends.SequentialC: [cCLI] :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: [cCLI] :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: [cHeader] :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: [cHeader] :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: [cLib] :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: [cLib] :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: [cServer] :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: [cServer] :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: [cUtils] :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: [cUtils] :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: asExecutable :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: asExecutable :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialC: asLibrary :: CParts -> (String, String)
+ Futhark.CodeGen.Backends.SequentialC: asLibrary :: CParts -> (Text, Text)
- Futhark.CodeGen.Backends.SequentialC: asServer :: CParts -> String
+ Futhark.CodeGen.Backends.SequentialC: asServer :: CParts -> Text
- Futhark.CodeGen.Backends.SequentialPython: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog SeqMem -> m (Warnings, String)
+ Futhark.CodeGen.Backends.SequentialPython: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog SeqMem -> m (Warnings, Text)
- Futhark.CodeGen.ImpCode.OpenCL: Program :: String -> String -> Map KernelName KernelSafety -> [PrimType] -> Map Name SizeClass -> [FailureMsg] -> Definitions OpenCL -> Program
+ Futhark.CodeGen.ImpCode.OpenCL: Program :: Text -> Text -> Map KernelName KernelSafety -> [PrimType] -> Map Name SizeClass -> [FailureMsg] -> Definitions OpenCL -> Program
- Futhark.CodeGen.ImpCode.OpenCL: [openClPrelude] :: Program -> String
+ Futhark.CodeGen.ImpCode.OpenCL: [openClPrelude] :: Program -> Text
- Futhark.CodeGen.ImpCode.OpenCL: [openClProgram] :: Program -> String
+ Futhark.CodeGen.ImpCode.OpenCL: [openClProgram] :: Program -> Text
- Futhark.CodeGen.ImpGen: ArrayEntry :: MemLocation -> PrimType -> ArrayEntry
+ Futhark.CodeGen.ImpGen: ArrayEntry :: MemLoc -> PrimType -> ArrayEntry
- Futhark.CodeGen.ImpGen: compileAlloc :: Mem rep => Pattern rep -> SubExp -> Space -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: compileAlloc :: Mem rep inner => Pat rep -> SubExp -> Space -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileBody :: Mem rep => Pattern rep -> Body rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: compileBody :: Pat rep -> Body rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileExp :: Pattern rep -> Exp rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: compileExp :: Pat rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileProg :: (Mem rep, FreeIn op, MonadFreshNames m) => r -> Operations rep r op -> Space -> Prog rep -> m (Warnings, Definitions op)
+ Futhark.CodeGen.ImpGen: compileProg :: (Mem rep inner, FreeIn op, MonadFreshNames m) => r -> Operations rep r op -> Space -> Prog rep -> m (Warnings, Definitions op)
- Futhark.CodeGen.ImpGen: dFParams :: Mem rep => [FParam rep] -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: dFParams :: Mem rep inner => [FParam rep] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dLParams :: Mem rep => [LParam rep] -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: dLParams :: Mem rep inner => [LParam rep] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dScope :: Mem rep => Maybe (Exp rep) -> Scope rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: dScope :: Mem rep inner => Maybe (Exp rep) -> Scope rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: defCompileExp :: Mem rep => Pattern rep -> Exp rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: defCompileExp :: Mem rep inner => Pat rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: defCompileStms :: (Mem rep, FreeIn op) => Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: defCompileStms :: (Mem rep inner, FreeIn op) => Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: defaultOperations :: (Mem rep, FreeIn op) => OpCompiler rep r op -> Operations rep r op
+ Futhark.CodeGen.ImpGen: defaultOperations :: (Mem rep inner, FreeIn op) => OpCompiler rep r op -> Operations rep r op
- Futhark.CodeGen.ImpGen: fullyIndexArray' :: MemLocation -> [TExp Int64] -> ImpM rep r op (VName, Space, Count Elements (TExp Int64))
+ Futhark.CodeGen.ImpGen: fullyIndexArray' :: MemLoc -> [TExp Int64] -> ImpM rep r op (VName, Space, Count Elements (TExp Int64))
- Futhark.CodeGen.ImpGen: isMapTransposeCopy :: PrimType -> MemLocation -> Slice (TExp Int64) -> MemLocation -> Slice (TExp Int64) -> Maybe (TExp Int64, TExp Int64, TExp Int64, TExp Int64, TExp Int64)
+ Futhark.CodeGen.ImpGen: isMapTransposeCopy :: PrimType -> MemLoc -> MemLoc -> Maybe (TExp Int64, TExp Int64, TExp Int64, TExp Int64, TExp Int64)
- Futhark.CodeGen.ImpGen: type CopyCompiler rep r op = PrimType -> MemLocation -> Slice (TExp Int64) -> MemLocation -> Slice (TExp Int64) -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: type CopyCompiler rep r op = PrimType -> MemLoc -> MemLoc -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type ExpCompiler rep r op = Pattern rep -> Exp rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: type ExpCompiler rep r op = Pat rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type OpCompiler rep r op = Pattern rep -> Op rep -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen: type OpCompiler rep r op = Pat rep -> Op rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen.GPU.SegHist: compileSegHist :: Pattern GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [HistOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegHist: compileSegHist :: Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [HistOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegMap: compileSegMap :: Pattern GPUMem -> SegLevel -> SegSpace -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegMap: compileSegMap :: Pat GPUMem -> SegLevel -> SegSpace -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegRed: compileSegRed :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegRed: compileSegRed :: Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegRed: compileSegRed' :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> DoSegBody -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegRed: compileSegRed' :: Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> DoSegBody -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegScan: compileSegScan :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegScan: compileSegScan :: Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass: compileSegScan :: Pattern GPUMem -> SegLevel -> SegSpace -> SegBinOp GPUMem -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass: compileSegScan :: Pat GPUMem -> SegLevel -> SegSpace -> SegBinOp GPUMem -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass: compileSegScan :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass: compileSegScan :: Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Multicore.Base: getReturnParams :: Pattern MCMem -> SegOp () MCMem -> MulticoreGen [Param]
+ Futhark.CodeGen.ImpGen.Multicore.Base: getReturnParams :: Pat MCMem -> SegOp () MCMem -> MulticoreGen [Param]
- Futhark.CodeGen.ImpGen.Multicore.SegHist: compileSegHist :: Pattern MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
+ Futhark.CodeGen.ImpGen.Multicore.SegHist: compileSegHist :: Pat MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
- Futhark.CodeGen.ImpGen.Multicore.SegMap: compileSegMap :: Pattern MCMem -> SegSpace -> KernelBody MCMem -> MulticoreGen Code
+ Futhark.CodeGen.ImpGen.Multicore.SegMap: compileSegMap :: Pat MCMem -> SegSpace -> KernelBody MCMem -> MulticoreGen Code
- Futhark.CodeGen.ImpGen.Multicore.SegRed: compileSegRed :: Pattern MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
+ Futhark.CodeGen.ImpGen.Multicore.SegRed: compileSegRed :: Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
- Futhark.CodeGen.ImpGen.Multicore.SegRed: compileSegRed' :: Pattern MCMem -> SegSpace -> [SegBinOp MCMem] -> TV Int32 -> DoSegBody -> MulticoreGen Code
+ Futhark.CodeGen.ImpGen.Multicore.SegRed: compileSegRed' :: Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> TV Int32 -> DoSegBody -> MulticoreGen Code
- Futhark.CodeGen.ImpGen.Multicore.SegScan: compileSegScan :: Pattern MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
+ Futhark.CodeGen.ImpGen.Multicore.SegScan: compileSegScan :: Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem -> TV Int32 -> MulticoreGen Code
- Futhark.Construct: asIntS :: MonadBinder m => IntType -> SubExp -> m SubExp
+ Futhark.Construct: asIntS :: MonadBuilder m => IntType -> SubExp -> m SubExp
- Futhark.Construct: asIntZ :: MonadBinder m => IntType -> SubExp -> m SubExp
+ Futhark.Construct: asIntZ :: MonadBuilder m => IntType -> SubExp -> m SubExp
- Futhark.Construct: binOpLambda :: (MonadBinder m, Bindable (Rep m)) => BinOp -> PrimType -> m (Lambda (Rep m))
+ Futhark.Construct: binOpLambda :: (MonadBuilder m, Buildable (Rep m)) => BinOp -> PrimType -> m (Lambda (Rep m))
- Futhark.Construct: buildBody :: MonadBinder m => m (Result, a) -> m (Body (Rep m), a)
+ Futhark.Construct: buildBody :: MonadBuilder m => m (Result, a) -> m (Body (Rep m), a)
- Futhark.Construct: buildBody_ :: MonadBinder m => m Result -> m (Body (Rep m))
+ Futhark.Construct: buildBody_ :: MonadBuilder m => m Result -> m (Body (Rep m))
- Futhark.Construct: cmpOpLambda :: (MonadBinder m, Bindable (Rep m)) => CmpOp -> m (Lambda (Rep m))
+ Futhark.Construct: cmpOpLambda :: (MonadBuilder m, Buildable (Rep m)) => CmpOp -> m (Lambda (Rep m))
- Futhark.Construct: eAll :: MonadBinder m => [SubExp] -> m (Exp (Rep m))
+ Futhark.Construct: eAll :: MonadBuilder m => [SubExp] -> m (Exp (Rep m))
- Futhark.Construct: eBinOp :: MonadBinder m => BinOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eBinOp :: MonadBuilder m => BinOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eBlank :: MonadBinder m => Type -> m (Exp (Rep m))
+ Futhark.Construct: eBlank :: MonadBuilder m => Type -> m (Exp (Rep m))
- Futhark.Construct: eBody :: MonadBinder m => [m (Exp (Rep m))] -> m (Body (Rep m))
+ Futhark.Construct: eBody :: MonadBuilder m => [m (Exp (Rep m))] -> m (Body (Rep m))
- Futhark.Construct: eCmpOp :: MonadBinder m => CmpOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eCmpOp :: MonadBuilder m => CmpOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eConvOp :: MonadBinder m => ConvOp -> m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eConvOp :: MonadBuilder m => ConvOp -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eCopy :: MonadBinder m => m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eCopy :: MonadBuilder m => m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eIf :: (MonadBinder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eIf :: (MonadBuilder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eIf' :: (MonadBinder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) -> IfSort -> m (Exp (Rep m))
+ Futhark.Construct: eIf' :: (MonadBuilder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) -> IfSort -> m (Exp (Rep m))
- Futhark.Construct: eLambda :: MonadBinder m => Lambda (Rep m) -> [m (Exp (Rep m))] -> m [SubExp]
+ Futhark.Construct: eLambda :: MonadBuilder m => Lambda (Rep m) -> [m (Exp (Rep m))] -> m [SubExpRes]
- Futhark.Construct: eOutOfBounds :: MonadBinder m => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m))
+ Futhark.Construct: eOutOfBounds :: MonadBuilder m => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m))
- Futhark.Construct: eRoundToMultipleOf :: MonadBinder m => IntType -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eRoundToMultipleOf :: MonadBuilder m => IntType -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSignum :: MonadBinder m => m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eSignum :: MonadBuilder m => m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSliceArray :: MonadBinder m => Int -> VName -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
+ Futhark.Construct: eSliceArray :: MonadBuilder m => Int -> VName -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSubExp :: MonadBinder m => SubExp -> m (Exp (Rep m))
+ Futhark.Construct: eSubExp :: MonadBuilder m => SubExp -> m (Exp (Rep m))
- Futhark.Construct: foldBinOp :: MonadBinder m => BinOp -> SubExp -> [SubExp] -> m (Exp (Rep m))
+ Futhark.Construct: foldBinOp :: MonadBuilder m => BinOp -> SubExp -> [SubExp] -> m (Exp (Rep m))
- Futhark.Construct: insertStmsM :: MonadBinder m => m (Body (Rep m)) -> m (Body (Rep m))
+ Futhark.Construct: insertStmsM :: MonadBuilder m => m (Body (Rep m)) -> m (Body (Rep m))
- Futhark.Construct: instantiateShapes' :: MonadFreshNames m => [TypeBase ExtShape u] -> m ([TypeBase Shape u], [Ident])
+ Futhark.Construct: instantiateShapes' :: [VName] -> [TypeBase ExtShape u] -> [TypeBase Shape u]
- Futhark.Construct: letExp :: MonadBinder m => String -> Exp (Rep m) -> m VName
+ Futhark.Construct: letExp :: MonadBuilder m => String -> Exp (Rep m) -> m VName
- Futhark.Construct: letInPlace :: MonadBinder m => String -> VName -> Slice SubExp -> Exp (Rep m) -> m VName
+ Futhark.Construct: letInPlace :: MonadBuilder m => String -> VName -> Slice SubExp -> Exp (Rep m) -> m VName
- Futhark.Construct: letSubExp :: MonadBinder m => String -> Exp (Rep m) -> m SubExp
+ Futhark.Construct: letSubExp :: MonadBuilder m => String -> Exp (Rep m) -> m SubExp
- Futhark.Construct: letSubExps :: MonadBinder m => String -> [Exp (Rep m)] -> m [SubExp]
+ Futhark.Construct: letSubExps :: MonadBuilder m => String -> [Exp (Rep m)] -> m [SubExp]
- Futhark.Construct: letTupExp :: MonadBinder m => String -> Exp (Rep m) -> m [VName]
+ Futhark.Construct: letTupExp :: MonadBuilder m => String -> Exp (Rep m) -> m [VName]
- Futhark.Construct: letTupExp' :: MonadBinder m => String -> Exp (Rep m) -> m [SubExp]
+ Futhark.Construct: letTupExp' :: MonadBuilder m => String -> Exp (Rep m) -> m [SubExp]
- Futhark.Construct: mapResult :: Bindable rep => (Result -> Body rep) -> Body rep -> Body rep
+ Futhark.Construct: mapResult :: Buildable rep => (Result -> Body rep) -> Body rep -> Body rep
- Futhark.Construct: mkLambda :: MonadBinder m => [LParam (Rep m)] -> m Result -> m (Lambda (Rep m))
+ Futhark.Construct: mkLambda :: MonadBuilder m => [LParam (Rep m)] -> m Result -> m (Lambda (Rep m))
- Futhark.Construct: resultBody :: Bindable rep => [SubExp] -> Body rep
+ Futhark.Construct: resultBody :: Buildable rep => [SubExp] -> Body rep
- Futhark.Construct: resultBodyM :: MonadBinder m => [SubExp] -> m (Body (Rep m))
+ Futhark.Construct: resultBodyM :: MonadBuilder m => [SubExp] -> m (Body (Rep m))
- Futhark.Construct: toExp :: (ToExp a, MonadBinder m) => a -> m (Exp (Rep m))
+ Futhark.Construct: toExp :: (ToExp a, MonadBuilder m) => a -> m (Exp (Rep m))
- Futhark.Construct: toSubExp :: (MonadBinder m, ToExp a) => String -> a -> m SubExp
+ Futhark.Construct: toSubExp :: (MonadBuilder m, ToExp a) => String -> a -> m SubExp
- Futhark.IR.Aliases: mkAliasedLetStm :: (ASTRep rep, CanBeAliased (Op rep)) => Pattern rep -> StmAux (ExpDec rep) -> Exp (Aliases rep) -> Stm (Aliases rep)
+ Futhark.IR.Aliases: mkAliasedLetStm :: (ASTRep rep, CanBeAliased (Op rep)) => Pat rep -> StmAux (ExpDec rep) -> Exp (Aliases rep) -> Stm (Aliases rep)
- Futhark.IR.Aliases: mkStmsAliases :: Aliased rep => Stms rep -> [SubExp] -> ([Names], Names)
+ Futhark.IR.Aliases: mkStmsAliases :: Aliased rep => Stms rep -> Result -> ([Names], Names)
- Futhark.IR.GPU: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
+ Futhark.IR.GPU: mkIdentityLambda :: (Buildable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
- Futhark.IR.GPU: nilFn :: Bindable rep => Lambda rep
+ Futhark.IR.GPU: nilFn :: Buildable rep => Lambda rep
- Futhark.IR.GPU: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
+ Futhark.IR.GPU: reduceSOAC :: (Buildable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
- Futhark.IR.GPU: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
+ Futhark.IR.GPU: scanSOAC :: (Buildable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
- Futhark.IR.GPU: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
+ Futhark.IR.GPU: singleReduce :: Buildable rep => [Reduce rep] -> Reduce rep
- Futhark.IR.GPU: singleScan :: Bindable rep => [Scan rep] -> Scan rep
+ Futhark.IR.GPU: singleScan :: Buildable rep => [Scan rep] -> Scan rep
- Futhark.IR.MC: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
+ Futhark.IR.MC: mkIdentityLambda :: (Buildable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
- Futhark.IR.MC: nilFn :: Bindable rep => Lambda rep
+ Futhark.IR.MC: nilFn :: Buildable rep => Lambda rep
- Futhark.IR.MC: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
+ Futhark.IR.MC: reduceSOAC :: (Buildable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
- Futhark.IR.MC: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
+ Futhark.IR.MC: scanSOAC :: (Buildable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
- Futhark.IR.MC: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
+ Futhark.IR.MC: singleReduce :: Buildable rep => [Reduce rep] -> Reduce rep
- Futhark.IR.MC: singleScan :: Bindable rep => [Scan rep] -> Scan rep
+ Futhark.IR.MC: singleScan :: Buildable rep => [Scan rep] -> Scan rep
- Futhark.IR.Mem: class TypedOp (Op rep) => OpReturns rep
+ Futhark.IR.Mem: class TypedOp op => OpReturns op
- Futhark.IR.Mem: expReturns :: (Monad m, LocalScope rep m, Mem rep) => Exp rep -> m [ExpReturns]
+ Futhark.IR.Mem: expReturns :: (Monad m, LocalScope rep m, Mem rep inner) => Exp rep -> m [ExpReturns]
- Futhark.IR.Mem: lookupArraySummary :: (Mem rep, HasScope rep m, Monad m) => VName -> m (VName, IxFun (TPrimExp Int64 VName))
+ Futhark.IR.Mem: lookupArraySummary :: (Mem rep inner, HasScope rep m, Monad m) => VName -> m (VName, IxFun (TPrimExp Int64 VName))
- Futhark.IR.Mem: lookupMemInfo :: (HasScope rep m, Mem rep) => VName -> m (MemInfo SubExp NoUniqueness MemBind)
+ Futhark.IR.Mem: lookupMemInfo :: (HasScope rep m, Mem rep inner) => VName -> m (MemInfo SubExp NoUniqueness MemBind)
- Futhark.IR.Mem: matchBranchReturnType :: (Mem rep, Checkable rep) => [BodyReturns] -> Body (Aliases rep) -> TypeM rep ()
+ Futhark.IR.Mem: matchBranchReturnType :: (Mem rep inner, Checkable rep) => [BodyReturns] -> Body (Aliases rep) -> TypeM rep ()
- Futhark.IR.Mem: matchFunctionReturnType :: (Mem rep, Checkable rep) => [FunReturns] -> Result -> TypeM rep ()
+ Futhark.IR.Mem: matchFunctionReturnType :: (Mem rep inner, Checkable rep) => [FunReturns] -> Result -> TypeM rep ()
- Futhark.IR.Mem: matchLoopResultMem :: (Mem rep, Checkable rep) => [FParam (Aliases rep)] -> [FParam (Aliases rep)] -> [SubExp] -> TypeM rep ()
+ Futhark.IR.Mem: matchLoopResultMem :: (Mem rep inner, Checkable rep) => [FParam (Aliases rep)] -> Result -> TypeM rep ()
- Futhark.IR.Mem: opReturns :: (OpReturns rep, Monad m, HasScope rep m) => Op rep -> m [ExpReturns]
+ Futhark.IR.Mem: opReturns :: (OpReturns op, Mem rep inner, Monad m, HasScope rep m) => op -> m [ExpReturns]
- Futhark.IR.Mem: subExpMemInfo :: (HasScope rep m, Monad m, Mem rep) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind)
+ Futhark.IR.Mem: subExpMemInfo :: (HasScope rep m, Monad m, Mem rep inner) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind)
- Futhark.IR.Mem: type Mem rep = (AllocOp (Op rep), FParamInfo rep ~ FParamMem, LParamInfo rep ~ LParamMem, LetDec rep ~ LetDecMem, RetType rep ~ RetTypeMem, BranchType rep ~ BranchTypeMem, ASTRep rep, OpReturns rep)
+ Futhark.IR.Mem: type Mem rep inner = (FParamInfo rep ~ FParamMem, LParamInfo rep ~ LParamMem, HasLetDecMem (LetDec rep), RetType rep ~ RetTypeMem, BranchType rep ~ BranchTypeMem, ASTRep rep, OpReturns inner, Op rep ~ MemOp inner)
- Futhark.IR.Mem: varReturns :: (HasScope rep m, Monad m, Mem rep) => VName -> m ExpReturns
+ Futhark.IR.Mem: varReturns :: (HasScope rep m, Monad m, Mem rep inner) => VName -> m ExpReturns
- Futhark.IR.Mem.Simplify: simpleGeneric :: (SimplifyMemory rep, Op rep ~ MemOp inner) => (OpWithWisdom inner -> UsageTable) -> SimplifyOp rep inner -> SimpleOps rep
+ Futhark.IR.Mem.Simplify: simpleGeneric :: SimplifyMemory rep inner => (OpWithWisdom inner -> UsageTable) -> SimplifyOp rep inner -> SimpleOps rep
- Futhark.IR.Mem.Simplify: simplifyProgGeneric :: (SimplifyMemory rep, Op rep ~ MemOp inner) => SimpleOps rep -> Prog rep -> PassM (Prog rep)
+ Futhark.IR.Mem.Simplify: simplifyProgGeneric :: SimplifyMemory rep inner => SimpleOps rep -> Prog rep -> PassM (Prog rep)
- Futhark.IR.Mem.Simplify: simplifyStmsGeneric :: (HasScope rep m, MonadFreshNames m, SimplifyMemory rep, Op rep ~ MemOp inner) => SimpleOps rep -> Stms rep -> m (SymbolTable (Wise rep), Stms rep)
+ Futhark.IR.Mem.Simplify: simplifyStmsGeneric :: (HasScope rep m, MonadFreshNames m, SimplifyMemory rep inner) => SimpleOps rep -> Stms rep -> m (SymbolTable (Wise rep), Stms rep)
- Futhark.IR.Mem.Simplify: type SimplifyMemory rep = (SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (), AllocOp (Op (Wise rep)), CanBeWise (Op rep), BinderOps (Wise rep), Mem rep)
+ Futhark.IR.Mem.Simplify: type SimplifyMemory rep inner = (SimplifiableRep rep, LetDec rep ~ LetDecMem, ExpDec rep ~ (), BodyDec rep ~ (), CanBeWise (Op rep), BuilderOps (Wise rep), Mem rep inner)
- Futhark.IR.Prop: certify :: Certificates -> Stm rep -> Stm rep
+ Futhark.IR.Prop: certify :: Certs -> Stm rep -> Stm rep
- Futhark.IR.Prop: stmCerts :: Stm rep -> Certificates
+ Futhark.IR.Prop: stmCerts :: Stm rep -> Certs
- Futhark.IR.SOACS: DoLoop :: [(FParam rep, SubExp)] -> [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
+ Futhark.IR.SOACS: DoLoop :: [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
- Futhark.IR.SOACS: Opaque :: SubExp -> BasicOp
+ Futhark.IR.SOACS: Opaque :: OpaqueOp -> SubExp -> BasicOp
- Futhark.IR.SOACS: StmAux :: !Certificates -> Attrs -> dec -> StmAux dec
+ Futhark.IR.SOACS: StmAux :: !Certs -> Attrs -> dec -> StmAux dec
- Futhark.IR.SOACS: Update :: VName -> Slice SubExp -> SubExp -> BasicOp
+ Futhark.IR.SOACS: Update :: Safety -> VName -> Slice SubExp -> SubExp -> BasicOp
- Futhark.IR.SOACS: [stmAuxCerts] :: StmAux dec -> !Certificates
+ Futhark.IR.SOACS: [stmAuxCerts] :: StmAux dec -> !Certs
- Futhark.IR.SOACS: type Result = [SubExp]
+ Futhark.IR.SOACS: type Result = [SubExpRes]
- Futhark.IR.SOACS.SOAC: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
+ Futhark.IR.SOACS.SOAC: mkIdentityLambda :: (Buildable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
- Futhark.IR.SOACS.SOAC: nilFn :: Bindable rep => Lambda rep
+ Futhark.IR.SOACS.SOAC: nilFn :: Buildable rep => Lambda rep
- Futhark.IR.SOACS.SOAC: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
+ Futhark.IR.SOACS.SOAC: reduceSOAC :: (Buildable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
- Futhark.IR.SOACS.SOAC: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
+ Futhark.IR.SOACS.SOAC: scanSOAC :: (Buildable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
- Futhark.IR.SOACS.SOAC: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
+ Futhark.IR.SOACS.SOAC: singleReduce :: Buildable rep => [Reduce rep] -> Reduce rep
- Futhark.IR.SOACS.SOAC: singleScan :: Bindable rep => [Scan rep] -> Scan rep
+ Futhark.IR.SOACS.SOAC: singleScan :: Buildable rep => [Scan rep] -> Scan rep
- Futhark.IR.SOACS.Simplify: liftIdentityMapping :: forall rep. (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
+ Futhark.IR.SOACS.Simplify: liftIdentityMapping :: forall rep. (Buildable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SOACS.Simplify: removeReplicateMapping :: (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
+ Futhark.IR.SOACS.Simplify: removeReplicateMapping :: (Buildable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SOACS.Simplify: simplifyKnownIterationSOAC :: (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
+ Futhark.IR.SOACS.Simplify: simplifyKnownIterationSOAC :: (Buildable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SegOp: ConcatReturns :: SplitOrdering -> SubExp -> SubExp -> VName -> KernelResult
+ Futhark.IR.SegOp: ConcatReturns :: Certs -> SplitOrdering -> SubExp -> SubExp -> VName -> KernelResult
- Futhark.IR.SegOp: RegTileReturns :: [(SubExp, SubExp, SubExp)] -> VName -> KernelResult
+ Futhark.IR.SegOp: RegTileReturns :: Certs -> [(SubExp, SubExp, SubExp)] -> VName -> KernelResult
- Futhark.IR.SegOp: Returns :: ResultManifest -> SubExp -> KernelResult
+ Futhark.IR.SegOp: Returns :: ResultManifest -> Certs -> SubExp -> KernelResult
- Futhark.IR.SegOp: TileReturns :: [(SubExp, SubExp)] -> VName -> KernelResult
+ Futhark.IR.SegOp: TileReturns :: Certs -> [(SubExp, SubExp)] -> VName -> KernelResult
- Futhark.IR.SegOp: WriteReturns :: Shape -> VName -> [(Slice SubExp, SubExp)] -> KernelResult
+ Futhark.IR.SegOp: WriteReturns :: Certs -> Shape -> VName -> [(Slice SubExp, SubExp)] -> KernelResult
- Futhark.IR.SegOp: segOpReturns :: (Mem rep, Monad m, HasScope rep m) => SegOp lvl rep -> m [ExpReturns]
+ Futhark.IR.SegOp: segOpReturns :: (Mem rep inner, Monad m, HasScope rep m) => SegOp lvl somerep -> m [ExpReturns]
- Futhark.IR.SegOp: segOpRules :: (HasSegOp rep, BinderOps rep, Bindable rep) => RuleBook rep
+ Futhark.IR.SegOp: segOpRules :: (HasSegOp rep, BuilderOps rep, Buildable rep) => RuleBook rep
- Futhark.IR.Syntax: DoLoop :: [(FParam rep, SubExp)] -> [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
+ Futhark.IR.Syntax: DoLoop :: [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
- Futhark.IR.Syntax: Let :: Pattern rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
+ Futhark.IR.Syntax: Let :: Pat rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
- Futhark.IR.Syntax: Opaque :: SubExp -> BasicOp
+ Futhark.IR.Syntax: Opaque :: OpaqueOp -> SubExp -> BasicOp
- Futhark.IR.Syntax: StmAux :: !Certificates -> Attrs -> dec -> StmAux dec
+ Futhark.IR.Syntax: StmAux :: !Certs -> Attrs -> dec -> StmAux dec
- Futhark.IR.Syntax: Update :: VName -> Slice SubExp -> SubExp -> BasicOp
+ Futhark.IR.Syntax: Update :: Safety -> VName -> Slice SubExp -> SubExp -> BasicOp
- Futhark.IR.Syntax: [stmAuxCerts] :: StmAux dec -> !Certificates
+ Futhark.IR.Syntax: [stmAuxCerts] :: StmAux dec -> !Certs
- Futhark.IR.Syntax: type Result = [SubExp]
+ Futhark.IR.Syntax: type Result = [SubExpRes]
- Futhark.Internalise.Bindings: bindingFParams :: [TypeParam] -> [Pattern] -> ([FParam] -> [[FParam]] -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.Bindings: bindingFParams :: [TypeParam] -> [Pat] -> ([FParam] -> [[FParam]] -> InternaliseM a) -> InternaliseM a
- Futhark.Internalise.Bindings: bindingLambdaParams :: [Pattern] -> [Type] -> ([LParam] -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.Bindings: bindingLambdaParams :: [Pat] -> [Type] -> ([LParam] -> InternaliseM a) -> InternaliseM a
- Futhark.Internalise.Bindings: bindingLoopParams :: [TypeParam] -> Pattern -> [Type] -> ([FParam] -> [FParam] -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.Bindings: bindingLoopParams :: [TypeParam] -> Pat -> [Type] -> ([FParam] -> [FParam] -> InternaliseM a) -> InternaliseM a
- Futhark.Internalise.Monad: InternaliseEnv :: VarSubstitutions -> Bool -> Bool -> Attrs -> InternaliseEnv
+ Futhark.Internalise.Monad: InternaliseEnv :: VarSubsts -> Bool -> Bool -> Attrs -> InternaliseEnv
- Futhark.Internalise.Monad: [envSubsts] :: InternaliseEnv -> VarSubstitutions
+ Futhark.Internalise.Monad: [envSubsts] :: InternaliseEnv -> VarSubsts
- Futhark.Internalise.Monad: assert :: String -> SubExp -> ErrorMsg SubExp -> SrcLoc -> InternaliseM Certificates
+ Futhark.Internalise.Monad: assert :: String -> SubExp -> ErrorMsg SubExp -> SrcLoc -> InternaliseM Certs
- Futhark.Internalise.Monad: substitutingVars :: VarSubstitutions -> InternaliseM a -> InternaliseM a
+ Futhark.Internalise.Monad: substitutingVars :: VarSubsts -> InternaliseM a -> InternaliseM a
- Futhark.Optimise.Fusion.Composing: fuseMaps :: Bindable rep => Names -> Lambda rep -> [Input] -> [(VName, Ident)] -> Lambda rep -> [Input] -> (Lambda rep, [Input])
+ Futhark.Optimise.Fusion.Composing: fuseMaps :: Buildable rep => Names -> Lambda rep -> [Input] -> [(VName, Ident)] -> Lambda rep -> [Input] -> (Lambda rep, [Input])
- Futhark.Optimise.Fusion.Composing: fuseRedomap :: Bindable rep => Names -> [VName] -> Lambda rep -> [SubExp] -> [SubExp] -> [Input] -> [(VName, Ident)] -> Lambda rep -> [SubExp] -> [SubExp] -> [Input] -> (Lambda rep, [Input])
+ Futhark.Optimise.Fusion.Composing: fuseRedomap :: Buildable rep => Names -> [VName] -> Lambda rep -> [SubExp] -> [SubExp] -> [Input] -> [(VName, Ident)] -> Lambda rep -> [SubExp] -> [SubExp] -> [Input] -> (Lambda rep, [Input])
- Futhark.Optimise.Fusion.LoopKernel: transformOutput :: ArrayTransforms -> [VName] -> [Ident] -> Binder SOACS ()
+ Futhark.Optimise.Fusion.LoopKernel: transformOutput :: ArrayTransforms -> [VName] -> [Ident] -> Builder SOACS ()
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: DesiredUpdate :: VName -> dec -> Certificates -> VName -> Slice SubExp -> VName -> DesiredUpdate dec
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: DesiredUpdate :: VName -> dec -> Certs -> VName -> Slice SubExp -> VName -> DesiredUpdate dec
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdate :: (MonadFreshNames m, Bindable rep, LetDec rep ~ Type, CanBeAliased (Op rep)) => LowerUpdate rep m
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdate :: (MonadFreshNames m, Buildable rep, LetDec rep ~ Type, CanBeAliased (Op rep)) => LowerUpdate rep m
- Futhark.Optimise.InPlaceLowering.SubstituteIndices: substituteIndices :: (MonadFreshNames m, BinderOps rep, Bindable rep, Aliased rep, LetDec rep ~ dec) => IndexSubstitutions dec -> Stms rep -> m (IndexSubstitutions dec, Stms rep)
+ Futhark.Optimise.InPlaceLowering.SubstituteIndices: substituteIndices :: (MonadFreshNames m, BuilderOps rep, Buildable rep, Aliased rep, LetDec rep ~ dec) => IndexSubstitutions dec -> Stms rep -> m (IndexSubstitutions dec, Stms rep)
- Futhark.Optimise.InPlaceLowering.SubstituteIndices: type IndexSubstitution dec = (Certificates, VName, dec, Slice SubExp)
+ Futhark.Optimise.InPlaceLowering.SubstituteIndices: type IndexSubstitution dec = (Certs, VName, dec, Slice SubExp)
- Futhark.Optimise.Simplify: SimpleOps :: (SymbolTable (Wise rep) -> Pattern (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))) -> (SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))) -> Protect (Binder (Wise rep)) -> (Op (Wise rep) -> UsageTable) -> SimplifyOp rep (Op rep) -> SimpleOps rep
+ Futhark.Optimise.Simplify: SimpleOps :: (SymbolTable (Wise rep) -> Pat (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))) -> (SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))) -> Protect (Builder (Wise rep)) -> (Op (Wise rep) -> UsageTable) -> SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify: [mkExpDecS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Pattern (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))
+ Futhark.Optimise.Simplify: [mkExpDecS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Pat (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))
- Futhark.Optimise.Simplify: [protectHoistedOpS] :: SimpleOps rep -> Protect (Binder (Wise rep))
+ Futhark.Optimise.Simplify: [protectHoistedOpS] :: SimpleOps rep -> Protect (Builder (Wise rep))
- Futhark.Optimise.Simplify: bindableSimpleOps :: (SimplifiableRep rep, Bindable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
+ Futhark.Optimise.Simplify: bindableSimpleOps :: (SimplifiableRep rep, Buildable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify: type SimplifiableRep rep = (ASTRep rep, Simplifiable (LetDec rep), Simplifiable (FParamInfo rep), Simplifiable (LParamInfo rep), Simplifiable (RetType rep), Simplifiable (BranchType rep), CanBeWise (Op rep), IndexOp (OpWithWisdom (Op rep)), BinderOps (Wise rep), IsOp (Op rep))
+ Futhark.Optimise.Simplify: type SimplifiableRep rep = (ASTRep rep, Simplifiable (LetDec rep), Simplifiable (FParamInfo rep), Simplifiable (LParamInfo rep), Simplifiable (RetType rep), Simplifiable (BranchType rep), CanBeWise (Op rep), IndexOp (OpWithWisdom (Op rep)), BuilderOps (Wise rep), IsOp (Op rep))
- Futhark.Optimise.Simplify.Engine: SimpleOps :: (SymbolTable (Wise rep) -> Pattern (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))) -> (SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))) -> Protect (Binder (Wise rep)) -> (Op (Wise rep) -> UsageTable) -> SimplifyOp rep (Op rep) -> SimpleOps rep
+ Futhark.Optimise.Simplify.Engine: SimpleOps :: (SymbolTable (Wise rep) -> Pat (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))) -> (SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))) -> Protect (Builder (Wise rep)) -> (Op (Wise rep) -> UsageTable) -> SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify.Engine: [mkExpDecS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Pattern (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))
+ Futhark.Optimise.Simplify.Engine: [mkExpDecS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Pat (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))
- Futhark.Optimise.Simplify.Engine: [protectHoistedOpS] :: SimpleOps rep -> Protect (Binder (Wise rep))
+ Futhark.Optimise.Simplify.Engine: [protectHoistedOpS] :: SimpleOps rep -> Protect (Builder (Wise rep))
- Futhark.Optimise.Simplify.Engine: bindableSimpleOps :: (SimplifiableRep rep, Bindable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
+ Futhark.Optimise.Simplify.Engine: bindableSimpleOps :: (SimplifiableRep rep, Buildable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify.Engine: type SimplifiableRep rep = (ASTRep rep, Simplifiable (LetDec rep), Simplifiable (FParamInfo rep), Simplifiable (LParamInfo rep), Simplifiable (RetType rep), Simplifiable (BranchType rep), CanBeWise (Op rep), IndexOp (OpWithWisdom (Op rep)), BinderOps (Wise rep), IsOp (Op rep))
+ Futhark.Optimise.Simplify.Engine: type SimplifiableRep rep = (ASTRep rep, Simplifiable (LetDec rep), Simplifiable (FParamInfo rep), Simplifiable (LParamInfo rep), Simplifiable (RetType rep), Simplifiable (BranchType rep), CanBeWise (Op rep), IndexOp (OpWithWisdom (Op rep)), BuilderOps (Wise rep), IsOp (Op rep))
- Futhark.Optimise.Simplify.Rep: mkWiseExpDec :: (ASTRep rep, CanBeWise (Op rep)) => Pattern (Wise rep) -> ExpDec rep -> Exp (Wise rep) -> ExpDec (Wise rep)
+ Futhark.Optimise.Simplify.Rep: mkWiseExpDec :: (ASTRep rep, CanBeWise (Op rep)) => Pat (Wise rep) -> ExpDec rep -> Exp (Wise rep) -> ExpDec (Wise rep)
- Futhark.Optimise.Simplify.Rep: mkWiseLetStm :: (ASTRep rep, CanBeWise (Op rep)) => Pattern rep -> StmAux (ExpDec rep) -> Exp (Wise rep) -> Stm (Wise rep)
+ Futhark.Optimise.Simplify.Rep: mkWiseLetStm :: (ASTRep rep, CanBeWise (Op rep)) => Pat rep -> StmAux (ExpDec rep) -> Exp (Wise rep) -> Stm (Wise rep)
- Futhark.Optimise.Simplify.Rule: type RuleBasicOp rep a = (a -> Pattern rep -> StmAux (ExpDec rep) -> BasicOp -> Rule rep)
+ Futhark.Optimise.Simplify.Rule: type RuleBasicOp rep a = (a -> Pat rep -> StmAux (ExpDec rep) -> BasicOp -> Rule rep)
- Futhark.Optimise.Simplify.Rule: type RuleDoLoop rep a = a -> Pattern rep -> StmAux (ExpDec rep) -> ([(FParam rep, SubExp)], [(FParam rep, SubExp)], LoopForm rep, BodyT rep) -> Rule rep
+ Futhark.Optimise.Simplify.Rule: type RuleDoLoop rep a = a -> Pat rep -> StmAux (ExpDec rep) -> ([(FParam rep, SubExp)], LoopForm rep, BodyT rep) -> Rule rep
- Futhark.Optimise.Simplify.Rule: type RuleIf rep a = a -> Pattern rep -> StmAux (ExpDec rep) -> (SubExp, BodyT rep, BodyT rep, IfDec (BranchType rep)) -> Rule rep
+ Futhark.Optimise.Simplify.Rule: type RuleIf rep a = a -> Pat rep -> StmAux (ExpDec rep) -> (SubExp, BodyT rep, BodyT rep, IfDec (BranchType rep)) -> Rule rep
- Futhark.Optimise.Simplify.Rules: removeUnnecessaryCopy :: (BinderOps rep, Aliased rep) => BottomUpRuleBasicOp rep
+ Futhark.Optimise.Simplify.Rules: removeUnnecessaryCopy :: (BuilderOps rep, Aliased rep) => BottomUpRuleBasicOp rep
- Futhark.Optimise.Simplify.Rules: standardRules :: (BinderOps rep, Aliased rep) => RuleBook rep
+ Futhark.Optimise.Simplify.Rules: standardRules :: (BuilderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.BasicOp: basicOpRules :: (BinderOps rep, Aliased rep) => RuleBook rep
+ Futhark.Optimise.Simplify.Rules.BasicOp: basicOpRules :: (BuilderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.ClosedForm: foldClosedForm :: (ASTRep rep, BinderOps rep) => VarLookup rep -> Pattern rep -> Lambda rep -> [SubExp] -> [VName] -> RuleM rep ()
+ Futhark.Optimise.Simplify.Rules.ClosedForm: foldClosedForm :: (ASTRep rep, BuilderOps rep) => VarLookup rep -> Pat rep -> Lambda rep -> [SubExp] -> [VName] -> RuleM rep ()
- Futhark.Optimise.Simplify.Rules.ClosedForm: loopClosedForm :: (ASTRep rep, BinderOps rep) => Pattern rep -> [(FParam rep, SubExp)] -> Names -> IntType -> SubExp -> Body rep -> RuleM rep ()
+ Futhark.Optimise.Simplify.Rules.ClosedForm: loopClosedForm :: (ASTRep rep, BuilderOps rep) => Pat rep -> [(FParam rep, SubExp)] -> Names -> IntType -> SubExp -> Body rep -> RuleM rep ()
- Futhark.Optimise.Simplify.Rules.Index: IndexResult :: Certificates -> VName -> Slice SubExp -> IndexResult
+ Futhark.Optimise.Simplify.Rules.Index: IndexResult :: Certs -> VName -> Slice SubExp -> IndexResult
- Futhark.Optimise.Simplify.Rules.Index: SubExpResult :: Certificates -> SubExp -> IndexResult
+ Futhark.Optimise.Simplify.Rules.Index: SubExpResult :: Certs -> SubExp -> IndexResult
- Futhark.Optimise.Simplify.Rules.Index: simplifyIndexing :: MonadBinder m => SymbolTable (Rep m) -> TypeLookup -> VName -> Slice SubExp -> Bool -> Maybe (m IndexResult)
+ Futhark.Optimise.Simplify.Rules.Index: simplifyIndexing :: MonadBuilder m => SymbolTable (Rep m) -> TypeLookup -> VName -> Slice SubExp -> Bool -> Maybe (m IndexResult)
- Futhark.Optimise.Simplify.Rules.Loop: loopRules :: (BinderOps rep, Aliased rep) => RuleBook rep
+ Futhark.Optimise.Simplify.Rules.Loop: loopRules :: (BuilderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.Simple: applySimpleRules :: VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)
+ Futhark.Optimise.Simplify.Rules.Simple: applySimpleRules :: VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certs)
- Futhark.Optimise.Simplify.Rules.Simple: type VarLookup rep = VName -> Maybe (Exp rep, Certificates)
+ Futhark.Optimise.Simplify.Rules.Simple: type VarLookup rep = VName -> Maybe (Exp rep, Certs)
- Futhark.Optimise.TileLoops.Shared: segMap1D :: String -> SegLevel -> ResultManifest -> (VName -> Binder GPU [SubExp]) -> Binder GPU [VName]
+ Futhark.Optimise.TileLoops.Shared: segMap1D :: String -> SegLevel -> ResultManifest -> (VName -> Builder GPU Result) -> Builder GPU [VName]
- Futhark.Optimise.TileLoops.Shared: segMap2D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp) -> ((VName, VName) -> Binder GPU [SubExp]) -> Binder GPU [VName]
+ Futhark.Optimise.TileLoops.Shared: segMap2D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp) -> ((VName, VName) -> Builder GPU Result) -> Builder GPU [VName]
- Futhark.Optimise.TileLoops.Shared: segMap3D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp, SubExp) -> ((VName, VName, VName) -> Binder GPU [SubExp]) -> Binder GPU [VName]
+ Futhark.Optimise.TileLoops.Shared: segMap3D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp, SubExp) -> ((VName, VName, VName) -> Builder GPU Result) -> Builder GPU [VName]
- Futhark.Optimise.TileLoops.Shared: segScatter2D :: String -> SubExp -> VName -> SegLevel -> (SubExp, SubExp) -> ((VName, VName) -> Binder GPU (SubExp, SubExp)) -> Binder GPU [VName]
+ Futhark.Optimise.TileLoops.Shared: segScatter2D :: String -> SubExp -> VName -> SegLevel -> (SubExp, SubExp) -> ((VName, VName) -> Builder GPU (SubExp, SubExp)) -> Builder GPU [VName]
- Futhark.Pass.ExplicitAllocations: allocForArray :: Allocator rep m => Type -> Space -> m VName
+ Futhark.Pass.ExplicitAllocations: allocForArray :: Allocable fromrep torep inner => Type -> Space -> AllocM fromrep torep VName
- Futhark.Pass.ExplicitAllocations: allocInStms :: Allocable fromrep torep => Stms fromrep -> AllocM fromrep torep a -> AllocM fromrep torep a
+ Futhark.Pass.ExplicitAllocations: allocInStms :: Allocable fromrep torep inner => Stms fromrep -> AllocM fromrep torep a -> AllocM fromrep torep a
- Futhark.Pass.ExplicitAllocations: dimAllocationSize :: (Allocator rep m, m ~ AllocM fromrep rep) => SubExp -> m SubExp
+ Futhark.Pass.ExplicitAllocations: dimAllocationSize :: ChunkMap -> SubExp -> SubExp
- Futhark.Pass.ExplicitAllocations: explicitAllocationsGeneric :: (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> Pass fromrep torep
+ Futhark.Pass.ExplicitAllocations: explicitAllocationsGeneric :: Allocable fromrep torep inner => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> Pass fromrep torep
- Futhark.Pass.ExplicitAllocations: explicitAllocationsInStmsGeneric :: (MonadFreshNames m, HasScope torep m, Allocable fromrep torep) => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> Stms fromrep -> m (Stms torep)
+ Futhark.Pass.ExplicitAllocations: explicitAllocationsInStmsGeneric :: (MonadFreshNames m, HasScope torep m, Allocable fromrep torep inner) => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> Stms fromrep -> m (Stms torep)
- Futhark.Pass.ExplicitAllocations: mkLetNamesB' :: (Op (Rep m) ~ MemOp inner, MonadBinder m, ExpDec (Rep m) ~ (), Allocator (Rep m) (PatAllocM (Rep m))) => ExpDec (Rep m) -> [VName] -> Exp (Rep m) -> m (Stm (Rep m))
+ Futhark.Pass.ExplicitAllocations: mkLetNamesB' :: (LetDec (Rep m) ~ LetDecMem, Mem (Rep m) inner, MonadBuilder m, ExpDec (Rep m) ~ ()) => ExpDec (Rep m) -> [VName] -> Exp (Rep m) -> m (Stm (Rep m))
- Futhark.Pass.ExplicitAllocations: mkLetNamesB'' :: (Op (Rep m) ~ MemOp inner, ExpDec rep ~ (), HasScope (Wise rep) m, Allocator rep (PatAllocM rep), MonadBinder m, CanBeWise (Op rep)) => [VName] -> Exp (Wise rep) -> m (Stm (Wise rep))
+ Futhark.Pass.ExplicitAllocations: mkLetNamesB'' :: (BuilderOps rep, Mem rep inner, LetDec rep ~ LetDecMem, OpReturns (OpWithWisdom inner), ExpDec rep ~ (), Rep m ~ Wise rep, HasScope (Wise rep) m, MonadBuilder m, CanBeWise inner) => [VName] -> Exp (Wise rep) -> m (Stm (Wise rep))
- Futhark.Pass.ExplicitAllocations: opSizeSubst :: SizeSubst op => PatternT dec -> op -> ChunkMap
+ Futhark.Pass.ExplicitAllocations: opSizeSubst :: SizeSubst op => PatT dec -> op -> ChunkMap
- Futhark.Pass.ExplicitAllocations: simplifiable :: (SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (), Op rep ~ MemOp inner, Allocator rep (PatAllocM rep)) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM rep (OpWithWisdom inner, Stms (Wise rep))) -> SimpleOps rep
+ Futhark.Pass.ExplicitAllocations: simplifiable :: (SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (), Mem rep inner) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM rep (OpWithWisdom inner, Stms (Wise rep))) -> SimpleOps rep
- Futhark.Pass.ExplicitAllocations: type Allocable fromrep torep = (PrettyRep fromrep, PrettyRep torep, Mem torep, FParamInfo fromrep ~ DeclType, LParamInfo fromrep ~ Type, BranchType fromrep ~ ExtType, RetType fromrep ~ DeclExtType, BodyDec fromrep ~ (), BodyDec torep ~ (), ExpDec torep ~ (), SizeSubst (Op torep), BinderOps torep)
+ Futhark.Pass.ExplicitAllocations: type Allocable fromrep torep inner = (PrettyRep fromrep, PrettyRep torep, Mem torep inner, LetDec torep ~ LetDecMem, FParamInfo fromrep ~ DeclType, LParamInfo fromrep ~ Type, BranchType fromrep ~ ExtType, RetType fromrep ~ DeclExtType, BodyDec fromrep ~ (), BodyDec torep ~ (), ExpDec torep ~ (), SizeSubst inner, BuilderOps torep)
- Futhark.Pass.ExplicitAllocations.SegOp: allocInBinOpLambda :: Allocable fromrep torep => SubExp -> SegSpace -> Lambda fromrep -> AllocM fromrep torep (Lambda torep)
+ Futhark.Pass.ExplicitAllocations.SegOp: allocInBinOpLambda :: Allocable fromrep torep inner => SubExp -> SegSpace -> Lambda fromrep -> AllocM fromrep torep (Lambda torep)
- Futhark.Pass.ExplicitAllocations.SegOp: allocInKernelBody :: Allocable fromrep torep => KernelBody fromrep -> AllocM fromrep torep (KernelBody torep)
+ Futhark.Pass.ExplicitAllocations.SegOp: allocInKernelBody :: Allocable fromrep torep inner => KernelBody fromrep -> AllocM fromrep torep (KernelBody torep)
- Futhark.Pass.ExplicitAllocations.Seq: simplifiable :: (SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (), Op rep ~ MemOp inner, Allocator rep (PatAllocM rep)) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM rep (OpWithWisdom inner, Stms (Wise rep))) -> SimpleOps rep
+ Futhark.Pass.ExplicitAllocations.Seq: simplifiable :: (SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (), Mem rep inner) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM rep (OpWithWisdom inner, Stms (Wise rep))) -> SimpleOps rep
- Futhark.Pass.ExtractKernels.BlockedKernel: dummyDim :: (MonadFreshNames m, MonadBinder m, DistRep (Rep m)) => Pattern (Rep m) -> m (Pattern (Rep m), [(VName, SubExp)], m ())
+ Futhark.Pass.ExtractKernels.BlockedKernel: dummyDim :: (MonadFreshNames m, MonadBuilder m, DistRep (Rep m)) => Pat (Rep m) -> m (Pat (Rep m), [(VName, SubExp)], m ())
- Futhark.Pass.ExtractKernels.BlockedKernel: nonSegRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pattern rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> m (Stms rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: nonSegRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pat rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> m (Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: readKernelInput :: (DistRep (Rep m), MonadBinder m) => KernelInput -> m ()
+ Futhark.Pass.ExtractKernels.BlockedKernel: readKernelInput :: (DistRep (Rep m), MonadBuilder m) => KernelInput -> m ()
- Futhark.Pass.ExtractKernels.BlockedKernel: segHist :: (DistRep rep, MonadFreshNames m, HasScope rep m) => SegOpLevel rep -> Pattern rep -> SubExp -> [(VName, SubExp)] -> [KernelInput] -> [HistOp rep] -> Lambda rep -> [VName] -> m (Stms rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: segHist :: (DistRep rep, MonadFreshNames m, HasScope rep m) => SegOpLevel rep -> Pat rep -> SubExp -> [(VName, SubExp)] -> [KernelInput] -> [HistOp rep] -> Lambda rep -> [VName] -> m (Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: segMap :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pattern rep -> SubExp -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: segMap :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pat rep -> SubExp -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: segRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pattern rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: segRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pat rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: segScan :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pattern rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: segScan :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep -> Pat rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: type DistRep rep = (Bindable rep, HasSegOp rep, BinderOps rep, LetDec rep ~ Type, ExpDec rep ~ (), BodyDec rep ~ (), CanBeAliased (Op rep))
+ Futhark.Pass.ExtractKernels.BlockedKernel: type DistRep rep = (Buildable rep, HasSegOp rep, BuilderOps rep, LetDec rep ~ Type, ExpDec rep ~ (), BodyDec rep ~ (), CanBeAliased (Op rep))
- Futhark.Pass.ExtractKernels.BlockedKernel: type MkSegLevel rep m = [SubExp] -> String -> ThreadRecommendation -> BinderT rep m (SegOpLevel rep)
+ Futhark.Pass.ExtractKernels.BlockedKernel: type MkSegLevel rep m = [SubExp] -> String -> ThreadRecommendation -> BuilderT rep m (SegOpLevel rep)
- Futhark.Pass.ExtractKernels.DistributeNests: DistEnv :: Nestings -> Scope rep -> (Stms SOACS -> DistNestT rep m (Stms rep)) -> (MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep)) -> (Stm SOACS -> Binder rep (Stms rep)) -> (Lambda SOACS -> Binder rep (Lambda rep)) -> MkSegLevel rep m -> DistEnv rep m
+ Futhark.Pass.ExtractKernels.DistributeNests: DistEnv :: Nestings -> Scope rep -> (Stms SOACS -> DistNestT rep m (Stms rep)) -> (MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep)) -> (Stm SOACS -> Builder rep (Stms rep)) -> (Lambda SOACS -> Builder rep (Lambda rep)) -> MkSegLevel rep m -> DistEnv rep m
- Futhark.Pass.ExtractKernels.DistributeNests: MapLoop :: Pattern -> StmAux () -> SubExp -> Lambda -> [VName] -> MapLoop
+ Futhark.Pass.ExtractKernels.DistributeNests: MapLoop :: Pat -> StmAux () -> SubExp -> Lambda -> [VName] -> MapLoop
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSLambda] :: DistEnv rep m -> Lambda SOACS -> Binder rep (Lambda rep)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSLambda] :: DistEnv rep m -> Lambda SOACS -> Builder rep (Lambda rep)
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSStms] :: DistEnv rep m -> Stm SOACS -> Binder rep (Stms rep)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSStms] :: DistEnv rep m -> Stm SOACS -> Builder rep (Stms rep)
- Futhark.Pass.ExtractKernels.DistributeNests: determineReduceOp :: MonadBinder m => Lambda SOACS -> [SubExp] -> m (Lambda SOACS, [SubExp], Shape)
+ Futhark.Pass.ExtractKernels.DistributeNests: determineReduceOp :: MonadBuilder m => Lambda SOACS -> [SubExp] -> m (Lambda SOACS, [SubExp], Shape)
- Futhark.Pass.ExtractKernels.DistributeNests: histKernel :: (MonadBinder m, DistRep (Rep m)) => (Lambda SOACS -> m (Lambda (Rep m))) -> SegOpLevel (Rep m) -> PatternT Type -> [(VName, SubExp)] -> [KernelInput] -> Certificates -> SubExp -> [HistOp SOACS] -> Lambda (Rep m) -> [VName] -> m (Stms (Rep m))
+ Futhark.Pass.ExtractKernels.DistributeNests: histKernel :: (MonadBuilder m, DistRep (Rep m)) => (Lambda SOACS -> m (Lambda (Rep m))) -> SegOpLevel (Rep m) -> PatT Type -> [(VName, SubExp)] -> [KernelInput] -> Certs -> SubExp -> [HistOp SOACS] -> Lambda (Rep m) -> [VName] -> m (Stms (Rep m))
- Futhark.Pass.ExtractKernels.DistributeNests: permutationAndMissing :: PatternT Type -> [SubExp] -> Maybe ([Int], [PatElemT Type])
+ Futhark.Pass.ExtractKernels.DistributeNests: permutationAndMissing :: PatT Type -> Result -> Maybe ([Int], [PatElemT Type])
- Futhark.Pass.ExtractKernels.Distribution: MapNesting :: PatternT Type -> StmAux () -> SubExp -> [(Param Type, VName)] -> LoopNesting
+ Futhark.Pass.ExtractKernels.Distribution: MapNesting :: PatT Type -> StmAux () -> SubExp -> [(Param Type, VName)] -> LoopNesting
- Futhark.Pass.ExtractKernels.Distribution: type Target = (PatternT Type, Result)
+ Futhark.Pass.ExtractKernels.Distribution: type Target = (PatT Type, Result)
- Futhark.Pass.ExtractKernels.ISRWIM: irwim :: (MonadBinder m, Rep m ~ SOACS) => Pattern -> SubExp -> Commutativity -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
+ Futhark.Pass.ExtractKernels.ISRWIM: irwim :: (MonadBuilder m, Rep m ~ SOACS) => Pat -> SubExp -> Commutativity -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
- Futhark.Pass.ExtractKernels.ISRWIM: iswim :: (MonadBinder m, Rep m ~ SOACS) => Pattern -> SubExp -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
+ Futhark.Pass.ExtractKernels.ISRWIM: iswim :: (MonadBuilder m, Rep m ~ SOACS) => Pat -> SubExp -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
- Futhark.Pass.ExtractKernels.ISRWIM: rwimPossible :: Lambda -> Maybe (Pattern, Certificates, SubExp, Lambda)
+ Futhark.Pass.ExtractKernels.ISRWIM: rwimPossible :: Lambda -> Maybe (Pat, Certs, SubExp, Lambda)
- Futhark.Pass.ExtractKernels.Interchange: Branch :: [Int] -> Pattern -> SubExp -> Body -> Body -> IfDec (BranchType SOACS) -> Branch
+ Futhark.Pass.ExtractKernels.Interchange: Branch :: [Int] -> Pat -> SubExp -> Body -> Body -> IfDec (BranchType SOACS) -> Branch
- Futhark.Pass.ExtractKernels.Interchange: SeqLoop :: [Int] -> Pattern -> [(FParam, SubExp)] -> LoopForm SOACS -> Body -> SeqLoop
+ Futhark.Pass.ExtractKernels.Interchange: SeqLoop :: [Int] -> Pat -> [(FParam, SubExp)] -> LoopForm SOACS -> Body -> SeqLoop
- Futhark.Pass.ExtractKernels.Interchange: WithAccStm :: [Int] -> Pattern -> [(Shape, [VName], Maybe (Lambda, [SubExp]))] -> Lambda -> WithAccStm
+ Futhark.Pass.ExtractKernels.Interchange: WithAccStm :: [Int] -> Pat -> [(Shape, [VName], Maybe (Lambda, [SubExp]))] -> Lambda -> WithAccStm
- Futhark.Pass.ExtractKernels.StreamKernel: streamRed :: (MonadFreshNames m, HasScope GPU m) => MkSegLevel GPU m -> Pattern GPU -> SubExp -> Commutativity -> Lambda GPU -> Lambda GPU -> [SubExp] -> [VName] -> m (Stms GPU)
+ Futhark.Pass.ExtractKernels.StreamKernel: streamRed :: (MonadFreshNames m, HasScope GPU m) => MkSegLevel GPU m -> Pat GPU -> SubExp -> Commutativity -> Lambda GPU -> Lambda GPU -> [SubExp] -> [VName] -> m (Stms GPU)
- Futhark.Pass.ExtractKernels.ToGPU: getSize :: (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SizeClass -> m SubExp
+ Futhark.Pass.ExtractKernels.ToGPU: getSize :: (MonadBuilder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SizeClass -> m SubExp
- Futhark.Pass.ExtractKernels.ToGPU: segThread :: (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> m SegLevel
+ Futhark.Pass.ExtractKernels.ToGPU: segThread :: (MonadBuilder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> m SegLevel
- Futhark.Tools: dissectScrema :: (MonadBinder m, Op (Rep m) ~ SOAC (Rep m), Bindable (Rep m)) => Pattern (Rep m) -> SubExp -> ScremaForm (Rep m) -> [VName] -> m ()
+ Futhark.Tools: dissectScrema :: (MonadBuilder m, Op (Rep m) ~ SOAC (Rep m), Buildable (Rep m)) => Pat (Rep m) -> SubExp -> ScremaForm (Rep m) -> [VName] -> m ()
- Futhark.Tools: redomapToMapAndReduce :: (MonadFreshNames m, Bindable rep, ExpDec rep ~ (), Op rep ~ SOAC rep) => Pattern rep -> (SubExp, Commutativity, LambdaT rep, LambdaT rep, [SubExp], [VName]) -> m (Stm rep, Stm rep)
+ Futhark.Tools: redomapToMapAndReduce :: (MonadFreshNames m, Buildable rep, ExpDec rep ~ (), Op rep ~ SOAC rep) => Pat rep -> (SubExp, [Reduce rep], LambdaT rep, [VName]) -> m (Stm rep, Stm rep)
- Futhark.Tools: sequentialStreamWholeArray :: (MonadBinder m, Bindable (Rep m)) => Pattern (Rep m) -> SubExp -> [SubExp] -> LambdaT (Rep m) -> [VName] -> m ()
+ Futhark.Tools: sequentialStreamWholeArray :: (MonadBuilder m, Buildable (Rep m)) => Pat (Rep m) -> SubExp -> [SubExp] -> LambdaT (Rep m) -> [VName] -> m ()
- Futhark.Transform.FirstOrderTransform: transformLambda :: (MonadFreshNames m, Bindable rep, BinderOps rep, LocalScope somerep m, SameScope somerep rep, LetDec rep ~ LetDec SOACS, CanBeAliased (Op rep)) => Lambda -> m (Lambda rep)
+ Futhark.Transform.FirstOrderTransform: transformLambda :: (MonadFreshNames m, Buildable rep, BuilderOps rep, LocalScope somerep m, SameScope somerep rep, LetDec rep ~ LetDec SOACS, CanBeAliased (Op rep)) => Lambda -> m (Lambda rep)
- Futhark.Transform.FirstOrderTransform: transformSOAC :: Transformer m => Pattern (Rep m) -> SOAC (Rep m) -> m ()
+ Futhark.Transform.FirstOrderTransform: transformSOAC :: Transformer m => Pat (Rep m) -> SOAC (Rep m) -> m ()
- Futhark.Transform.FirstOrderTransform: type FirstOrderRep rep = (Bindable rep, BinderOps rep, LetDec SOACS ~ LetDec rep, LParamInfo SOACS ~ LParamInfo rep, CanBeAliased (Op rep))
+ Futhark.Transform.FirstOrderTransform: type FirstOrderRep rep = (Buildable rep, BuilderOps rep, LetDec SOACS ~ LetDec rep, LParamInfo SOACS ~ LParamInfo rep, CanBeAliased (Op rep))
- Futhark.Transform.FirstOrderTransform: type Transformer m = (MonadBinder m, LocalScope (Rep m) m, Bindable (Rep m), BinderOps (Rep m), LParamInfo SOACS ~ LParamInfo (Rep m), CanBeAliased (Op (Rep m)))
+ Futhark.Transform.FirstOrderTransform: type Transformer m = (MonadBuilder m, LocalScope (Rep m) m, Buildable (Rep m), BuilderOps (Rep m), LParamInfo SOACS ~ LParamInfo (Rep m), CanBeAliased (Op (Rep m)))
- Futhark.TypeCheck: matchLoopResult :: (Checkable rep, FParamInfo rep ~ DeclType) => [FParam (Aliases rep)] -> [FParam (Aliases rep)] -> [SubExp] -> TypeM rep ()
+ Futhark.TypeCheck: matchLoopResult :: (Checkable rep, FParamInfo rep ~ DeclType) => [FParam (Aliases rep)] -> Result -> TypeM rep ()
- Language.Futhark.Interpreter: ExtOpBreak :: BreakReason -> NonEmpty StackFrame -> a -> ExtOp a
+ Language.Futhark.Interpreter: ExtOpBreak :: Loc -> BreakReason -> NonEmpty StackFrame -> a -> ExtOp a
- Language.Futhark.Interpreter: ExtOpTrace :: Loc -> String -> a -> ExtOp a
+ Language.Futhark.Interpreter: ExtOpTrace :: String -> String -> a -> ExtOp a
- Language.Futhark.Parser: STRINGLIT :: String -> Token
+ Language.Futhark.Parser: STRINGLIT :: Text -> Token
- Language.Futhark.Prop: funType :: [PatternBase Info VName] -> StructType -> StructType
+ Language.Futhark.Prop: funType :: [PatBase Info VName] -> StructType -> StructType
- Language.Futhark.Prop: patternDimNames :: PatternBase Info VName -> Set VName
+ Language.Futhark.Prop: patternDimNames :: PatBase Info VName -> Set VName
- Language.Futhark.Prop: patternMap :: Functor f => PatternBase f VName -> Map VName (IdentBase f VName)
+ Language.Futhark.Prop: patternMap :: Functor f => PatBase f VName -> Map VName (IdentBase f VName)
- Language.Futhark.Prop: patternOrderZero :: PatternBase Info vn -> Bool
+ Language.Futhark.Prop: patternOrderZero :: PatBase Info vn -> Bool
- Language.Futhark.Prop: patternParam :: PatternBase Info VName -> (PName, StructType)
+ Language.Futhark.Prop: patternParam :: PatBase Info VName -> (PName, StructType)
- Language.Futhark.Prop: patternStructType :: PatternBase Info VName -> StructType
+ Language.Futhark.Prop: patternStructType :: PatBase Info VName -> StructType
- Language.Futhark.Prop: patternType :: PatternBase Info VName -> PatternType
+ Language.Futhark.Prop: patternType :: PatBase Info VName -> PatType
- Language.Futhark.Prop: typeOf :: ExpBase Info VName -> PatternType
+ Language.Futhark.Prop: typeOf :: ExpBase Info VName -> PatType
- Language.Futhark.Syntax: AppRes :: PatternType -> [VName] -> AppRes
+ Language.Futhark.Syntax: AppRes :: PatType -> [VName] -> AppRes
- Language.Futhark.Syntax: ArrayLit :: [ExpBase f vn] -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: ArrayLit :: [ExpBase f vn] -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: BinOp :: (QualName vn, SrcLoc) -> f PatternType -> (ExpBase f vn, f (StructType, Maybe VName)) -> (ExpBase f vn, f (StructType, Maybe VName)) -> SrcLoc -> AppExpBase f vn
+ Language.Futhark.Syntax: BinOp :: (QualName vn, SrcLoc) -> f PatType -> (ExpBase f vn, f (StructType, Maybe VName)) -> (ExpBase f vn, f (StructType, Maybe VName)) -> SrcLoc -> AppExpBase f vn
- Language.Futhark.Syntax: CasePat :: PatternBase f vn -> ExpBase f vn -> SrcLoc -> CaseBase f vn
+ Language.Futhark.Syntax: CasePat :: PatBase f vn -> ExpBase f vn -> SrcLoc -> CaseBase f vn
- Language.Futhark.Syntax: Constr :: Name -> [ExpBase f vn] -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: Constr :: Name -> [ExpBase f vn] -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: DoLoop :: [VName] -> PatternBase f vn -> ExpBase f vn -> LoopFormBase f vn -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
+ Language.Futhark.Syntax: DoLoop :: [VName] -> PatBase f vn -> ExpBase f vn -> LoopFormBase f vn -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
- Language.Futhark.Syntax: FloatLit :: Double -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: FloatLit :: Double -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: ForIn :: PatternBase f vn -> ExpBase f vn -> LoopFormBase f vn
+ Language.Futhark.Syntax: ForIn :: PatBase f vn -> ExpBase f vn -> LoopFormBase f vn
- Language.Futhark.Syntax: Id :: vn -> f PatternType -> SrcLoc -> PatternBase f vn
+ Language.Futhark.Syntax: Id :: vn -> f PatType -> SrcLoc -> PatBase f vn
- Language.Futhark.Syntax: Ident :: vn -> f PatternType -> SrcLoc -> IdentBase f vn
+ Language.Futhark.Syntax: Ident :: vn -> f PatType -> SrcLoc -> IdentBase f vn
- Language.Futhark.Syntax: IndexSection :: SliceBase f vn -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: IndexSection :: SliceBase f vn -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: IntLit :: Integer -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: IntLit :: Integer -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: Lambda :: [PatternBase f vn] -> ExpBase f vn -> Maybe (TypeExp vn) -> f (Aliasing, StructType) -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: Lambda :: [PatBase f vn] -> ExpBase f vn -> Maybe (TypeExp vn) -> f (Aliasing, StructType) -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: LetFun :: vn -> ([TypeParamBase vn], [PatternBase f vn], Maybe (TypeExp vn), f StructType, ExpBase f vn) -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
+ Language.Futhark.Syntax: LetFun :: vn -> ([TypeParamBase vn], [PatBase f vn], Maybe (TypeExp vn), f StructType, ExpBase f vn) -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
- Language.Futhark.Syntax: LetPat :: [SizeBinder vn] -> PatternBase f vn -> ExpBase f vn -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
+ Language.Futhark.Syntax: LetPat :: [SizeBinder vn] -> PatBase f vn -> ExpBase f vn -> ExpBase f vn -> SrcLoc -> AppExpBase f vn
- Language.Futhark.Syntax: OpSection :: QualName vn -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: OpSection :: QualName vn -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: OpSectionLeft :: QualName vn -> f PatternType -> ExpBase f vn -> (f (PName, StructType, Maybe VName), f (PName, StructType)) -> (f PatternType, f [VName]) -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: OpSectionLeft :: QualName vn -> f PatType -> ExpBase f vn -> (f (PName, StructType, Maybe VName), f (PName, StructType)) -> (f PatType, f [VName]) -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: OpSectionRight :: QualName vn -> f PatternType -> ExpBase f vn -> (f (PName, StructType), f (PName, StructType, Maybe VName)) -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: OpSectionRight :: QualName vn -> f PatType -> ExpBase f vn -> (f (PName, StructType), f (PName, StructType, Maybe VName)) -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: Project :: Name -> ExpBase f vn -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: Project :: Name -> ExpBase f vn -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: ProjectSection :: [Name] -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: ProjectSection :: [Name] -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: RecordFieldImplicit :: vn -> f PatternType -> SrcLoc -> FieldBase f vn
+ Language.Futhark.Syntax: RecordFieldImplicit :: vn -> f PatType -> SrcLoc -> FieldBase f vn
- Language.Futhark.Syntax: RecordUpdate :: ExpBase f vn -> [Name] -> ExpBase f vn -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: RecordUpdate :: ExpBase f vn -> [Name] -> ExpBase f vn -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: ValBind :: Maybe (f EntryPoint) -> vn -> Maybe (TypeExp vn) -> f (StructType, [VName]) -> [TypeParamBase vn] -> [PatternBase f vn] -> ExpBase f vn -> Maybe DocComment -> [AttrInfo] -> SrcLoc -> ValBindBase f vn
+ Language.Futhark.Syntax: ValBind :: Maybe (f EntryPoint) -> vn -> Maybe (TypeExp vn) -> f (StructType, [VName]) -> [TypeParamBase vn] -> [PatBase f vn] -> ExpBase f vn -> Maybe DocComment -> [AttrInfo] -> SrcLoc -> ValBindBase f vn
- Language.Futhark.Syntax: Var :: QualName vn -> f PatternType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.Syntax: Var :: QualName vn -> f PatType -> SrcLoc -> ExpBase f vn
- Language.Futhark.Syntax: Wildcard :: f PatternType -> SrcLoc -> PatternBase f vn
+ Language.Futhark.Syntax: Wildcard :: f PatType -> SrcLoc -> PatBase f vn
- Language.Futhark.Syntax: [appResType] :: AppRes -> PatternType
+ Language.Futhark.Syntax: [appResType] :: AppRes -> PatType
- Language.Futhark.Syntax: [identType] :: IdentBase f vn -> f PatternType
+ Language.Futhark.Syntax: [identType] :: IdentBase f vn -> f PatType
- Language.Futhark.Syntax: [valBindParams] :: ValBindBase f vn -> [PatternBase f vn]
+ Language.Futhark.Syntax: [valBindParams] :: ValBindBase f vn -> [PatBase f vn]
- Language.Futhark.Syntax: class (Show vn, Show (f VName), Show (f (Diet, Maybe VName)), Show (f String), Show (f [VName]), Show (f ([VName], [VName])), Show (f PatternType), Show (f (PatternType, [VName])), Show (f (StructType, [VName])), Show (f EntryPoint), Show (f StructType), Show (f (StructType, Maybe VName)), Show (f (PName, StructType)), Show (f (PName, StructType, Maybe VName)), Show (f (Aliasing, StructType)), Show (f (Map VName VName)), Show (f AppRes)) => Showable f vn
+ Language.Futhark.Syntax: class (Show vn, Show (f VName), Show (f (Diet, Maybe VName)), Show (f String), Show (f [VName]), Show (f ([VName], [VName])), Show (f PatType), Show (f (PatType, [VName])), Show (f (StructType, [VName])), Show (f EntryPoint), Show (f StructType), Show (f (StructType, Maybe VName)), Show (f (PName, StructType)), Show (f (PName, StructType, Maybe VName)), Show (f (Aliasing, StructType)), Show (f (Map VName VName)), Show (f AppRes)) => Showable f vn
- Language.Futhark.Traversals: ASTMapper :: (ExpBase Info VName -> m (ExpBase Info VName)) -> (VName -> m VName) -> (QualName VName -> m (QualName VName)) -> (StructType -> m StructType) -> (PatternType -> m PatternType) -> ASTMapper m
+ Language.Futhark.Traversals: ASTMapper :: (ExpBase Info VName -> m (ExpBase Info VName)) -> (VName -> m VName) -> (QualName VName -> m (QualName VName)) -> (StructType -> m StructType) -> (PatType -> m PatType) -> ASTMapper m
- Language.Futhark.TypeChecker.Match: unmatched :: [Pattern] -> [Match]
+ Language.Futhark.TypeChecker.Match: unmatched :: [Pat] -> [Match]
- Language.Futhark.TypeChecker.Monad: lookupVar :: MonadTypeChecker m => SrcLoc -> QualName Name -> m (QualName VName, PatternType)
+ Language.Futhark.TypeChecker.Monad: lookupVar :: MonadTypeChecker m => SrcLoc -> QualName Name -> m (QualName VName, PatType)
- Language.Futhark.TypeChecker.Terms: checkFunDef :: (Name, Maybe UncheckedTypeExp, [UncheckedTypeParam], [UncheckedPattern], UncheckedExp, SrcLoc) -> TypeM (VName, [TypeParam], [Pattern], Maybe (TypeExp VName), StructType, [VName], Exp)
+ Language.Futhark.TypeChecker.Terms: checkFunDef :: (Name, Maybe UncheckedTypeExp, [UncheckedTypeParam], [UncheckedPat], UncheckedExp, SrcLoc) -> TypeM (VName, [TypeParam], [Pat], Maybe (TypeExp VName), StructType, [VName], Exp)
- Language.Futhark.TypeChecker.Types: checkForDuplicateNames :: MonadTypeChecker m => [UncheckedPattern] -> m ()
+ Language.Futhark.TypeChecker.Types: checkForDuplicateNames :: MonadTypeChecker m => [UncheckedPat] -> m ()
- Language.Futhark.TypeChecker.Unify: mustHaveField :: MonadUnify m => Usage -> Name -> PatternType -> m PatternType
+ Language.Futhark.TypeChecker.Unify: mustHaveField :: MonadUnify m => Usage -> Name -> PatType -> m PatType
- Language.Futhark.TypeChecker.Unify: unifyMostCommon :: MonadUnify m => Usage -> PatternType -> PatternType -> m (PatternType, [VName])
+ Language.Futhark.TypeChecker.Unify: unifyMostCommon :: MonadUnify m => Usage -> PatType -> PatType -> m (PatType, [VName])
Files
- docs/binary-data-format.rst +3/−4
- docs/c-api.rst +11/−5
- docs/conf.py +2/−0
- docs/index.rst +3/−0
- docs/js-api.rst +142/−0
- docs/language-reference.rst +41/−5
- docs/man/futhark-cuda.rst +7/−1
- docs/man/futhark-repl.rst +2/−1
- docs/man/futhark-run.rst +4/−12
- docs/man/futhark-wasm-multicore.rst +99/−0
- docs/man/futhark-wasm.rst +98/−0
- docs/man/futhark.rst +1/−1
- docs/server-protocol.rst +2/−2
- futhark.cabal +20/−11
- prelude/math.fut +157/−29
- prelude/prelude.fut +7/−6
- rts/c/cuda.h +12/−0
- rts/c/half.h +238/−0
- rts/c/opencl.h +8/−2
- rts/c/scalar.h +1654/−0
- rts/c/scalar_f16.h +627/−0
- rts/c/scheduler.h +8/−1
- rts/c/server.h +8/−2
- rts/c/tuning.h +1/−1
- rts/c/util.h +15/−8
- rts/c/values.h +58/−18
- rts/javascript/server.js +251/−0
- rts/javascript/values.js +165/−0
- rts/javascript/wrapperclasses.js +83/−0
- rts/python/memory.py +5/−5
- rts/python/opencl.py +10/−3
- rts/python/scalar.py +118/−11
- rts/python/values.py +37/−0
- src/Futhark/Actions.hs +157/−29
- src/Futhark/Analysis/Alias.hs +1/−1
- src/Futhark/Analysis/CallGraph.hs +70/−19
- src/Futhark/Analysis/DataDependencies.hs +3/−3
- src/Futhark/Analysis/HORep/MapNest.hs +7/−7
- src/Futhark/Analysis/HORep/SOAC.hs +42/−60
- src/Futhark/Analysis/Interference.hs +38/−21
- src/Futhark/Analysis/LastUse.hs +5/−5
- src/Futhark/Analysis/Metrics.hs +26/−24
- src/Futhark/Analysis/PrimExp.hs +30/−0
- src/Futhark/Analysis/PrimExp/Convert.hs +12/−12
- src/Futhark/Analysis/PrimExp/Parse.hs +3/−0
- src/Futhark/Analysis/Rephrase.hs +6/−6
- src/Futhark/Analysis/SymbolTable.hs +15/−16
- src/Futhark/Analysis/UsageTable.hs +6/−4
- src/Futhark/Bench.hs +2/−0
- src/Futhark/Binder.hs +0/−259
- src/Futhark/Binder/Class.hs +0/−173
- src/Futhark/Builder.hs +246/−0
- src/Futhark/Builder/Class.hs +173/−0
- src/Futhark/CLI/Bench.hs +1/−6
- src/Futhark/CLI/Dataset.hs +19/−1
- src/Futhark/CLI/Dev.hs +83/−56
- src/Futhark/CLI/Literate.hs +72/−61
- src/Futhark/CLI/Misc.hs +4/−3
- src/Futhark/CLI/MulticoreWASM.hs +19/−0
- src/Futhark/CLI/REPL.hs +6/−25
- src/Futhark/CLI/Run.hs +2/−2
- src/Futhark/CLI/Test.hs +8/−7
- src/Futhark/CLI/WASM.hs +19/−0
- src/Futhark/CodeGen/Backends/CCUDA.hs +15/−19
- src/Futhark/CodeGen/Backends/CCUDA/Boilerplate.hs +9/−9
- src/Futhark/CodeGen/Backends/COpenCL.hs +38/−29
- src/Futhark/CodeGen/Backends/COpenCL/Boilerplate.hs +14/−15
- src/Futhark/CodeGen/Backends/GenericC.hs +203/−196
- src/Futhark/CodeGen/Backends/GenericC/CLI.hs +20/−21
- src/Futhark/CodeGen/Backends/GenericC/Server.hs +10/−10
- src/Futhark/CodeGen/Backends/GenericPython.hs +70/−37
- src/Futhark/CodeGen/Backends/GenericPython/AST.hs +5/−4
- src/Futhark/CodeGen/Backends/GenericPython/Definitions.hs +0/−31
- src/Futhark/CodeGen/Backends/GenericWASM.hs +338/−0
- src/Futhark/CodeGen/Backends/MulticoreC.hs +142/−138
- src/Futhark/CodeGen/Backends/MulticoreWASM.hs +61/−0
- src/Futhark/CodeGen/Backends/PyOpenCL.hs +6/−4
- src/Futhark/CodeGen/Backends/PyOpenCL/Boilerplate.hs +3/−11
- src/Futhark/CodeGen/Backends/SequentialC.hs +3/−1
- src/Futhark/CodeGen/Backends/SequentialC/Boilerplate.hs +1/−1
- src/Futhark/CodeGen/Backends/SequentialPython.hs +2/−1
- src/Futhark/CodeGen/Backends/SequentialWASM.hs +61/−0
- src/Futhark/CodeGen/Backends/SimpleRep.hs +69/−928
- src/Futhark/CodeGen/ImpCode.hs +16/−1
- src/Futhark/CodeGen/ImpCode/OpenCL.hs +3/−2
- src/Futhark/CodeGen/ImpGen.hs +289/−274
- src/Futhark/CodeGen/ImpGen/GPU.hs +54/−56
- src/Futhark/CodeGen/ImpGen/GPU/Base.hs +103/−98
- src/Futhark/CodeGen/ImpGen/GPU/SegHist.hs +11/−11
- src/Futhark/CodeGen/ImpGen/GPU/SegMap.hs +3/−3
- src/Futhark/CodeGen/ImpGen/GPU/SegRed.hs +11/−11
- src/Futhark/CodeGen/ImpGen/GPU/SegScan.hs +5/−6
- src/Futhark/CodeGen/ImpGen/GPU/SegScan/SinglePass.hs +8/−8
- src/Futhark/CodeGen/ImpGen/GPU/SegScan/TwoPass.hs +8/−8
- src/Futhark/CodeGen/ImpGen/GPU/ToOpenCL.hs +73/−90
- src/Futhark/CodeGen/ImpGen/Multicore.hs +4/−4
- src/Futhark/CodeGen/ImpGen/Multicore/Base.hs +4/−4
- src/Futhark/CodeGen/ImpGen/Multicore/SegHist.hs +14/−14
- src/Futhark/CodeGen/ImpGen/Multicore/SegMap.hs +8/−13
- src/Futhark/CodeGen/ImpGen/Multicore/SegRed.hs +12/−12
- src/Futhark/CodeGen/ImpGen/Multicore/SegScan.hs +17/−17
- src/Futhark/CodeGen/RTS/C.hs +102/−0
- src/Futhark/CodeGen/RTS/JavaScript.hs +24/−0
- src/Futhark/CodeGen/RTS/Python.hs +44/−0
- src/Futhark/CodeGen/SetDefaultSpace.hs +35/−28
- src/Futhark/Construct.hs +90/−120
- src/Futhark/Doc/Generator.hs +2/−2
- src/Futhark/IR/Aliases.hs +43/−81
- src/Futhark/IR/GPU.hs +7/−7
- src/Futhark/IR/GPU/Kernel.hs +0/−346
- src/Futhark/IR/GPU/Op.hs +346/−0
- src/Futhark/IR/GPU/Simplify.hs +1/−1
- src/Futhark/IR/GPUMem.hs +13/−11
- src/Futhark/IR/MC.hs +6/−6
- src/Futhark/IR/MCMem.hs +12/−9
- src/Futhark/IR/Mem.hs +154/−208
- src/Futhark/IR/Mem/IxFun.hs +46/−10
- src/Futhark/IR/Mem/Simplify.hs +30/−38
- src/Futhark/IR/Parse.hs +81/−66
- src/Futhark/IR/Pretty.hs +41/−27
- src/Futhark/IR/Primitive.hs +213/−24
- src/Futhark/IR/Primitive/Parse.hs +3/−0
- src/Futhark/IR/Prop.hs +25/−22
- src/Futhark/IR/Prop/Aliases.hs +14/−12
- src/Futhark/IR/Prop/Names.hs +23/−17
- src/Futhark/IR/Prop/Patterns.hs +21/−51
- src/Futhark/IR/Prop/Scope.hs +5/−6
- src/Futhark/IR/Prop/TypeOf.hs +46/−38
- src/Futhark/IR/Prop/Types.hs +3/−10
- src/Futhark/IR/RetType.hs +2/−2
- src/Futhark/IR/SOACS.hs +9/−9
- src/Futhark/IR/SOACS/SOAC.hs +13/−13
- src/Futhark/IR/SOACS/Simplify.hs +78/−81
- src/Futhark/IR/SegOp.hs +145/−107
- src/Futhark/IR/Seq.hs +6/−6
- src/Futhark/IR/SeqMem.hs +5/−9
- src/Futhark/IR/Syntax.hs +71/−37
- src/Futhark/IR/Syntax/Core.hs +90/−38
- src/Futhark/IR/Traversals.hs +37/−26
- src/Futhark/Internalise.hs +1/−1
- src/Futhark/Internalise/AccurateSizes.hs +5/−5
- src/Futhark/Internalise/Bindings.hs +45/−45
- src/Futhark/Internalise/Defunctionalise.hs +90/−87
- src/Futhark/Internalise/Defunctorise.hs +3/−5
- src/Futhark/Internalise/Exps.hs +214/−96
- src/Futhark/Internalise/FreeVars.hs +10/−14
- src/Futhark/Internalise/Lambdas.hs +4/−4
- src/Futhark/Internalise/LiftLambdas.hs +3/−4
- src/Futhark/Internalise/Monad.hs +14/−14
- src/Futhark/Internalise/Monomorphise.hs +52/−50
- src/Futhark/Optimise/BlkRegTiling.hs +52/−54
- src/Futhark/Optimise/CSE.hs +36/−30
- src/Futhark/Optimise/DoubleBuffer.hs +216/−81
- src/Futhark/Optimise/Fusion.hs +59/−72
- src/Futhark/Optimise/Fusion/Composing.hs +9/−14
- src/Futhark/Optimise/Fusion/LoopKernel.hs +9/−9
- src/Futhark/Optimise/InPlaceLowering.hs +13/−17
- src/Futhark/Optimise/InPlaceLowering/LowerIntoStm.hs +58/−68
- src/Futhark/Optimise/InPlaceLowering/SubstituteIndices.hs +29/−28
- src/Futhark/Optimise/InliningDeadFun.hs +110/−91
- src/Futhark/Optimise/ReuseAllocations.hs +16/−23
- src/Futhark/Optimise/ReuseAllocations/GreedyColoring.hs +11/−13
- src/Futhark/Optimise/Simplify/Engine.hs +78/−116
- src/Futhark/Optimise/Simplify/Rep.hs +19/−25
- src/Futhark/Optimise/Simplify/Rule.hs +10/−11
- src/Futhark/Optimise/Simplify/Rules.hs +80/−91
- src/Futhark/Optimise/Simplify/Rules/BasicOp.hs +53/−46
- src/Futhark/Optimise/Simplify/Rules/ClosedForm.hs +15/−20
- src/Futhark/Optimise/Simplify/Rules/Index.hs +41/−31
- src/Futhark/Optimise/Simplify/Rules/Loop.hs +54/−102
- src/Futhark/Optimise/Simplify/Rules/Simple.hs +55/−52
- src/Futhark/Optimise/Sink.hs +2/−2
- src/Futhark/Optimise/TileLoops.hs +77/−82
- src/Futhark/Optimise/TileLoops/Shared.hs +26/−26
- src/Futhark/Optimise/Unstream.hs +3/−3
- src/Futhark/Pass/ExpandAllocations.hs +80/−73
- src/Futhark/Pass/ExplicitAllocations.hs +397/−517
- src/Futhark/Pass/ExplicitAllocations/GPU.hs +19/−18
- src/Futhark/Pass/ExplicitAllocations/MC.hs +2/−0
- src/Futhark/Pass/ExplicitAllocations/SegOp.hs +4/−4
- src/Futhark/Pass/ExtractKernels.hs +52/−58
- src/Futhark/Pass/ExtractKernels/BlockedKernel.hs +31/−28
- src/Futhark/Pass/ExtractKernels/DistributeNests.hs +109/−125
- src/Futhark/Pass/ExtractKernels/Distribution.hs +39/−41
- src/Futhark/Pass/ExtractKernels/ISRWIM.hs +26/−31
- src/Futhark/Pass/ExtractKernels/Interchange.hs +24/−26
- src/Futhark/Pass/ExtractKernels/Intragroup.hs +25/−19
- src/Futhark/Pass/ExtractKernels/StreamKernel.hs +26/−38
- src/Futhark/Pass/ExtractKernels/ToGPU.hs +2/−2
- src/Futhark/Pass/ExtractMulticore.hs +31/−28
- src/Futhark/Pass/KernelBabysitting.hs +21/−21
- src/Futhark/Passes.hs +3/−1
- src/Futhark/Script.hs +3/−3
- src/Futhark/Test.hs +6/−2
- src/Futhark/Tools.hs +29/−37
- src/Futhark/Transform/FirstOrderTransform.hs +46/−44
- src/Futhark/Transform/Rename.hs +30/−43
- src/Futhark/Transform/Substitute.hs +19/−6
- src/Futhark/TypeCheck.hs +94/−86
- src/Futhark/Util.hs +24/−14
- src/Futhark/Util/Console.hs +0/−5
- src/Futhark/Util/Options.hs +8/−1
- src/Futhark/Util/Pretty.hs +5/−1
- src/Futhark/Version.hs +27/−16
- src/Language/Futhark.hs +2/−2
- src/Language/Futhark/Core.hs +3/−1
- src/Language/Futhark/Interpreter.hs +199/−46
- src/Language/Futhark/Parser/Lexer.x +8/−11
- src/Language/Futhark/Parser/Parser.y +79/−95
- src/Language/Futhark/Pretty.hs +10/−9
- src/Language/Futhark/Prop.hs +139/−67
- src/Language/Futhark/Query.hs +26/−26
- src/Language/Futhark/Syntax.hs +56/−59
- src/Language/Futhark/Traversals.hs +47/−44
- src/Language/Futhark/TypeChecker.hs +86/−58
- src/Language/Futhark/TypeChecker/Match.hs +8/−8
- src/Language/Futhark/TypeChecker/Modules.hs +1/−1
- src/Language/Futhark/TypeChecker/Monad.hs +4/−7
- src/Language/Futhark/TypeChecker/Terms.hs +164/−159
- src/Language/Futhark/TypeChecker/Types.hs +10/−15
- src/Language/Futhark/TypeChecker/Unify.hs +12/−12
- src/futhark.hs +4/−0
- unittests/Futhark/IR/Mem/IxFun/Alg.hs +21/−4
- unittests/Futhark/IR/Mem/IxFunTests.hs +194/−76
- unittests/Futhark/IR/Mem/IxFunWrapper.hs +9/−1
- unittests/Futhark/IR/PrimitiveTests.hs +7/−1
- unittests/Futhark/Optimise/ReuseAllocations/GreedyColoringTests.hs +15/−15
docs/binary-data-format.rst view
@@ -12,10 +12,8 @@ not used for Futhark programs compiled to libraries, which instead use whichever format is supported by their host language. -Currently reading binary input is only supported for programs-generated by ``futhark c``/``futhark opencl``, and-``futhark py``/``futhark pyopencl``. It is *not* supported for-``futhark run``.+Currently reading binary input is only supported for compiled programs.+It is *not* supported for ``futhark run``. You can generate random data in the binary format with ``futhark dataset`` (:ref:`futhark-dataset(1)`). This tool can also be used to@@ -72,6 +70,7 @@ " u16" " u32" " u64"+ " f16" " f32" " f64" "bool"
docs/c-api.rst view
@@ -148,11 +148,17 @@ ------ Primitive types (``i32``, ``bool``, etc) are mapped directly to their-corresponding C type. For each distinct array type of primitives-(ignoring sizes), an opaque C struct is defined. For types that do-not map cleanly to C, including records, sum types, and arrays of-tuples, see :ref:`opaques`.+corresponding C type. The ``f16`` type is mapped to ``uint16_t``,+because C does not have a standard ``half`` type. This integer+contains the bitwise representation of the ``f16`` value in the IEEE+754 binary16 format. +For each distinct array type of primitives (ignoring sizes), an opaque+C struct is defined. Arrays of ``f16`` are presented as containing+``uint16_t`` elements. For types that do not map cleanly to C,+including records, sum types, and arrays of tuples, see+:ref:`opaques`.+ All array values share a similar API, which is illustrated here for the case of the type ``[]i32``. The creation/retrieval functions are all asynchronous, so make sure to call :c:func:`futhark_context_sync`@@ -281,7 +287,7 @@ Results in the following C function: -.. c:function:: int futhark_entry_main(struct futhark_context *ctx, int32_t *out0, const struct futhark_i32_1d *in0)+.. c:function:: int futhark_entry_sum(struct futhark_context *ctx, int32_t *out0, const struct futhark_i32_1d *in0) Asynchronously call the entry point with the given arguments. Make sure to call :c:func:`futhark_context_sync` before using the value
docs/conf.py view
@@ -268,6 +268,8 @@ ('man/futhark-cuda', 'futhark-cuda', 'compile Futhark to CUDA', [], 1), ('man/futhark-python', 'futhark-python', 'compile Futhark to sequential Python', [], 1), ('man/futhark-pyopencl', 'futhark-pyopencl', 'compile Futhark to Python and OpenCL', [], 1),+ ('man/futhark-wasm', 'futhark-wasm', 'compile Futhark to WebAssembly', [], 1),+ ('man/futhark-wasm-multicore', 'futhark-wasm-multicore', 'compile Futhark to parallel WebAssembly', [], 1), ('man/futhark-run', 'futhark-run', 'interpret Futhark program', [], 1), ('man/futhark-repl', 'futhark-repl', 'interactive Futhark read-eval-print-loop', [], 1), ('man/futhark-test', 'futhark-test', 'test Futhark programs', [], 1),
docs/index.rst view
@@ -31,6 +31,7 @@ usage.rst language-reference.rst c-api.rst+ js-api.rst package-management.rst server-protocol.rst c-porting-guide.rst@@ -54,6 +55,8 @@ man/futhark-pkg.rst man/futhark-pyopencl.rst man/futhark-python.rst+ man/futhark-wasm.rst+ man/futhark-wasm-multicore.rst man/futhark-repl.rst man/futhark-run.rst man/futhark-literate.rst
+ docs/js-api.rst view
@@ -0,0 +1,142 @@+.. _js-api:++JavaScript API Reference+========================++The :ref:`futhark-wasm(1)` and :ref:`futhark-wasm-multicore(1)`+compilers produce JavaScript wrapper code to allow JavaScript programs+to invoke the generated WebAssembly code. This chapter describes the+API exposed by the wrapper.++First a warning: **the JavaScript API is experimental**. It may+change incompatibly even in minor versions of the compiler.++A Futhark program ``futlib.fut`` compiled with a WASM backend as a library+with the ``--library`` command line option produces four files:++* ``futlib.c``, ``futlib.h``: Implementation and header C files+ generated by the compiler, similar to ``futhark c``. You can delete+ these - they are not needed at run-time.+* ``futlib.class.js``: An intermediate build artifact. Feel free to+ delete it.+* ``futlib.wasm``: A compiled WebAssembly module, which must be+ present at runtime.+* ``futlib.mjs``: An ES6 module that can can be imported by other+ JavaScript code, and implements the API given in the following.++The module exports a function, ``newFutharkContext``, which is a factory+function that returns a Promise producing a ``FutharkContext``+instance (see below). A simple usage example:++.. code-block:: javascript++ import { newFutharkContext } from './futlib.mjs';+ var fc;+ newFutharkContext().then(x => fc = x);++General concerns+----------------++Memory management is completely manual, as JavaScript does not support+finalizers that could let Futhark hook into the garbage collector.+You are responsible for eventually freeing all objects produced by the+API, using the appropriate methods.++FutharkContext+--------------++FutharkContext is a class that contains information about the context+and configuration from the C API. It has methods for invoking the+Futhark entry points and creating FutharkArrays on the WebAssembly+heap.++.. js:function:: newFutharkContext()++ Asynchronously create a new ``FutharkContext`` object.++.. js:class:: FutharkContext()++ A bookkeeping class representing an instance of a Futhark program.+ Do *not* directly invoke its constructor - always use the+ ``newFutharkContext()`` factory function.++.. js:function:: FutharkContext.free()++ Frees all memory created by the ``FutharkContext`` object. Should+ be called when the ``FutharkContext`` is done being used. It is an+ error use a ``FutharkArray`` or ``FutharkOpaque`` after the+ ``FutharkContext`` on which they were defined has been freed.++Values+------++Numeric types ``u8``, ``u16``, ``u32``, ``i8``, ``i16``, ``i32``, ``f32``,+and ``f64`` are mapped to JavaScript's standard number type. 64-bit integers+``u64``, and ``i64`` are mapped to ``BigInt``. ``bool`` is mapped to+JavaScript's ``boolean`` type. Arrays are represented by the ``FutharkArray``.+complex types (records, nested tuples, etc) are represented by the+``FutharkOpaque`` class.++FutharkArray+------------++``FutharkArray`` has the following API++.. js:function:: FutharkArray.toArray()++ Returns a nested JavaScript array++.. js:function:: FutharkArray.toTypedArray()++ Returns a flat typed array of the underlying data.++.. js:function:: FutharkArray.shape()++ Returns the shape of the FutharkArray as an array of BigInts.++.. js:function:: FutharkArray.free()++ Frees the memory used by the FutharkArray class++``FutharkContext`` also contains two functions for creating+``FutharkArrays`` from JavaScript arrays, and typed arrays for each+array type that appears in an entry point. All array types share+similar API methods on the ``FutharkContext``, which is illustrated+here for the case of the type ``[]i32``.++.. js:function:: FutharkContext.new_i32_1d_from_jsarray(jsarray)++ Creates and returns a one-dimensional ``i32`` ``FutharkArray`` representing+ the JavaScript array jsarray++.. js:function:: FutharkContext.new_i32_1d(array, dim1)++ Creates and returns a one-dimensional ``i32`` ``FutharkArray`` representing+ the typed array of array, with the size given by dim1.+++FutharkOpaque+-------------++Complex types (records, nested tuples, etc) are represented by+``FutharkOpaque``. It has no use outside of being accepted and+returned by entry point functions. For this reason the method only has+one function for freeing the memory when ``FutharkOpaque`` is no+longer used.++.. js:function:: FutharkOpaque.free()++ Frees memory used by FutharkOpaque. Should be called when Futhark+ Opaque is no longer used.++Entry Points+------------++Each entry point in the compiled futhark program has an entry point method on+the FutharkContext++.. js:function:: FutharkContext.<entry_point_name>(in1, ..., inN)++ The entry point function taking the N arguments of the Futhark entry point+ function, and returns the result. If the result is a tuple the return value+ is an array.
docs/language-reference.rst view
@@ -51,13 +51,12 @@ Boolean literals are written ``true`` and ``false``. The primitive types in Futhark are the signed integer types ``i8``, ``i16``, ``i32``, ``i64``, the unsigned integer types ``u8``, ``u16``, ``u32``,-``u64``, the floating-point types ``f32``, ``f64``, as well as-``bool``. An ``f32`` is always a single-precision float and a ``f64``-is a double-precision float.+``u64``, the floating-point types ``f16``, ``f32``, ``f64``, as well+as ``bool``. .. productionlist:: int_type: "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64"- float_type: "f32" | "f64"+ float_type: "f16" | "f32" | "f64" Numeric literals can be suffixed with their intended type. For example ``42i8`` is of type ``i8``, and ``1337e2f64`` is of type@@ -429,6 +428,8 @@ exp: `atom` : | `exp` `qualbinop` `exp` : | `exp` `exp`+ : | "!" `exp`+ : | "-" `exp` : | `constructor` `exp`* : | `exp` ":" `type` : | `exp` ":>" `type`@@ -503,6 +504,10 @@ enclosed in parentheses, rather than an operator section partially applying the infix operator ``-``. +* Function application and prefix operators bind more tightly than any+ infix operator. Note that the only prefix operators are ``!`` and+ ``-``, and more cannot be defined.+ * The following table describes the precedence and associativity of infix operators. All operators in the same row have the same precedence. The rows are listed in increasing order of precedence.@@ -1401,7 +1406,7 @@ .. productionlist:: mod_bind: "module" `id` `mod_param`* "=" [":" mod_type_exp] "=" `mod_exp` mod_param: "(" `id` ":" `mod_type_exp` ")"- mod_type_bind: "module" "type" `id` `type_param`* "=" `mod_type_exp`+ mod_type_bind: "module" "type" `id` "=" `mod_type_exp` Futhark supports an ML-style higher-order module system. *Modules* can contain types, functions, and other modules and module types.@@ -1657,6 +1662,32 @@ The following expression attributes are supported. +``trace``+.........++Print the value produced by the attributed expression. Used for+debugging. Somewhat unreliable outside of the interpreter, and in+particular does not work for GPU device code.++``trace(tag)``+..............++Like ``trace``, but prefix output with *tag*, which must lexically be+an identifier.++``break``+.........++In the interpreter, pause execution *before* evaluating the expression.+No effect for compiled code.++``opaque``+..........++The compiler will treat the attributed expression as a black box.+This is used to work around optimisation deficiencies (or bugs),+although it should hopefully rarely be necessary.+ ``incremental_flattening(no_outer)`` .................................... @@ -1744,6 +1775,11 @@ Do not inline any calls to this function. If the function is then used within a parallel construct (e.g. ``map``), this will likely prevent the GPU backends from generating working code.++``inline``+..........++Always inline calls to this function. Spec attributes ~~~~~~~~~~~~~~~
docs/man/futhark-cuda.rst view
@@ -161,13 +161,19 @@ compiler to compile the generated C program into a binary. This only works if the C compiler can find the necessary CUDA libraries. On most systems, CUDA is installed in ``/usr/local/cuda``, which is-usually not part of the default compiler search path. You may need to+usually not part of the default compiler search path. You may need to set the following environment variables before running ``futhark cuda``:: LIBRARY_PATH=/usr/local/cuda/lib64 LD_LIBRARY_PATH=/usr/local/cuda/lib64/ CPATH=/usr/local/cuda/include++At runtime the generated program must be able to find the CUDA+installation directory, which is normally located at+``/usr/local/cuda``. If you have CUDA installed elsewhere, set any of+the ``CUDA_HOME``, ``CUDA_ROOT``, or ``CUDA_PATH`` environment+variables to the proper directory. SEE ALSO ========
docs/man/futhark-repl.rst view
@@ -25,7 +25,8 @@ colon. ``futhark repl`` uses the Futhark interpreter, which grants access to-certain special functions. See :ref:`futhark-run(1)` for a description.+the ``#[trace]`` and ``#[break]`` attributes. See+:ref:`futhark-run(1)` for a description. OPTIONS =======
docs/man/futhark-run.rst view
@@ -19,18 +19,10 @@ output. ``futhark run`` is very slow, and in practice only useful for testing,-teaching, and experimenting with the language. Certain special-debugging functions are available in ``futhark run``:--``trace 'a : a -> a``- Semantically identity, but prints the value on standard output.--``break 'a : a -> a``- Semantically identity, but interrupts execution at the calling- point, such that the environment can be inspected. Continue- execution by entering an empty input line. Breakpoints are only- respected when starting a program from the prompt, not when- passing a program on the command line.+teaching, and experimenting with the language. The ``#[trace]`` and+``#[break]`` attributes are fully supported in the interpreter.+Tracing prints values to stdout in contrast to compiled code, which+prints to stderr. OPTIONS =======
+ docs/man/futhark-wasm-multicore.rst view
@@ -0,0 +1,99 @@+.. role:: ref(emphasis)++.. _futhark-wasm-multicore(1):++======================+futhark-wasm-multicore+======================++SYNOPSIS+========++futhark wasm-multicore [options...] <program.fut>++DESCRIPTION+===========++``futhark wasm-multicore`` translates a Futhark program to+multi-threaded WebAssembly code by first generating C as ``futhark+c``, and then using Emscripten (``emcc``). This produces a ``.js``+file that allows the compiled code to be invoked from JavaScript.+Executables implement the Futhark server protocol and can be run with+Node.js.++OPTIONS+=======++-h+ Print help text to standard output and exit.++--entry-point NAME+ Treat this top-level function as an entry point.++--library+ Generate a library instead of an executable. Appends ``.js``+ to the name indicated by the ``-o`` option to determine output+ file names.++-o outfile+ Where to write the result. If the source program is named+ ``foo.fut``, this defaults to ``foo``.++--safe+ Ignore ``unsafe`` in program and perform safety checks unconditionally.++--server+ Generate a server-mode executable that reads commands from stdin.++-v verbose+ Enable debugging output. If compilation fails due to a compiler+ error, the result of the last successful compiler step will be+ printed to standard error.++-V+ Print version information on standard output and exit.++-W+ Do not print any warnings.++--Werror+ Treat warnings as errors.++++ENVIRONMENT VARIABLES+=====================++``CFLAGS``++ Space-separated list of options passed to ``emcc``. Defaults+ to ``-O3 -std=c99`` if unset.++``EMCFLAGS``++ Space-separated list of options passed to ``emcc``.++EXECUTABLE OPTIONS+==================++The following options are accepted by executables generated by+``futhark wasm-multicore``.++-h, --help++ Print help text to standard output and exit.++-D, --debugging++ Perform possibly expensive internal correctness checks and verbose+ logging. Implies ``-L``.++-L, --log++ Print various low-overhead logging information to stderr while+ running.++SEE ALSO+========++:ref:`futhark-c(1)`, :ref:`futhark-wasm(1)`
+ docs/man/futhark-wasm.rst view
@@ -0,0 +1,98 @@+.. role:: ref(emphasis)++.. _futhark-wasm(1):++============+futhark-wasm+============++SYNOPSIS+========++futhark wasm [options...] <program.fut>++DESCRIPTION+===========++``futhark wasm`` translates a Futhark program to sequential+WebAssembly code by first generating C as ``futhark c``, and then+using Emscripten (``emcc``). This produces a ``.js`` file that allows+the compiled code to be invoked from JavaScript. Executables+implement the Futhark server protocol and can be run with Node.js.++OPTIONS+=======++-h+ Print help text to standard output and exit.++--entry-point NAME+ Treat this top-level function as an entry point.++--library+ Generate a library instead of an executable. Appends ``.js``+ to the name indicated by the ``-o`` option to determine output+ file names.++-o outfile+ Where to write the result. If the source program is named+ ``foo.fut``, this defaults to ``foo``.++--safe+ Ignore ``unsafe`` in program and perform safety checks unconditionally.++--server+ Generate a server-mode executable that reads commands from stdin.+ This is the default.++-v verbose+ Enable debugging output. If compilation fails due to a compiler+ error, the result of the last successful compiler step will be+ printed to standard error.++-V+ Print version information on standard output and exit.++-W+ Do not print any warnings.++--Werror+ Treat warnings as errors.++ENVIRONMENT VARIABLES+=====================++``CFLAGS``++ Space-separated list of options passed to ``emcc``. Defaults+ to ``-O3 -std=c99`` if unset.++``EMCFLAGS``++ Space-separated list of options passed to ``emcc``.++EXECUTABLE OPTIONS+==================++The following options are accepted by executables generated by+``futhark wasm``.++-h, --help++ Print help text to standard output and exit.++-D, --debugging++ Perform possibly expensive internal correctness checks and verbose+ logging. Implies ``-L``.++-L, --log++ Print various low-overhead logging information to stderr while+ running.+++SEE ALSO+========++:ref:`futhark-c(1)`, :ref:`futhark-wasm-multicore(1)`
docs/man/futhark.rst view
@@ -74,4 +74,4 @@ SEE ALSO ======== -:ref:`futhark-opencl(1)`, :ref:`futhark-c(1)`, :ref:`futhark-py(1)`, :ref:`futhark-pyopencl(1)`, :ref:`futhark-dataset(1)`, :ref:`futhark-doc(1)`, :ref:`futhark-test(1)`, :ref:`futhark-bench(1)`, :ref:`futhark-run(1)`, :ref:`futhark-repl(1)`, :ref:`futhark-literate(1)`+:ref:`futhark-opencl(1)`, :ref:`futhark-c(1)`, :ref:`futhark-py(1)`, :ref:`futhark-pyopencl(1)`, :ref:`futhark-wasm(1)`, :ref:`futhark-wasm-multicore(1)`, :ref:`futhark-dataset(1)`, :ref:`futhark-doc(1)`, :ref:`futhark-test(1)`, :ref:`futhark-bench(1)`, :ref:`futhark-run(1)`, :ref:`futhark-repl(1)`, :ref:`futhark-literate(1)`
docs/server-protocol.rst view
@@ -71,10 +71,10 @@ The following commands are supported. -``call`` *entry* *o1* ... *oN* *i1* ... *oM*+``call`` *entry* *o1* ... *oN* *i1* ... *iM* ............................................ -Call the given entry point with input from the variables *i1* to *oM*.+Call the given entry point with input from the variables *i1* to *iM*. The results are stored in *o1* to *oN*, which must not already exist. ``restore`` *file* *v1* *t1* ... *vN* *tN*
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: futhark-version: 0.19.7+version: 0.20.1 synopsis: An optimising compiler for a functional, array-oriented language. description: Futhark is a small programming language designed to be compiled to@@ -35,6 +35,7 @@ extra-source-files: rts/c/*.h rts/futhark-doc/*.css+ rts/javascript/*.js rts/python/*.py prelude/*.fut -- Just enough of the docs to build the manpages.@@ -70,8 +71,8 @@ Futhark.Analysis.SymbolTable Futhark.Analysis.UsageTable Futhark.Bench- Futhark.Binder- Futhark.Binder.Class+ Futhark.Builder+ Futhark.Builder.Class Futhark.CLI.Autotune Futhark.CLI.Bench Futhark.CLI.C@@ -84,6 +85,7 @@ Futhark.CLI.Literate Futhark.CLI.Misc Futhark.CLI.Multicore+ Futhark.CLI.MulticoreWASM Futhark.CLI.OpenCL Futhark.CLI.Pkg Futhark.CLI.PyOpenCL@@ -92,6 +94,7 @@ Futhark.CLI.REPL Futhark.CLI.Run Futhark.CLI.Test+ Futhark.CLI.WASM Futhark.CodeGen.Backends.CCUDA Futhark.CodeGen.Backends.CCUDA.Boilerplate Futhark.CodeGen.Backends.COpenCL@@ -102,15 +105,20 @@ Futhark.CodeGen.Backends.GenericC.Server Futhark.CodeGen.Backends.GenericPython Futhark.CodeGen.Backends.GenericPython.AST- Futhark.CodeGen.Backends.GenericPython.Definitions Futhark.CodeGen.Backends.GenericPython.Options+ Futhark.CodeGen.Backends.GenericWASM Futhark.CodeGen.Backends.MulticoreC+ Futhark.CodeGen.Backends.MulticoreWASM Futhark.CodeGen.Backends.PyOpenCL Futhark.CodeGen.Backends.PyOpenCL.Boilerplate Futhark.CodeGen.Backends.SequentialC Futhark.CodeGen.Backends.SequentialC.Boilerplate Futhark.CodeGen.Backends.SequentialPython+ Futhark.CodeGen.Backends.SequentialWASM Futhark.CodeGen.Backends.SimpleRep+ Futhark.CodeGen.RTS.C+ Futhark.CodeGen.RTS.Python+ Futhark.CodeGen.RTS.JavaScript Futhark.CodeGen.ImpCode Futhark.CodeGen.ImpCode.GPU Futhark.CodeGen.ImpCode.Multicore@@ -150,7 +158,7 @@ Futhark.IR Futhark.IR.Aliases Futhark.IR.GPU- Futhark.IR.GPU.Kernel+ Futhark.IR.GPU.Op Futhark.IR.GPU.Simplify Futhark.IR.GPU.Sizes Futhark.IR.GPUMem@@ -303,25 +311,27 @@ , ansi-terminal >=0.6.3.1 , array >=0.4 , base >=4.13 && <5+ , base16-bytestring , binary >=0.8.3 , blaze-html >=0.9.0.1 , bytestring >=0.10.8 , bytestring-to-vector >=0.3.0.1 , bmp >=1.2.6.3 , containers >=0.6.2.1+ , cryptohash-md5 , directory >=1.3.0.0 , directory-tree >=0.12.1 , dlist >=0.6.0.1- , file-embed >=0.0.9+ , file-embed >=0.0.14.0 , filepath >=1.4.1.1 , free >=4.12.4- , futhark-data >= 1.0.0.1+ , futhark-data >= 1.0.2.0 , futhark-server >= 1.1.0.0- , gitrev >=1.2.0- , hashable+ , githash >=0.1.6.1+ , half >= 0.3 , haskeline , language-c-quote >=0.12- , mainland-pretty >=0.6.1+ , mainland-pretty >=0.7.1 , cmark-gfm >=0.2.1 , megaparsec >=9.0.0 , mtl >=2.2.1@@ -339,7 +349,6 @@ , time >=1.6.0.1 , transformers >=0.3 , unordered-containers >=0.2.7- , utf8-string >=1 , vector >=0.12 , vector-binary-instances >=0.2.2.0 , versions >=5.0.0
prelude/math.fut view
@@ -17,6 +17,7 @@ val u32: u32 -> t val u64: u64 -> t + val f16: f16 -> t val f32: f32 -> t val f64: f64 -> t @@ -89,8 +90,10 @@ val &: t -> t -> t val |: t -> t -> t val ^: t -> t -> t- val !: t -> t + -- | Bitwise negation.+ val not: t -> t+ val <<: t -> t -> t val >>: t -> t -> t val >>>: t -> t -> t@@ -111,12 +114,13 @@ val mad_hi: (a: t) -> (b: t) -> (c: t) -> t -- | Count number of zero bits preceding the most significant set- -- bit.+ -- bit. Returns the number of bits in the type if the argument is+ -- zero. val clz: t -> i32 -- | Count number of trailing zero bits following the least -- significant set bit. Returns the number of bits in the type if- -- the argument is all-zero.+ -- the argument is zero. val ctz: t -> i32 } @@ -233,6 +237,7 @@ let u32 (x: u32) = intrinsics.itob_i32_bool (intrinsics.sign_i32 x) let u64 (x: u64) = intrinsics.itob_i64_bool (intrinsics.sign_i64 x) + let f16 (x: f16) = x != 0f16 let f32 (x: f32) = x != 0f32 let f64 (x: f64) = x != 0f64 @@ -254,7 +259,7 @@ let (x: i8) & (y: i8) = intrinsics.and8 (x, y) let (x: i8) | (y: i8) = intrinsics.or8 (x, y) let (x: i8) ^ (y: i8) = intrinsics.xor8 (x, y)- let ! (x: i8) = intrinsics.complement8 x+ let not (x: i8) = intrinsics.complement8 x let (x: i8) << (y: i8) = intrinsics.shl8 (x, y) let (x: i8) >> (y: i8) = intrinsics.ashr8 (x, y)@@ -270,6 +275,7 @@ let u32 (x: u32) = intrinsics.zext_i32_i8 (intrinsics.sign_i32 x) let u64 (x: u64) = intrinsics.zext_i64_i8 (intrinsics.sign_i64 x) + let f16 (x: f16) = intrinsics.fptosi_f16_i8 x let f32 (x: f32) = intrinsics.fptosi_f32_i8 x let f64 (x: f64) = intrinsics.fptosi_f64_i8 x @@ -283,7 +289,7 @@ let (x: i8) > (y: i8) = intrinsics.slt8 (y, x) let (x: i8) <= (y: i8) = intrinsics.sle8 (x, y) let (x: i8) >= (y: i8) = intrinsics.sle8 (y, x)- let (x: i8) != (y: i8) = intrinsics.! (x == y)+ let (x: i8) != (y: i8) = !(x == y) let sgn (x: i8) = intrinsics.ssignum8 x let abs (x: i8) = intrinsics.abs8 x@@ -298,7 +304,7 @@ let num_bits = 8i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc = intrinsics.popc8 let mul_hi a b = intrinsics.mul_hi8 (i8 a, i8 b) let mad_hi a b c = intrinsics.mad_hi8 (i8 a, i8 b, i8 c)@@ -326,7 +332,7 @@ let (x: i16) & (y: i16) = intrinsics.and16 (x, y) let (x: i16) | (y: i16) = intrinsics.or16 (x, y) let (x: i16) ^ (y: i16) = intrinsics.xor16 (x, y)- let ! (x: i16) = intrinsics.complement16 x+ let not (x: i16) = intrinsics.complement16 x let (x: i16) << (y: i16) = intrinsics.shl16 (x, y) let (x: i16) >> (y: i16) = intrinsics.ashr16 (x, y)@@ -342,6 +348,7 @@ let u32 (x: u32) = intrinsics.zext_i32_i16 (intrinsics.sign_i32 x) let u64 (x: u64) = intrinsics.zext_i64_i16 (intrinsics.sign_i64 x) + let f16 (x: f16) = intrinsics.fptosi_f16_i16 x let f32 (x: f32) = intrinsics.fptosi_f32_i16 x let f64 (x: f64) = intrinsics.fptosi_f64_i16 x @@ -355,7 +362,7 @@ let (x: i16) > (y: i16) = intrinsics.slt16 (y, x) let (x: i16) <= (y: i16) = intrinsics.sle16 (x, y) let (x: i16) >= (y: i16) = intrinsics.sle16 (y, x)- let (x: i16) != (y: i16) = intrinsics.! (x == y)+ let (x: i16) != (y: i16) = !(x == y) let sgn (x: i16) = intrinsics.ssignum16 x let abs (x: i16) = intrinsics.abs16 x@@ -370,7 +377,7 @@ let num_bits = 16i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc = intrinsics.popc16 let mul_hi a b = intrinsics.mul_hi16 (i16 a, i16 b) let mad_hi a b c = intrinsics.mad_hi16 (i16 a, i16 b, i16 c)@@ -401,7 +408,7 @@ let (x: i32) & (y: i32) = intrinsics.and32 (x, y) let (x: i32) | (y: i32) = intrinsics.or32 (x, y) let (x: i32) ^ (y: i32) = intrinsics.xor32 (x, y)- let ! (x: i32) = intrinsics.complement32 x+ let not (x: i32) = intrinsics.complement32 x let (x: i32) << (y: i32) = intrinsics.shl32 (x, y) let (x: i32) >> (y: i32) = intrinsics.ashr32 (x, y)@@ -417,6 +424,7 @@ let u32 (x: u32) = intrinsics.zext_i32_i32 (intrinsics.sign_i32 x) let u64 (x: u64) = intrinsics.zext_i64_i32 (intrinsics.sign_i64 x) + let f16 (x: f16) = intrinsics.fptosi_f16_i32 x let f32 (x: f32) = intrinsics.fptosi_f32_i32 x let f64 (x: f64) = intrinsics.fptosi_f64_i32 x @@ -430,7 +438,7 @@ let (x: i32) > (y: i32) = intrinsics.slt32 (y, x) let (x: i32) <= (y: i32) = intrinsics.sle32 (x, y) let (x: i32) >= (y: i32) = intrinsics.sle32 (y, x)- let (x: i32) != (y: i32) = intrinsics.! (x == y)+ let (x: i32) != (y: i32) = !(x == y) let sgn (x: i32) = intrinsics.ssignum32 x let abs (x: i32) = intrinsics.abs32 x@@ -445,7 +453,7 @@ let num_bits = 32i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc = intrinsics.popc32 let mul_hi a b = intrinsics.mul_hi32 (i32 a, i32 b) let mad_hi a b c = intrinsics.mad_hi32 (i32 a, i32 b, i32 c)@@ -476,7 +484,7 @@ let (x: i64) & (y: i64) = intrinsics.and64 (x, y) let (x: i64) | (y: i64) = intrinsics.or64 (x, y) let (x: i64) ^ (y: i64) = intrinsics.xor64 (x, y)- let ! (x: i64) = intrinsics.complement64 x+ let not (x: i64) = intrinsics.complement64 x let (x: i64) << (y: i64) = intrinsics.shl64 (x, y) let (x: i64) >> (y: i64) = intrinsics.ashr64 (x, y)@@ -492,6 +500,7 @@ let u32 (x: u32) = intrinsics.zext_i32_i64 (intrinsics.sign_i32 x) let u64 (x: u64) = intrinsics.zext_i64_i64 (intrinsics.sign_i64 x) + let f16 (x: f16) = intrinsics.fptosi_f16_i64 x let f32 (x: f32) = intrinsics.fptosi_f32_i64 x let f64 (x: f64) = intrinsics.fptosi_f64_i64 x @@ -505,7 +514,7 @@ let (x: i64) > (y: i64) = intrinsics.slt64 (y, x) let (x: i64) <= (y: i64) = intrinsics.sle64 (x, y) let (x: i64) >= (y: i64) = intrinsics.sle64 (y, x)- let (x: i64) != (y: i64) = intrinsics.! (x == y)+ let (x: i64) != (y: i64) = !(x == y) let sgn (x: i64) = intrinsics.ssignum64 x let abs (x: i64) = intrinsics.abs64 x@@ -520,7 +529,7 @@ let num_bits = 64i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | intrinsics.zext_i32_i64 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | intrinsics.zext_i32_i64 (b intrinsics.<< bit)) let popc = intrinsics.popc64 let mul_hi a b = intrinsics.mul_hi64 (i64 a, i64 b) let mad_hi a b c = intrinsics.mad_hi64 (i64 a, i64 b, i64 c)@@ -551,7 +560,7 @@ let (x: u8) & (y: u8) = unsign (intrinsics.and8 (sign x, sign y)) let (x: u8) | (y: u8) = unsign (intrinsics.or8 (sign x, sign y)) let (x: u8) ^ (y: u8) = unsign (intrinsics.xor8 (sign x, sign y))- let ! (x: u8) = unsign (intrinsics.complement8 (sign x))+ let not (x: u8) = unsign (intrinsics.complement8 (sign x)) let (x: u8) << (y: u8) = unsign (intrinsics.shl8 (sign x, sign y)) let (x: u8) >> (y: u8) = unsign (intrinsics.ashr8 (sign x, sign y))@@ -567,6 +576,7 @@ let i32 (x: i32) = unsign (intrinsics.zext_i32_i8 x) let i64 (x: i64) = unsign (intrinsics.zext_i64_i8 x) + let f16 (x: f16) = unsign (intrinsics.fptoui_f16_i8 x) let f32 (x: f32) = unsign (intrinsics.fptoui_f32_i8 x) let f64 (x: f64) = unsign (intrinsics.fptoui_f64_i8 x) @@ -580,7 +590,7 @@ let (x: u8) > (y: u8) = intrinsics.ult8 (sign y, sign x) let (x: u8) <= (y: u8) = intrinsics.ule8 (sign x, sign y) let (x: u8) >= (y: u8) = intrinsics.ule8 (sign y, sign x)- let (x: u8) != (y: u8) = intrinsics.! (x == y)+ let (x: u8) != (y: u8) = !(x == y) let sgn (x: u8) = unsign (intrinsics.usignum8 (sign x)) let abs (x: u8) = x@@ -595,7 +605,7 @@ let num_bits = 8i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc x = intrinsics.popc8 (sign x) let mul_hi a b = unsign (intrinsics.mul_hi8 (sign a, sign b)) let mad_hi a b c = unsign (intrinsics.mad_hi8 (sign a, sign b, sign c))@@ -626,7 +636,7 @@ let (x: u16) & (y: u16) = unsign (intrinsics.and16 (sign x, sign y)) let (x: u16) | (y: u16) = unsign (intrinsics.or16 (sign x, sign y)) let (x: u16) ^ (y: u16) = unsign (intrinsics.xor16 (sign x, sign y))- let ! (x: u16) = unsign (intrinsics.complement16 (sign x))+ let not (x: u16) = unsign (intrinsics.complement16 (sign x)) let (x: u16) << (y: u16) = unsign (intrinsics.shl16 (sign x, sign y)) let (x: u16) >> (y: u16) = unsign (intrinsics.ashr16 (sign x, sign y))@@ -642,6 +652,7 @@ let i32 (x: i32) = unsign (intrinsics.zext_i32_i16 x) let i64 (x: i64) = unsign (intrinsics.zext_i64_i16 x) + let f16 (x: f16) = unsign (intrinsics.fptoui_f16_i16 x) let f32 (x: f32) = unsign (intrinsics.fptoui_f32_i16 x) let f64 (x: f64) = unsign (intrinsics.fptoui_f64_i16 x) @@ -655,7 +666,7 @@ let (x: u16) > (y: u16) = intrinsics.ult16 (sign y, sign x) let (x: u16) <= (y: u16) = intrinsics.ule16 (sign x, sign y) let (x: u16) >= (y: u16) = intrinsics.ule16 (sign y, sign x)- let (x: u16) != (y: u16) = intrinsics.! (x == y)+ let (x: u16) != (y: u16) = !(x == y) let sgn (x: u16) = unsign (intrinsics.usignum16 (sign x)) let abs (x: u16) = x@@ -670,7 +681,7 @@ let num_bits = 16i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc x = intrinsics.popc16 (sign x) let mul_hi a b = unsign (intrinsics.mul_hi16 (sign a, sign b)) let mad_hi a b c = unsign (intrinsics.mad_hi16 (sign a, sign b, sign c))@@ -701,7 +712,7 @@ let (x: u32) & (y: u32) = unsign (intrinsics.and32 (sign x, sign y)) let (x: u32) | (y: u32) = unsign (intrinsics.or32 (sign x, sign y)) let (x: u32) ^ (y: u32) = unsign (intrinsics.xor32 (sign x, sign y))- let ! (x: u32) = unsign (intrinsics.complement32 (sign x))+ let not (x: u32) = unsign (intrinsics.complement32 (sign x)) let (x: u32) << (y: u32) = unsign (intrinsics.shl32 (sign x, sign y)) let (x: u32) >> (y: u32) = unsign (intrinsics.ashr32 (sign x, sign y))@@ -717,6 +728,7 @@ let i32 (x: i32) = unsign (intrinsics.zext_i32_i32 x) let i64 (x: i64) = unsign (intrinsics.zext_i64_i32 x) + let f16 (x: f16) = unsign (intrinsics.fptoui_f16_i32 x) let f32 (x: f32) = unsign (intrinsics.fptoui_f32_i32 x) let f64 (x: f64) = unsign (intrinsics.fptoui_f64_i32 x) @@ -730,7 +742,7 @@ let (x: u32) > (y: u32) = intrinsics.ult32 (sign y, sign x) let (x: u32) <= (y: u32) = intrinsics.ule32 (sign x, sign y) let (x: u32) >= (y: u32) = intrinsics.ule32 (sign y, sign x)- let (x: u32) != (y: u32) = intrinsics.! (x == y)+ let (x: u32) != (y: u32) = !(x == y) let sgn (x: u32) = unsign (intrinsics.usignum32 (sign x)) let abs (x: u32) = x@@ -745,7 +757,7 @@ let num_bits = 32i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc x = intrinsics.popc32 (sign x) let mul_hi a b = unsign (intrinsics.mul_hi32 (sign a, sign b)) let mad_hi a b c = unsign (intrinsics.mad_hi32 (sign a, sign b, sign c))@@ -776,7 +788,7 @@ let (x: u64) & (y: u64) = unsign (intrinsics.and64 (sign x, sign y)) let (x: u64) | (y: u64) = unsign (intrinsics.or64 (sign x, sign y)) let (x: u64) ^ (y: u64) = unsign (intrinsics.xor64 (sign x, sign y))- let ! (x: u64) = unsign (intrinsics.complement64 (sign x))+ let not (x: u64) = unsign (intrinsics.complement64 (sign x)) let (x: u64) << (y: u64) = unsign (intrinsics.shl64 (sign x, sign y)) let (x: u64) >> (y: u64) = unsign (intrinsics.ashr64 (sign x, sign y))@@ -792,6 +804,7 @@ let i32 (x: i32) = unsign (intrinsics.zext_i32_i64 x) let i64 (x: i64) = unsign (intrinsics.zext_i64_i64 x) + let f16 (x: f16) = unsign (intrinsics.fptoui_f16_i64 x) let f32 (x: f32) = unsign (intrinsics.fptoui_f32_i64 x) let f64 (x: f64) = unsign (intrinsics.fptoui_f64_i64 x) @@ -805,7 +818,7 @@ let (x: u64) > (y: u64) = intrinsics.ult64 (sign y, sign x) let (x: u64) <= (y: u64) = intrinsics.ule64 (sign x, sign y) let (x: u64) >= (y: u64) = intrinsics.ule64 (sign y, sign x)- let (x: u64) != (y: u64) = intrinsics.! (x == y)+ let (x: u64) != (y: u64) = !(x == y) let sgn (x: u64) = unsign (intrinsics.usignum64 (sign x)) let abs (x: u64) = x@@ -820,7 +833,7 @@ let num_bits = 64i32 let get_bit (bit: i32) (x: t) = to_i32 ((x >> i32 bit) & i32 1) let set_bit (bit: i32) (x: t) (b: i32) =- ((x & i32 (intrinsics.!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit))+ ((x & i32 (!(1 intrinsics.<< bit))) | i32 (b intrinsics.<< bit)) let popc x = intrinsics.popc64 (sign x) let mul_hi a b = unsign (intrinsics.mul_hi64 (sign a, sign b)) let mad_hi a b c = unsign (intrinsics.mad_hi64 (sign a, sign b, sign c))@@ -857,6 +870,7 @@ let i32 (x: i32) = intrinsics.sitofp_i32_f64 x let i64 (x: i64) = intrinsics.sitofp_i64_f64 x + let f16 (x: f16) = intrinsics.fpconv_f16_f64 x let f32 (x: f32) = intrinsics.fpconv_f32_f64 x let f64 (x: f64) = intrinsics.fpconv_f64_f64 x @@ -871,7 +885,7 @@ let (x: f64) > (y: f64) = intrinsics.lt64 (y, x) let (x: f64) <= (y: f64) = intrinsics.le64 (x, y) let (x: f64) >= (y: f64) = intrinsics.le64 (y, x)- let (x: f64) != (y: f64) = intrinsics.! (x == y)+ let (x: f64) != (y: f64) = !(x == y) let neg (x: t) = -x let recip (x: t) = 1/x@@ -965,6 +979,7 @@ let i32 (x: i32) = intrinsics.sitofp_i32_f32 x let i64 (x: i64) = intrinsics.sitofp_i64_f32 x + let f16 (x: f16) = intrinsics.fpconv_f16_f32 x let f32 (x: f32) = intrinsics.fpconv_f32_f32 x let f64 (x: f64) = intrinsics.fpconv_f64_f32 x @@ -979,7 +994,7 @@ let (x: f32) > (y: f32) = intrinsics.lt32 (y, x) let (x: f32) <= (y: f32) = intrinsics.le32 (x, y) let (x: f32) >= (y: f32) = intrinsics.le32 (y, x)- let (x: f32) != (y: f32) = intrinsics.! (x == y)+ let (x: f32) != (y: f32) = !(x == y) let neg (x: t) = -x let recip (x: t) = 1/x@@ -1038,6 +1053,119 @@ let highest = inf let lowest = -inf let epsilon = 1.1920929e-7f32++ let pi = f64 f64m.pi+ let e = f64 f64m.e++ let sum = reduce (+) (i32 0)+ let product = reduce (*) (i32 1)+ let maximum = reduce max lowest+ let minimum = reduce min highest+}++-- | Emulated with single precision on systems that do not natively+-- support half precision. This means you might get more accurate+-- results than on real systems, but it is also likely to be+-- significantly slower than just using `f32` in the first place.+module f16: (float with t = f16 with int_t = u16) = {+ type t = f16+ type int_t = u16++ module i16m = i16+ module u16m = u16+ module f64m = f64++ let (x: f16) + (y: f16) = intrinsics.fadd16 (x, y)+ let (x: f16) - (y: f16) = intrinsics.fsub16 (x, y)+ let (x: f16) * (y: f16) = intrinsics.fmul16 (x, y)+ let (x: f16) / (y: f16) = intrinsics.fdiv16 (x, y)+ let (x: f16) % (y: f16) = intrinsics.fmod16 (x, y)+ let (x: f16) ** (y: f16) = intrinsics.fpow16 (x, y)++ let u8 (x: u8) = intrinsics.uitofp_i8_f16 (i8.u8 x)+ let u16 (x: u16) = intrinsics.uitofp_i16_f16 (i16.u16 x)+ let u32 (x: u32) = intrinsics.uitofp_i32_f16 (i32.u32 x)+ let u64 (x: u64) = intrinsics.uitofp_i64_f16 (i64.u64 x)++ let i8 (x: i8) = intrinsics.sitofp_i8_f16 x+ let i16 (x: i16) = intrinsics.sitofp_i16_f16 x+ let i32 (x: i32) = intrinsics.sitofp_i32_f16 x+ let i64 (x: i64) = intrinsics.sitofp_i64_f16 x++ let f16 (x: f16) = intrinsics.fpconv_f16_f16 x+ let f32 (x: f32) = intrinsics.fpconv_f32_f16 x+ let f64 (x: f64) = intrinsics.fpconv_f64_f16 x++ let bool (x: bool) = if x then 1f16 else 0f16++ let from_fraction (x: i64) (y: i64) = i64 x / i64 y+ let to_i64 (x: f16) = intrinsics.fptosi_f16_i64 x+ let to_f64 (x: f16) = intrinsics.fpconv_f16_f64 x++ let (x: f16) == (y: f16) = intrinsics.eq_f16 (x, y)+ let (x: f16) < (y: f16) = intrinsics.lt16 (x, y)+ let (x: f16) > (y: f16) = intrinsics.lt16 (y, x)+ let (x: f16) <= (y: f16) = intrinsics.le16 (x, y)+ let (x: f16) >= (y: f16) = intrinsics.le16 (y, x)+ let (x: f16) != (y: f16) = !(x == y)++ let neg (x: t) = -x+ let recip (x: t) = 1/x+ let max (x: t) (y: t) = intrinsics.fmax16 (x, y)+ let min (x: t) (y: t) = intrinsics.fmin16 (x, y)++ let sgn (x: f16) = intrinsics.fsignum16 x+ let abs (x: f16) = intrinsics.fabs16 x++ let sqrt (x: f16) = intrinsics.sqrt16 x++ let log (x: f16) = intrinsics.log16 x+ let log2 (x: f16) = intrinsics.log2_16 x+ let log10 (x: f16) = intrinsics.log10_16 x+ let exp (x: f16) = intrinsics.exp16 x+ let sin (x: f16) = intrinsics.sin16 x+ let cos (x: f16) = intrinsics.cos16 x+ let tan (x: f16) = intrinsics.tan16 x+ let acos (x: f16) = intrinsics.acos16 x+ let asin (x: f16) = intrinsics.asin16 x+ let atan (x: f16) = intrinsics.atan16 x+ let sinh (x: f16) = intrinsics.sinh16 x+ let cosh (x: f16) = intrinsics.cosh16 x+ let tanh (x: f16) = intrinsics.tanh16 x+ let acosh (x: f16) = intrinsics.acosh16 x+ let asinh (x: f16) = intrinsics.asinh16 x+ let atanh (x: f16) = intrinsics.atanh16 x+ let atan2 (x: f16) (y: f16) = intrinsics.atan2_16 (x, y)+ let hypot (x: f16) (y: f16) = intrinsics.hypot16 (x, y)+ let gamma = intrinsics.gamma16+ let lgamma = intrinsics.lgamma16++ let lerp v0 v1 t = intrinsics.lerp16 (v0,v1,t)+ let fma a b c = intrinsics.fma16 (a,b,c)+ let mad a b c = intrinsics.mad16 (a,b,c)++ let ceil = intrinsics.ceil16+ let floor = intrinsics.floor16+ let trunc (x: f16) : f16 = i16 (i16m.f16 x)++ let round = intrinsics.round16++ let to_bits (x: f16): u16 = u16m.i16 (intrinsics.to_bits16 x)+ let from_bits (x: u16): f16 = intrinsics.from_bits16 (intrinsics.sign_i16 x)++ let num_bits = 16i32+ let get_bit (bit: i32) (x: t) = u16m.get_bit bit (to_bits x)+ let set_bit (bit: i32) (x: t) (b: i32) = from_bits (u16m.set_bit bit (to_bits x) b)++ let isinf (x: f16) = intrinsics.isinf16 x+ let isnan (x: f16) = intrinsics.isnan16 x++ let inf = 1f16 / 0f16+ let nan = 0f16 / 0f16++ let highest = inf+ let lowest = -inf+ let epsilon = 1.1920929e-7f16 let pi = f64 f64m.pi let e = f64 f64m.e
prelude/prelude.fut view
@@ -20,15 +20,16 @@ -- inhibitor. The compiler will treat this function as a black box. -- You can use this to work around optimisation deficiencies (or -- bugs), although it should hopefully rarely be necessary.+-- Deprecated: use `#[opaque]` attribute instead. let opaque 't (x: t): t =- intrinsics.opaque x+ #[opaque] x --- | Semantically just identity, but when run in the interpreter, the--- argument value will be printed.+-- | Semantically just identity, but at runtime, the argument value+-- will be printed. Deprecated: use `#[trace]` attribute instead. let trace 't (x: t): t =- intrinsics.trace x+ #[trace(trace)] x -- | Semantically just identity, but acts as a break point in--- `futhark repl`.+-- `futhark repl`. Deprecated: use `#[break]` attribute instead. let break 't (x: t): t =- intrinsics.break x+ #[break] x
rts/c/cuda.h view
@@ -345,6 +345,18 @@ opts[i++] = msgprintf("-DLOCKSTEP_WIDTH=%zu", ctx->lockstep_width); opts[i++] = msgprintf("-DMAX_THREADS_PER_BLOCK=%zu", ctx->max_block_size); + // Time for the best lines of the code in the entire compiler.+ if (getenv("CUDA_HOME") != NULL) {+ opts[i++] = msgprintf("-I%s/include", getenv("CUDA_HOME"));+ }+ if (getenv("CUDA_ROOT") != NULL) {+ opts[i++] = msgprintf("-I%s/include", getenv("CUDA_ROOT"));+ }+ if (getenv("CUDA_PATH") != NULL) {+ opts[i++] = msgprintf("-I%s/include", getenv("CUDA_PATH"));+ }+ opts[i++] = msgprintf("-I/usr/local/cuda/include");+ // It is crucial that the extra_opts are last, so that the free() // logic below does not cause problems. for (int j = 0; extra_opts[j] != NULL; j++) {
+ rts/c/half.h view
@@ -0,0 +1,238 @@+// Start of half.h.++// Conversion functions are from http://half.sourceforge.net/, but+// translated to C.+//+// Copyright (c) 2012-2021 Christian Rau+//+// Permission is hereby granted, free of charge, to any person obtaining a copy+// of this software and associated documentation files (the "Software"), to deal+// in the Software without restriction, including without limitation the rights+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+// copies of the Software, and to permit persons to whom the Software is+// furnished to do so, subject to the following conditions:+//+// The above copyright notice and this permission notice shall be included in+// all copies or substantial portions of the Software.+//+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+// THE SOFTWARE.++#ifndef __OPENCL_VERSION__+#define __constant+#endif++__constant static const uint16_t base_table[512] = {+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,+ 0x0200, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, 0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00,+ 0x4000, 0x4400, 0x4800, 0x4C00, 0x5000, 0x5400, 0x5800, 0x5C00, 0x6000, 0x6400, 0x6800, 0x6C00, 0x7000, 0x7400, 0x7800, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,+ 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100,+ 0x8200, 0x8400, 0x8800, 0x8C00, 0x9000, 0x9400, 0x9800, 0x9C00, 0xA000, 0xA400, 0xA800, 0xAC00, 0xB000, 0xB400, 0xB800, 0xBC00,+ 0xC000, 0xC400, 0xC800, 0xCC00, 0xD000, 0xD400, 0xD800, 0xDC00, 0xE000, 0xE400, 0xE800, 0xEC00, 0xF000, 0xF400, 0xF800, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,+ 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00 };++__constant static const unsigned char shift_table[512] = {+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 };++__constant static const uint32_t mantissa_table[2048] = {+ 0x00000000, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34A00000, 0x34C00000, 0x34E00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000, 0x35400000, 0x35500000, 0x35600000, 0x35700000,+ 0x35800000, 0x35880000, 0x35900000, 0x35980000, 0x35A00000, 0x35A80000, 0x35B00000, 0x35B80000, 0x35C00000, 0x35C80000, 0x35D00000, 0x35D80000, 0x35E00000, 0x35E80000, 0x35F00000, 0x35F80000,+ 0x36000000, 0x36040000, 0x36080000, 0x360C0000, 0x36100000, 0x36140000, 0x36180000, 0x361C0000, 0x36200000, 0x36240000, 0x36280000, 0x362C0000, 0x36300000, 0x36340000, 0x36380000, 0x363C0000,+ 0x36400000, 0x36440000, 0x36480000, 0x364C0000, 0x36500000, 0x36540000, 0x36580000, 0x365C0000, 0x36600000, 0x36640000, 0x36680000, 0x366C0000, 0x36700000, 0x36740000, 0x36780000, 0x367C0000,+ 0x36800000, 0x36820000, 0x36840000, 0x36860000, 0x36880000, 0x368A0000, 0x368C0000, 0x368E0000, 0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369A0000, 0x369C0000, 0x369E0000,+ 0x36A00000, 0x36A20000, 0x36A40000, 0x36A60000, 0x36A80000, 0x36AA0000, 0x36AC0000, 0x36AE0000, 0x36B00000, 0x36B20000, 0x36B40000, 0x36B60000, 0x36B80000, 0x36BA0000, 0x36BC0000, 0x36BE0000,+ 0x36C00000, 0x36C20000, 0x36C40000, 0x36C60000, 0x36C80000, 0x36CA0000, 0x36CC0000, 0x36CE0000, 0x36D00000, 0x36D20000, 0x36D40000, 0x36D60000, 0x36D80000, 0x36DA0000, 0x36DC0000, 0x36DE0000,+ 0x36E00000, 0x36E20000, 0x36E40000, 0x36E60000, 0x36E80000, 0x36EA0000, 0x36EC0000, 0x36EE0000, 0x36F00000, 0x36F20000, 0x36F40000, 0x36F60000, 0x36F80000, 0x36FA0000, 0x36FC0000, 0x36FE0000,+ 0x37000000, 0x37010000, 0x37020000, 0x37030000, 0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000, 0x370A0000, 0x370B0000, 0x370C0000, 0x370D0000, 0x370E0000, 0x370F0000,+ 0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000, 0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371A0000, 0x371B0000, 0x371C0000, 0x371D0000, 0x371E0000, 0x371F0000,+ 0x37200000, 0x37210000, 0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000, 0x37280000, 0x37290000, 0x372A0000, 0x372B0000, 0x372C0000, 0x372D0000, 0x372E0000, 0x372F0000,+ 0x37300000, 0x37310000, 0x37320000, 0x37330000, 0x37340000, 0x37350000, 0x37360000, 0x37370000, 0x37380000, 0x37390000, 0x373A0000, 0x373B0000, 0x373C0000, 0x373D0000, 0x373E0000, 0x373F0000,+ 0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, 0x37460000, 0x37470000, 0x37480000, 0x37490000, 0x374A0000, 0x374B0000, 0x374C0000, 0x374D0000, 0x374E0000, 0x374F0000,+ 0x37500000, 0x37510000, 0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000, 0x37580000, 0x37590000, 0x375A0000, 0x375B0000, 0x375C0000, 0x375D0000, 0x375E0000, 0x375F0000,+ 0x37600000, 0x37610000, 0x37620000, 0x37630000, 0x37640000, 0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000, 0x376A0000, 0x376B0000, 0x376C0000, 0x376D0000, 0x376E0000, 0x376F0000,+ 0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, 0x37760000, 0x37770000, 0x37780000, 0x37790000, 0x377A0000, 0x377B0000, 0x377C0000, 0x377D0000, 0x377E0000, 0x377F0000,+ 0x37800000, 0x37808000, 0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000, 0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, 0x37870000, 0x37878000,+ 0x37880000, 0x37888000, 0x37890000, 0x37898000, 0x378A0000, 0x378A8000, 0x378B0000, 0x378B8000, 0x378C0000, 0x378C8000, 0x378D0000, 0x378D8000, 0x378E0000, 0x378E8000, 0x378F0000, 0x378F8000,+ 0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000, 0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000, 0x37960000, 0x37968000, 0x37970000, 0x37978000,+ 0x37980000, 0x37988000, 0x37990000, 0x37998000, 0x379A0000, 0x379A8000, 0x379B0000, 0x379B8000, 0x379C0000, 0x379C8000, 0x379D0000, 0x379D8000, 0x379E0000, 0x379E8000, 0x379F0000, 0x379F8000,+ 0x37A00000, 0x37A08000, 0x37A10000, 0x37A18000, 0x37A20000, 0x37A28000, 0x37A30000, 0x37A38000, 0x37A40000, 0x37A48000, 0x37A50000, 0x37A58000, 0x37A60000, 0x37A68000, 0x37A70000, 0x37A78000,+ 0x37A80000, 0x37A88000, 0x37A90000, 0x37A98000, 0x37AA0000, 0x37AA8000, 0x37AB0000, 0x37AB8000, 0x37AC0000, 0x37AC8000, 0x37AD0000, 0x37AD8000, 0x37AE0000, 0x37AE8000, 0x37AF0000, 0x37AF8000,+ 0x37B00000, 0x37B08000, 0x37B10000, 0x37B18000, 0x37B20000, 0x37B28000, 0x37B30000, 0x37B38000, 0x37B40000, 0x37B48000, 0x37B50000, 0x37B58000, 0x37B60000, 0x37B68000, 0x37B70000, 0x37B78000,+ 0x37B80000, 0x37B88000, 0x37B90000, 0x37B98000, 0x37BA0000, 0x37BA8000, 0x37BB0000, 0x37BB8000, 0x37BC0000, 0x37BC8000, 0x37BD0000, 0x37BD8000, 0x37BE0000, 0x37BE8000, 0x37BF0000, 0x37BF8000,+ 0x37C00000, 0x37C08000, 0x37C10000, 0x37C18000, 0x37C20000, 0x37C28000, 0x37C30000, 0x37C38000, 0x37C40000, 0x37C48000, 0x37C50000, 0x37C58000, 0x37C60000, 0x37C68000, 0x37C70000, 0x37C78000,+ 0x37C80000, 0x37C88000, 0x37C90000, 0x37C98000, 0x37CA0000, 0x37CA8000, 0x37CB0000, 0x37CB8000, 0x37CC0000, 0x37CC8000, 0x37CD0000, 0x37CD8000, 0x37CE0000, 0x37CE8000, 0x37CF0000, 0x37CF8000,+ 0x37D00000, 0x37D08000, 0x37D10000, 0x37D18000, 0x37D20000, 0x37D28000, 0x37D30000, 0x37D38000, 0x37D40000, 0x37D48000, 0x37D50000, 0x37D58000, 0x37D60000, 0x37D68000, 0x37D70000, 0x37D78000,+ 0x37D80000, 0x37D88000, 0x37D90000, 0x37D98000, 0x37DA0000, 0x37DA8000, 0x37DB0000, 0x37DB8000, 0x37DC0000, 0x37DC8000, 0x37DD0000, 0x37DD8000, 0x37DE0000, 0x37DE8000, 0x37DF0000, 0x37DF8000,+ 0x37E00000, 0x37E08000, 0x37E10000, 0x37E18000, 0x37E20000, 0x37E28000, 0x37E30000, 0x37E38000, 0x37E40000, 0x37E48000, 0x37E50000, 0x37E58000, 0x37E60000, 0x37E68000, 0x37E70000, 0x37E78000,+ 0x37E80000, 0x37E88000, 0x37E90000, 0x37E98000, 0x37EA0000, 0x37EA8000, 0x37EB0000, 0x37EB8000, 0x37EC0000, 0x37EC8000, 0x37ED0000, 0x37ED8000, 0x37EE0000, 0x37EE8000, 0x37EF0000, 0x37EF8000,+ 0x37F00000, 0x37F08000, 0x37F10000, 0x37F18000, 0x37F20000, 0x37F28000, 0x37F30000, 0x37F38000, 0x37F40000, 0x37F48000, 0x37F50000, 0x37F58000, 0x37F60000, 0x37F68000, 0x37F70000, 0x37F78000,+ 0x37F80000, 0x37F88000, 0x37F90000, 0x37F98000, 0x37FA0000, 0x37FA8000, 0x37FB0000, 0x37FB8000, 0x37FC0000, 0x37FC8000, 0x37FD0000, 0x37FD8000, 0x37FE0000, 0x37FE8000, 0x37FF0000, 0x37FF8000,+ 0x38000000, 0x38004000, 0x38008000, 0x3800C000, 0x38010000, 0x38014000, 0x38018000, 0x3801C000, 0x38020000, 0x38024000, 0x38028000, 0x3802C000, 0x38030000, 0x38034000, 0x38038000, 0x3803C000,+ 0x38040000, 0x38044000, 0x38048000, 0x3804C000, 0x38050000, 0x38054000, 0x38058000, 0x3805C000, 0x38060000, 0x38064000, 0x38068000, 0x3806C000, 0x38070000, 0x38074000, 0x38078000, 0x3807C000,+ 0x38080000, 0x38084000, 0x38088000, 0x3808C000, 0x38090000, 0x38094000, 0x38098000, 0x3809C000, 0x380A0000, 0x380A4000, 0x380A8000, 0x380AC000, 0x380B0000, 0x380B4000, 0x380B8000, 0x380BC000,+ 0x380C0000, 0x380C4000, 0x380C8000, 0x380CC000, 0x380D0000, 0x380D4000, 0x380D8000, 0x380DC000, 0x380E0000, 0x380E4000, 0x380E8000, 0x380EC000, 0x380F0000, 0x380F4000, 0x380F8000, 0x380FC000,+ 0x38100000, 0x38104000, 0x38108000, 0x3810C000, 0x38110000, 0x38114000, 0x38118000, 0x3811C000, 0x38120000, 0x38124000, 0x38128000, 0x3812C000, 0x38130000, 0x38134000, 0x38138000, 0x3813C000,+ 0x38140000, 0x38144000, 0x38148000, 0x3814C000, 0x38150000, 0x38154000, 0x38158000, 0x3815C000, 0x38160000, 0x38164000, 0x38168000, 0x3816C000, 0x38170000, 0x38174000, 0x38178000, 0x3817C000,+ 0x38180000, 0x38184000, 0x38188000, 0x3818C000, 0x38190000, 0x38194000, 0x38198000, 0x3819C000, 0x381A0000, 0x381A4000, 0x381A8000, 0x381AC000, 0x381B0000, 0x381B4000, 0x381B8000, 0x381BC000,+ 0x381C0000, 0x381C4000, 0x381C8000, 0x381CC000, 0x381D0000, 0x381D4000, 0x381D8000, 0x381DC000, 0x381E0000, 0x381E4000, 0x381E8000, 0x381EC000, 0x381F0000, 0x381F4000, 0x381F8000, 0x381FC000,+ 0x38200000, 0x38204000, 0x38208000, 0x3820C000, 0x38210000, 0x38214000, 0x38218000, 0x3821C000, 0x38220000, 0x38224000, 0x38228000, 0x3822C000, 0x38230000, 0x38234000, 0x38238000, 0x3823C000,+ 0x38240000, 0x38244000, 0x38248000, 0x3824C000, 0x38250000, 0x38254000, 0x38258000, 0x3825C000, 0x38260000, 0x38264000, 0x38268000, 0x3826C000, 0x38270000, 0x38274000, 0x38278000, 0x3827C000,+ 0x38280000, 0x38284000, 0x38288000, 0x3828C000, 0x38290000, 0x38294000, 0x38298000, 0x3829C000, 0x382A0000, 0x382A4000, 0x382A8000, 0x382AC000, 0x382B0000, 0x382B4000, 0x382B8000, 0x382BC000,+ 0x382C0000, 0x382C4000, 0x382C8000, 0x382CC000, 0x382D0000, 0x382D4000, 0x382D8000, 0x382DC000, 0x382E0000, 0x382E4000, 0x382E8000, 0x382EC000, 0x382F0000, 0x382F4000, 0x382F8000, 0x382FC000,+ 0x38300000, 0x38304000, 0x38308000, 0x3830C000, 0x38310000, 0x38314000, 0x38318000, 0x3831C000, 0x38320000, 0x38324000, 0x38328000, 0x3832C000, 0x38330000, 0x38334000, 0x38338000, 0x3833C000,+ 0x38340000, 0x38344000, 0x38348000, 0x3834C000, 0x38350000, 0x38354000, 0x38358000, 0x3835C000, 0x38360000, 0x38364000, 0x38368000, 0x3836C000, 0x38370000, 0x38374000, 0x38378000, 0x3837C000,+ 0x38380000, 0x38384000, 0x38388000, 0x3838C000, 0x38390000, 0x38394000, 0x38398000, 0x3839C000, 0x383A0000, 0x383A4000, 0x383A8000, 0x383AC000, 0x383B0000, 0x383B4000, 0x383B8000, 0x383BC000,+ 0x383C0000, 0x383C4000, 0x383C8000, 0x383CC000, 0x383D0000, 0x383D4000, 0x383D8000, 0x383DC000, 0x383E0000, 0x383E4000, 0x383E8000, 0x383EC000, 0x383F0000, 0x383F4000, 0x383F8000, 0x383FC000,+ 0x38400000, 0x38404000, 0x38408000, 0x3840C000, 0x38410000, 0x38414000, 0x38418000, 0x3841C000, 0x38420000, 0x38424000, 0x38428000, 0x3842C000, 0x38430000, 0x38434000, 0x38438000, 0x3843C000,+ 0x38440000, 0x38444000, 0x38448000, 0x3844C000, 0x38450000, 0x38454000, 0x38458000, 0x3845C000, 0x38460000, 0x38464000, 0x38468000, 0x3846C000, 0x38470000, 0x38474000, 0x38478000, 0x3847C000,+ 0x38480000, 0x38484000, 0x38488000, 0x3848C000, 0x38490000, 0x38494000, 0x38498000, 0x3849C000, 0x384A0000, 0x384A4000, 0x384A8000, 0x384AC000, 0x384B0000, 0x384B4000, 0x384B8000, 0x384BC000,+ 0x384C0000, 0x384C4000, 0x384C8000, 0x384CC000, 0x384D0000, 0x384D4000, 0x384D8000, 0x384DC000, 0x384E0000, 0x384E4000, 0x384E8000, 0x384EC000, 0x384F0000, 0x384F4000, 0x384F8000, 0x384FC000,+ 0x38500000, 0x38504000, 0x38508000, 0x3850C000, 0x38510000, 0x38514000, 0x38518000, 0x3851C000, 0x38520000, 0x38524000, 0x38528000, 0x3852C000, 0x38530000, 0x38534000, 0x38538000, 0x3853C000,+ 0x38540000, 0x38544000, 0x38548000, 0x3854C000, 0x38550000, 0x38554000, 0x38558000, 0x3855C000, 0x38560000, 0x38564000, 0x38568000, 0x3856C000, 0x38570000, 0x38574000, 0x38578000, 0x3857C000,+ 0x38580000, 0x38584000, 0x38588000, 0x3858C000, 0x38590000, 0x38594000, 0x38598000, 0x3859C000, 0x385A0000, 0x385A4000, 0x385A8000, 0x385AC000, 0x385B0000, 0x385B4000, 0x385B8000, 0x385BC000,+ 0x385C0000, 0x385C4000, 0x385C8000, 0x385CC000, 0x385D0000, 0x385D4000, 0x385D8000, 0x385DC000, 0x385E0000, 0x385E4000, 0x385E8000, 0x385EC000, 0x385F0000, 0x385F4000, 0x385F8000, 0x385FC000,+ 0x38600000, 0x38604000, 0x38608000, 0x3860C000, 0x38610000, 0x38614000, 0x38618000, 0x3861C000, 0x38620000, 0x38624000, 0x38628000, 0x3862C000, 0x38630000, 0x38634000, 0x38638000, 0x3863C000,+ 0x38640000, 0x38644000, 0x38648000, 0x3864C000, 0x38650000, 0x38654000, 0x38658000, 0x3865C000, 0x38660000, 0x38664000, 0x38668000, 0x3866C000, 0x38670000, 0x38674000, 0x38678000, 0x3867C000,+ 0x38680000, 0x38684000, 0x38688000, 0x3868C000, 0x38690000, 0x38694000, 0x38698000, 0x3869C000, 0x386A0000, 0x386A4000, 0x386A8000, 0x386AC000, 0x386B0000, 0x386B4000, 0x386B8000, 0x386BC000,+ 0x386C0000, 0x386C4000, 0x386C8000, 0x386CC000, 0x386D0000, 0x386D4000, 0x386D8000, 0x386DC000, 0x386E0000, 0x386E4000, 0x386E8000, 0x386EC000, 0x386F0000, 0x386F4000, 0x386F8000, 0x386FC000,+ 0x38700000, 0x38704000, 0x38708000, 0x3870C000, 0x38710000, 0x38714000, 0x38718000, 0x3871C000, 0x38720000, 0x38724000, 0x38728000, 0x3872C000, 0x38730000, 0x38734000, 0x38738000, 0x3873C000,+ 0x38740000, 0x38744000, 0x38748000, 0x3874C000, 0x38750000, 0x38754000, 0x38758000, 0x3875C000, 0x38760000, 0x38764000, 0x38768000, 0x3876C000, 0x38770000, 0x38774000, 0x38778000, 0x3877C000,+ 0x38780000, 0x38784000, 0x38788000, 0x3878C000, 0x38790000, 0x38794000, 0x38798000, 0x3879C000, 0x387A0000, 0x387A4000, 0x387A8000, 0x387AC000, 0x387B0000, 0x387B4000, 0x387B8000, 0x387BC000,+ 0x387C0000, 0x387C4000, 0x387C8000, 0x387CC000, 0x387D0000, 0x387D4000, 0x387D8000, 0x387DC000, 0x387E0000, 0x387E4000, 0x387E8000, 0x387EC000, 0x387F0000, 0x387F4000, 0x387F8000, 0x387FC000,+ 0x38000000, 0x38002000, 0x38004000, 0x38006000, 0x38008000, 0x3800A000, 0x3800C000, 0x3800E000, 0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801A000, 0x3801C000, 0x3801E000,+ 0x38020000, 0x38022000, 0x38024000, 0x38026000, 0x38028000, 0x3802A000, 0x3802C000, 0x3802E000, 0x38030000, 0x38032000, 0x38034000, 0x38036000, 0x38038000, 0x3803A000, 0x3803C000, 0x3803E000,+ 0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804A000, 0x3804C000, 0x3804E000, 0x38050000, 0x38052000, 0x38054000, 0x38056000, 0x38058000, 0x3805A000, 0x3805C000, 0x3805E000,+ 0x38060000, 0x38062000, 0x38064000, 0x38066000, 0x38068000, 0x3806A000, 0x3806C000, 0x3806E000, 0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807A000, 0x3807C000, 0x3807E000,+ 0x38080000, 0x38082000, 0x38084000, 0x38086000, 0x38088000, 0x3808A000, 0x3808C000, 0x3808E000, 0x38090000, 0x38092000, 0x38094000, 0x38096000, 0x38098000, 0x3809A000, 0x3809C000, 0x3809E000,+ 0x380A0000, 0x380A2000, 0x380A4000, 0x380A6000, 0x380A8000, 0x380AA000, 0x380AC000, 0x380AE000, 0x380B0000, 0x380B2000, 0x380B4000, 0x380B6000, 0x380B8000, 0x380BA000, 0x380BC000, 0x380BE000,+ 0x380C0000, 0x380C2000, 0x380C4000, 0x380C6000, 0x380C8000, 0x380CA000, 0x380CC000, 0x380CE000, 0x380D0000, 0x380D2000, 0x380D4000, 0x380D6000, 0x380D8000, 0x380DA000, 0x380DC000, 0x380DE000,+ 0x380E0000, 0x380E2000, 0x380E4000, 0x380E6000, 0x380E8000, 0x380EA000, 0x380EC000, 0x380EE000, 0x380F0000, 0x380F2000, 0x380F4000, 0x380F6000, 0x380F8000, 0x380FA000, 0x380FC000, 0x380FE000,+ 0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810A000, 0x3810C000, 0x3810E000, 0x38110000, 0x38112000, 0x38114000, 0x38116000, 0x38118000, 0x3811A000, 0x3811C000, 0x3811E000,+ 0x38120000, 0x38122000, 0x38124000, 0x38126000, 0x38128000, 0x3812A000, 0x3812C000, 0x3812E000, 0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813A000, 0x3813C000, 0x3813E000,+ 0x38140000, 0x38142000, 0x38144000, 0x38146000, 0x38148000, 0x3814A000, 0x3814C000, 0x3814E000, 0x38150000, 0x38152000, 0x38154000, 0x38156000, 0x38158000, 0x3815A000, 0x3815C000, 0x3815E000,+ 0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816A000, 0x3816C000, 0x3816E000, 0x38170000, 0x38172000, 0x38174000, 0x38176000, 0x38178000, 0x3817A000, 0x3817C000, 0x3817E000,+ 0x38180000, 0x38182000, 0x38184000, 0x38186000, 0x38188000, 0x3818A000, 0x3818C000, 0x3818E000, 0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819A000, 0x3819C000, 0x3819E000,+ 0x381A0000, 0x381A2000, 0x381A4000, 0x381A6000, 0x381A8000, 0x381AA000, 0x381AC000, 0x381AE000, 0x381B0000, 0x381B2000, 0x381B4000, 0x381B6000, 0x381B8000, 0x381BA000, 0x381BC000, 0x381BE000,+ 0x381C0000, 0x381C2000, 0x381C4000, 0x381C6000, 0x381C8000, 0x381CA000, 0x381CC000, 0x381CE000, 0x381D0000, 0x381D2000, 0x381D4000, 0x381D6000, 0x381D8000, 0x381DA000, 0x381DC000, 0x381DE000,+ 0x381E0000, 0x381E2000, 0x381E4000, 0x381E6000, 0x381E8000, 0x381EA000, 0x381EC000, 0x381EE000, 0x381F0000, 0x381F2000, 0x381F4000, 0x381F6000, 0x381F8000, 0x381FA000, 0x381FC000, 0x381FE000,+ 0x38200000, 0x38202000, 0x38204000, 0x38206000, 0x38208000, 0x3820A000, 0x3820C000, 0x3820E000, 0x38210000, 0x38212000, 0x38214000, 0x38216000, 0x38218000, 0x3821A000, 0x3821C000, 0x3821E000,+ 0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822A000, 0x3822C000, 0x3822E000, 0x38230000, 0x38232000, 0x38234000, 0x38236000, 0x38238000, 0x3823A000, 0x3823C000, 0x3823E000,+ 0x38240000, 0x38242000, 0x38244000, 0x38246000, 0x38248000, 0x3824A000, 0x3824C000, 0x3824E000, 0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825A000, 0x3825C000, 0x3825E000,+ 0x38260000, 0x38262000, 0x38264000, 0x38266000, 0x38268000, 0x3826A000, 0x3826C000, 0x3826E000, 0x38270000, 0x38272000, 0x38274000, 0x38276000, 0x38278000, 0x3827A000, 0x3827C000, 0x3827E000,+ 0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828A000, 0x3828C000, 0x3828E000, 0x38290000, 0x38292000, 0x38294000, 0x38296000, 0x38298000, 0x3829A000, 0x3829C000, 0x3829E000,+ 0x382A0000, 0x382A2000, 0x382A4000, 0x382A6000, 0x382A8000, 0x382AA000, 0x382AC000, 0x382AE000, 0x382B0000, 0x382B2000, 0x382B4000, 0x382B6000, 0x382B8000, 0x382BA000, 0x382BC000, 0x382BE000,+ 0x382C0000, 0x382C2000, 0x382C4000, 0x382C6000, 0x382C8000, 0x382CA000, 0x382CC000, 0x382CE000, 0x382D0000, 0x382D2000, 0x382D4000, 0x382D6000, 0x382D8000, 0x382DA000, 0x382DC000, 0x382DE000,+ 0x382E0000, 0x382E2000, 0x382E4000, 0x382E6000, 0x382E8000, 0x382EA000, 0x382EC000, 0x382EE000, 0x382F0000, 0x382F2000, 0x382F4000, 0x382F6000, 0x382F8000, 0x382FA000, 0x382FC000, 0x382FE000,+ 0x38300000, 0x38302000, 0x38304000, 0x38306000, 0x38308000, 0x3830A000, 0x3830C000, 0x3830E000, 0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831A000, 0x3831C000, 0x3831E000,+ 0x38320000, 0x38322000, 0x38324000, 0x38326000, 0x38328000, 0x3832A000, 0x3832C000, 0x3832E000, 0x38330000, 0x38332000, 0x38334000, 0x38336000, 0x38338000, 0x3833A000, 0x3833C000, 0x3833E000,+ 0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834A000, 0x3834C000, 0x3834E000, 0x38350000, 0x38352000, 0x38354000, 0x38356000, 0x38358000, 0x3835A000, 0x3835C000, 0x3835E000,+ 0x38360000, 0x38362000, 0x38364000, 0x38366000, 0x38368000, 0x3836A000, 0x3836C000, 0x3836E000, 0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837A000, 0x3837C000, 0x3837E000,+ 0x38380000, 0x38382000, 0x38384000, 0x38386000, 0x38388000, 0x3838A000, 0x3838C000, 0x3838E000, 0x38390000, 0x38392000, 0x38394000, 0x38396000, 0x38398000, 0x3839A000, 0x3839C000, 0x3839E000,+ 0x383A0000, 0x383A2000, 0x383A4000, 0x383A6000, 0x383A8000, 0x383AA000, 0x383AC000, 0x383AE000, 0x383B0000, 0x383B2000, 0x383B4000, 0x383B6000, 0x383B8000, 0x383BA000, 0x383BC000, 0x383BE000,+ 0x383C0000, 0x383C2000, 0x383C4000, 0x383C6000, 0x383C8000, 0x383CA000, 0x383CC000, 0x383CE000, 0x383D0000, 0x383D2000, 0x383D4000, 0x383D6000, 0x383D8000, 0x383DA000, 0x383DC000, 0x383DE000,+ 0x383E0000, 0x383E2000, 0x383E4000, 0x383E6000, 0x383E8000, 0x383EA000, 0x383EC000, 0x383EE000, 0x383F0000, 0x383F2000, 0x383F4000, 0x383F6000, 0x383F8000, 0x383FA000, 0x383FC000, 0x383FE000,+ 0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840A000, 0x3840C000, 0x3840E000, 0x38410000, 0x38412000, 0x38414000, 0x38416000, 0x38418000, 0x3841A000, 0x3841C000, 0x3841E000,+ 0x38420000, 0x38422000, 0x38424000, 0x38426000, 0x38428000, 0x3842A000, 0x3842C000, 0x3842E000, 0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843A000, 0x3843C000, 0x3843E000,+ 0x38440000, 0x38442000, 0x38444000, 0x38446000, 0x38448000, 0x3844A000, 0x3844C000, 0x3844E000, 0x38450000, 0x38452000, 0x38454000, 0x38456000, 0x38458000, 0x3845A000, 0x3845C000, 0x3845E000,+ 0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846A000, 0x3846C000, 0x3846E000, 0x38470000, 0x38472000, 0x38474000, 0x38476000, 0x38478000, 0x3847A000, 0x3847C000, 0x3847E000,+ 0x38480000, 0x38482000, 0x38484000, 0x38486000, 0x38488000, 0x3848A000, 0x3848C000, 0x3848E000, 0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849A000, 0x3849C000, 0x3849E000,+ 0x384A0000, 0x384A2000, 0x384A4000, 0x384A6000, 0x384A8000, 0x384AA000, 0x384AC000, 0x384AE000, 0x384B0000, 0x384B2000, 0x384B4000, 0x384B6000, 0x384B8000, 0x384BA000, 0x384BC000, 0x384BE000,+ 0x384C0000, 0x384C2000, 0x384C4000, 0x384C6000, 0x384C8000, 0x384CA000, 0x384CC000, 0x384CE000, 0x384D0000, 0x384D2000, 0x384D4000, 0x384D6000, 0x384D8000, 0x384DA000, 0x384DC000, 0x384DE000,+ 0x384E0000, 0x384E2000, 0x384E4000, 0x384E6000, 0x384E8000, 0x384EA000, 0x384EC000, 0x384EE000, 0x384F0000, 0x384F2000, 0x384F4000, 0x384F6000, 0x384F8000, 0x384FA000, 0x384FC000, 0x384FE000,+ 0x38500000, 0x38502000, 0x38504000, 0x38506000, 0x38508000, 0x3850A000, 0x3850C000, 0x3850E000, 0x38510000, 0x38512000, 0x38514000, 0x38516000, 0x38518000, 0x3851A000, 0x3851C000, 0x3851E000,+ 0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852A000, 0x3852C000, 0x3852E000, 0x38530000, 0x38532000, 0x38534000, 0x38536000, 0x38538000, 0x3853A000, 0x3853C000, 0x3853E000,+ 0x38540000, 0x38542000, 0x38544000, 0x38546000, 0x38548000, 0x3854A000, 0x3854C000, 0x3854E000, 0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855A000, 0x3855C000, 0x3855E000,+ 0x38560000, 0x38562000, 0x38564000, 0x38566000, 0x38568000, 0x3856A000, 0x3856C000, 0x3856E000, 0x38570000, 0x38572000, 0x38574000, 0x38576000, 0x38578000, 0x3857A000, 0x3857C000, 0x3857E000,+ 0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858A000, 0x3858C000, 0x3858E000, 0x38590000, 0x38592000, 0x38594000, 0x38596000, 0x38598000, 0x3859A000, 0x3859C000, 0x3859E000,+ 0x385A0000, 0x385A2000, 0x385A4000, 0x385A6000, 0x385A8000, 0x385AA000, 0x385AC000, 0x385AE000, 0x385B0000, 0x385B2000, 0x385B4000, 0x385B6000, 0x385B8000, 0x385BA000, 0x385BC000, 0x385BE000,+ 0x385C0000, 0x385C2000, 0x385C4000, 0x385C6000, 0x385C8000, 0x385CA000, 0x385CC000, 0x385CE000, 0x385D0000, 0x385D2000, 0x385D4000, 0x385D6000, 0x385D8000, 0x385DA000, 0x385DC000, 0x385DE000,+ 0x385E0000, 0x385E2000, 0x385E4000, 0x385E6000, 0x385E8000, 0x385EA000, 0x385EC000, 0x385EE000, 0x385F0000, 0x385F2000, 0x385F4000, 0x385F6000, 0x385F8000, 0x385FA000, 0x385FC000, 0x385FE000,+ 0x38600000, 0x38602000, 0x38604000, 0x38606000, 0x38608000, 0x3860A000, 0x3860C000, 0x3860E000, 0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861A000, 0x3861C000, 0x3861E000,+ 0x38620000, 0x38622000, 0x38624000, 0x38626000, 0x38628000, 0x3862A000, 0x3862C000, 0x3862E000, 0x38630000, 0x38632000, 0x38634000, 0x38636000, 0x38638000, 0x3863A000, 0x3863C000, 0x3863E000,+ 0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864A000, 0x3864C000, 0x3864E000, 0x38650000, 0x38652000, 0x38654000, 0x38656000, 0x38658000, 0x3865A000, 0x3865C000, 0x3865E000,+ 0x38660000, 0x38662000, 0x38664000, 0x38666000, 0x38668000, 0x3866A000, 0x3866C000, 0x3866E000, 0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867A000, 0x3867C000, 0x3867E000,+ 0x38680000, 0x38682000, 0x38684000, 0x38686000, 0x38688000, 0x3868A000, 0x3868C000, 0x3868E000, 0x38690000, 0x38692000, 0x38694000, 0x38696000, 0x38698000, 0x3869A000, 0x3869C000, 0x3869E000,+ 0x386A0000, 0x386A2000, 0x386A4000, 0x386A6000, 0x386A8000, 0x386AA000, 0x386AC000, 0x386AE000, 0x386B0000, 0x386B2000, 0x386B4000, 0x386B6000, 0x386B8000, 0x386BA000, 0x386BC000, 0x386BE000,+ 0x386C0000, 0x386C2000, 0x386C4000, 0x386C6000, 0x386C8000, 0x386CA000, 0x386CC000, 0x386CE000, 0x386D0000, 0x386D2000, 0x386D4000, 0x386D6000, 0x386D8000, 0x386DA000, 0x386DC000, 0x386DE000,+ 0x386E0000, 0x386E2000, 0x386E4000, 0x386E6000, 0x386E8000, 0x386EA000, 0x386EC000, 0x386EE000, 0x386F0000, 0x386F2000, 0x386F4000, 0x386F6000, 0x386F8000, 0x386FA000, 0x386FC000, 0x386FE000,+ 0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870A000, 0x3870C000, 0x3870E000, 0x38710000, 0x38712000, 0x38714000, 0x38716000, 0x38718000, 0x3871A000, 0x3871C000, 0x3871E000,+ 0x38720000, 0x38722000, 0x38724000, 0x38726000, 0x38728000, 0x3872A000, 0x3872C000, 0x3872E000, 0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873A000, 0x3873C000, 0x3873E000,+ 0x38740000, 0x38742000, 0x38744000, 0x38746000, 0x38748000, 0x3874A000, 0x3874C000, 0x3874E000, 0x38750000, 0x38752000, 0x38754000, 0x38756000, 0x38758000, 0x3875A000, 0x3875C000, 0x3875E000,+ 0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876A000, 0x3876C000, 0x3876E000, 0x38770000, 0x38772000, 0x38774000, 0x38776000, 0x38778000, 0x3877A000, 0x3877C000, 0x3877E000,+ 0x38780000, 0x38782000, 0x38784000, 0x38786000, 0x38788000, 0x3878A000, 0x3878C000, 0x3878E000, 0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879A000, 0x3879C000, 0x3879E000,+ 0x387A0000, 0x387A2000, 0x387A4000, 0x387A6000, 0x387A8000, 0x387AA000, 0x387AC000, 0x387AE000, 0x387B0000, 0x387B2000, 0x387B4000, 0x387B6000, 0x387B8000, 0x387BA000, 0x387BC000, 0x387BE000,+ 0x387C0000, 0x387C2000, 0x387C4000, 0x387C6000, 0x387C8000, 0x387CA000, 0x387CC000, 0x387CE000, 0x387D0000, 0x387D2000, 0x387D4000, 0x387D6000, 0x387D8000, 0x387DA000, 0x387DC000, 0x387DE000,+ 0x387E0000, 0x387E2000, 0x387E4000, 0x387E6000, 0x387E8000, 0x387EA000, 0x387EC000, 0x387EE000, 0x387F0000, 0x387F2000, 0x387F4000, 0x387F6000, 0x387F8000, 0x387FA000, 0x387FC000, 0x387FE000 };+__constant static const uint32_t exponent_table[64] = {+ 0x00000000, 0x00800000, 0x01000000, 0x01800000, 0x02000000, 0x02800000, 0x03000000, 0x03800000, 0x04000000, 0x04800000, 0x05000000, 0x05800000, 0x06000000, 0x06800000, 0x07000000, 0x07800000,+ 0x08000000, 0x08800000, 0x09000000, 0x09800000, 0x0A000000, 0x0A800000, 0x0B000000, 0x0B800000, 0x0C000000, 0x0C800000, 0x0D000000, 0x0D800000, 0x0E000000, 0x0E800000, 0x0F000000, 0x47800000,+ 0x80000000, 0x80800000, 0x81000000, 0x81800000, 0x82000000, 0x82800000, 0x83000000, 0x83800000, 0x84000000, 0x84800000, 0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000,+ 0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8A000000, 0x8A800000, 0x8B000000, 0x8B800000, 0x8C000000, 0x8C800000, 0x8D000000, 0x8D800000, 0x8E000000, 0x8E800000, 0x8F000000, 0xC7800000 };+__constant static const unsigned short offset_table[64] = {+ 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,+ 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024 };++static uint16_t float2halfbits(float value) {+ union { float x; uint32_t y; } u;+ u.x = value;+ uint32_t bits = u.y;++ uint16_t hbits = base_table[bits>>23] + (uint16_t)((bits&0x7FFFFF)>>shift_table[bits>>23]);;++ return hbits;+}++static float halfbits2float(uint16_t value) {+ uint32_t bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];++ union { uint32_t x; float y; } u;+ u.x = bits;+ return u.y;+}++// End of half.h.
rts/c/opencl.h view
@@ -195,7 +195,7 @@ } } -static void opencl_succeed_fatal(unsigned int ret,+static void opencl_succeed_fatal(cl_int ret, const char *call, const char *file, int line) {@@ -205,7 +205,7 @@ } } -static char* opencl_succeed_nonfatal(unsigned int ret,+static char* opencl_succeed_nonfatal(cl_int ret, const char *call, const char *file, int line) {@@ -734,6 +734,12 @@ for (int i = 0; extra_build_opts[i] != NULL; i++) { w += snprintf(compile_opts+w, compile_opts_size-w, "%s ", extra_build_opts[i]);+ }++ // Oclgrind claims to support cl_khr_fp16, but this is not actually+ // the case.+ if (strcmp(device_option.platform_name, "Oclgrind") == 0) {+ w += snprintf(compile_opts+w, compile_opts_size-w, "-DEMULATE_F16 "); } if (ctx->cfg.debugging) {
+ rts/c/scalar.h view
@@ -0,0 +1,1654 @@+// Start of scalar.h.++// Implementation of the primitive scalar operations. Very+// repetitive. This code is inserted directly into both CUDA and+// OpenCL programs, as well as the CPU code, so it has some #ifdefs to+// work everywhere. Some operations are defined as macros because+// this allows us to use them as constant expressions in things like+// array sizes and static initialisers.++// Some of the #ifdefs are because OpenCL uses type-generic functions+// for some operations (e.g. sqrt), while C and CUDA sensibly use+// distinct functions for different precisions (e.g. sqrtf() and+// sqrt()). This is quite annoying. Due to C's unfortunate casting+// rules, it is also really easy to accidentally implement+// floating-point functions in the wrong precision, so be careful.++// Double-precision definitions are only included if the preprocessor+// macro FUTHARK_F64_ENABLED is set.++static inline uint8_t add8(uint8_t x, uint8_t y) {+ return x + y;+}++static inline uint16_t add16(uint16_t x, uint16_t y) {+ return x + y;+}++static inline uint32_t add32(uint32_t x, uint32_t y) {+ return x + y;+}++static inline uint64_t add64(uint64_t x, uint64_t y) {+ return x + y;+}++static inline uint8_t sub8(uint8_t x, uint8_t y) {+ return x - y;+}++static inline uint16_t sub16(uint16_t x, uint16_t y) {+ return x - y;+}++static inline uint32_t sub32(uint32_t x, uint32_t y) {+ return x - y;+}++static inline uint64_t sub64(uint64_t x, uint64_t y) {+ return x - y;+}++static inline uint8_t mul8(uint8_t x, uint8_t y) {+ return x * y;+}++static inline uint16_t mul16(uint16_t x, uint16_t y) {+ return x * y;+}++static inline uint32_t mul32(uint32_t x, uint32_t y) {+ return x * y;+}++static inline uint64_t mul64(uint64_t x, uint64_t y) {+ return x * y;+}++static inline uint8_t udiv8(uint8_t x, uint8_t y) {+ return x / y;+}++static inline uint16_t udiv16(uint16_t x, uint16_t y) {+ return x / y;+}++static inline uint32_t udiv32(uint32_t x, uint32_t y) {+ return x / y;+}++static inline uint64_t udiv64(uint64_t x, uint64_t y) {+ return x / y;+}++static inline uint8_t udiv_up8(uint8_t x, uint8_t y) {+ return (x + y - 1) / y;+}++static inline uint16_t udiv_up16(uint16_t x, uint16_t y) {+ return (x + y - 1) / y;+}++static inline uint32_t udiv_up32(uint32_t x, uint32_t y) {+ return (x + y - 1) / y;+}++static inline uint64_t udiv_up64(uint64_t x, uint64_t y) {+ return (x + y - 1) / y;+}++static inline uint8_t umod8(uint8_t x, uint8_t y) {+ return x % y;+}++static inline uint16_t umod16(uint16_t x, uint16_t y) {+ return x % y;+}++static inline uint32_t umod32(uint32_t x, uint32_t y) {+ return x % y;+}++static inline uint64_t umod64(uint64_t x, uint64_t y) {+ return x % y;+}++static inline uint8_t udiv_safe8(uint8_t x, uint8_t y) {+ return y == 0 ? 0 : x / y;+}++static inline uint16_t udiv_safe16(uint16_t x, uint16_t y) {+ return y == 0 ? 0 : x / y;+}++static inline uint32_t udiv_safe32(uint32_t x, uint32_t y) {+ return y == 0 ? 0 : x / y;+}++static inline uint64_t udiv_safe64(uint64_t x, uint64_t y) {+ return y == 0 ? 0 : x / y;+}++static inline uint8_t udiv_up_safe8(uint8_t x, uint8_t y) {+ return y == 0 ? 0 : (x + y - 1) / y;+}++static inline uint16_t udiv_up_safe16(uint16_t x, uint16_t y) {+ return y == 0 ? 0 : (x + y - 1) / y;+}++static inline uint32_t udiv_up_safe32(uint32_t x, uint32_t y) {+ return y == 0 ? 0 : (x + y - 1) / y;+}++static inline uint64_t udiv_up_safe64(uint64_t x, uint64_t y) {+ return y == 0 ? 0 : (x + y - 1) / y;+}++static inline uint8_t umod_safe8(uint8_t x, uint8_t y) {+ return y == 0 ? 0 : x % y;+}++static inline uint16_t umod_safe16(uint16_t x, uint16_t y) {+ return y == 0 ? 0 : x % y;+}++static inline uint32_t umod_safe32(uint32_t x, uint32_t y) {+ return y == 0 ? 0 : x % y;+}++static inline uint64_t umod_safe64(uint64_t x, uint64_t y) {+ return y == 0 ? 0 : x % y;+}++static inline int8_t sdiv8(int8_t x, int8_t y) {+ int8_t q = x / y;+ int8_t r = x % y;++ return q - ((r != 0 && r < 0 != y < 0) ? 1 : 0);+}++static inline int16_t sdiv16(int16_t x, int16_t y) {+ int16_t q = x / y;+ int16_t r = x % y;++ return q - ((r != 0 && r < 0 != y < 0) ? 1 : 0);+}++static inline int32_t sdiv32(int32_t x, int32_t y) {+ int32_t q = x / y;+ int32_t r = x % y;++ return q - ((r != 0 && r < 0 != y < 0) ? 1 : 0);+}++static inline int64_t sdiv64(int64_t x, int64_t y) {+ int64_t q = x / y;+ int64_t r = x % y;++ return q - ((r != 0 && r < 0 != y < 0) ? 1 : 0);+}++static inline int8_t sdiv_up8(int8_t x, int8_t y) {+ return sdiv8(x + y - 1, y);+}++static inline int16_t sdiv_up16(int16_t x, int16_t y) {+ return sdiv16(x + y - 1, y);+}++static inline int32_t sdiv_up32(int32_t x, int32_t y) {+ return sdiv32(x + y - 1, y);+}++static inline int64_t sdiv_up64(int64_t x, int64_t y) {+ return sdiv64(x + y - 1, y);+}++static inline int8_t smod8(int8_t x, int8_t y) {+ int8_t r = x % y;++ return r + (r == 0 || (x > 0 && y > 0) || (x < 0 && y < 0) ? 0 : y);+}++static inline int16_t smod16(int16_t x, int16_t y) {+ int16_t r = x % y;++ return r + (r == 0 || (x > 0 && y > 0) || (x < 0 && y < 0) ? 0 : y);+}++static inline int32_t smod32(int32_t x, int32_t y) {+ int32_t r = x % y;++ return r + (r == 0 || (x > 0 && y > 0) || (x < 0 && y < 0) ? 0 : y);+}++static inline int64_t smod64(int64_t x, int64_t y) {+ int64_t r = x % y;++ return r + (r == 0 || (x > 0 && y > 0) || (x < 0 && y < 0) ? 0 : y);+}++static inline int8_t sdiv_safe8(int8_t x, int8_t y) {+ return y == 0 ? 0 : sdiv8(x, y);+}++static inline int16_t sdiv_safe16(int16_t x, int16_t y) {+ return y == 0 ? 0 : sdiv16(x, y);+}++static inline int32_t sdiv_safe32(int32_t x, int32_t y) {+ return y == 0 ? 0 : sdiv32(x, y);+}++static inline int64_t sdiv_safe64(int64_t x, int64_t y) {+ return y == 0 ? 0 : sdiv64(x, y);+}++static inline int8_t sdiv_up_safe8(int8_t x, int8_t y) {+ return sdiv_safe8(x + y - 1, y);+}++static inline int16_t sdiv_up_safe16(int16_t x, int16_t y) {+ return sdiv_safe16(x + y - 1, y);+}++static inline int32_t sdiv_up_safe32(int32_t x, int32_t y) {+ return sdiv_safe32(x + y - 1, y);+}++static inline int64_t sdiv_up_safe64(int64_t x, int64_t y) {+ return sdiv_safe64(x + y - 1, y);+}++static inline int8_t smod_safe8(int8_t x, int8_t y) {+ return y == 0 ? 0 : smod8(x, y);+}++static inline int16_t smod_safe16(int16_t x, int16_t y) {+ return y == 0 ? 0 : smod16(x, y);+}++static inline int32_t smod_safe32(int32_t x, int32_t y) {+ return y == 0 ? 0 : smod32(x, y);+}++static inline int64_t smod_safe64(int64_t x, int64_t y) {+ return y == 0 ? 0 : smod64(x, y);+}++static inline int8_t squot8(int8_t x, int8_t y) {+ return x / y;+}++static inline int16_t squot16(int16_t x, int16_t y) {+ return x / y;+}++static inline int32_t squot32(int32_t x, int32_t y) {+ return x / y;+}++static inline int64_t squot64(int64_t x, int64_t y) {+ return x / y;+}++static inline int8_t srem8(int8_t x, int8_t y) {+ return x % y;+}++static inline int16_t srem16(int16_t x, int16_t y) {+ return x % y;+}++static inline int32_t srem32(int32_t x, int32_t y) {+ return x % y;+}++static inline int64_t srem64(int64_t x, int64_t y) {+ return x % y;+}++static inline int8_t squot_safe8(int8_t x, int8_t y) {+ return y == 0 ? 0 : x / y;+}++static inline int16_t squot_safe16(int16_t x, int16_t y) {+ return y == 0 ? 0 : x / y;+}++static inline int32_t squot_safe32(int32_t x, int32_t y) {+ return y == 0 ? 0 : x / y;+}++static inline int64_t squot_safe64(int64_t x, int64_t y) {+ return y == 0 ? 0 : x / y;+}++static inline int8_t srem_safe8(int8_t x, int8_t y) {+ return y == 0 ? 0 : x % y;+}++static inline int16_t srem_safe16(int16_t x, int16_t y) {+ return y == 0 ? 0 : x % y;+}++static inline int32_t srem_safe32(int32_t x, int32_t y) {+ return y == 0 ? 0 : x % y;+}++static inline int64_t srem_safe64(int64_t x, int64_t y) {+ return y == 0 ? 0 : x % y;+}++static inline int8_t smin8(int8_t x, int8_t y) {+ return x < y ? x : y;+}++static inline int16_t smin16(int16_t x, int16_t y) {+ return x < y ? x : y;+}++static inline int32_t smin32(int32_t x, int32_t y) {+ return x < y ? x : y;+}++static inline int64_t smin64(int64_t x, int64_t y) {+ return x < y ? x : y;+}++static inline uint8_t umin8(uint8_t x, uint8_t y) {+ return x < y ? x : y;+}++static inline uint16_t umin16(uint16_t x, uint16_t y) {+ return x < y ? x : y;+}++static inline uint32_t umin32(uint32_t x, uint32_t y) {+ return x < y ? x : y;+}++static inline uint64_t umin64(uint64_t x, uint64_t y) {+ return x < y ? x : y;+}++static inline int8_t smax8(int8_t x, int8_t y) {+ return x < y ? y : x;+}++static inline int16_t smax16(int16_t x, int16_t y) {+ return x < y ? y : x;+}++static inline int32_t smax32(int32_t x, int32_t y) {+ return x < y ? y : x;+}++static inline int64_t smax64(int64_t x, int64_t y) {+ return x < y ? y : x;+}++static inline uint8_t umax8(uint8_t x, uint8_t y) {+ return x < y ? y : x;+}++static inline uint16_t umax16(uint16_t x, uint16_t y) {+ return x < y ? y : x;+}++static inline uint32_t umax32(uint32_t x, uint32_t y) {+ return x < y ? y : x;+}++static inline uint64_t umax64(uint64_t x, uint64_t y) {+ return x < y ? y : x;+}++static inline uint8_t shl8(uint8_t x, uint8_t y) {+ return (uint8_t)(x << y);+}++static inline uint16_t shl16(uint16_t x, uint16_t y) {+ return (uint16_t)(x << y);+}++static inline uint32_t shl32(uint32_t x, uint32_t y) {+ return x << y;+}++static inline uint64_t shl64(uint64_t x, uint64_t y) {+ return x << y;+}++static inline uint8_t lshr8(uint8_t x, uint8_t y) {+ return x >> y;+}++static inline uint16_t lshr16(uint16_t x, uint16_t y) {+ return x >> y;+}++static inline uint32_t lshr32(uint32_t x, uint32_t y) {+ return x >> y;+}++static inline uint64_t lshr64(uint64_t x, uint64_t y) {+ return x >> y;+}++static inline int8_t ashr8(int8_t x, int8_t y) {+ return x >> y;+}++static inline int16_t ashr16(int16_t x, int16_t y) {+ return x >> y;+}++static inline int32_t ashr32(int32_t x, int32_t y) {+ return x >> y;+}++static inline int64_t ashr64(int64_t x, int64_t y) {+ return x >> y;+}++static inline uint8_t and8(uint8_t x, uint8_t y) {+ return x & y;+}++static inline uint16_t and16(uint16_t x, uint16_t y) {+ return x & y;+}++static inline uint32_t and32(uint32_t x, uint32_t y) {+ return x & y;+}++static inline uint64_t and64(uint64_t x, uint64_t y) {+ return x & y;+}++static inline uint8_t or8(uint8_t x, uint8_t y) {+ return x | y;+}++static inline uint16_t or16(uint16_t x, uint16_t y) {+ return x | y;+}++static inline uint32_t or32(uint32_t x, uint32_t y) {+ return x | y;+}++static inline uint64_t or64(uint64_t x, uint64_t y) {+ return x | y;+}++static inline uint8_t xor8(uint8_t x, uint8_t y) {+ return x ^ y;+}++static inline uint16_t xor16(uint16_t x, uint16_t y) {+ return x ^ y;+}++static inline uint32_t xor32(uint32_t x, uint32_t y) {+ return x ^ y;+}++static inline uint64_t xor64(uint64_t x, uint64_t y) {+ return x ^ y;+}++static inline bool ult8(uint8_t x, uint8_t y) {+ return x < y;+}++static inline bool ult16(uint16_t x, uint16_t y) {+ return x < y;+}++static inline bool ult32(uint32_t x, uint32_t y) {+ return x < y;+}++static inline bool ult64(uint64_t x, uint64_t y) {+ return x < y;+}++static inline bool ule8(uint8_t x, uint8_t y) {+ return x <= y;+}++static inline bool ule16(uint16_t x, uint16_t y) {+ return x <= y;+}++static inline bool ule32(uint32_t x, uint32_t y) {+ return x <= y;+}++static inline bool ule64(uint64_t x, uint64_t y) {+ return x <= y;+}++static inline bool slt8(int8_t x, int8_t y) {+ return x < y;+}++static inline bool slt16(int16_t x, int16_t y) {+ return x < y;+}++static inline bool slt32(int32_t x, int32_t y) {+ return x < y;+}++static inline bool slt64(int64_t x, int64_t y) {+ return x < y;+}++static inline bool sle8(int8_t x, int8_t y) {+ return x <= y;+}++static inline bool sle16(int16_t x, int16_t y) {+ return x <= y;+}++static inline bool sle32(int32_t x, int32_t y) {+ return x <= y;+}++static inline bool sle64(int64_t x, int64_t y) {+ return x <= y;+}++static inline uint8_t pow8(uint8_t x, uint8_t y) {+ uint8_t res = 1, rem = y;++ while (rem != 0) {+ if (rem & 1)+ res *= x;+ rem >>= 1;+ x *= x;+ }+ return res;+}++static inline uint16_t pow16(uint16_t x, uint16_t y) {+ uint16_t res = 1, rem = y;++ while (rem != 0) {+ if (rem & 1)+ res *= x;+ rem >>= 1;+ x *= x;+ }+ return res;+}++static inline uint32_t pow32(uint32_t x, uint32_t y) {+ uint32_t res = 1, rem = y;++ while (rem != 0) {+ if (rem & 1)+ res *= x;+ rem >>= 1;+ x *= x;+ }+ return res;+}++static inline uint64_t pow64(uint64_t x, uint64_t y) {+ uint64_t res = 1, rem = y;++ while (rem != 0) {+ if (rem & 1)+ res *= x;+ rem >>= 1;+ x *= x;+ }+ return res;+}++static inline bool itob_i8_bool(int8_t x) {+ return x;+}++static inline bool itob_i16_bool(int16_t x) {+ return x;+}++static inline bool itob_i32_bool(int32_t x) {+ return x;+}++static inline bool itob_i64_bool(int64_t x) {+ return x;+}++static inline int8_t btoi_bool_i8(bool x) {+ return x;+}++static inline int16_t btoi_bool_i16(bool x) {+ return x;+}++static inline int32_t btoi_bool_i32(bool x) {+ return x;+}++static inline int64_t btoi_bool_i64(bool x) {+ return x;+}++#define sext_i8_i8(x) ((int8_t) (int8_t) (x))+#define sext_i8_i16(x) ((int16_t) (int8_t) (x))+#define sext_i8_i32(x) ((int32_t) (int8_t) (x))+#define sext_i8_i64(x) ((int64_t) (int8_t) (x))+#define sext_i16_i8(x) ((int8_t) (int16_t) (x))+#define sext_i16_i16(x) ((int16_t) (int16_t) (x))+#define sext_i16_i32(x) ((int32_t) (int16_t) (x))+#define sext_i16_i64(x) ((int64_t) (int16_t) (x))+#define sext_i32_i8(x) ((int8_t) (int32_t) (x))+#define sext_i32_i16(x) ((int16_t) (int32_t) (x))+#define sext_i32_i32(x) ((int32_t) (int32_t) (x))+#define sext_i32_i64(x) ((int64_t) (int32_t) (x))+#define sext_i64_i8(x) ((int8_t) (int64_t) (x))+#define sext_i64_i16(x) ((int16_t) (int64_t) (x))+#define sext_i64_i32(x) ((int32_t) (int64_t) (x))+#define sext_i64_i64(x) ((int64_t) (int64_t) (x))+#define zext_i8_i8(x) ((int8_t) (uint8_t) (x))+#define zext_i8_i16(x) ((int16_t) (uint8_t) (x))+#define zext_i8_i32(x) ((int32_t) (uint8_t) (x))+#define zext_i8_i64(x) ((int64_t) (uint8_t) (x))+#define zext_i16_i8(x) ((int8_t) (uint16_t) (x))+#define zext_i16_i16(x) ((int16_t) (uint16_t) (x))+#define zext_i16_i32(x) ((int32_t) (uint16_t) (x))+#define zext_i16_i64(x) ((int64_t) (uint16_t) (x))+#define zext_i32_i8(x) ((int8_t) (uint32_t) (x))+#define zext_i32_i16(x) ((int16_t) (uint32_t) (x))+#define zext_i32_i32(x) ((int32_t) (uint32_t) (x))+#define zext_i32_i64(x) ((int64_t) (uint32_t) (x))+#define zext_i64_i8(x) ((int8_t) (uint64_t) (x))+#define zext_i64_i16(x) ((int16_t) (uint64_t) (x))+#define zext_i64_i32(x) ((int32_t) (uint64_t) (x))+#define zext_i64_i64(x) ((int64_t) (uint64_t) (x))++static int8_t abs8(int8_t x) {+ return (int8_t)abs(x);+}++static int16_t abs16(int16_t x) {+ return (int16_t)abs(x);+}++static int32_t abs32(int32_t x) {+ return abs(x);+}++static int64_t abs64(int64_t x) {+#if defined(__OPENCL_VERSION__)+ return abs(x);+#else+ return llabs(x);+#endif+}++#if defined(__OPENCL_VERSION__)+static int32_t futrts_popc8(int8_t x) {+ return popcount(x);+}++static int32_t futrts_popc16(int16_t x) {+ return popcount(x);+}++static int32_t futrts_popc32(int32_t x) {+ return popcount(x);+}++static int32_t futrts_popc64(int64_t x) {+ return popcount(x);+}+#elif defined(__CUDA_ARCH__)++static int32_t futrts_popc8(int8_t x) {+ return __popc(zext_i8_i32(x));+}++static int32_t futrts_popc16(int16_t x) {+ return __popc(zext_i16_i32(x));+}++static int32_t futrts_popc32(int32_t x) {+ return __popc(x);+}++static int32_t futrts_popc64(int64_t x) {+ return __popcll(x);+}++#else // Not OpenCL or CUDA, but plain C.++static int32_t futrts_popc8(uint8_t x) {+ int c = 0;+ for (; x; ++c) { x &= x - 1; }+ return c;+}++static int32_t futrts_popc16(uint16_t x) {+ int c = 0;+ for (; x; ++c) { x &= x - 1; }+ return c;+}++static int32_t futrts_popc32(uint32_t x) {+ int c = 0;+ for (; x; ++c) { x &= x - 1; }+ return c;+}++static int32_t futrts_popc64(uint64_t x) {+ int c = 0;+ for (; x; ++c) { x &= x - 1; }+ return c;+}+#endif++#if defined(__OPENCL_VERSION__)+static uint8_t futrts_mul_hi8(uint8_t a, uint8_t b) {+ return mul_hi(a, b);+}++static uint16_t futrts_mul_hi16(uint16_t a, uint16_t b) {+ return mul_hi(a, b);+}++static uint32_t futrts_mul_hi32(uint32_t a, uint32_t b) {+ return mul_hi(a, b);+}++static uint64_t futrts_mul_hi64(uint64_t a, uint64_t b) {+ return mul_hi(a, b);+}++#elif defined(__CUDA_ARCH__)++static uint8_t futrts_mul_hi8(uint8_t a, uint8_t b) {+ uint16_t aa = a;+ uint16_t bb = b;++ return aa * bb >> 8;+}++static uint16_t futrts_mul_hi16(uint16_t a, uint16_t b) {+ uint32_t aa = a;+ uint32_t bb = b;++ return aa * bb >> 16;+}++static uint32_t futrts_mul_hi32(uint32_t a, uint32_t b) {+ return mulhi(a, b);+}++static uint64_t futrts_mul_hi64(uint64_t a, uint64_t b) {+ return mul64hi(a, b);+}++#else // Not OpenCL or CUDA, but plain C.++static uint8_t futrts_mul_hi8(uint8_t a, uint8_t b) {+ uint16_t aa = a;+ uint16_t bb = b;++ return aa * bb >> 8;+}++static uint16_t futrts_mul_hi16(uint16_t a, uint16_t b) {+ uint32_t aa = a;+ uint32_t bb = b;++ return aa * bb >> 16;+}++static uint32_t futrts_mul_hi32(uint32_t a, uint32_t b) {+ uint64_t aa = a;+ uint64_t bb = b;++ return aa * bb >> 32;+}++static uint64_t futrts_mul_hi64(uint64_t a, uint64_t b) {+ __uint128_t aa = a;+ __uint128_t bb = b;++ return aa * bb >> 64;+}+#endif++#if defined(__OPENCL_VERSION__)+static uint8_t futrts_mad_hi8(uint8_t a, uint8_t b, uint8_t c) {+ return mad_hi(a, b, c);+}++static uint16_t futrts_mad_hi16(uint16_t a, uint16_t b, uint16_t c) {+ return mad_hi(a, b, c);+}++static uint32_t futrts_mad_hi32(uint32_t a, uint32_t b, uint32_t c) {+ return mad_hi(a, b, c);+}++static uint64_t futrts_mad_hi64(uint64_t a, uint64_t b, uint64_t c) {+ return mad_hi(a, b, c);+}++#else // Not OpenCL++static uint8_t futrts_mad_hi8(uint8_t a, uint8_t b, uint8_t c) {+ return futrts_mul_hi8(a, b) + c;+}++static uint16_t futrts_mad_hi16(uint16_t a, uint16_t b, uint16_t c) {+ return futrts_mul_hi16(a, b) + c;+}++static uint32_t futrts_mad_hi32(uint32_t a, uint32_t b, uint32_t c) {+ return futrts_mul_hi32(a, b) + c;+}++static uint64_t futrts_mad_hi64(uint64_t a, uint64_t b, uint64_t c) {+ return futrts_mul_hi64(a, b) + c;+}+#endif++#if defined(__OPENCL_VERSION__)+static int32_t futrts_clzz8(int8_t x) {+ return clz(x);+}++static int32_t futrts_clzz16(int16_t x) {+ return clz(x);+}++static int32_t futrts_clzz32(int32_t x) {+ return clz(x);+}++static int32_t futrts_clzz64(int64_t x) {+ return clz(x);+}++#elif defined(__CUDA_ARCH__)++static int32_t futrts_clzz8(int8_t x) {+ return __clz(zext_i8_i32(x)) - 24;+}++static int32_t futrts_clzz16(int16_t x) {+ return __clz(zext_i16_i32(x)) - 16;+}++static int32_t futrts_clzz32(int32_t x) {+ return __clz(x);+}++static int32_t futrts_clzz64(int64_t x) {+ return __clzll(x);+}++#else // Not OpenCL or CUDA, but plain C.++static int32_t futrts_clzz8(int8_t x) {+ return x == 0 ? 8 : __builtin_clz((uint32_t)zext_i8_i32(x)) - 24;+}++static int32_t futrts_clzz16(int16_t x) {+ return x == 0 ? 16 : __builtin_clz((uint32_t)zext_i16_i32(x)) - 16;+}++static int32_t futrts_clzz32(int32_t x) {+ return x == 0 ? 32 : __builtin_clz((uint32_t)x);+}++static int32_t futrts_clzz64(int64_t x) {+ return x == 0 ? 64 : __builtin_clzll((uint64_t)x);+}+#endif++#if defined(__OPENCL_VERSION__)+static int32_t futrts_ctzz8(int8_t x) {+ int i = 0;+ for (; i < 8 && (x & 1) == 0; i++, x >>= 1)+ ;+ return i;+}++static int32_t futrts_ctzz16(int16_t x) {+ int i = 0;+ for (; i < 16 && (x & 1) == 0; i++, x >>= 1)+ ;+ return i;+}++static int32_t futrts_ctzz32(int32_t x) {+ int i = 0;+ for (; i < 32 && (x & 1) == 0; i++, x >>= 1)+ ;+ return i;+}++static int32_t futrts_ctzz64(int64_t x) {+ int i = 0;+ for (; i < 64 && (x & 1) == 0; i++, x >>= 1)+ ;+ return i;+}++#elif defined(__CUDA_ARCH__)++static int32_t futrts_ctzz8(int8_t x) {+ int y = __ffs(x);+ return y == 0 ? 8 : y - 1;+}++static int32_t futrts_ctzz16(int16_t x) {+ int y = __ffs(x);+ return y == 0 ? 16 : y - 1;+}++static int32_t futrts_ctzz32(int32_t x) {+ int y = __ffs(x);+ return y == 0 ? 32 : y - 1;+}++static int32_t futrts_ctzz64(int64_t x) {+ int y = __ffsll(x);+ return y == 0 ? 64 : y - 1;+}++#else // Not OpenCL or CUDA, but plain C.++static int32_t futrts_ctzz8(int8_t x) {+ return x == 0 ? 8 : __builtin_ctz((uint32_t)x);+}++static int32_t futrts_ctzz16(int16_t x) {+ return x == 0 ? 16 : __builtin_ctz((uint32_t)x);+}++static int32_t futrts_ctzz32(int32_t x) {+ return x == 0 ? 32 : __builtin_ctz((uint32_t)x);+}++static int32_t futrts_ctzz64(int64_t x) {+ return x == 0 ? 64 : __builtin_ctzll((uint64_t)x);+}+#endif++static inline float fdiv32(float x, float y) {+ return x / y;+}++static inline float fadd32(float x, float y) {+ return x + y;+}++static inline float fsub32(float x, float y) {+ return x - y;+}++static inline float fmul32(float x, float y) {+ return x * y;+}++static inline bool cmplt32(float x, float y) {+ return x < y;+}++static inline bool cmple32(float x, float y) {+ return x <= y;+}++static inline float sitofp_i8_f32(int8_t x) {+ return (float) x;+}++static inline float sitofp_i16_f32(int16_t x) {+ return (float) x;+}++static inline float sitofp_i32_f32(int32_t x) {+ return (float) x;+}++static inline float sitofp_i64_f32(int64_t x) {+ return (float) x;+}++static inline float uitofp_i8_f32(uint8_t x) {+ return (float) x;+}++static inline float uitofp_i16_f32(uint16_t x) {+ return (float) x;+}++static inline float uitofp_i32_f32(uint32_t x) {+ return (float) x;+}++static inline float uitofp_i64_f32(uint64_t x) {+ return (float) x;+}++static inline int8_t fptosi_f32_i8(float x) {+ return (int8_t) x;+}++static inline int16_t fptosi_f32_i16(float x) {+ return (int16_t) x;+}++static inline int32_t fptosi_f32_i32(float x) {+ return (int32_t) x;+}++static inline int64_t fptosi_f32_i64(float x) {+ return (int64_t) x;+}++static inline uint8_t fptoui_f32_i8(float x) {+ return (uint8_t) x;+}++static inline uint16_t fptoui_f32_i16(float x) {+ return (uint16_t) x;+}++static inline uint32_t fptoui_f32_i32(float x) {+ return (uint32_t) x;+}++static inline uint64_t fptoui_f32_i64(float x) {+ return (uint64_t) x;+}++#ifdef __OPENCL_VERSION__+static inline float fabs32(float x) {+ return fabs(x);+}++static inline float fmax32(float x, float y) {+ return fmax(x, y);+}++static inline float fmin32(float x, float y) {+ return fmin(x, y);+}++static inline float fpow32(float x, float y) {+ return pow(x, y);+}++#else // Not OpenCL, but CUDA or plain C.++static inline float fabs32(float x) {+ return fabsf(x);+}++static inline float fmax32(float x, float y) {+ return fmaxf(x, y);+}++static inline float fmin32(float x, float y) {+ return fminf(x, y);+}++static inline float fpow32(float x, float y) {+ return powf(x, y);+}+#endif++static inline bool futrts_isnan32(float x) {+ return isnan(x);+}++static inline bool futrts_isinf32(float x) {+ return isinf(x);+}++#ifdef __OPENCL_VERSION__+static inline float futrts_log32(float x) {+ return log(x);+}++static inline float futrts_log2_32(float x) {+ return log2(x);+}++static inline float futrts_log10_32(float x) {+ return log10(x);+}++static inline float futrts_sqrt32(float x) {+ return sqrt(x);+}++static inline float futrts_exp32(float x) {+ return exp(x);+}++static inline float futrts_cos32(float x) {+ return cos(x);+}++static inline float futrts_sin32(float x) {+ return sin(x);+}++static inline float futrts_tan32(float x) {+ return tan(x);+}++static inline float futrts_acos32(float x) {+ return acos(x);+}++static inline float futrts_asin32(float x) {+ return asin(x);+}++static inline float futrts_atan32(float x) {+ return atan(x);+}++static inline float futrts_cosh32(float x) {+ return cosh(x);+}++static inline float futrts_sinh32(float x) {+ return sinh(x);+}++static inline float futrts_tanh32(float x) {+ return tanh(x);+}++static inline float futrts_acosh32(float x) {+ return acosh(x);+}++static inline float futrts_asinh32(float x) {+ return asinh(x);+}++static inline float futrts_atanh32(float x) {+ return atanh(x);+}++static inline float futrts_atan2_32(float x, float y) {+ return atan2(x, y);+}++static inline float futrts_hypot32(float x, float y) {+ return hypot(x, y);+}++static inline float futrts_gamma32(float x) {+ return tgamma(x);+}++static inline float futrts_lgamma32(float x) {+ return lgamma(x);+}++static inline float fmod32(float x, float y) {+ return fmod(x, y);+}++static inline float futrts_round32(float x) {+ return rint(x);+}++static inline float futrts_floor32(float x) {+ return floor(x);+}++static inline float futrts_ceil32(float x) {+ return ceil(x);+}++static inline float futrts_lerp32(float v0, float v1, float t) {+ return mix(v0, v1, t);+}++static inline float futrts_mad32(float a, float b, float c) {+ return mad(a, b, c);+}++static inline float futrts_fma32(float a, float b, float c) {+ return fma(a, b, c);+}++#else // Not OpenCL, but CUDA or plain C.++static inline float futrts_log32(float x) {+ return logf(x);+}++static inline float futrts_log2_32(float x) {+ return log2f(x);+}++static inline float futrts_log10_32(float x) {+ return log10f(x);+}++static inline float futrts_sqrt32(float x) {+ return sqrtf(x);+}++static inline float futrts_exp32(float x) {+ return expf(x);+}++static inline float futrts_cos32(float x) {+ return cosf(x);+}++static inline float futrts_sin32(float x) {+ return sinf(x);+}++static inline float futrts_tan32(float x) {+ return tanf(x);+}++static inline float futrts_acos32(float x) {+ return acosf(x);+}++static inline float futrts_asin32(float x) {+ return asinf(x);+}++static inline float futrts_atan32(float x) {+ return atanf(x);+}++static inline float futrts_cosh32(float x) {+ return coshf(x);+}++static inline float futrts_sinh32(float x) {+ return sinhf(x);+}++static inline float futrts_tanh32(float x) {+ return tanhf(x);+}++static inline float futrts_acosh32(float x) {+ return acoshf(x);+}++static inline float futrts_asinh32(float x) {+ return asinhf(x);+}++static inline float futrts_atanh32(float x) {+ return atanhf(x);+}++static inline float futrts_atan2_32(float x, float y) {+ return atan2f(x, y);+}++static inline float futrts_hypot32(float x, float y) {+ return hypotf(x, y);+}++static inline float futrts_gamma32(float x) {+ return tgammaf(x);+}++static inline float futrts_lgamma32(float x) {+ return lgammaf(x);+}++static inline float fmod32(float x, float y) {+ return fmodf(x, y);+}++static inline float futrts_round32(float x) {+ return rintf(x);+}++static inline float futrts_floor32(float x) {+ return floorf(x);+}++static inline float futrts_ceil32(float x) {+ return ceilf(x);+}++static inline float futrts_lerp32(float v0, float v1, float t) {+ return v0 + (v1 - v0) * t;+}++static inline float futrts_mad32(float a, float b, float c) {+ return a * b + c;+}++static inline float futrts_fma32(float a, float b, float c) {+ return fmaf(a, b, c);+}+#endif++static inline int32_t futrts_to_bits32(float x) {+ union {+ float f;+ int32_t t;+ } p;++ p.f = x;+ return p.t;+}++static inline float futrts_from_bits32(int32_t x) {+ union {+ int32_t f;+ float t;+ } p;++ p.f = x;+ return p.t;+}++static inline float fsignum32(float x) {+ return futrts_isnan32(x) ? x : (x > 0) - (x < 0);+}++#ifdef FUTHARK_F64_ENABLED++static inline double fdiv64(double x, double y) {+ return x / y;+}++static inline double fadd64(double x, double y) {+ return x + y;+}++static inline double fsub64(double x, double y) {+ return x - y;+}++static inline double fmul64(double x, double y) {+ return x * y;+}++static inline bool cmplt64(double x, double y) {+ return x < y;+}++static inline bool cmple64(double x, double y) {+ return x <= y;+}++static inline double sitofp_i8_f64(int8_t x) {+ return (double) x;+}++static inline double sitofp_i16_f64(int16_t x) {+ return (double) x;+}++static inline double sitofp_i32_f64(int32_t x) {+ return (double) x;+}++static inline double sitofp_i64_f64(int64_t x) {+ return (double) x;+}++static inline double uitofp_i8_f64(uint8_t x) {+ return (double) x;+}++static inline double uitofp_i16_f64(uint16_t x) {+ return (double) x;+}++static inline double uitofp_i32_f64(uint32_t x) {+ return (double) x;+}++static inline double uitofp_i64_f64(uint64_t x) {+ return (double) x;+}++static inline int8_t fptosi_f64_i8(double x) {+ return (int8_t) x;+}++static inline int16_t fptosi_f64_i16(double x) {+ return (int16_t) x;+}++static inline int32_t fptosi_f64_i32(double x) {+ return (int32_t) x;+}++static inline int64_t fptosi_f64_i64(double x) {+ return (int64_t) x;+}++static inline uint8_t fptoui_f64_i8(double x) {+ return (uint8_t) x;+}++static inline uint16_t fptoui_f64_i16(double x) {+ return (uint16_t) x;+}++static inline uint32_t fptoui_f64_i32(double x) {+ return (uint32_t) x;+}++static inline uint64_t fptoui_f64_i64(double x) {+ return (uint64_t) x;+}++static inline double fabs64(double x) {+ return fabs(x);+}++static inline double fmax64(double x, double y) {+ return fmax(x, y);+}++static inline double fmin64(double x, double y) {+ return fmin(x, y);+}++static inline double fpow64(double x, double y) {+ return pow(x, y);+}++static inline double futrts_log64(double x) {+ return log(x);+}++static inline double futrts_log2_64(double x) {+ return log2(x);+}++static inline double futrts_log10_64(double x) {+ return log10(x);+}++static inline double futrts_sqrt64(double x) {+ return sqrt(x);+}++static inline double futrts_exp64(double x) {+ return exp(x);+}++static inline double futrts_cos64(double x) {+ return cos(x);+}++static inline double futrts_sin64(double x) {+ return sin(x);+}++static inline double futrts_tan64(double x) {+ return tan(x);+}++static inline double futrts_acos64(double x) {+ return acos(x);+}++static inline double futrts_asin64(double x) {+ return asin(x);+}++static inline double futrts_atan64(double x) {+ return atan(x);+}++static inline double futrts_cosh64(double x) {+ return cosh(x);+}++static inline double futrts_sinh64(double x) {+ return sinh(x);+}++static inline double futrts_tanh64(double x) {+ return tanh(x);+}++static inline double futrts_acosh64(double x) {+ return acosh(x);+}++static inline double futrts_asinh64(double x) {+ return asinh(x);+}++static inline double futrts_atanh64(double x) {+ return atanh(x);+}++static inline double futrts_atan2_64(double x, double y) {+ return atan2(x, y);+}++static inline double futrts_hypot64(double x, double y) {+ return hypot(x, y);+}++static inline double futrts_gamma64(double x) {+ return tgamma(x);+}++static inline double futrts_lgamma64(double x) {+ return lgamma(x);+}++static inline double futrts_fma64(double a, double b, double c) {+ return fma(a, b, c);+}++static inline double futrts_round64(double x) {+ return rint(x);+}++static inline double futrts_ceil64(double x) {+ return ceil(x);+}++static inline double futrts_floor64(double x) {+ return floor(x);+}++static inline bool futrts_isnan64(double x) {+ return isnan(x);+}++static inline bool futrts_isinf64(double x) {+ return isinf(x);+}++static inline int64_t futrts_to_bits64(double x) {+ union {+ double f;+ int64_t t;+ } p;++ p.f = x;+ return p.t;+}++static inline double futrts_from_bits64(int64_t x) {+ union {+ int64_t f;+ double t;+ } p;++ p.f = x;+ return p.t;+}++static inline double fmod64(double x, double y) {+ return fmod(x, y);+}++static inline double fsignum64(double x) {+ return futrts_isnan64(x) ? x : (x > 0) - (x < 0);+}++static inline double futrts_lerp64(double v0, double v1, double t) {+#ifdef __OPENCL_VERSION__+ return mix(v0, v1, t);+#else+ return v0 + (v1 - v0) * t;+#endif+}++static inline double futrts_mad64(double a, double b, double c) {+#ifdef __OPENCL_VERSION__+ return mad(a, b, c);+#else+ return a * b + c;+#endif+}++static inline float fpconv_f32_f32(float x) {+ return (float) x;+}++static inline double fpconv_f32_f64(float x) {+ return (double) x;+}++static inline float fpconv_f64_f32(double x) {+ return (float) x;+}++static inline double fpconv_f64_f64(double x) {+ return (double) x;+}++#endif++// End of scalar.h.
+ rts/c/scalar_f16.h view
@@ -0,0 +1,627 @@+// Start of scalar_f16.h.++// Half-precision is emulated if needed (e.g. in straight C) with the+// native type used if possible. The emulation works by typedef'ing+// 'float' to 'f16', and then implementing all operations on single+// precision. To cut down on duplication, we use the same code for+// those Futhark functions that require just operators or casts. The+// in-memory representation for arrays will still be 16 bits even+// under emulation, so the compiler will have to be careful when+// generating reads or writes.++#if !defined(cl_khr_fp16) && !(defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 600)+#define EMULATE_F16+#endif++#if !defined(EMULATE_F16) && defined(__OPENCL_VERSION__)+#pragma OPENCL EXTENSION cl_khr_fp16 : enable+#endif++#ifdef EMULATE_F16++// Note that the half-precision storage format is still 16 bits - the+// compiler will have to be real careful!+typedef float f16;++#else++#ifdef __CUDA_ARCH__+#include <cuda_fp16.h>+#endif++typedef half f16;++#endif++// Some of these functions convert to single precision because half+// precision versions are not available.++static inline f16 fadd16(f16 x, f16 y) {+ return x + y;+}++static inline f16 fsub16(f16 x, f16 y) {+ return x - y;+}++static inline f16 fmul16(f16 x, f16 y) {+ return x * y;+}++static inline bool cmplt16(f16 x, f16 y) {+ return x < y;+}++static inline bool cmple16(f16 x, f16 y) {+ return x <= y;+}++static inline f16 sitofp_i8_f16(int8_t x) {+ return (f16) x;+}++static inline f16 sitofp_i16_f16(int16_t x) {+ return (f16) x;+}++static inline f16 sitofp_i32_f16(int32_t x) {+ return (f16) x;+}++static inline f16 sitofp_i64_f16(int64_t x) {+ return (f16) x;+}++static inline f16 uitofp_i8_f16(uint8_t x) {+ return (f16) x;+}++static inline f16 uitofp_i16_f16(uint16_t x) {+ return (f16) x;+}++static inline f16 uitofp_i32_f16(uint32_t x) {+ return (f16) x;+}++static inline f16 uitofp_i64_f16(uint64_t x) {+ return (f16) x;+}++static inline int8_t fptosi_f16_i8(f16 x) {+ return (int8_t) (float) x;+}++static inline int16_t fptosi_f16_i16(f16 x) {+ return (int16_t) x;+}++static inline int32_t fptosi_f16_i32(f16 x) {+ return (int32_t) x;+}++static inline int64_t fptosi_f16_i64(f16 x) {+ return (int64_t) x;+}++static inline uint8_t fptoui_f16_i8(f16 x) {+ return (uint8_t) (float) x;+}++static inline uint16_t fptoui_f16_i16(f16 x) {+ return (uint16_t) x;+}++static inline uint32_t fptoui_f16_i32(f16 x) {+ return (uint32_t) x;+}++static inline uint64_t fptoui_f16_i64(f16 x) {+ return (uint64_t) x;+}++#ifndef EMULATE_F16++#ifdef __OPENCL_VERSION__+static inline f16 fabs16(f16 x) {+ return fabs(x);+}++static inline f16 fmax16(f16 x, f16 y) {+ return fmax(x, y);+}++static inline f16 fmin16(f16 x, f16 y) {+ return fmin(x, y);+}++static inline f16 fpow16(f16 x, f16 y) {+ return pow(x, y);+}++#else // Assuming CUDA.++static inline f16 fabs16(f16 x) {+ return fabsf(x);+}++static inline f16 fmax16(f16 x, f16 y) {+ return fmaxf(x, y);+}++static inline f16 fmin16(f16 x, f16 y) {+ return fminf(x, y);+}++static inline f16 fpow16(f16 x, f16 y) {+ return powf(x, y);+}+#endif++static inline bool futrts_isnan16(f16 x) {+ return isnan((float)x);+}++static inline bool futrts_isinf16(f16 x) {+ return isinf((float)x);+}++#ifdef __OPENCL_VERSION__+static inline f16 futrts_log16(f16 x) {+ return log(x);+}++static inline f16 futrts_log2_16(f16 x) {+ return log2(x);+}++static inline f16 futrts_log10_16(f16 x) {+ return log10(x);+}++static inline f16 futrts_sqrt16(f16 x) {+ return sqrt(x);+}++static inline f16 futrts_exp16(f16 x) {+ return exp(x);+}++static inline f16 futrts_cos16(f16 x) {+ return cos(x);+}++static inline f16 futrts_sin16(f16 x) {+ return sin(x);+}++static inline f16 futrts_tan16(f16 x) {+ return tan(x);+}++static inline f16 futrts_acos16(f16 x) {+ return acos(x);+}++static inline f16 futrts_asin16(f16 x) {+ return asin(x);+}++static inline f16 futrts_atan16(f16 x) {+ return atan(x);+}++static inline f16 futrts_cosh16(f16 x) {+ return cosh(x);+}++static inline f16 futrts_sinh16(f16 x) {+ return sinh(x);+}++static inline f16 futrts_tanh16(f16 x) {+ return tanh(x);+}++static inline f16 futrts_acosh16(f16 x) {+ return acosh(x);+}++static inline f16 futrts_asinh16(f16 x) {+ return asinh(x);+}++static inline f16 futrts_atanh16(f16 x) {+ return atanh(x);+}++static inline f16 futrts_atan2_16(f16 x, f16 y) {+ return atan2(x, y);+}++static inline f16 futrts_hypot16(f16 x, f16 y) {+ return hypot(x, y);+}++static inline f16 futrts_gamma16(f16 x) {+ return tgamma(x);+}++static inline f16 futrts_lgamma16(f16 x) {+ return lgamma(x);+}++static inline f16 fmod16(f16 x, f16 y) {+ return fmod(x, y);+}++static inline f16 futrts_round16(f16 x) {+ return rint(x);+}++static inline f16 futrts_floor16(f16 x) {+ return floor(x);+}++static inline f16 futrts_ceil16(f16 x) {+ return ceil(x);+}++static inline f16 futrts_lerp16(f16 v0, f16 v1, f16 t) {+ return mix(v0, v1, t);+}++static inline f16 futrts_mad16(f16 a, f16 b, f16 c) {+ return mad(a, b, c);+}++static inline f16 futrts_fma16(f16 a, f16 b, f16 c) {+ return fma(a, b, c);+}++#else // Assume CUDA.++static inline f16 futrts_log16(f16 x) {+ return hlog(x);+}++static inline f16 futrts_log2_16(f16 x) {+ return hlog2(x);+}++static inline f16 futrts_log10_16(f16 x) {+ return hlog10(x);+}++static inline f16 futrts_sqrt16(f16 x) {+ return hsqrt(x);+}++static inline f16 futrts_exp16(f16 x) {+ return hexp(x);+}++static inline f16 futrts_cos16(f16 x) {+ return hcos(x);+}++static inline f16 futrts_sin16(f16 x) {+ return hsin(x);+}++static inline f16 futrts_tan16(f16 x) {+ return tanf(x);+}++static inline f16 futrts_acos16(f16 x) {+ return acosf(x);+}++static inline f16 futrts_asin16(f16 x) {+ return asinf(x);+}++static inline f16 futrts_atan16(f16 x) {+ return atanf(x);+}++static inline f16 futrts_cosh16(f16 x) {+ return coshf(x);+}++static inline f16 futrts_sinh16(f16 x) {+ return sinhf(x);+}++static inline f16 futrts_tanh16(f16 x) {+ return tanhf(x);+}++static inline f16 futrts_acosh16(f16 x) {+ return acoshf(x);+}++static inline f16 futrts_asinh16(f16 x) {+ return asinhf(x);+}++static inline f16 futrts_atanh16(f16 x) {+ return atanhf(x);+}++static inline f16 futrts_atan2_16(f16 x, f16 y) {+ return atan2f(x, y);+}++static inline f16 futrts_hypot16(f16 x, f16 y) {+ return hypotf(x, y);+}++static inline f16 futrts_gamma16(f16 x) {+ return tgammaf(x);+}++static inline f16 futrts_lgamma16(f16 x) {+ return lgammaf(x);+}++static inline f16 fmod16(f16 x, f16 y) {+ return fmodf(x, y);+}++static inline f16 futrts_round16(f16 x) {+ return rintf(x);+}++static inline f16 futrts_floor16(f16 x) {+ return hfloor(x);+}++static inline f16 futrts_ceil16(f16 x) {+ return hceil(x);+}++static inline f16 futrts_lerp16(f16 v0, f16 v1, f16 t) {+ return v0 + (v1 - v0) * t;+}++static inline f16 futrts_mad16(f16 a, f16 b, f16 c) {+ return a * b + c;+}++static inline f16 futrts_fma16(f16 a, f16 b, f16 c) {+ return fmaf(a, b, c);+}++#endif++// The CUDA __half type cannot be put in unions for some reason, so we+// use bespoke conversion functions instead.+#ifdef __CUDA_ARCH__+static inline int16_t futrts_to_bits16(f16 x) {+ return __half_as_ushort(x);+}+static inline f16 futrts_from_bits16(int16_t x) {+ return __ushort_as_half(x);+}+#else+static inline int16_t futrts_to_bits16(f16 x) {+ union {+ f16 f;+ int16_t t;+ } p;++ p.f = x;+ return p.t;+}++static inline f16 futrts_from_bits16(int16_t x) {+ union {+ int16_t f;+ f16 t;+ } p;++ p.f = x;+ return p.t;+}+#endif++#else // No native f16 - emulate.++static inline f16 fabs16(f16 x) {+ return fabs32(x);+}++static inline f16 fmax16(f16 x, f16 y) {+ return fmax32(x, y);+}++static inline f16 fmin16(f16 x, f16 y) {+ return fmin32(x, y);+}++static inline f16 fpow16(f16 x, f16 y) {+ return fpow32(x, y);+}++static inline bool futrts_isnan16(f16 x) {+ return futrts_isnan32(x);+}++static inline bool futrts_isinf16(f16 x) {+ return futrts_isinf32(x);+}++static inline f16 futrts_log16(f16 x) {+ return futrts_log32(x);+}++static inline f16 futrts_log2_16(f16 x) {+ return futrts_log2_32(x);+}++static inline f16 futrts_log10_16(f16 x) {+ return futrts_log10_32(x);+}++static inline f16 futrts_sqrt16(f16 x) {+ return futrts_sqrt32(x);+}++static inline f16 futrts_exp16(f16 x) {+ return futrts_exp32(x);+}++static inline f16 futrts_cos16(f16 x) {+ return futrts_cos32(x);+}++static inline f16 futrts_sin16(f16 x) {+ return futrts_sin32(x);+}++static inline f16 futrts_tan16(f16 x) {+ return futrts_tan32(x);+}++static inline f16 futrts_acos16(f16 x) {+ return futrts_acos32(x);+}++static inline f16 futrts_asin16(f16 x) {+ return futrts_asin32(x);+}++static inline f16 futrts_atan16(f16 x) {+ return futrts_atan32(x);+}++static inline f16 futrts_cosh16(f16 x) {+ return futrts_cosh32(x);+}++static inline f16 futrts_sinh16(f16 x) {+ return futrts_sinh32(x);+}++static inline f16 futrts_tanh16(f16 x) {+ return futrts_tanh32(x);+}++static inline f16 futrts_acosh16(f16 x) {+ return futrts_acosh32(x);+}++static inline f16 futrts_asinh16(f16 x) {+ return futrts_asinh32(x);+}++static inline f16 futrts_atanh16(f16 x) {+ return futrts_atanh32(x);+}++static inline f16 futrts_atan2_16(f16 x, f16 y) {+ return futrts_atan2_32(x, y);+}++static inline f16 futrts_hypot16(f16 x, f16 y) {+ return futrts_hypot32(x, y);+}++static inline f16 futrts_gamma16(f16 x) {+ return futrts_gamma32(x);+}++static inline f16 futrts_lgamma16(f16 x) {+ return futrts_lgamma32(x);+}++static inline f16 fmod16(f16 x, f16 y) {+ return fmod32(x, y);+}++static inline f16 futrts_round16(f16 x) {+ return futrts_round32(x);+}++static inline f16 futrts_floor16(f16 x) {+ return futrts_floor32(x);+}++static inline f16 futrts_ceil16(f16 x) {+ return futrts_ceil32(x);+}++static inline f16 futrts_lerp16(f16 v0, f16 v1, f16 t) {+ return futrts_lerp32(v0, v1, t);+}++static inline f16 futrts_mad16(f16 a, f16 b, f16 c) {+ return futrts_mad32(a, b, c);+}++static inline f16 futrts_fma16(f16 a, f16 b, f16 c) {+ return futrts_fma32(a, b, c);+}++// Even when we are using an OpenCL that does not support cl_khr_fp16,+// it must still support vload_half for actually creating a+// half-precision number, which can then be efficiently converted to a+// float. Similarly for vstore_half.+#ifdef __OPENCL_VERSION__++static inline int16_t futrts_to_bits16(f16 x) {+ int16_t y;+ // Violating strict aliasing here.+ vstore_half((float)x, 0, (half*)&y);+ return y;+}++static inline f16 futrts_from_bits16(int16_t x) {+ return (f16)vload_half(0, (half*)&x);+}++#else++static inline int16_t futrts_to_bits16(f16 x) {+ return (int16_t)float2halfbits(x);+}++static inline f16 futrts_from_bits16(int16_t x) {+ return halfbits2float((uint16_t)x);+}++static inline f16 fsignum16(f16 x) {+ return futrts_isnan16(x) ? x : (x > 0) - (x < 0);+}++#endif++#endif++static inline float fpconv_f16_f16(f16 x) {+ return x;+}++static inline float fpconv_f16_f32(f16 x) {+ return x;+}++static inline f16 fpconv_f32_f16(float x) {+ return x;+}++#ifdef FUTHARK_F64_ENABLED++static inline double fpconv_f16_f64(f16 x) {+ return (double) x;+}++static inline f16 fpconv_f64_f16(double x) {+ return (f16) x;+}++#endif+++// End of scalar_f16.h.
rts/c/scheduler.h view
@@ -100,6 +100,11 @@ #include <sys/sysinfo.h> #include <sys/resource.h> #include <signal.h>+#elif defined(__EMSCRIPTEN__)+#include <emscripten/threading.h>+#include <sys/sysinfo.h>+#include <sys/resource.h>+#include <signal.h> #endif /* Multicore Utility functions */@@ -128,7 +133,7 @@ } else { errno = EINVAL; }-#elif defined(__linux__)+#elif defined(__linux__) || __EMSCRIPTEN__ err = getrusage(RUSAGE_THREAD, rusage); #endif return err;@@ -152,6 +157,8 @@ return ncores; #elif defined(__linux__) return get_nprocs();+#elif __EMSCRIPTEN__+ return emscripten_num_logical_cores(); #else fprintf(stderr, "operating system not recognised\n"); return -1;
rts/c/server.h view
@@ -57,6 +57,7 @@ DEF_SCALAR_TYPE(u16); DEF_SCALAR_TYPE(u32); DEF_SCALAR_TYPE(u64);+DEF_SCALAR_TYPE(f16); DEF_SCALAR_TYPE(f32); DEF_SCALAR_TYPE(f64); DEF_SCALAR_TYPE(bool);@@ -75,6 +76,7 @@ uint32_t v_u32; uint64_t v_u64; + uint16_t v_f16; float v_f32; double v_f64; @@ -107,6 +109,9 @@ if (v->type == &type_u64) { return &v->value.v_u64; }+ if (v->type == &type_f16) {+ return &v->value.v_f16;+ } if (v->type == &type_f32) { return &v->value.v_f32; }@@ -286,8 +291,9 @@ int num_outs = entry_num_outs(e); int num_ins = entry_num_ins(e);- void* outs[num_outs];- void* ins[num_ins];+ // +1 to avoid zero-size arrays, which is UB.+ void* outs[num_outs+1];+ void* ins[num_ins+1]; for (int i = 0; i < num_ins; i++) { const char *in_name = get_arg(args, 1+num_outs+i);
rts/c/tuning.h view
@@ -20,7 +20,7 @@ if (eql) { *eql = 0; int value = atoi(eql+1);- if (set_size(cfg, line, value) != 0) {+ if (set_size(cfg, line, (size_t)value) != 0) { char* err = (char*) malloc(max_line_len + 50); snprintf(err, max_line_len + 50, "Unknown name '%s' on line %d.", line, lineno); free(line);
rts/c/util.h view
@@ -7,6 +7,14 @@ static const char *fut_progname = "(embedded Futhark)"; +static void futhark_panic(int eval, const char *fmt, ...) __attribute__((noreturn));+static char* msgprintf(const char *s, ...);+static void* slurp_file(const char *filename, size_t *size);+static int dump_file(const char *file, const void *buf, size_t n);+struct str_builder;+static void str_builder_init(struct str_builder *b);+static void str_builder(struct str_builder *b, const char *s, ...);+ static void futhark_panic(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt);@@ -28,7 +36,6 @@ return buffer; } - static inline void check_err(int errval, int sets_errno, const char *fun, int line, const char *msg, ...) { if (errval) {@@ -46,18 +53,18 @@ } } -#define CHECK_ERR(err, msg...) check_err(err, 0, __func__, __LINE__, msg)-#define CHECK_ERRNO(err, msg...) check_err(err, 1, __func__, __LINE__, msg)+#define CHECK_ERR(err, ...) check_err(err, 0, __func__, __LINE__, __VA_ARGS__)+#define CHECK_ERRNO(err, ...) check_err(err, 1, __func__, __LINE__, __VA_ARGS__) // Read the rest of an open file into a NUL-terminated string; returns // NULL on error. static void* fslurp_file(FILE *f, size_t *size) {- size_t start = ftell(f);+ long start = ftell(f); fseek(f, 0, SEEK_END);- size_t src_size = ftell(f)-start;+ long src_size = ftell(f)-start; fseek(f, start, SEEK_SET);- unsigned char *s = (unsigned char*) malloc(src_size + 1);- if (fread(s, 1, src_size, f) != src_size) {+ unsigned char *s = (unsigned char*) malloc((size_t)src_size + 1);+ if (fread(s, 1, (size_t)src_size, f) != (size_t)src_size) { free(s); s = NULL; } else {@@ -65,7 +72,7 @@ } if (size) {- *size = src_size;+ *size = (size_t)src_size; } return s;
rts/c/values.h view
@@ -107,7 +107,7 @@ int ret; int first = 1; char *knows_dimsize = (char*) calloc((size_t)dims, sizeof(char));- int cur_dim = dims-1;+ int cur_dim = (int)dims-1; int64_t *elems_read_in_dim = (int64_t*) calloc((size_t)dims, sizeof(int64_t)); while (1) {@@ -337,16 +337,40 @@ READ_STR(SCNu64, uint64_t, "u64"); } +static int read_str_f16(char *buf, void* dest) {+ remove_underscores(buf);+ if (strcmp(buf, "f16.nan") == 0) {+ *(uint16_t*)dest = float2halfbits(NAN);+ return 0;+ } else if (strcmp(buf, "f16.inf") == 0) {+ *(uint16_t*)dest = float2halfbits(INFINITY);+ return 0;+ } else if (strcmp(buf, "-f16.inf") == 0) {+ *(uint16_t*)dest = float2halfbits(-INFINITY);+ return 0;+ } else {+ int j;+ float x;+ if (sscanf(buf, "%f%n", &x, &j) == 1) {+ if (strcmp(buf+j, "") == 0 || strcmp(buf+j, "f16") == 0) {+ *(uint16_t*)dest = float2halfbits(x);+ return 0;+ }+ }+ return 1;+ }+}+ static int read_str_f32(char *buf, void* dest) { remove_underscores(buf); if (strcmp(buf, "f32.nan") == 0) {- *(float*)dest = NAN;+ *(float*)dest = (float)NAN; return 0; } else if (strcmp(buf, "f32.inf") == 0) {- *(float*)dest = INFINITY;+ *(float*)dest = (float)INFINITY; return 0; } else if (strcmp(buf, "-f32.inf") == 0) {- *(float*)dest = -INFINITY;+ *(float*)dest = (float)-INFINITY; return 0; } else { READ_STR("f", float, "f32");@@ -356,13 +380,13 @@ static int read_str_f64(char *buf, void* dest) { remove_underscores(buf); if (strcmp(buf, "f64.nan") == 0) {- *(double*)dest = NAN;+ *(double*)dest = (double)NAN; return 0; } else if (strcmp(buf, "f64.inf") == 0) {- *(double*)dest = INFINITY;+ *(double*)dest = (double)INFINITY; return 0; } else if (strcmp(buf, "-f64.inf") == 0) {- *(double*)dest = -INFINITY;+ *(double*)dest = (double)-INFINITY; return 0; } else { READ_STR("lf", double, "f64");@@ -413,6 +437,19 @@ return fprintf(out, "%"PRIu64"u64", *src); } +static int write_str_f16(FILE *out, uint16_t *src) {+ float x = halfbits2float(*src);+ if (isnan(x)) {+ return fprintf(out, "f16.nan");+ } else if (isinf(x) && x >= 0) {+ return fprintf(out, "f16.inf");+ } else if (isinf(x)) {+ return fprintf(out, "-f16.inf");+ } else {+ return fprintf(out, "%.6ff16", x);+ }+}+ static int write_str_f32(FILE *out, float *src) { float x = *src; if (isnan(x)) {@@ -448,10 +485,10 @@ #define BINARY_FORMAT_VERSION 2 #define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1}) -static void flip_bytes(int elem_size, unsigned char *elem) {- for (int j=0; j<elem_size/2; j++) {+static void flip_bytes(size_t elem_size, unsigned char *elem) {+ for (size_t j=0; j<elem_size/2; j++) { unsigned char head = elem[j];- int tail_index = elem_size-1-j;+ size_t tail_index = elem_size-1-j; elem[j] = elem[tail_index]; elem[tail_index] = head; }@@ -472,7 +509,7 @@ #endif static int read_byte(FILE *f, void* dest) {- int num_elems_read = fread(dest, 1, 1, f);+ size_t num_elems_read = fread(dest, 1, 1, f); return num_elems_read == 1 ? 0 : 1; } @@ -510,6 +547,9 @@ static const struct primtype_info_t u64_info = {.binname = " u64", .type_name = "u64", .size = 8, .write_str = (writer)write_str_u64, .read_str = (str_reader)read_str_u64};+static const struct primtype_info_t f16_info =+ {.binname = " f16", .type_name = "f16", .size = 2,+ .write_str = (writer)write_str_f16, .read_str = (str_reader)read_str_f16}; static const struct primtype_info_t f32_info = {.binname = " f32", .type_name = "f32", .size = 4, .write_str = (writer)write_str_f32, .read_str = (str_reader)read_str_f32};@@ -523,7 +563,7 @@ static const struct primtype_info_t* primtypes[] = { &i8_info, &i16_info, &i32_info, &i64_info, &u8_info, &u16_info, &u32_info, &u64_info,- &f32_info, &f64_info,+ &f16_info, &f32_info, &f64_info, &bool_info, NULL // NULL-terminated };@@ -612,7 +652,7 @@ int64_t elem_count = 1; for (int i=0; i<dims; i++) { int64_t bin_shape;- ret = fread(&bin_shape, sizeof(bin_shape), 1, f);+ ret = (int)fread(&bin_shape, sizeof(bin_shape), 1, f); if (ret != 1) { futhark_panic(1, "binary-input: Couldn't read size for dimension %i of array.\n", i); }@@ -640,7 +680,7 @@ // If we're on big endian platform we must change all multibyte elements // from using little endian to big endian if (IS_BIG_ENDIAN && elem_size != 1) {- flip_bytes(elem_size, (unsigned char*) *data);+ flip_bytes((size_t)elem_size, (unsigned char*) *data); } return 0;@@ -671,7 +711,7 @@ const int64_t *shape, int8_t rank) { if (rank==0) {- elem_type->write_str(out, (void*)data);+ elem_type->write_str(out, (const void*)data); } else { int64_t len = (int64_t)shape[0]; int64_t slice_size = 1;@@ -691,7 +731,7 @@ } else if (rank==1) { fputc('[', out); for (int64_t i = 0; i < len; i++) {- elem_type->write_str(out, (void*) (data + i * elem_size));+ elem_type->write_str(out, (const void*) (data + i * elem_size)); if (i != len-1) { fprintf(out, ", "); }@@ -763,8 +803,8 @@ return expected_type->read_str(buf, dest); } else { read_bin_ensure_scalar(f, expected_type);- int64_t elem_size = expected_type->size;- int num_elems_read = fread(dest, (size_t)elem_size, 1, f);+ size_t elem_size = (size_t)expected_type->size;+ size_t num_elems_read = fread(dest, elem_size, 1, f); if (IS_BIG_ENDIAN) { flip_bytes(elem_size, (unsigned char*) dest); }
+ rts/javascript/server.js view
@@ -0,0 +1,251 @@+// Start of server.js++class Server {++ constructor(ctx) {+ this.ctx = ctx;+ this._vars = {};+ this._types = {};+ this._commands = [ 'inputs',+ 'outputs',+ 'call',+ 'restore',+ 'store',+ 'free',+ 'clear',+ 'pause_profiling',+ 'unpause_profiling',+ 'report',+ 'rename'+ ];+ }++ _get_arg(args, i) {+ if (i < args.length) {+ return args[i];+ } else {+ throw 'Insufficient command args';+ }+ }++ _get_entry_point(entry) {+ if (entry in this.ctx.get_entry_points()) {+ return this.ctx.get_entry_points()[entry];+ } else {+ throw "Unkown entry point: " + entry;+ }+ }++ _check_var(vname) {+ if (!(vname in this._vars)) {+ throw 'Unknown variable: ' + vname;+ }+ }++ _set_var(vname, v, t) {+ this._vars[vname] = v;+ this._types[vname] = t;+ }++ _get_type(vname) {+ this._check_var(vname);+ return this._types[vname];+ }++ _get_var(vname) {+ this._check_var(vname);+ return this._vars[vname];+ }++ _cmd_inputs(args) {+ var entry = this._get_arg(args, 0);+ var inputs = this._get_entry_point(entry)[0];+ for (var i = 0; i < inputs.length; i++) {+ console.log(inputs[i]);+ }+ }++ _cmd_outputs(args) {+ var entry = this._get_arg(args, 0);+ var outputs = this._get_entry_point(entry)[1];+ for (var i = 0; i < outputs.length; i++) {+ console.log(outputs[i]);+ }+ }++ _cmd_dummy(args) {+ // pass+ }++ _cmd_free(args) {+ for (var i = 0; i < args.length; i++) {+ var vname = args[i];+ this._check_var(vname);+ delete this._vars[vname];+ }+ }++ _cmd_rename(args) {+ var oldname = this._get_arg(args, 0)+ var newname = this._get_arg(args, 1)+ if (newname in this._vars) {+ throw "Variable already exists: " + newname;+ }+ this._vars[newname] = this._vars[oldname];+ this._types[newname] = this._types[oldname];+ delete this._vars[oldname];+ delete this._types[oldname];+ }++ _cmd_call(args) {+ var entry = this._get_entry_point(this._get_arg(args, 0));+ var num_ins = entry[0].length;+ var num_outs = entry[1].length;+ var expected_len = 1 + num_outs + num_ins++ if (args.length != expected_len) {+ throw "Invalid argument count, expected " + expected_len+ }++ var out_vnames = args.slice(1, num_outs+1)+ for (var i = 0; i < out_vnames.length; i++) {+ var out_vname = out_vnames[i];+ if (out_vname in this._vars) {+ throw "Variable already exists: " + out_vname;+ }+ }+ var in_vnames = args.slice(1+num_outs);+ var ins = [];+ for (var i = 0; i < in_vnames.length; i++) {+ ins.push(this._get_var(in_vnames[i]));+ }+ // Call entry point function from string name+ var bef = performance.now()*1000;+ var vals = this.ctx[args[0]].apply(this.ctx, ins);+ var aft = performance.now()*1000;+ if (num_outs == 1) {+ this._set_var(out_vnames[0], vals, entry[1][0]);+ } else {+ for (var i = 0; i < out_vnames.length; i++) {+ this._set_var(out_vnames[i], vals[i], entry[1][i]);+ }+ }+ console.log("runtime: " + Math.round(aft-bef));+ }++ _cmd_store(args) {+ var fname = this._get_arg(args, 0);+ for (var i = 1; i < args.length; i++) {+ var vname = args[i];+ var value = this._get_var(vname);+ var typ = this._get_type(vname);+ var fs = require("fs");+ var bin_val = construct_binary_value(value, typ);+ fs.appendFileSync(fname, bin_val, 'binary')+ }+ }++ fut_to_dim_typ(typ) {+ var type = typ;+ var count = 0;+ while (type.substr(0, 2) == '[]') {+ count = count + 1;+ type = type.slice(2);+ }+ return [count, type];+ }++ _cmd_restore(args) {+ if (args.length % 2 == 0) {+ throw "Invalid argument count";+ }++ var fname = args[0];+ var args = args.slice(1);++ var as = args;+ var reader = new Reader(fname);+ while (as.length != 0) {+ var vname = as[0];+ var typename = as[1];+ as = as.slice(2);++ if (vname in this._vars) {+ throw "Variable already exists: " + vname;+ }+ try {+ var value = read_value(typename, reader);+ if (typeof value == 'number' || typeof value == 'bigint') {+ this._set_var(vname, value, typename);+ } else {+ // We are working with an array and need to create to convert [shape, arr] to futhark ptr+ var shape= value[0];+ var arr = value[1];+ var dimtyp = this.fut_to_dim_typ(typename);+ var dim = dimtyp[0];+ var typ = dimtyp[1];+ var arg_list = [arr, ...shape];+ var fnam = "new_" + typ + "_" + dim + "d";+ var ptr = this.ctx[fnam].apply(this.ctx, arg_list);+ this._set_var(vname, ptr, typename);+ }+ } catch (err) {+ var err_msg = "Failed to restore variable " + vname + ".\nPossibly malformed data in " + fname + ".\n" + err.toString();+ throw err_msg;+ }+ }+ skip_spaces(reader);+ if (reader.get_buff().length != 0) {+ throw "Expected EOF after reading values";+ }+ }++ _process_line(line) {+ // TODO make sure it splits on anywhite space+ var words = line.split(" ");+ if (words.length == 0) {+ throw "Empty line";+ } else {+ var cmd = words[0];+ var args = words.splice(1);+ if (this._commands.includes(cmd)) {+ switch (cmd) {+ case 'inputs': this._cmd_inputs(args); break;+ case 'outputs': this._cmd_outputs(args); break+ case 'call': this._cmd_call(args); break+ case 'restore': this._cmd_restore(args); break+ case 'store': this._cmd_store(args); break+ case 'free': this._cmd_free(args); break+ case 'clear': this._cmd_dummy(args); break+ case 'pause_profiling': this._cmd_dummy(args); break+ case 'unpause_profiling': this._cmd_dummy(args); break+ case 'report': this._cmd_dummy(args); break+ case 'rename': this._cmd_rename(args); break+ }+ } else {+ throw "Unknown command: " + cmd;+ }+ }+ }++ run() {+ console.log('%%% OK'); // TODO figure out if flushing is neccesary for JS+ const readline = require('readline');+ const rl = readline.createInterface(process.stdin);+ rl.on('line', (line) => {+ if (line == "") {+ rl.close();+ }+ try {+ this._process_line(line);+ console.log('%%% OK');+ } catch (err) {+ console.log('%%% FAILURE');+ console.log(err);+ console.log('%%% OK');+ }+ }).on('close', () => { process.exit(0); });+ }+}++// End of server.js
+ rts/javascript/values.js view
@@ -0,0 +1,165 @@+// Start of values.js++var typToType = { ' i8' : Int8Array ,+ ' i16' : Int16Array ,+ ' i32' : Int32Array ,+ ' i64' : BigInt64Array ,+ ' u8' : Uint8Array ,+ ' u16' : Uint16Array ,+ ' u32' : Uint32Array ,+ ' u64' : BigUint64Array ,+ ' f16' : Uint16Array ,+ ' f32' : Float32Array ,+ ' f64' : Float64Array ,+ 'bool' : Uint8Array+ };++function binToStringArray(buff, array) {+ for (var i = 0; i < array.length; i++) {+ array[i] = buff[i];+ }+}++function fileToBuff(fname) {+ var readline = require('readline');+ var fs = require('fs');+ var buff = fs.readFileSync(fname);+ return buff;+}++var typToSize = {+ "bool" : 1,+ " u8" : 1,+ " i8" : 1,+ " u16" : 2,+ " i16" : 2,+ " u32" : 4,+ " i32" : 4,+ " f16" : 2,+ " f32" : 4,+ " u64" : 8,+ " i64" : 8,+ " f64" : 8,+}++function toU8(ta) {+ return new Uint8Array(ta.buffer, ta.byteOffset, ta.byteLength);+}++function construct_binary_value(v, typ) {+ var dims;+ var payload_bytes;+ var filler;+ if (v instanceof FutharkOpaque) {+ throw "Opaques are not supported";+ } else if (v instanceof FutharkArray) {+ var t = v.futharkType();+ var ftype = " ".slice(t.length) + t;+ var shape = v.shape();+ var ta = v.toTypedArray(shape);+ var da = new BigInt64Array(shape);+ dims = shape.length;+ payload_bytes = da.byteLength + ta.byteLength;+ filler = (bytes) => {+ bytes.set(toU8(da), 7);+ bytes.set(toU8(ta), 7 + da.byteLength);+ }+ } else {+ var ftype = " ".slice(typ.length) + typ;+ dims = 0;+ payload_bytes = typToSize[ftype];+ filler = (bytes) => {+ var scalar = new (typToType[ftype])([v]);+ bytes.set(toU8(scalar), 7);+ }+ }+ var total_bytes = 7 + payload_bytes;+ var bytes = new Uint8Array(total_bytes);+ bytes[0] = Buffer.from('b').readUInt8();+ bytes[1] = 2;+ bytes[2] = dims;+ for (var i = 0; i < 4; i++) {+ bytes[3+i] = ftype.charCodeAt(i);+ }+ filler(bytes);+ return Buffer.from(bytes);+}++class Reader {+ constructor(f) {+ this.f = f;+ this.buff = fileToBuff(f);+ }++ read_bin_array(num_dim, typ) {+ var u8_array = new Uint8Array(num_dim * 8);+ binToStringArray(this.buff.slice(0, num_dim * 8), u8_array);+ var shape = new BigInt64Array(u8_array.buffer);+ var length = shape[0];+ for (var i = 1; i < shape.length; i++) {+ length = length * shape[i];+ }+ length = Number(length);+ var dbytes = typToSize[typ];+ var u8_data = new Uint8Array(length * dbytes);+ binToStringArray(this.buff.slice(num_dim * 8, num_dim * 8 + dbytes * length), u8_data);+ var data = new (typToType[typ])(u8_data.buffer);+ var tmp_buff = this.buff.slice(num_dim * 8, num_dim * 8 + dbytes * length);+ this.buff = this.buff.slice(num_dim * 8 + dbytes * length);+ return [shape, data];+ }++ read_bin_scalar(typ) {+ var size = typToSize[typ];+ var u8_array = new Uint8Array(size);+ binToStringArray(this.buff, u8_array);+ var array = new (typToType[typ])(u8_array.buffer);+ this.buff = this.buff.slice(u8_array.length); // Update buff to be unread part of the string+ return array[0];+ }++ skip_spaces() {+ while (this.buff.length > 0 && this.buff.slice(0, 1).toString().trim() == "") {+ this.buff = this.buff.slice(1);+ }+ }++ read_binary() {+ // Skip leading white space+ while (this.buff.slice(0, 1).toString().trim() == "") {+ this.buff = this.buff.slice(1);+ }+ if (this.buff[0] != 'b'.charCodeAt(0)) {+ throw "Not in binary format"+ }+ var version = this.buff[1];+ if (version != 2) {+ throw "Not version 2";+ }+ var num_dim = this.buff[2];+ var typ = this.buff.slice(3, 7);+ this.buff = this.buff.slice(7);+ if (num_dim == 0) {+ return this.read_bin_scalar(typ);+ } else {+ return this.read_bin_array(num_dim, typ);+ }+ }++ get_buff() {+ return this.buff;+ }+}++// Function is redudant but is helpful for keeping consistent with python implementation+function skip_spaces(reader) {+ reader.skip_spaces();+}++function read_value(typename, reader) {+ // TODO include typename in implementation+ var val = reader.read_binary();+ return val;+}++// End of values.js
+ rts/javascript/wrapperclasses.js view
@@ -0,0 +1,83 @@+// Start of wrapperclasses.js++class FutharkArray {+ constructor(ctx, ptr, type_name, dim, heap, fshape, fvalues, ffree) {+ this.ctx = ctx;+ this.ptr = ptr;+ this.type_name = type_name;+ this.dim = dim;+ this.heap = heap;+ this.fshape = fshape;+ this.fvalues = fvalues;+ this.ffree = ffree;+ this.valid = true;+ }++ validCheck() {+ if (!this.valid) {+ throw "Using freed memory"+ }+ }++ futharkType() {+ return this.type_name;+ }++ free() {+ this.validCheck();+ this.ffree(this.ctx.ctx, this.ptr);+ this.valid = false;+ }++ shape() {+ this.validCheck();+ var s = this.fshape(this.ctx.ctx, this.ptr) >> 3;+ return Array.from(this.ctx.wasm.HEAP64.subarray(s, s + this.dim));+ }++ toTypedArray(dims = this.shape()) {+ this.validCheck();+ console.assert(dims.length === this.dim, "dim=%s,dims=%s", this.dim, dims.toString());+ var length = Number(dims.reduce((a, b) => a * b));+ var v = this.fvalues(this.ctx.ctx, this.ptr) / this.heap.BYTES_PER_ELEMENT;+ return this.heap.subarray(v, v + length);+ }++ toArray() {+ this.validCheck();+ var dims = this.shape();+ var ta = this.toTypedArray(dims);+ return (function nest(offs, ds) {+ var d0 = Number(ds[0]);+ if (ds.length === 1) {+ return Array.from(ta.subarray(offs, offs + d0));+ } else {+ var d1 = Number(ds[1]);+ return Array.from(Array(d0), (x,i) => nest(offs + i * d1, ds.slice(1)));+ }+ })(0, dims);+ }+}++class FutharkOpaque {+ constructor(ctx, ptr, ffree) {+ this.ctx = ctx;+ this.ptr = ptr;+ this.ffree = ffree;+ this.valid = true;+ }++ validCheck() {+ if (!this.valid) {+ throw "Using freed memory"+ }+ }++ free() {+ this.validCheck();+ this.ffree(this.ctx.ctx, this.ptr);+ this.valid = false;+ }+}++// End of wrapperclasses.js
rts/python/memory.py view
@@ -19,16 +19,16 @@ def unwrapArray(x): return normaliseArray(x).ctypes.data_as(ct.POINTER(ct.c_byte)) -def createArray(x, shape):+def createArray(x, shape, t): # HACK: np.ctypeslib.as_array may fail if the shape contains zeroes, # for some reason. if any(map(lambda x: x == 0, shape)):- return np.ndarray(shape, dtype=x._type_)+ return np.ndarray(shape, dtype=t) else:- return np.ctypeslib.as_array(x, shape=shape)+ return np.ctypeslib.as_array(x, shape=shape).view(t) -def indexArray(x, offset, bt, nptype):- return nptype(addressOffset(x, offset*ct.sizeof(bt), bt)[0])+def indexArray(x, offset, bt):+ return addressOffset(x, offset*ct.sizeof(bt), bt)[0] def writeScalarArray(x, offset, v): ct.memmove(ct.addressof(x.contents)+int(offset)*ct.sizeof(v), ct.addressof(v), ct.sizeof(v))
rts/python/opencl.py view
@@ -214,9 +214,16 @@ # compiler should provide us with the variables to which # parameters are mapped. if (len(program_src) >= 0):- return cl.Program(self.ctx, program_src).build(- ["-DLOCKSTEP_WIDTH={}".format(lockstep_width)]- + ["-D{}={}".format(s.replace('z', 'zz').replace('.', 'zi').replace('#', 'zh'),v) for (s,v) in self.sizes.items()])+ build_options = []++ build_options += ["-DLOCKSTEP_WIDTH={}".format(lockstep_width)]++ build_options += ["-D{}={}".format(s.replace('z', 'zz').replace('.', 'zi').replace('#', 'zh'),v) for (s,v) in self.sizes.items()]++ if (self.platform.name == 'Oclgrind'):+ build_options += ['-DEMULATE_F16']++ return cl.Program(self.ctx, program_src).build(build_options) def opencl_alloc(self, min_size, tag): min_size = 1 if min_size == 0 else min_size
rts/python/scalar.py view
@@ -238,9 +238,9 @@ umax8 = umax16 = umax32 = umax64 = umaxN umin8 = umin16 = umin32 = umin64 = uminN pow8 = pow16 = pow32 = pow64 = powN-fpow32 = fpow64 = fpowN-fmax32 = fmax64 = fmaxN-fmin32 = fmin64 = fminN+fpow16 = fpow32 = fpow64 = fpowN+fmax16 = fmax32 = fmax64 = fmaxN+fmin16 = fmin32 = fmin64 = fminN sle8 = sle16 = sle32 = sle64 = sleN slt8 = slt16 = slt32 = slt64 = sltN ule8 = ule16 = ule32 = ule64 = uleN@@ -309,39 +309,51 @@ def fptosi_T_i8(x): return np.int8(np.trunc(x))-fptosi_f32_i8 = fptosi_f64_i8 = fptosi_T_i8+fptosi_f16_i8 = fptosi_f32_i8 = fptosi_f64_i8 = fptosi_T_i8 def fptosi_T_i16(x): return np.int16(np.trunc(x))-fptosi_f32_i16 = fptosi_f64_i16 = fptosi_T_i16+fptosi_f16_i16 = fptosi_f32_i16 = fptosi_f64_i16 = fptosi_T_i16 def fptosi_T_i32(x): return np.int32(np.trunc(x))-fptosi_f32_i32 = fptosi_f64_i32 = fptosi_T_i32+fptosi_f16_i32 = fptosi_f32_i32 = fptosi_f64_i32 = fptosi_T_i32 def fptosi_T_i64(x): return np.int64(np.trunc(x))-fptosi_f32_i64 = fptosi_f64_i64 = fptosi_T_i64+fptosi_f16_i64 = fptosi_f32_i64 = fptosi_f64_i64 = fptosi_T_i64 def fptoui_T_i8(x): return np.uint8(np.trunc(x))-fptoui_f32_i8 = fptoui_f64_i8 = fptoui_T_i8+fptoui_f16_i8 = fptoui_f32_i8 = fptoui_f64_i8 = fptoui_T_i8 def fptoui_T_i16(x): return np.uint16(np.trunc(x))-fptoui_f32_i16 = fptoui_f64_i16 = fptoui_T_i16+fptoui_f16_i16 = fptoui_f32_i16 = fptoui_f64_i16 = fptoui_T_i16 def fptoui_T_i32(x): return np.uint32(np.trunc(x))-fptoui_f32_i32 = fptoui_f64_i32 = fptoui_T_i32+fptoui_f16_i32 = fptoui_f32_i32 = fptoui_f64_i32 = fptoui_T_i32 def fptoui_T_i64(x): return np.uint64(np.trunc(x))-fptoui_f32_i64 = fptoui_f64_i64 = fptoui_T_i64+fptoui_f16_i64 = fptoui_f32_i64 = fptoui_f64_i64 = fptoui_T_i64 +def fpconv_f16_f32(x):+ return np.float32(x)++def fpconv_f16_f64(x):+ return np.float64(x)++def fpconv_f32_f16(x):+ return np.float16(x)+ def fpconv_f32_f64(x): return np.float64(x) +def fpconv_f64_f16(x):+ return np.float16(x)+ def fpconv_f64_f32(x): return np.float32(x) @@ -550,16 +562,111 @@ s = struct.pack('>l', x) return np.float32(struct.unpack('>f', s)[0]) +def futhark_log16(x):+ return np.float16(np.log(x))++def futhark_log2_16(x):+ return np.float16(np.log2(x))++def futhark_log10_16(x):+ return np.float16(np.log10(x))++def futhark_sqrt16(x):+ return np.float16(np.sqrt(x))++def futhark_exp16(x):+ return np.exp(x)++def futhark_cos16(x):+ return np.cos(x)++def futhark_sin16(x):+ return np.sin(x)++def futhark_tan16(x):+ return np.tan(x)++def futhark_acos16(x):+ return np.arccos(x)++def futhark_asin16(x):+ return np.arcsin(x)++def futhark_atan16(x):+ return np.arctan(x)++def futhark_cosh16(x):+ return np.cosh(x)++def futhark_sinh16(x):+ return np.sinh(x)++def futhark_tanh16(x):+ return np.tanh(x)++def futhark_acosh16(x):+ return np.arccosh(x)++def futhark_asinh16(x):+ return np.arcsinh(x)++def futhark_atanh16(x):+ return np.arctanh(x)++def futhark_atan2_16(x, y):+ return np.arctan2(x, y)++def futhark_hypot16(x, y):+ return np.hypot(x, y)++def futhark_gamma16(x):+ return np.float16(math.gamma(x))++def futhark_lgamma16(x):+ return np.float16(math.lgamma(x))++def futhark_round16(x):+ return np.round(x)++def futhark_ceil16(x):+ return np.ceil(x)++def futhark_floor16(x):+ return np.floor(x)++def futhark_isnan16(x):+ return np.isnan(x)++def futhark_isinf16(x):+ return np.isinf(x)++def futhark_to_bits16(x):+ s = struct.pack('>e', x)+ return np.int16(struct.unpack('>H', s)[0])++def futhark_from_bits16(x):+ s = struct.pack('>H', np.uint16(x))+ return np.float16(struct.unpack('>e', s)[0])++def futhark_lerp16(v0, v1, t):+ return v0 + (v1-v0)*t+ def futhark_lerp32(v0, v1, t): return v0 + (v1-v0)*t def futhark_lerp64(v0, v1, t): return v0 + (v1-v0)*t +def futhark_mad16(a, b, c):+ return a * b + c+ def futhark_mad32(a, b, c): return a * b + c def futhark_mad64(a, b, c):+ return a * b + c++def futhark_fma16(a, b, c): return a * b + c def futhark_fma32(a, b, c):
rts/python/values.py view
@@ -249,6 +249,24 @@ expt = b'0' return float(sign + bef + b'.' + aft + b'E' + expt) +def read_str_f16(f):+ skip_spaces(f)+ try:+ parse_specific_string(f, 'f16.nan')+ return np.float32(np.nan)+ except ValueError:+ try:+ parse_specific_string(f, 'f16.inf')+ return np.float32(np.inf)+ except ValueError:+ try:+ parse_specific_string(f, '-f16.inf')+ return np.float32(-np.inf)+ except ValueError:+ x = read_str_decimal(f)+ optional_specific_string(f, 'f16')+ return x+ def read_str_f32(f): skip_spaces(f) try:@@ -385,6 +403,7 @@ read_bin_u32 = mk_bin_scalar_reader('u32') read_bin_u64 = mk_bin_scalar_reader('u64') +read_bin_f16 = mk_bin_scalar_reader('f16') read_bin_f32 = mk_bin_scalar_reader('f32') read_bin_f64 = mk_bin_scalar_reader('f64') @@ -460,6 +479,13 @@ 'bin_format': 'Q', 'numpy_type': np.uint64 }, + 'f16': {'binname' : b" f16",+ 'size' : 2,+ 'bin_reader': read_bin_f16,+ 'str_reader': read_str_f16,+ 'bin_format': 'e',+ 'numpy_type': np.float16 },+ 'f32': {'binname' : b" f32", 'size' : 4, 'bin_reader': read_bin_f32,@@ -600,6 +626,16 @@ out.write("true") else: out.write("false")+ elif type(v) == np.float16:+ if np.isnan(v):+ out.write('f16.nan')+ elif np.isinf(v):+ if v >= 0:+ out.write('f16.inf')+ else:+ out.write('-f16.inf')+ else:+ out.write("%.6ff16" % v) elif type(v) == np.float32: if np.isnan(v): out.write('f32.nan')@@ -644,6 +680,7 @@ np.dtype('uint16'): b' u16', np.dtype('uint32'): b' u32', np.dtype('uint64'): b' u64',+ np.dtype('float16'): b' f16', np.dtype('float32'): b' f32', np.dtype('float64'): b' f64', np.dtype('bool'): b'bool'}
src/Futhark/Actions.hs view
@@ -1,18 +1,22 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} -- | All (almost) compiler pipelines end with an 'Action', which does -- something with the result of the pipeline. module Futhark.Actions ( printAction, printAliasesAction,+ callGraphAction, impCodeGenAction, kernelImpCodeGenAction, multicoreImpCodeGenAction, metricsAction, compileCAction,+ compileCtoWASMAction, compileOpenCLAction, compileCUDAAction, compileMulticoreAction,+ compileMulticoreToWASMAction, compilePythonAction, compilePyOpenCLAction, )@@ -20,15 +24,21 @@ import Control.Monad import Control.Monad.IO.Class+import Data.List (intercalate) import Data.Maybe (fromMaybe)+import qualified Data.Text as T+import qualified Data.Text.IO as T import Futhark.Analysis.Alias+import Futhark.Analysis.CallGraph (buildCallGraph) import Futhark.Analysis.Metrics import qualified Futhark.CodeGen.Backends.CCUDA as CCUDA import qualified Futhark.CodeGen.Backends.COpenCL as COpenCL import qualified Futhark.CodeGen.Backends.MulticoreC as MulticoreC+import qualified Futhark.CodeGen.Backends.MulticoreWASM as MulticoreWASM import qualified Futhark.CodeGen.Backends.PyOpenCL as PyOpenCL import qualified Futhark.CodeGen.Backends.SequentialC as SequentialC import qualified Futhark.CodeGen.Backends.SequentialPython as SequentialPy+import qualified Futhark.CodeGen.Backends.SequentialWASM as SequentialWASM import qualified Futhark.CodeGen.ImpGen.GPU as ImpGenGPU import qualified Futhark.CodeGen.ImpGen.Multicore as ImpGenMulticore import qualified Futhark.CodeGen.ImpGen.Sequential as ImpGenSequential@@ -37,6 +47,7 @@ import Futhark.IR.GPUMem (GPUMem) import Futhark.IR.MCMem (MCMem) import Futhark.IR.Prop.Aliases+import Futhark.IR.SOACS (SOACS) import Futhark.IR.SeqMem (SeqMem) import Futhark.Util (runProgramWithExitCode, unixEnvironment) import Futhark.Version (versionString)@@ -63,6 +74,15 @@ actionProcedure = liftIO . putStrLn . pretty . aliasAnalysis } +-- | Print call graph to stdout.+callGraphAction :: Action SOACS+callGraphAction =+ Action+ { actionName = "call-graph",+ actionDescription = "Prettyprint the callgraph of the result to standard output.",+ actionProcedure = liftIO . putStrLn . pretty . buildCallGraph+ }+ -- | Print metrics about AST node counts to stdout. metricsAction :: OpMetrics (Op rep) => Action rep metricsAction =@@ -100,20 +120,20 @@ } -- Lines that we prepend (in comments) to generated code.-headerLines :: [String]-headerLines = lines $ "Generated by Futhark " ++ versionString+headerLines :: [T.Text]+headerLines = T.lines $ "Generated by Futhark " <> T.pack versionString -cHeaderLines :: [String]+cHeaderLines :: [T.Text] cHeaderLines = map ("// " <>) headerLines -pyHeaderLines :: [String]+pyHeaderLines :: [T.Text] pyHeaderLines = map ("# " <>) headerLines -cPrependHeader :: String -> String-cPrependHeader = (unlines cHeaderLines ++)+cPrependHeader :: T.Text -> T.Text+cPrependHeader = (T.unlines cHeaderLines <>) -pyPrependHeader :: String -> String-pyPrependHeader = (unlines pyHeaderLines ++)+pyPrependHeader :: T.Text -> T.Text+pyPrependHeader = (T.unlines pyHeaderLines <>) cmdCC :: String cmdCC = fromMaybe "cc" $ lookup "CC" unixEnvironment@@ -163,13 +183,13 @@ case mode of ToLibrary -> do let (header, impl) = SequentialC.asLibrary cprog- liftIO $ writeFile hpath $ cPrependHeader header- liftIO $ writeFile cpath $ cPrependHeader impl+ liftIO $ T.writeFile hpath $ cPrependHeader header+ liftIO $ T.writeFile cpath $ cPrependHeader impl ToExecutable -> do- liftIO $ writeFile cpath $ SequentialC.asExecutable cprog+ liftIO $ T.writeFile cpath $ SequentialC.asExecutable cprog runCC cpath outpath ["-O3", "-std=c99"] ["-lm"] ToServer -> do- liftIO $ writeFile cpath $ SequentialC.asServer cprog+ liftIO $ T.writeFile cpath $ SequentialC.asServer cprog runCC cpath outpath ["-O3", "-std=c99"] ["-lm"] -- | The @futhark opencl@ action.@@ -196,13 +216,13 @@ case mode of ToLibrary -> do let (header, impl) = COpenCL.asLibrary cprog- liftIO $ writeFile hpath $ cPrependHeader header- liftIO $ writeFile cpath $ cPrependHeader impl+ liftIO $ T.writeFile hpath $ cPrependHeader header+ liftIO $ T.writeFile cpath $ cPrependHeader impl ToExecutable -> do- liftIO $ writeFile cpath $ cPrependHeader $ COpenCL.asExecutable cprog+ liftIO $ T.writeFile cpath $ cPrependHeader $ COpenCL.asExecutable cprog runCC cpath outpath ["-O", "-std=c99"] ("-lm" : extra_options) ToServer -> do- liftIO $ writeFile cpath $ cPrependHeader $ COpenCL.asServer cprog+ liftIO $ T.writeFile cpath $ cPrependHeader $ COpenCL.asServer cprog runCC cpath outpath ["-O", "-std=c99"] ("-lm" : extra_options) -- | The @futhark cuda@ action.@@ -226,13 +246,13 @@ case mode of ToLibrary -> do let (header, impl) = CCUDA.asLibrary cprog- liftIO $ writeFile hpath $ cPrependHeader header- liftIO $ writeFile cpath $ cPrependHeader impl+ liftIO $ T.writeFile hpath $ cPrependHeader header+ liftIO $ T.writeFile cpath $ cPrependHeader impl ToExecutable -> do- liftIO $ writeFile cpath $ cPrependHeader $ CCUDA.asExecutable cprog+ liftIO $ T.writeFile cpath $ cPrependHeader $ CCUDA.asExecutable cprog runCC cpath outpath ["-O", "-std=c99"] ("-lm" : extra_options) ToServer -> do- liftIO $ writeFile cpath $ cPrependHeader $ CCUDA.asServer cprog+ liftIO $ T.writeFile cpath $ cPrependHeader $ CCUDA.asServer cprog runCC cpath outpath ["-O", "-std=c99"] ("-lm" : extra_options) -- | The @futhark multicore@ action.@@ -252,17 +272,17 @@ case mode of ToLibrary -> do let (header, impl) = MulticoreC.asLibrary cprog- liftIO $ writeFile hpath $ cPrependHeader header- liftIO $ writeFile cpath $ cPrependHeader impl+ liftIO $ T.writeFile hpath $ cPrependHeader header+ liftIO $ T.writeFile cpath $ cPrependHeader impl ToExecutable -> do- liftIO $ writeFile cpath $ cPrependHeader $ MulticoreC.asExecutable cprog- runCC cpath outpath ["-O", "-std=c99"] ["-lm", "-pthread"]+ liftIO $ T.writeFile cpath $ cPrependHeader $ MulticoreC.asExecutable cprog+ runCC cpath outpath ["-O3", "-std=c99"] ["-lm", "-pthread"] ToServer -> do- liftIO $ writeFile cpath $ cPrependHeader $ MulticoreC.asServer cprog- runCC cpath outpath ["-O", "-std=c99"] ["-lm", "-pthread"]+ liftIO $ T.writeFile cpath $ cPrependHeader $ MulticoreC.asServer cprog+ runCC cpath outpath ["-O3", "-std=c99"] ["-lm", "-pthread"] pythonCommon ::- (CompilerMode -> String -> prog -> FutharkM (Warnings, String)) ->+ (CompilerMode -> String -> prog -> FutharkM (Warnings, T.Text)) -> FutharkConfig -> CompilerMode -> FilePath ->@@ -277,12 +297,13 @@ case mode of ToLibrary ->- liftIO $ writeFile (outpath `addExtension` "py") $ pyPrependHeader pyprog+ liftIO $ T.writeFile (outpath `addExtension` "py") $ pyPrependHeader pyprog _ -> liftIO $ do- writeFile outpath $ "#!/usr/bin/env python3\n" ++ pyPrependHeader pyprog+ T.writeFile outpath $ "#!/usr/bin/env python3\n" <> pyPrependHeader pyprog perms <- liftIO $ getPermissions outpath setPermissions outpath $ setOwnerExecutable True perms +-- | The @futhark python@ action. compilePythonAction :: FutharkConfig -> CompilerMode -> FilePath -> Action SeqMem compilePythonAction fcfg mode outpath = Action@@ -291,6 +312,7 @@ actionProcedure = pythonCommon SequentialPy.compileProg fcfg mode outpath } +-- | The @futhark pyopencl@ action. compilePyOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem compilePyOpenCLAction fcfg mode outpath = Action@@ -298,3 +320,109 @@ actionDescription = "Compile to Python with OpenCL", actionProcedure = pythonCommon PyOpenCL.compileProg fcfg mode outpath }++cmdEMCFLAGS :: [String] -> [String]+cmdEMCFLAGS def = maybe def words $ lookup "EMCFLAGS" unixEnvironment++runEMCC :: String -> String -> FilePath -> [String] -> [String] -> [String] -> Bool -> FutharkM ()+runEMCC cpath outpath classpath cflags_def ldflags expfuns lib = do+ ret <-+ liftIO $+ runProgramWithExitCode+ "emcc"+ ( [cpath, "-o", outpath]+ ++ ["-lnodefs.js"]+ ++ ["-s", "--extern-post-js", classpath]+ ++ ( if lib+ then ["-s", "EXPORT_NAME=loadWASM"]+ else []+ )+ ++ ["-s", "WASM_BIGINT"]+ ++ cmdCFLAGS cflags_def+ ++ cmdEMCFLAGS [""]+ ++ [ "-s",+ "EXPORTED_FUNCTIONS=["+ ++ intercalate "," ("'_malloc'" : "'_free'" : expfuns)+ ++ "]"+ ]+ -- The default LDFLAGS are always added.+ ++ ldflags+ )+ mempty+ case ret of+ Left err ->+ externalErrorS $ "Failed to run emcc: " ++ show err+ Right (ExitFailure code, _, emccerr) ->+ externalErrorS $+ "emcc failed with code "+ ++ show code+ ++ ":\n"+ ++ emccerr+ Right (ExitSuccess, _, _) ->+ return ()++-- | The @futhark wasm@ action.+compileCtoWASMAction :: FutharkConfig -> CompilerMode -> FilePath -> Action SeqMem+compileCtoWASMAction fcfg mode outpath =+ Action+ { actionName = "Compile to sequential C",+ actionDescription = "Compile to sequential C",+ actionProcedure = helper+ }+ where+ helper prog = do+ (cprog, jsprog, exps) <- handleWarnings fcfg $ SequentialWASM.compileProg prog+ case mode of+ ToLibrary -> do+ writeLibs cprog jsprog+ liftIO $ T.appendFile classpath SequentialWASM.libraryExports+ runEMCC cpath mjspath classpath ["-O3", "-msimd128"] ["-lm"] exps True+ _ -> do+ -- Non-server executables are not supported.+ writeLibs cprog jsprog+ liftIO $ T.appendFile classpath SequentialWASM.runServer+ runEMCC cpath outpath classpath ["-O3", "-msimd128"] ["-lm"] exps False+ writeLibs cprog jsprog = do+ let (h, imp) = SequentialC.asLibrary cprog+ liftIO $ T.writeFile hpath h+ liftIO $ T.writeFile cpath imp+ liftIO $ T.writeFile classpath jsprog++ cpath = outpath `addExtension` "c"+ hpath = outpath `addExtension` "h"+ mjspath = outpath `addExtension` "mjs"+ classpath = outpath `addExtension` ".class.js"++-- | The @futhark wasm-multicore@ action.+compileMulticoreToWASMAction :: FutharkConfig -> CompilerMode -> FilePath -> Action MCMem+compileMulticoreToWASMAction fcfg mode outpath =+ Action+ { actionName = "Compile to sequential C",+ actionDescription = "Compile to sequential C",+ actionProcedure = helper+ }+ where+ helper prog = do+ (cprog, jsprog, exps) <- handleWarnings fcfg $ MulticoreWASM.compileProg prog++ case mode of+ ToLibrary -> do+ writeLibs cprog jsprog+ liftIO $ T.appendFile classpath MulticoreWASM.libraryExports+ runEMCC cpath mjspath classpath ["-O3", "-msimd128"] ["-lm", "-pthread"] exps True+ _ -> do+ -- Non-server executables are not supported.+ writeLibs cprog jsprog+ liftIO $ T.appendFile classpath MulticoreWASM.runServer+ runEMCC cpath outpath classpath ["-O3", "-msimd128"] ["-lm", "-pthread"] exps False++ writeLibs cprog jsprog = do+ let (h, imp) = MulticoreC.asLibrary cprog+ liftIO $ T.writeFile hpath h+ liftIO $ T.writeFile cpath imp+ liftIO $ T.writeFile classpath jsprog++ cpath = outpath `addExtension` "c"+ hpath = outpath `addExtension` "h"+ mjspath = outpath `addExtension` "mjs"+ classpath = outpath `addExtension` ".class.js"
src/Futhark/Analysis/Alias.hs view
@@ -72,7 +72,7 @@ Stm (Aliases rep) analyseStm aliases (Let pat (StmAux cs attrs dec) e) = let e' = analyseExp aliases e- pat' = addAliasesToPattern pat e'+ pat' = addAliasesToPat pat e' rep' = (AliasDec $ consumedInExp e', dec) in Let pat' (StmAux cs attrs rep') e'
src/Futhark/Analysis/CallGraph.hs view
@@ -9,6 +9,7 @@ calls, calledByConsts, allCalledBy,+ numOccurences, findNoninlined, ) where@@ -16,9 +17,10 @@ import Control.Monad.Writer.Strict import Data.List (foldl') import qualified Data.Map.Strict as M-import Data.Maybe (fromMaybe)+import Data.Maybe (isJust) import qualified Data.Set as S import Futhark.IR.SOACS+import Futhark.Util.Pretty type FunctionTable = M.Map Name (FunDef SOACS) @@ -27,45 +29,78 @@ where expand ftab f = M.insert (funDefName f) f ftab -type FunGraph = M.Map Name (S.Set Name)+-- | A unique (at least within a function) name identifying a function+-- call. In practice the first element of the corresponding pattern.+type CallId = VName +data FunCalls = FunCalls+ { fcMap :: M.Map CallId (Attrs, Name),+ fcAllCalled :: S.Set Name+ }+ deriving (Eq, Ord, Show)++instance Monoid FunCalls where+ mempty = FunCalls mempty mempty++instance Semigroup FunCalls where+ FunCalls x1 y1 <> FunCalls x2 y2 = FunCalls (x1 <> x2) (y1 <> y2)++fcCalled :: Name -> FunCalls -> Bool+fcCalled f fcs = f `S.member` fcAllCalled fcs++type FunGraph = M.Map Name FunCalls+ -- | The call graph is a mapping from a function name, i.e., the--- caller, to a set of the names of functions called *directly* (not+-- caller, to a record of the names of functions called *directly* (not -- transitively!) by the function. -- -- We keep track separately of the functions called by constants. data CallGraph = CallGraph- { calledByFuns :: M.Map Name (S.Set Name),- calledInConsts :: S.Set Name+ { cgCalledByFuns :: FunGraph,+ cgCalledByConsts :: FunCalls }+ deriving (Eq, Ord, Show) -- | Is the given function known to the call graph? isFunInCallGraph :: Name -> CallGraph -> Bool-isFunInCallGraph f = M.member f . calledByFuns+isFunInCallGraph f = M.member f . cgCalledByFuns -- | Does the first function call the second? calls :: Name -> Name -> CallGraph -> Bool calls caller callee =- maybe False (S.member callee) . M.lookup caller . calledByFuns+ maybe False (fcCalled callee) . M.lookup caller . cgCalledByFuns -- | Is the function called in any of the constants? calledByConsts :: Name -> CallGraph -> Bool-calledByConsts f = S.member f . calledInConsts+calledByConsts callee = fcCalled callee . cgCalledByConsts -- | All functions called by this function. allCalledBy :: Name -> CallGraph -> S.Set Name-allCalledBy f = fromMaybe mempty . M.lookup f . calledByFuns+allCalledBy f = maybe mempty fcAllCalled . M.lookup f . cgCalledByFuns -- | @buildCallGraph prog@ build the program's call graph. buildCallGraph :: Prog SOACS -> CallGraph buildCallGraph prog =- CallGraph fg $ buildFGStms $ progConsts prog+ CallGraph fg cg where fg = foldl' (buildFGfun ftable) M.empty entry_points+ cg = buildFGStms $ progConsts prog - entry_points = map funDefName $ progFuns prog+ entry_points =+ S.fromList (map funDefName (filter (isJust . funDefEntryPoint) $ progFuns prog))+ <> fcAllCalled cg ftable = buildFunctionTable prog +count :: Ord k => [k] -> M.Map k Int+count ks = M.fromListWith (+) $ zip ks $ repeat 1++-- | Produce a mapping of the number of occurences in the call graph+-- of each function. Only counts functions that are called at least+-- once.+numOccurences :: CallGraph -> M.Map Name Int+numOccurences (CallGraph funs consts) =+ count $ map snd $ M.elems (fcMap consts <> foldMap fcMap (M.elems funs))+ -- | @buildCallGraph ftable fg fname@ updates @fg@ with the -- contributions of function @fname@. buildFGfun :: FunctionTable -> FunGraph -> Name -> FunGraph@@ -77,18 +112,19 @@ let callees = buildFGBody $ funDefBody f fg' = M.insert fname callees fg -- recursively build the callees- foldl' (buildFGfun ftable) fg' callees+ foldl' (buildFGfun ftable) fg' $ fcAllCalled callees _ -> fg -buildFGStms :: Stms SOACS -> S.Set Name-buildFGStms = mconcat . map (buildFGexp . stmExp) . stmsToList+buildFGStms :: Stms SOACS -> FunCalls+buildFGStms = mconcat . map buildFGstm . stmsToList -buildFGBody :: Body -> S.Set Name+buildFGBody :: Body -> FunCalls buildFGBody = buildFGStms . bodyStms -buildFGexp :: Exp -> S.Set Name-buildFGexp (Apply fname _ _ _) = S.singleton fname-buildFGexp (Op op) = execWriter $ mapSOACM folder op+buildFGstm :: Stm -> FunCalls+buildFGstm (Let (Pat (p : _)) aux (Apply fname _ _ _)) =+ FunCalls (M.singleton (patElemName p) (stmAuxAttrs aux, fname)) (S.singleton fname)+buildFGstm (Let _ _ (Op op)) = execWriter $ mapSOACM folder op where folder = identitySOACMapper@@ -96,7 +132,7 @@ tell $ buildFGBody $ lambdaBody lam return lam }-buildFGexp e = execWriter $ mapExpM folder e+buildFGstm (Let _ _ e) = execWriter $ mapExpM folder e where folder = identityMapper@@ -137,3 +173,18 @@ S.singleton $ funDefName fd | otherwise = mempty++instance Pretty FunCalls where+ ppr = stack . map f . M.toList . fcMap+ where+ f (x, (attrs, y)) = "=>" <+> ppr y <+> parens ("at" <+> ppr x <+> ppr attrs)++instance Pretty CallGraph where+ ppr (CallGraph fg cg) =+ stack $+ punctuate line $+ ppFunCalls ("called at top level", cg) : map ppFunCalls (M.toList fg)+ where+ ppFunCalls (f, fcalls) =+ ppr f </> text (map (const '=') (nameToString f))+ </> indent 2 (ppr fcalls)
src/Futhark/Analysis/DataDependencies.hs view
@@ -32,7 +32,7 @@ let tdeps = dataDependencies' deps tb fdeps = dataDependencies' deps fb cdeps = depsOf deps c- comb (pe, tres, fres) =+ comb (pe, SubExpRes _ tres, SubExpRes _ fres) = ( patElemName pe, mconcat $ [freeIn pe, cdeps, depsOf tdeps tres, depsOf fdeps fres]@@ -42,14 +42,14 @@ M.fromList $ map comb $ zip3- (patternElements pat)+ (patElems pat) (bodyResult tb) (bodyResult fb) in M.unions [branchdeps, deps, tdeps, fdeps] grow deps (Let pat _ e) = let free = freeIn pat <> freeIn e freeDeps = mconcat $ map (depsOfVar deps) $ namesToList free- in M.fromList [(name, freeDeps) | name <- patternNames pat] `M.union` deps+ in M.fromList [(name, freeDeps) | name <- patNames pat] `M.union` deps depsOf :: Dependencies -> SubExp -> Names depsOf _ (Constant _) = mempty
src/Futhark/Analysis/HORep/MapNest.hs view
@@ -60,7 +60,7 @@ setDepth n nw = n {nestingWidth = nw} fromSOAC ::- ( Bindable rep,+ ( Buildable rep, MonadFreshNames m, LocalScope rep m, Op rep ~ Futhark.SOAC rep@@ -70,7 +70,7 @@ fromSOAC = fromSOAC' mempty fromSOAC' ::- ( Bindable rep,+ ( Buildable rep, MonadFreshNames m, LocalScope rep m, Op rep ~ Futhark.SOAC rep@@ -83,7 +83,7 @@ bodyResult $ lambdaBody lam ) of ([Let pat _ e], res)- | res == map Var (patternNames pat) ->+ | map resSubExp res == map Var (patNames pat) -> localScope (scopeOfLParams $ lambdaParams lam) $ SOAC.fromExp e >>= either (return . Left) (fmap (Right . fmap (pat,)) . fromSOAC' bound')@@ -102,7 +102,7 @@ let n' = Nesting { nestingParamNames = ps,- nestingResult = patternNames pat,+ nestingResult = patNames pat, nestingReturnType = typeOf mn, nestingWidth = inner_w }@@ -143,8 +143,8 @@ toSOAC :: ( MonadFreshNames m, HasScope rep m,- Bindable rep,- BinderOps rep,+ Buildable rep,+ BuilderOps rep, Op rep ~ Futhark.SOAC rep ) => MapNest rep ->@@ -153,7 +153,7 @@ return $ SOAC.Screma w (Futhark.mapSOAC lam) inps toSOAC (MapNest w lam (Nesting npnames nres nrettype nw : ns) inps) = do let nparams = zipWith Param npnames $ map SOAC.inputRowType inps- body <- runBodyBinder $+ body <- runBodyBuilder $ localScope (scopeOfLParams nparams) $ do letBindNames nres =<< SOAC.toExp =<< toSOAC (MapNest nw lam ns $ map (SOAC.identInput . paramIdent) nparams)
src/Futhark/Analysis/HORep/SOAC.hs view
@@ -99,15 +99,15 @@ -- create a list, use 'ArrayTransforms' instead. data ArrayTransform = -- | A permutation of an otherwise valid input.- Rearrange Certificates [Int]+ Rearrange Certs [Int] | -- | A reshaping of an otherwise valid input.- Reshape Certificates (ShapeChange SubExp)+ Reshape Certs (ShapeChange SubExp) | -- | A reshaping of the outer dimension.- ReshapeOuter Certificates (ShapeChange SubExp)+ ReshapeOuter Certs (ShapeChange SubExp) | -- | A reshaping of everything but the outer dimension.- ReshapeInner Certificates (ShapeChange SubExp)+ ReshapeInner Certs (ShapeChange SubExp) | -- | Replicate the rows of the array a number of times.- Replicate Certificates Shape+ Replicate Certs Shape deriving (Show, Eq, Ord) instance Substitute ArrayTransform where@@ -226,7 +226,7 @@ -- an input transformation of an array variable. If so, return the -- variable and the transformation. Only 'Rearrange' and 'Reshape' -- are possible to express this way.-transformFromExp :: Certificates -> Exp rep -> Maybe (VName, ArrayTransform)+transformFromExp :: Certs -> Exp rep -> Maybe (VName, ArrayTransform) transformFromExp cs (BasicOp (Futhark.Rearrange perm v)) = Just (v, Rearrange cs perm) transformFromExp cs (BasicOp (Futhark.Reshape shape v)) =@@ -288,7 +288,7 @@ -- | Convert SOAC inputs to the corresponding expressions. inputsToSubExps ::- (MonadBinder m) =>+ (MonadBuilder m) => [Input] -> m [VName] inputsToSubExps = mapM inputToExp'@@ -472,14 +472,14 @@ -- | Convert a SOAC to the corresponding expression. toExp ::- (MonadBinder m, Op (Rep m) ~ Futhark.SOAC (Rep m)) =>+ (MonadBuilder m, Op (Rep m) ~ Futhark.SOAC (Rep m)) => SOAC (Rep m) -> m (Exp (Rep m)) toExp soac = Op <$> toSOAC soac -- | Convert a SOAC to a Futhark-level SOAC. toSOAC ::- MonadBinder m =>+ MonadBuilder m => SOAC (Rep m) -> m (Futhark.SOAC (Rep m)) toSOAC (Stream w form lam nes inps) =@@ -520,7 +520,7 @@ -- Returns the Stream SOAC and the -- extra-accumulator body-result ident if any. soacToStream ::- (MonadFreshNames m, Bindable rep, Op rep ~ Futhark.SOAC rep) =>+ (MonadFreshNames m, Buildable rep, Op rep ~ Futhark.SOAC rep) => SOAC rep -> m (SOAC rep, [Ident]) soacToStream soac = do@@ -547,8 +547,8 @@ let insoac = Futhark.Screma chvar (map paramName strm_inpids) $ Futhark.mapSOAC lam'- insbnd = mkLet [] strm_resids $ Op insoac- strmbdy = mkBody (oneStm insbnd) $ map (Futhark.Var . identName) strm_resids+ insbnd = mkLet strm_resids $ Op insoac+ strmbdy = mkBody (oneStm insbnd) $ map (subExpRes . Futhark.Var . identName) strm_resids strmpar = chunk_param : strm_inpids strmlam = Lambda strmpar strmbdy loutps empty_lam = Lambda [] (mkBody mempty []) []@@ -582,56 +582,48 @@ outszm1id <- newIdent "szm1" $ Prim int64 -- 1. let (scan0_ids,map_resids) = scanomap(scan_lam,nes,map_lam,a_ch) let insbnd =- mkLet [] (scan0_ids ++ map_resids) $- Op $- Futhark.Screma chvar (map paramName strm_inpids) $- Futhark.scanomapSOAC [Futhark.Scan scan_lam nes] lam'+ mkLet (scan0_ids ++ map_resids) . Op $+ Futhark.Screma chvar (map paramName strm_inpids) $+ Futhark.scanomapSOAC [Futhark.Scan scan_lam nes] lam' -- 2. let outerszm1id = chunksize - 1 outszm1bnd =- mkLet [] [outszm1id] $- BasicOp $- BinOp- (Sub Int64 OverflowUndef)- (Futhark.Var $ paramName chunk_param)- (constant (1 :: Int64))+ mkLet [outszm1id] . BasicOp $+ BinOp+ (Sub Int64 OverflowUndef)+ (Futhark.Var $ paramName chunk_param)+ (constant (1 :: Int64)) -- 3. let lasteel_ids = ... empty_arr_bnd =- mkLet [] [empty_arr] $- BasicOp $- CmpOp- (CmpSlt Int64)- (Futhark.Var $ identName outszm1id)- (constant (0 :: Int64))+ mkLet [empty_arr] . BasicOp $+ CmpOp+ (CmpSlt Int64)+ (Futhark.Var $ identName outszm1id)+ (constant (0 :: Int64)) leltmpbnds = zipWith ( \lid arrid ->- mkLet [] [lid] $- BasicOp $- Index (identName arrid) $- fullSlice- (identType arrid)- [DimFix $ Futhark.Var $ identName outszm1id]+ mkLet [lid] . BasicOp $+ Index (identName arrid) $+ fullSlice+ (identType arrid)+ [DimFix $ Futhark.Var $ identName outszm1id] ) lastel_tmp_ids scan0_ids lelbnd =- mkLet [] lastel_ids $+ mkLet lastel_ids $ If (Futhark.Var $ identName empty_arr)- (mkBody mempty nes)+ (mkBody mempty $ subExpsRes nes) ( mkBody (stmsFromList leltmpbnds) $- map (Futhark.Var . identName) lastel_tmp_ids+ varsRes $ map identName lastel_tmp_ids ) $ ifCommon $ map identType lastel_tmp_ids -- 4. let strm_resids = map (acc `+`,nes, scan0_ids) maplam <- mkMapPlusAccLam (map (Futhark.Var . paramName) inpacc_ids) scan_lam let mapbnd =- mkLet [] strm_resids $- Op $- Futhark.Screma- chvar- (map identName scan0_ids)- (Futhark.mapSOAC maplam)+ mkLet strm_resids . Op $+ Futhark.Screma chvar (map identName scan0_ids) (Futhark.mapSOAC maplam) -- 5. let acc' = acc + lasteel_ids addlelbdy <- mkPlusBnds scan_lam $@@ -641,7 +633,7 @@ let (addlelbnd, addlelres) = (bodyStms addlelbdy, bodyResult addlelbdy) strmbdy = mkBody (stmsFromList [insbnd, outszm1bnd, empty_arr_bnd, lelbnd, mapbnd] <> addlelbnd) $- addlelres ++ map (Futhark.Var . identName) (strm_resids ++ map_resids)+ addlelres ++ map (subExpRes . Futhark.Var . identName) (strm_resids ++ map_resids) strmpar = chunk_param : inpacc_ids ++ strm_inpids strmlam = Lambda strmpar strmbdy (accrtps ++ loutps) return@@ -670,7 +662,7 @@ chvar (map paramName strm_inpids) $ Futhark.redomapSOAC [Futhark.Reduce comm lamin nes] foldlam- insbnd = mkLet [] (acc0_ids ++ strm_resids) $ Op insoac+ insbnd = mkLet (acc0_ids ++ strm_resids) $ Op insoac -- 2. let acc' = acc + acc0_ids in addaccbdy <- mkPlusBnds lamin $@@ -680,7 +672,7 @@ let (addaccbnd, addaccres) = (bodyStms addaccbdy, bodyResult addaccbdy) strmbdy = mkBody (oneStm insbnd <> addaccbnd) $- addaccres ++ map (Futhark.Var . identName) strm_resids+ addaccres ++ map (subExpRes . Futhark.Var . identName) strm_resids strmpar = chunk_param : inpacc_ids ++ strm_inpids strmlam = Lambda strmpar strmbdy (accrtps ++ loutps') lam0 <- renameLambda lamin@@ -690,7 +682,7 @@ _ -> return (soac, []) where mkMapPlusAccLam ::- (MonadFreshNames m, Bindable rep) =>+ (MonadFreshNames m, Buildable rep) => [SubExp] -> Lambda rep -> m (Lambda rep)@@ -698,12 +690,7 @@ let (accpars, rempars) = splitAt (length accs) $ lambdaParams plus parbnds = zipWith- ( \par se ->- mkLet- []- [paramIdent par]- (BasicOp $ SubExp se)- )+ (\par se -> mkLet [paramIdent par] (BasicOp $ SubExp se)) accpars accs plus_bdy = lambdaBody plus@@ -715,7 +702,7 @@ renameLambda $ Lambda rempars newlambdy $ lambdaReturnType plus mkPlusBnds ::- (MonadFreshNames m, Bindable rep) =>+ (MonadFreshNames m, Buildable rep) => Lambda rep -> [SubExp] -> m (Body rep)@@ -723,12 +710,7 @@ plus' <- renameLambda plus let parbnds = zipWith- ( \par se ->- mkLet- []- [paramIdent par]- (BasicOp $ SubExp se)- )+ (\par se -> mkLet [paramIdent par] (BasicOp $ SubExp se)) (lambdaParams plus') accels body = lambdaBody plus'
src/Futhark/Analysis/Interference.hs view
@@ -11,24 +11,24 @@ import Data.Functor ((<&>)) import Data.Map (Map) import qualified Data.Map as M-import Data.Maybe (catMaybes, fromMaybe)+import Data.Maybe (catMaybes, fromMaybe, mapMaybe) import Data.Set (Set) import qualified Data.Set as S import Futhark.Analysis.LastUse (LastUseMap) import Futhark.IR.GPUMem import Futhark.Util (invertMap) --- | The set of `VName` currently in use.+-- | The set of 'VName' currently in use. type InUse = Names --- | The set of `VName` that are no longer in use.+-- | The set of 'VName' that are no longer in use. type LastUsed = Names --- | An interference graph. An element `(x, y)` in the set means that there is--- an undirected edge between `x` and `y`, and therefore the lifetimes of `x`--- and `y` overlap and they "interfere" with each other. We assume that pairs--- are always normalized, such that `x` < `y`, before inserting. This should--- prevent any duplicates. We also don't allow any pairs where `x == y`.+-- | An interference graph. An element @(x, y)@ in the set means that there is+-- an undirected edge between @x@ and @y@, and therefore the lifetimes of @x@+-- and @y@ overlap and they "interfere" with each other. We assume that pairs+-- are always normalized, such that @x@ < @y@, before inserting. This should+-- prevent any duplicates. We also don't allow any pairs where @x == y@. type Graph a = Set (a, a) -- | Insert an edge between two values into the graph.@@ -52,11 +52,11 @@ m (InUse, LastUsed, Graph VName) analyseStm lumap inuse0 stm = inScopeOf stm $ do- let pat_name = patElemName $ head $ patternValueElements $ stmPattern stm+ let pat_name = patElemName $ head $ patElems $ stmPat stm new_mems <-- stmPattern stm- & patternValueElements+ stmPat stm+ & patElems & mapM (memInfo . patElemName) <&> catMaybes <&> namesFromList@@ -91,6 +91,23 @@ (namesToList $ inuse_outside <> inuse <> lus <> last_use_mems) ) +-- We conservatively treat all memory arguments to a DoLoop to+-- interfere with each other, as well as anything used inside the+-- loop. This could potentially be improved by looking at the+-- interference computed by the loop body wrt. the loop arguments, but+-- probably very few programs would benefit from this.+analyseLoopParams ::+ [(FParam GPUMem, SubExp)] ->+ (InUse, LastUsed, Graph VName) ->+ (InUse, LastUsed, Graph VName)+analyseLoopParams merge (inuse, lastused, graph) =+ (inuse, lastused, cartesian makeEdge mems (mems <> inner_mems) <> graph)+ where+ mems = mapMaybe isMemArg merge+ inner_mems = namesToList lastused <> namesToList inuse+ isMemArg (Param _ MemMem {}, Var v) = Just v+ isMemArg _ = Nothing+ analyseExp :: LocalScope GPUMem m => LastUseMap ->@@ -103,8 +120,8 @@ res1 <- analyseBody lumap inuse_outside then_body res2 <- analyseBody lumap inuse_outside else_body return $ res1 <> res2- DoLoop _ _ _ body -> do- analyseBody lumap inuse_outside body+ DoLoop merge _ body ->+ analyseLoopParams merge <$> analyseBody lumap inuse_outside body Op (Inner (SegOp segop)) -> do analyseSegOp lumap inuse_outside segop _ ->@@ -235,7 +252,7 @@ where memSizesStm :: LocalScope GPUMem m => Stm GPUMem -> m (Map VName Int) memSizesStm (Let pat _ e) = do- arraySizes <- fmap mconcat <$> mapM memElemSize $ patternNames pat+ arraySizes <- fmap mconcat <$> mapM memElemSize $ patNames pat arraySizes' <- memSizesExp e return $ arraySizes <> arraySizes' memSizesExp :: LocalScope GPUMem m => Exp GPUMem -> m (Map VName Int)@@ -249,7 +266,7 @@ then_res <- memSizes $ bodyStms then_body else_res <- memSizes $ bodyStms else_body return $ then_res <> else_res- memSizesExp (DoLoop _ _ _ body) =+ memSizesExp (DoLoop _ _ body) = memSizes $ bodyStms body memSizesExp _ = return mempty @@ -259,7 +276,7 @@ return $ foldMap getSpacesStm stms where getSpacesStm :: Stm GPUMem -> Map VName Space- getSpacesStm (Let (Pattern [] [PatElem name _]) _ (Op (Alloc _ sp))) =+ getSpacesStm (Let (Pat [PatElem name _]) _ (Op (Alloc _ sp))) = M.singleton name sp getSpacesStm (Let _ _ (Op (Alloc _ _))) = error "impossible" getSpacesStm (Let _ _ (Op (Inner (SegOp segop)))) =@@ -267,7 +284,7 @@ getSpacesStm (Let _ _ (If _ then_body else_body _)) = foldMap getSpacesStm (bodyStms then_body) <> foldMap getSpacesStm (bodyStms else_body)- getSpacesStm (Let _ _ (DoLoop _ _ _ body)) =+ getSpacesStm (Let _ _ (DoLoop _ _ body)) = foldMap getSpacesStm (bodyStms body) getSpacesStm _ = mempty @@ -290,18 +307,18 @@ res1 <- analyseGPU' lumap (bodyStms then_body) res2 <- analyseGPU' lumap (bodyStms else_body) return (res1 <> res2)- helper stm@Let {stmExp = DoLoop _ _ _ body} =- inScopeOf stm $+ helper stm@Let {stmExp = DoLoop merge _ body} =+ fmap (analyseLoopParams merge) . inScopeOf stm $ analyseGPU' lumap $ bodyStms body helper stm = inScopeOf stm $ return mempty -nameInfoToMemInfo :: Mem rep => NameInfo rep -> MemBound NoUniqueness+nameInfoToMemInfo :: Mem rep inner => NameInfo rep -> MemBound NoUniqueness nameInfoToMemInfo info = case info of FParamName summary -> noUniquenessReturns summary LParamName summary -> summary- LetName summary -> summary+ LetName summary -> letDecMem summary IndexName it -> MemPrim $ IntType it memInfo :: LocalScope GPUMem m => VName -> m (Maybe VName)
src/Futhark/Analysis/LastUse.hs view
@@ -34,7 +34,7 @@ analyseProg prog = let consts = progConsts prog- & concatMap (toList . fmap patElemName . patternValueElements . stmPattern)+ & concatMap (toList . fmap patElemName . patElems . stmPat) & namesFromList funs = progFuns $ aliasAnalysis prog (lus, used) = foldMap (analyseFun mempty consts) funs@@ -50,7 +50,7 @@ analyseStm :: Stm (Aliases GPUMem) -> (LastUse, Used) -> (LastUse, Used) analyseStm (Let pat _ e) (lumap0, used0) =- let (lumap', used') = patternValueElements pat & foldl helper (lumap0, used0)+ let (lumap', used') = patElems pat & foldl helper (lumap0, used0) in analyseExp (lumap', used') e where helper (lumap_acc, used_acc) (PatElem name (aliases, _)) =@@ -62,7 +62,7 @@ used_acc <> unAliases aliases ) - pat_name = patElemName $ head $ patternValueElements pat+ pat_name = patElemName $ head $ patElems pat analyseExp :: (LastUse, Used) -> Exp (Aliases GPUMem) -> (LastUse, Used) analyseExp (lumap, used) (BasicOp _) = let nms = freeIn e `namesSubtract` used@@ -76,9 +76,9 @@ used' = used_then <> used_else nms = ((freeIn cse <> freeIn dec) `namesSubtract` used') in (insertNames pat_name nms (lumap_then <> lumap_else), used' <> nms)- analyseExp (lumap, used) (DoLoop ctx vals form body) =+ analyseExp (lumap, used) (DoLoop merge form body) = let (lumap', used') = analyseBody lumap used body- nms = (freeIn ctx <> freeIn vals <> freeIn form) `namesSubtract` used'+ nms = (freeIn merge <> freeIn form) `namesSubtract` used' in (insertNames pat_name nms lumap', used' <> nms) analyseExp (lumap, used) (Op (Alloc se sp)) = let nms = (freeIn se <> freeIn sp) `namesSubtract` used
src/Futhark/Analysis/Metrics.hs view
@@ -100,10 +100,10 @@ expMetrics :: OpMetrics (Op rep) => Exp rep -> MetricsM () expMetrics (BasicOp op) =- seen "BasicOp" >> primOpMetrics op-expMetrics (DoLoop _ _ ForLoop {} body) =+ seen "BasicOp" >> basicOpMetrics op+expMetrics (DoLoop _ ForLoop {} body) = inside "DoLoop" $ seen "ForLoop" >> bodyMetrics body-expMetrics (DoLoop _ _ WhileLoop {} body) =+expMetrics (DoLoop _ WhileLoop {} body) = inside "DoLoop" $ seen "WhileLoop" >> bodyMetrics body expMetrics (If _ tb fb _) = inside "If" $ do@@ -116,27 +116,29 @@ expMetrics (Op op) = opMetrics op -primOpMetrics :: BasicOp -> MetricsM ()-primOpMetrics (SubExp _) = seen "SubExp"-primOpMetrics (Opaque _) = seen "Opaque"-primOpMetrics ArrayLit {} = seen "ArrayLit"-primOpMetrics BinOp {} = seen "BinOp"-primOpMetrics UnOp {} = seen "UnOp"-primOpMetrics ConvOp {} = seen "ConvOp"-primOpMetrics CmpOp {} = seen "ConvOp"-primOpMetrics Assert {} = seen "Assert"-primOpMetrics Index {} = seen "Index"-primOpMetrics Update {} = seen "Update"-primOpMetrics Concat {} = seen "Concat"-primOpMetrics Copy {} = seen "Copy"-primOpMetrics Manifest {} = seen "Manifest"-primOpMetrics Iota {} = seen "Iota"-primOpMetrics Replicate {} = seen "Replicate"-primOpMetrics Scratch {} = seen "Scratch"-primOpMetrics Reshape {} = seen "Reshape"-primOpMetrics Rearrange {} = seen "Rearrange"-primOpMetrics Rotate {} = seen "Rotate"-primOpMetrics UpdateAcc {} = seen "UpdateAcc"+basicOpMetrics :: BasicOp -> MetricsM ()+basicOpMetrics (SubExp _) = seen "SubExp"+basicOpMetrics (Opaque _ _) = seen "Opaque"+basicOpMetrics ArrayLit {} = seen "ArrayLit"+basicOpMetrics BinOp {} = seen "BinOp"+basicOpMetrics UnOp {} = seen "UnOp"+basicOpMetrics ConvOp {} = seen "ConvOp"+basicOpMetrics CmpOp {} = seen "ConvOp"+basicOpMetrics Assert {} = seen "Assert"+basicOpMetrics Index {} = seen "Index"+basicOpMetrics Update {} = seen "Update"+basicOpMetrics FlatIndex {} = seen "FlatIndex"+basicOpMetrics FlatUpdate {} = seen "FlatUpdate"+basicOpMetrics Concat {} = seen "Concat"+basicOpMetrics Copy {} = seen "Copy"+basicOpMetrics Manifest {} = seen "Manifest"+basicOpMetrics Iota {} = seen "Iota"+basicOpMetrics Replicate {} = seen "Replicate"+basicOpMetrics Scratch {} = seen "Scratch"+basicOpMetrics Reshape {} = seen "Reshape"+basicOpMetrics Rearrange {} = seen "Rearrange"+basicOpMetrics Rotate {} = seen "Rotate"+basicOpMetrics UpdateAcc {} = seen "UpdateAcc" -- | Compute metrics for this lambda. lambdaMetrics :: OpMetrics (Op rep) => Lambda rep -> MetricsM ()
src/Futhark/Analysis/PrimExp.hs view
@@ -13,6 +13,7 @@ isInt32, isInt64, isBool,+ isF16, isF32, isF64, evalPrimExp,@@ -147,6 +148,10 @@ isBool :: PrimExp v -> TPrimExp Bool v isBool = TPrimExp +-- | This expression is of type t'Half'.+isF16 :: PrimExp v -> TPrimExp Half v+isF16 = TPrimExp+ -- | This expression is of type t'Float'. isF32 :: PrimExp v -> TPrimExp Float v isF32 = TPrimExp@@ -258,6 +263,10 @@ -- | Construct a typed expression from a rational. fromRational' :: Rational -> TPrimExp t v +instance NumExp Half where+ fromInteger' = isF16 . ValueExp . FloatValue . Float16Value . fromInteger+ fromBoolExp = isF16 . ConvOpExp (SIToFP Int16 Float16) . ConvOpExp (BToI Int16) . untyped+ instance NumExp Float where fromInteger' = isF32 . ValueExp . FloatValue . Float32Value . fromInteger fromBoolExp = isF32 . ConvOpExp (SIToFP Int32 Float32) . ConvOpExp (BToI Int32) . untyped@@ -266,6 +275,9 @@ fromInteger' = TPrimExp . ValueExp . FloatValue . Float64Value . fromInteger fromBoolExp = isF64 . ConvOpExp (SIToFP Int32 Float64) . ConvOpExp (BToI Int32) . untyped +instance FloatExp Half where+ fromRational' = TPrimExp . ValueExp . FloatValue . Float16Value . fromRational+ instance FloatExp Float where fromRational' = TPrimExp . ValueExp . FloatValue . Float32Value . fromRational @@ -317,6 +329,24 @@ | otherwise = numBad "/" (x, y) fromRational = fromRational'++instance Pretty v => Floating (TPrimExp Half v) where+ x ** y = isF16 $ BinOpExp (FPow Float16) (untyped x) (untyped y)+ pi = isF16 $ ValueExp $ FloatValue $ Float16Value pi+ exp x = isF16 $ FunExp "exp16" [untyped x] $ FloatType Float16+ log x = isF16 $ FunExp "log16" [untyped x] $ FloatType Float16+ sin x = isF16 $ FunExp "sin16" [untyped x] $ FloatType Float16+ cos x = isF16 $ FunExp "cos16" [untyped x] $ FloatType Float16+ tan x = isF16 $ FunExp "tan16" [untyped x] $ FloatType Float16+ asin x = isF16 $ FunExp "asin16" [untyped x] $ FloatType Float16+ acos x = isF16 $ FunExp "acos16" [untyped x] $ FloatType Float16+ atan x = isF16 $ FunExp "atan16" [untyped x] $ FloatType Float16+ sinh x = isF16 $ FunExp "sinh16" [untyped x] $ FloatType Float16+ cosh x = isF16 $ FunExp "cosh16" [untyped x] $ FloatType Float16+ tanh x = isF16 $ FunExp "tanh16" [untyped x] $ FloatType Float16+ asinh x = isF16 $ FunExp "asinh16" [untyped x] $ FloatType Float16+ acosh x = isF16 $ FunExp "acosh16" [untyped x] $ FloatType Float16+ atanh x = isF16 $ FunExp "atanh16" [untyped x] $ FloatType Float16 instance Pretty v => Floating (TPrimExp Float v) where x ** y = isF32 $ BinOpExp (FPow Float32) (untyped x) (untyped y)
src/Futhark/Analysis/PrimExp/Convert.hs view
@@ -90,19 +90,19 @@ primExpFromSubExp t (Var v) = LeafExp v t primExpFromSubExp _ (Constant v) = ValueExp v --- | Shorthand for constructing a 'TPrimExp' of type 'Int32'.+-- | Shorthand for constructing a 'TPrimExp' of type v'Int32'. pe32 :: SubExp -> TPrimExp Int32 VName pe32 = isInt32 . primExpFromSubExp int32 --- | Shorthand for constructing a 'TPrimExp' of type 'Int32', from a leaf.+-- | Shorthand for constructing a 'TPrimExp' of type v'Int32', from a leaf. le32 :: a -> TPrimExp Int32 a le32 = isInt32 . flip LeafExp int32 --- | Shorthand for constructing a 'TPrimExp' of type 'Int64'.+-- | Shorthand for constructing a 'TPrimExp' of type v'Int64'. pe64 :: SubExp -> TPrimExp Int64 VName pe64 = isInt64 . primExpFromSubExp int64 --- | Shorthand for constructing a 'TPrimExp' of type 'Int64', from a leaf.+-- | Shorthand for constructing a 'TPrimExp' of type v'Int64', from a leaf. le64 :: a -> TPrimExp Int64 a le64 = isInt64 . flip LeafExp int64 @@ -110,15 +110,15 @@ f32pe :: SubExp -> TPrimExp Float VName f32pe = isF32 . primExpFromSubExp float32 --- | Shorthand for constructing a 'TPrimExp' of type 'Float32', from a leaf.+-- | Shorthand for constructing a 'TPrimExp' of type v'Float32', from a leaf. f32le :: a -> TPrimExp Float a f32le = isF32 . flip LeafExp float32 --- | Shorthand for constructing a 'TPrimExp' of type 'Float64'.+-- | Shorthand for constructing a 'TPrimExp' of type v'Float64'. f64pe :: SubExp -> TPrimExp Double VName f64pe = isF64 . primExpFromSubExp float64 --- | Shorthand for constructing a 'TPrimExp' of type 'Float64', from a leaf.+-- | Shorthand for constructing a 'TPrimExp' of type v'Float64', from a leaf. f64le :: a -> TPrimExp Double a f64le = isF64 . flip LeafExp float64 @@ -162,10 +162,10 @@ substituteInPrimExp tab = replaceInPrimExp $ \v t -> fromMaybe (LeafExp v t) $ M.lookup v tab --- | Convert a 'SubExp' slice to a 'PrimExp' slice.+-- | Convert a t'SubExp' slice to a 'PrimExp' slice. primExpSlice :: Slice SubExp -> Slice (TPrimExp Int64 VName)-primExpSlice = map $ fmap pe64+primExpSlice = fmap pe64 --- | Convert a 'PrimExp' slice to a 'SubExp' slice.-subExpSlice :: MonadBinder m => Slice (TPrimExp Int64 VName) -> m (Slice SubExp)-subExpSlice = mapM $ traverse $ toSubExp "slice"+-- | Convert a 'PrimExp' slice to a t'SubExp' slice.+subExpSlice :: MonadBuilder m => Slice (TPrimExp Int64 VName) -> m (Slice SubExp)+subExpSlice = traverse $ toSubExp "slice"
src/Futhark/Analysis/PrimExp/Parse.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} +-- | Building blocks for parsing prim primexpressions. *Not* an infix+-- representation. module Futhark.Analysis.PrimExp.Parse ( pPrimExp, pPrimValue,@@ -42,6 +44,7 @@ parens :: Parser a -> Parser a parens = between (lexeme "(") (lexeme ")") +-- | Parse a 'PrimExp' given a leaf parser. pPrimExp :: Parser (v, PrimType) -> Parser (PrimExp v) pPrimExp pLeaf = choice
src/Futhark/Analysis/Rephrase.hs view
@@ -9,7 +9,7 @@ rephraseBody, rephraseStm, rephraseLambda,- rephrasePattern,+ rephrasePat, rephrasePatElem, Rephraser (..), )@@ -56,17 +56,17 @@ rephraseStm :: Monad m => Rephraser m from to -> Stm from -> m (Stm to) rephraseStm rephraser (Let pat (StmAux cs attrs dec) e) = Let- <$> rephrasePattern (rephraseLetBoundDec rephraser) pat+ <$> rephrasePat (rephraseLetBoundDec rephraser) pat <*> (StmAux cs attrs <$> rephraseExpDec rephraser dec) <*> rephraseExp rephraser e -- | Rephrase a pattern.-rephrasePattern ::+rephrasePat :: Monad m => (from -> m to) ->- PatternT from ->- m (PatternT to)-rephrasePattern = traverse+ PatT from ->+ m (PatT to)+rephrasePat = traverse -- | Rephrase a pattern element. rephrasePatElem :: Monad m => (from -> m to) -> PatElemT from -> m (PatElemT to)
src/Futhark/Analysis/SymbolTable.hs view
@@ -109,12 +109,12 @@ data Indexed = -- | A PrimExp based on the indexes (that is, without -- accessing any actual array).- Indexed Certificates (PrimExp VName)+ Indexed Certs (PrimExp VName) | -- | The indexing corresponds to another (perhaps more -- advantageous) array.- IndexedArray Certificates VName [TPrimExp Int64 VName]+ IndexedArray Certs VName [TPrimExp Int64 VName] -indexedAddCerts :: Certificates -> Indexed -> Indexed+indexedAddCerts :: Certs -> Indexed -> Indexed indexedAddCerts cs1 (Indexed cs2 v) = Indexed (cs1 <> cs2) v indexedAddCerts cs1 (IndexedArray cs2 arr v) = IndexedArray (cs1 <> cs2) arr v @@ -210,10 +210,10 @@ lookupStm :: VName -> SymbolTable rep -> Maybe (Stm rep) lookupStm name vtable = entryStm =<< lookup name vtable -lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certificates)+lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certs) lookupExp name vtable = (stmExp &&& stmCerts) <$> lookupStm name vtable -lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certificates)+lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certs) lookupBasicOp name vtable = case lookupExp name vtable of Just (BasicOp e, cs) -> Just (e, cs) _ -> Nothing@@ -225,7 +225,7 @@ lookupSubExpType (Var v) = lookupType v lookupSubExpType (Constant v) = const $ Just $ Prim $ primValueType v -lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certificates)+lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certs) lookupSubExp name vtable = do (e, cs) <- lookupExp name vtable case e of@@ -279,9 +279,8 @@ case entryType entry of LetBound entry' | Just k <-- elemIndex name $- patternValueNames $- stmPattern $ letBoundStm entry' ->+ elemIndex name . patNames . stmPat $+ letBoundStm entry' -> letBoundIndex entry' k is FreeVar entry' -> freeVarIndex entry' name is@@ -333,7 +332,7 @@ is in index' v is' table indexExp table (BasicOp (Index v slice)) _ is =- index' v (adjust slice is) table+ index' v (adjust (unSlice slice) is) table where adjust (DimFix j : js') is' = pe64 j : adjust js' is'@@ -367,7 +366,7 @@ SymbolTable rep -> [LetBoundEntry rep] bindingEntries bnd@(Let pat _ _) vtable = do- pat_elem <- patternElements pat+ pat_elem <- patElems pat return $ defBndEntry vtable pat_elem (Aliases.aliasesOf pat_elem) bnd adjustSeveral :: Ord k => (v -> v) -> [k] -> M.Map k v -> M.Map k v@@ -412,10 +411,10 @@ SymbolTable rep insertStm stm vtable = flip (foldl' $ flip consume) (namesToList stm_consumed) $- flip (foldl' addRevAliases) (patternElements $ stmPattern stm) $+ flip (foldl' addRevAliases) (patElems $ stmPat stm) $ insertEntries (zip names $ map LetBound $ bindingEntries stm vtable) vtable where- names = patternNames $ stmPattern stm+ names = patNames $ stmPat stm stm_consumed = expandAliases (Aliases.consumedInStm stm) vtable addRevAliases vtable' pe = vtable' {bindings = adjustSeveral update inedges $ bindings vtable'}@@ -490,12 +489,12 @@ -- parameters. insertLoopMerge :: ASTRep rep =>- [(AST.FParam rep, SubExp, SubExp)] ->+ [(AST.FParam rep, SubExp, SubExpRes)] -> SymbolTable rep -> SymbolTable rep insertLoopMerge = flip $ foldl' $ flip bind where- bind (p, initial, res) =+ bind (p, initial, SubExpRes _ res) = insertEntry (paramName p) $ FParam FParamEntry@@ -555,4 +554,4 @@ hideCertified :: Names -> SymbolTable rep -> SymbolTable rep hideCertified to_hide = hideIf $ maybe False hide . entryStm where- hide = any (`nameIn` to_hide) . unCertificates . stmCerts+ hide = any (`nameIn` to_hide) . unCerts . stmCerts
src/Futhark/Analysis/UsageTable.hs view
@@ -157,10 +157,10 @@ where usageInPat = usages- ( mconcat (map freeIn $ patternElements pat)- `namesSubtract` namesFromList (patternNames pat)+ ( mconcat (map freeIn $ patElems pat)+ `namesSubtract` namesFromList (patNames pat) )- <> sizeUsages (foldMap (freeIn . patElemType) (patternElements pat))+ <> sizeUsages (foldMap (freeIn . patElemType) (patElems pat)) usageInExpDec = usages $ freeIn rep @@ -181,7 +181,9 @@ foldMap inputUsage inputs <> usageInBody (lambdaBody lam) where inputUsage (_, arrs, _) = foldMap consumedUsage arrs-usageInExp (BasicOp (Update src _ _)) =+usageInExp (BasicOp (Update _ src _ _)) =+ consumedUsage src+usageInExp (BasicOp (FlatUpdate src _ _)) = consumedUsage src usageInExp (Op op) = mconcat $ map consumedUsage (namesToList $ consumedInOp op)
src/Futhark/Bench.hs view
@@ -38,6 +38,8 @@ newtype RunResult = RunResult {runMicroseconds :: Int} deriving (Eq, Show) +-- | The measurements resulting from various successful runs of a+-- benchmark (same dataset). data Result = Result { runResults :: [RunResult], memoryMap :: M.Map T.Text Int,
− src/Futhark/Binder.hs
@@ -1,259 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}---- | This module defines a convenience monad/typeclass for creating--- normalised programs. The fundamental building block is 'BinderT'--- and its execution functions, but it is usually easier to use--- 'Binder'.------ See "Futhark.Construct" for a high-level description.-module Futhark.Binder- ( -- * A concrete @MonadBinder@ monad.- BinderT,- runBinderT,- runBinderT_,- runBinderT',- runBinderT'_,- BinderOps (..),- Binder,- runBinder,- runBinder_,- runBodyBinder,-- -- * The 'MonadBinder' typeclass- module Futhark.Binder.Class,- )-where--import Control.Arrow (second)-import Control.Monad.Error.Class-import Control.Monad.Reader-import Control.Monad.State.Strict-import Control.Monad.Writer-import qualified Data.Map.Strict as M-import Futhark.Binder.Class-import Futhark.IR---- | A 'BinderT' (and by extension, a 'Binder') is only an instance of--- 'MonadBinder' for representations that implement this type class,--- which contains methods for constructing statements.-class ASTRep rep => BinderOps rep where- mkExpDecB ::- (MonadBinder m, Rep m ~ rep) =>- Pattern rep ->- Exp rep ->- m (ExpDec rep)- mkBodyB ::- (MonadBinder m, Rep m ~ rep) =>- Stms rep ->- Result ->- m (Body rep)- mkLetNamesB ::- (MonadBinder m, Rep m ~ rep) =>- [VName] ->- Exp rep ->- m (Stm rep)-- default mkExpDecB ::- (MonadBinder m, Bindable rep) =>- Pattern rep ->- Exp rep ->- m (ExpDec rep)- mkExpDecB pat e = return $ mkExpDec pat e-- default mkBodyB ::- (MonadBinder m, Bindable rep) =>- Stms rep ->- Result ->- m (Body rep)- mkBodyB stms res = return $ mkBody stms res-- default mkLetNamesB ::- (MonadBinder m, Rep m ~ rep, Bindable rep) =>- [VName] ->- Exp rep ->- m (Stm rep)- mkLetNamesB = mkLetNames---- | A monad transformer that tracks statements and provides a--- 'MonadBinder' instance, assuming that the underlying monad provides--- a name source. In almost all cases, this is what you will use for--- constructing statements (possibly as part of a larger monad stack).--- If you find yourself needing to implement 'MonadBinder' from--- scratch, then it is likely that you are making a mistake.-newtype BinderT rep m a = BinderT (StateT (Stms rep, Scope rep) m a)- deriving (Functor, Monad, Applicative)--instance MonadTrans (BinderT rep) where- lift = BinderT . lift---- | The most commonly used binder monad.-type Binder rep = BinderT rep (State VNameSource)--instance MonadFreshNames m => MonadFreshNames (BinderT rep m) where- getNameSource = lift getNameSource- putNameSource = lift . putNameSource--instance- (ASTRep rep, Monad m) =>- HasScope rep (BinderT rep m)- where- lookupType name = do- t <- BinderT $ gets $ M.lookup name . snd- case t of- Nothing -> error $ "BinderT.lookupType: unknown variable " ++ pretty name- Just t' -> return $ typeOf t'- askScope = BinderT $ gets snd--instance- (ASTRep rep, Monad m) =>- LocalScope rep (BinderT rep m)- where- localScope types (BinderT m) = BinderT $ do- modify $ second (M.union types)- x <- m- modify $ second (`M.difference` types)- return x--instance- (ASTRep rep, MonadFreshNames m, BinderOps rep) =>- MonadBinder (BinderT rep m)- where- type Rep (BinderT rep m) = rep- mkExpDecM = mkExpDecB- mkBodyM = mkBodyB- mkLetNamesM = mkLetNamesB-- addStms stms =- BinderT $- modify $ \(cur_stms, scope) ->- (cur_stms <> stms, scope `M.union` scopeOf stms)-- collectStms m = do- (old_stms, old_scope) <- BinderT get- BinderT $ put (mempty, old_scope)- x <- m- (new_stms, _) <- BinderT get- BinderT $ put (old_stms, old_scope)- return (x, new_stms)---- | Run a binder action given an initial scope, returning a value and--- the statements added ('addStm') during the action.-runBinderT ::- MonadFreshNames m =>- BinderT rep m a ->- Scope rep ->- m (a, Stms rep)-runBinderT (BinderT m) scope = do- (x, (stms, _)) <- runStateT m (mempty, scope)- return (x, stms)---- | Like 'runBinderT', but return only the statements.-runBinderT_ ::- MonadFreshNames m =>- BinderT rep m () ->- Scope rep ->- m (Stms rep)-runBinderT_ m = fmap snd . runBinderT m---- | Like 'runBinderT', but get the initial scope from the current--- monad.-runBinderT' ::- (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>- BinderT rep m a ->- m (a, Stms rep)-runBinderT' m = do- scope <- askScope- runBinderT m $ castScope scope---- | Like 'runBinderT_', but get the initial scope from the current--- monad.-runBinderT'_ ::- (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>- BinderT rep m a ->- m (Stms rep)-runBinderT'_ = fmap snd . runBinderT'---- | Run a binder action, returning a value and the statements added--- ('addStm') during the action. Assumes that the current monad--- provides initial scope and name source.-runBinder ::- ( MonadFreshNames m,- HasScope somerep m,- SameScope somerep rep- ) =>- Binder rep a ->- m (a, Stms rep)-runBinder m = do- types <- askScope- modifyNameSource $ runState $ runBinderT m $ castScope types---- | Like 'runBinder', but throw away the result and just return the--- added statements.-runBinder_ ::- ( MonadFreshNames m,- HasScope somerep m,- SameScope somerep rep- ) =>- Binder rep a ->- m (Stms rep)-runBinder_ = fmap snd . runBinder---- | Run a binder that produces a t'Body', and prefix that t'Body' by--- the statements produced during execution of the action.-runBodyBinder ::- ( Bindable rep,- MonadFreshNames m,- HasScope somerep m,- SameScope somerep rep- ) =>- Binder rep (Body rep) ->- m (Body rep)-runBodyBinder = fmap (uncurry $ flip insertStms) . runBinder---- Utility instance defintions for MTL classes. These require--- UndecidableInstances, but save on typing elsewhere.--mapInner ::- Monad m =>- ( m (a, (Stms rep, Scope rep)) ->- m (b, (Stms rep, Scope rep))- ) ->- BinderT rep m a ->- BinderT rep m b-mapInner f (BinderT m) = BinderT $ do- s <- get- (x, s') <- lift $ f $ runStateT m s- put s'- return x--instance MonadReader r m => MonadReader r (BinderT rep m) where- ask = BinderT $ lift ask- local f = mapInner $ local f--instance MonadState s m => MonadState s (BinderT rep m) where- get = BinderT $ lift get- put = BinderT . lift . put--instance MonadWriter w m => MonadWriter w (BinderT rep m) where- tell = BinderT . lift . tell- pass = mapInner $ \m -> pass $ do- ((x, f), s) <- m- return ((x, s), f)- listen = mapInner $ \m -> do- ((x, s), y) <- listen m- return ((x, y), s)--instance MonadError e m => MonadError e (BinderT rep m) where- throwError = lift . throwError- catchError (BinderT m) f =- BinderT $ catchError m $ unBinder . f- where- unBinder (BinderT m') = m'
− src/Futhark/Binder/Class.hs
@@ -1,173 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | This module defines a convenience typeclass for creating--- normalised programs.------ See "Futhark.Construct" for a high-level description.-module Futhark.Binder.Class- ( Bindable (..),- mkLet,- mkLet',- MonadBinder (..),- insertStms,- insertStm,- letBind,- letBindNames,- collectStms_,- bodyBind,- attributing,- auxing,- module Futhark.MonadFreshNames,- )-where--import qualified Data.Kind-import Futhark.IR-import Futhark.MonadFreshNames---- | The class of representations that can be constructed solely from--- an expression, within some monad. Very important: the methods--- should not have any significant side effects! They may be called--- more often than you think, and the results thrown away. If used--- exclusively within a 'MonadBinder' instance, it is acceptable for--- them to create new bindings, however.-class- ( ASTRep rep,- FParamInfo rep ~ DeclType,- LParamInfo rep ~ Type,- RetType rep ~ DeclExtType,- BranchType rep ~ ExtType,- SetType (LetDec rep)- ) =>- Bindable rep- where- mkExpPat :: [Ident] -> [Ident] -> Exp rep -> Pattern rep- mkExpDec :: Pattern rep -> Exp rep -> ExpDec rep- mkBody :: Stms rep -> Result -> Body rep- mkLetNames ::- (MonadFreshNames m, HasScope rep m) =>- [VName] ->- Exp rep ->- m (Stm rep)---- | A monad that supports the creation of bindings from expressions--- and bodies from bindings, with a specific rep. This is the main--- typeclass that a monad must implement in order for it to be useful--- for generating or modifying Futhark code. Most importantly--- maintains a current state of 'Stms' (as well as a 'Scope') that--- have been added with 'addStm'.------ Very important: the methods should not have any significant side--- effects! They may be called more often than you think, and the--- results thrown away. It is acceptable for them to create new--- bindings, however.-class- ( ASTRep (Rep m),- MonadFreshNames m,- Applicative m,- Monad m,- LocalScope (Rep m) m- ) =>- MonadBinder m- where- type Rep m :: Data.Kind.Type- mkExpDecM :: Pattern (Rep m) -> Exp (Rep m) -> m (ExpDec (Rep m))- mkBodyM :: Stms (Rep m) -> Result -> m (Body (Rep m))- mkLetNamesM :: [VName] -> Exp (Rep m) -> m (Stm (Rep m))-- -- | Add a statement to the 'Stms' under construction.- addStm :: Stm (Rep m) -> m ()- addStm = addStms . oneStm-- -- | Add multiple statements to the 'Stms' under construction.- addStms :: Stms (Rep m) -> m ()-- -- | Obtain the statements constructed during a monadic action,- -- instead of adding them to the state.- collectStms :: m a -> m (a, Stms (Rep m))-- -- | Add the provided certificates to any statements added during- -- execution of the action.- certifying :: Certificates -> m a -> m a- certifying = censorStms . fmap . certify---- | Apply a function to the statements added by this action.-censorStms ::- MonadBinder m =>- (Stms (Rep m) -> Stms (Rep m)) ->- m a ->- m a-censorStms f m = do- (x, stms) <- collectStms m- addStms $ f stms- return x---- | Add the given attributes to any statements added by this action.-attributing :: MonadBinder m => Attrs -> m a -> m a-attributing attrs = censorStms $ fmap onStm- where- onStm (Let pat aux e) =- Let pat aux {stmAuxAttrs = attrs <> stmAuxAttrs aux} e---- | Add the certificates and attributes to any statements added by--- this action.-auxing :: MonadBinder m => StmAux anyrep -> m a -> m a-auxing (StmAux cs attrs _) = censorStms $ fmap onStm- where- onStm (Let pat aux e) =- Let pat aux' e- where- aux' =- aux- { stmAuxAttrs = attrs <> stmAuxAttrs aux,- stmAuxCerts = cs <> stmAuxCerts aux- }---- | Add a statement with the given pattern and expression.-letBind ::- MonadBinder m =>- Pattern (Rep m) ->- Exp (Rep m) ->- m ()-letBind pat e =- addStm =<< Let pat <$> (defAux <$> mkExpDecM pat e) <*> pure e---- | Construct a 'Stm' from identifiers for the context- and value--- part of the pattern, as well as the expression.-mkLet :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Stm rep-mkLet ctx val e =- let pat = mkExpPat ctx val e- dec = mkExpDec pat e- in Let pat (defAux dec) e---- | Like mkLet, but also take attributes and certificates from the--- given 'StmAux'.-mkLet' :: Bindable rep => [Ident] -> [Ident] -> StmAux a -> Exp rep -> Stm rep-mkLet' ctx val (StmAux cs attrs _) e =- let pat = mkExpPat ctx val e- dec = mkExpDec pat e- in Let pat (StmAux cs attrs dec) e---- | Add a statement with the given pattern element names and--- expression.-letBindNames :: MonadBinder m => [VName] -> Exp (Rep m) -> m ()-letBindNames names e = addStm =<< mkLetNamesM names e---- | As 'collectStms', but throw away the ordinary result.-collectStms_ :: MonadBinder m => m a -> m (Stms (Rep m))-collectStms_ = fmap snd . collectStms---- | Add the statements of the body, then return the body result.-bodyBind :: MonadBinder m => Body (Rep m) -> m [SubExp]-bodyBind (Body _ stms es) = do- addStms stms- return es---- | Add several bindings at the outermost level of a t'Body'.-insertStms :: Bindable rep => Stms rep -> Body rep -> Body rep-insertStms stms1 (Body _ stms2 res) = mkBody (stms1 <> stms2) res---- | Add a single binding at the outermost level of a t'Body'.-insertStm :: Bindable rep => Stm rep -> Body rep -> Body rep-insertStm = insertStms . oneStm
+ src/Futhark/Builder.hs view
@@ -0,0 +1,246 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This module defines a convenience monad/typeclass for building+-- ASTs. The fundamental building block is 'BuilderT' and its+-- execution functions, but it is usually easier to use 'Builder'.+--+-- See "Futhark.Construct" for a high-level description.+module Futhark.Builder+ ( -- * A concrete @MonadBuilder@ monad.+ BuilderT,+ runBuilderT,+ runBuilderT_,+ runBuilderT',+ runBuilderT'_,+ BuilderOps (..),+ Builder,+ runBuilder,+ runBuilder_,+ runBodyBuilder,++ -- * The 'MonadBuilder' typeclass+ module Futhark.Builder.Class,+ )+where++import Control.Arrow (second)+import Control.Monad.Error.Class+import Control.Monad.Reader+import Control.Monad.State.Strict+import Control.Monad.Writer+import qualified Data.Map.Strict as M+import Futhark.Builder.Class+import Futhark.IR++-- | A 'BuilderT' (and by extension, a 'Builder') is only an instance of+-- 'MonadBuilder' for representations that implement this type class,+-- which contains methods for constructing statements.+class ASTRep rep => BuilderOps rep where+ mkExpDecB ::+ (MonadBuilder m, Rep m ~ rep) =>+ Pat rep ->+ Exp rep ->+ m (ExpDec rep)+ mkBodyB ::+ (MonadBuilder m, Rep m ~ rep) =>+ Stms rep ->+ Result ->+ m (Body rep)+ mkLetNamesB ::+ (MonadBuilder m, Rep m ~ rep) =>+ [VName] ->+ Exp rep ->+ m (Stm rep)++ default mkExpDecB ::+ (MonadBuilder m, Buildable rep) =>+ Pat rep ->+ Exp rep ->+ m (ExpDec rep)+ mkExpDecB pat e = return $ mkExpDec pat e++ default mkBodyB ::+ (MonadBuilder m, Buildable rep) =>+ Stms rep ->+ Result ->+ m (Body rep)+ mkBodyB stms res = return $ mkBody stms res++ default mkLetNamesB ::+ (MonadBuilder m, Rep m ~ rep, Buildable rep) =>+ [VName] ->+ Exp rep ->+ m (Stm rep)+ mkLetNamesB = mkLetNames++-- | A monad transformer that tracks statements and provides a+-- 'MonadBuilder' instance, assuming that the underlying monad provides+-- a name source. In almost all cases, this is what you will use for+-- constructing statements (possibly as part of a larger monad stack).+-- If you find yourself needing to implement 'MonadBuilder' from+-- scratch, then it is likely that you are making a mistake.+newtype BuilderT rep m a = BuilderT (StateT (Stms rep, Scope rep) m a)+ deriving (Functor, Monad, Applicative)++instance MonadTrans (BuilderT rep) where+ lift = BuilderT . lift++-- | The most commonly used binder monad.+type Builder rep = BuilderT rep (State VNameSource)++instance MonadFreshNames m => MonadFreshNames (BuilderT rep m) where+ getNameSource = lift getNameSource+ putNameSource = lift . putNameSource++instance (ASTRep rep, Monad m) => HasScope rep (BuilderT rep m) where+ lookupType name = do+ t <- BuilderT $ gets $ M.lookup name . snd+ case t of+ Nothing -> error $ "BuilderT.lookupType: unknown variable " ++ pretty name+ Just t' -> return $ typeOf t'+ askScope = BuilderT $ gets snd++instance (ASTRep rep, Monad m) => LocalScope rep (BuilderT rep m) where+ localScope types (BuilderT m) = BuilderT $ do+ modify $ second (M.union types)+ x <- m+ modify $ second (`M.difference` types)+ return x++instance+ (ASTRep rep, MonadFreshNames m, BuilderOps rep) =>+ MonadBuilder (BuilderT rep m)+ where+ type Rep (BuilderT rep m) = rep+ mkExpDecM = mkExpDecB+ mkBodyM = mkBodyB+ mkLetNamesM = mkLetNamesB++ addStms stms =+ BuilderT $+ modify $ \(cur_stms, scope) ->+ (cur_stms <> stms, scope `M.union` scopeOf stms)++ collectStms m = do+ (old_stms, old_scope) <- BuilderT get+ BuilderT $ put (mempty, old_scope)+ x <- m+ (new_stms, _) <- BuilderT get+ BuilderT $ put (old_stms, old_scope)+ return (x, new_stms)++-- | Run a binder action given an initial scope, returning a value and+-- the statements added ('addStm') during the action.+runBuilderT ::+ MonadFreshNames m =>+ BuilderT rep m a ->+ Scope rep ->+ m (a, Stms rep)+runBuilderT (BuilderT m) scope = do+ (x, (stms, _)) <- runStateT m (mempty, scope)+ return (x, stms)++-- | Like 'runBuilderT', but return only the statements.+runBuilderT_ ::+ MonadFreshNames m =>+ BuilderT rep m () ->+ Scope rep ->+ m (Stms rep)+runBuilderT_ m = fmap snd . runBuilderT m++-- | Like 'runBuilderT', but get the initial scope from the current+-- monad.+runBuilderT' ::+ (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>+ BuilderT rep m a ->+ m (a, Stms rep)+runBuilderT' m = do+ scope <- askScope+ runBuilderT m $ castScope scope++-- | Like 'runBuilderT_', but get the initial scope from the current+-- monad.+runBuilderT'_ ::+ (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>+ BuilderT rep m a ->+ m (Stms rep)+runBuilderT'_ = fmap snd . runBuilderT'++-- | Run a binder action, returning a value and the statements added+-- ('addStm') during the action. Assumes that the current monad+-- provides initial scope and name source.+runBuilder ::+ (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>+ Builder rep a ->+ m (a, Stms rep)+runBuilder m = do+ types <- askScope+ modifyNameSource $ runState $ runBuilderT m $ castScope types++-- | Like 'runBuilder', but throw away the result and just return the+-- added statements.+runBuilder_ ::+ (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) =>+ Builder rep a ->+ m (Stms rep)+runBuilder_ = fmap snd . runBuilder++-- | Run a binder that produces a t'Body', and prefix that t'Body' by+-- the statements produced during execution of the action.+runBodyBuilder ::+ ( Buildable rep,+ MonadFreshNames m,+ HasScope somerep m,+ SameScope somerep rep+ ) =>+ Builder rep (Body rep) ->+ m (Body rep)+runBodyBuilder = fmap (uncurry $ flip insertStms) . runBuilder++-- Utility instance defintions for MTL classes. These require+-- UndecidableInstances, but save on typing elsewhere.++mapInner ::+ Monad m =>+ ( m (a, (Stms rep, Scope rep)) ->+ m (b, (Stms rep, Scope rep))+ ) ->+ BuilderT rep m a ->+ BuilderT rep m b+mapInner f (BuilderT m) = BuilderT $ do+ s <- get+ (x, s') <- lift $ f $ runStateT m s+ put s'+ return x++instance MonadReader r m => MonadReader r (BuilderT rep m) where+ ask = BuilderT $ lift ask+ local f = mapInner $ local f++instance MonadState s m => MonadState s (BuilderT rep m) where+ get = BuilderT $ lift get+ put = BuilderT . lift . put++instance MonadWriter w m => MonadWriter w (BuilderT rep m) where+ tell = BuilderT . lift . tell+ pass = mapInner $ \m -> pass $ do+ ((x, f), s) <- m+ return ((x, s), f)+ listen = mapInner $ \m -> do+ ((x, s), y) <- listen m+ return ((x, y), s)++instance MonadError e m => MonadError e (BuilderT rep m) where+ throwError = lift . throwError+ catchError (BuilderT m) f =+ BuilderT $ catchError m $ unBuilder . f+ where+ unBuilder (BuilderT m') = m'
+ src/Futhark/Builder/Class.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | This module defines a convenience typeclass for creating+-- normalised programs.+--+-- See "Futhark.Construct" for a high-level description.+module Futhark.Builder.Class+ ( Buildable (..),+ mkLet,+ mkLet',+ MonadBuilder (..),+ insertStms,+ insertStm,+ letBind,+ letBindNames,+ collectStms_,+ bodyBind,+ attributing,+ auxing,+ module Futhark.MonadFreshNames,+ )+where++import qualified Data.Kind+import Futhark.IR+import Futhark.MonadFreshNames++-- | The class of representations that can be constructed solely from+-- an expression, within some monad. Very important: the methods+-- should not have any significant side effects! They may be called+-- more often than you think, and the results thrown away. If used+-- exclusively within a 'MonadBuilder' instance, it is acceptable for+-- them to create new bindings, however.+class+ ( ASTRep rep,+ FParamInfo rep ~ DeclType,+ LParamInfo rep ~ Type,+ RetType rep ~ DeclExtType,+ BranchType rep ~ ExtType,+ SetType (LetDec rep)+ ) =>+ Buildable rep+ where+ mkExpPat :: [Ident] -> Exp rep -> Pat rep+ mkExpDec :: Pat rep -> Exp rep -> ExpDec rep+ mkBody :: Stms rep -> Result -> Body rep+ mkLetNames ::+ (MonadFreshNames m, HasScope rep m) =>+ [VName] ->+ Exp rep ->+ m (Stm rep)++-- | A monad that supports the creation of bindings from expressions+-- and bodies from bindings, with a specific rep. This is the main+-- typeclass that a monad must implement in order for it to be useful+-- for generating or modifying Futhark code. Most importantly+-- maintains a current state of 'Stms' (as well as a 'Scope') that+-- have been added with 'addStm'.+--+-- Very important: the methods should not have any significant side+-- effects! They may be called more often than you think, and the+-- results thrown away. It is acceptable for them to create new+-- bindings, however.+class+ ( ASTRep (Rep m),+ MonadFreshNames m,+ Applicative m,+ Monad m,+ LocalScope (Rep m) m+ ) =>+ MonadBuilder m+ where+ type Rep m :: Data.Kind.Type+ mkExpDecM :: Pat (Rep m) -> Exp (Rep m) -> m (ExpDec (Rep m))+ mkBodyM :: Stms (Rep m) -> Result -> m (Body (Rep m))+ mkLetNamesM :: [VName] -> Exp (Rep m) -> m (Stm (Rep m))++ -- | Add a statement to the 'Stms' under construction.+ addStm :: Stm (Rep m) -> m ()+ addStm = addStms . oneStm++ -- | Add multiple statements to the 'Stms' under construction.+ addStms :: Stms (Rep m) -> m ()++ -- | Obtain the statements constructed during a monadic action,+ -- instead of adding them to the state.+ collectStms :: m a -> m (a, Stms (Rep m))++ -- | Add the provided certificates to any statements added during+ -- execution of the action.+ certifying :: Certs -> m a -> m a+ certifying = censorStms . fmap . certify++-- | Apply a function to the statements added by this action.+censorStms ::+ MonadBuilder m =>+ (Stms (Rep m) -> Stms (Rep m)) ->+ m a ->+ m a+censorStms f m = do+ (x, stms) <- collectStms m+ addStms $ f stms+ return x++-- | Add the given attributes to any statements added by this action.+attributing :: MonadBuilder m => Attrs -> m a -> m a+attributing attrs = censorStms $ fmap onStm+ where+ onStm (Let pat aux e) =+ Let pat aux {stmAuxAttrs = attrs <> stmAuxAttrs aux} e++-- | Add the certificates and attributes to any statements added by+-- this action.+auxing :: MonadBuilder m => StmAux anyrep -> m a -> m a+auxing (StmAux cs attrs _) = censorStms $ fmap onStm+ where+ onStm (Let pat aux e) =+ Let pat aux' e+ where+ aux' =+ aux+ { stmAuxAttrs = attrs <> stmAuxAttrs aux,+ stmAuxCerts = cs <> stmAuxCerts aux+ }++-- | Add a statement with the given pattern and expression.+letBind ::+ MonadBuilder m =>+ Pat (Rep m) ->+ Exp (Rep m) ->+ m ()+letBind pat e =+ addStm =<< Let pat <$> (defAux <$> mkExpDecM pat e) <*> pure e++-- | Construct a 'Stm' from identifiers for the context- and value+-- part of the pattern, as well as the expression.+mkLet :: Buildable rep => [Ident] -> Exp rep -> Stm rep+mkLet ids e =+ let pat = mkExpPat ids e+ dec = mkExpDec pat e+ in Let pat (defAux dec) e++-- | Like mkLet, but also take attributes and certificates from the+-- given 'StmAux'.+mkLet' :: Buildable rep => [Ident] -> StmAux a -> Exp rep -> Stm rep+mkLet' ids (StmAux cs attrs _) e =+ let pat = mkExpPat ids e+ dec = mkExpDec pat e+ in Let pat (StmAux cs attrs dec) e++-- | Add a statement with the given pattern element names and+-- expression.+letBindNames :: MonadBuilder m => [VName] -> Exp (Rep m) -> m ()+letBindNames names e = addStm =<< mkLetNamesM names e++-- | As 'collectStms', but throw away the ordinary result.+collectStms_ :: MonadBuilder m => m a -> m (Stms (Rep m))+collectStms_ = fmap snd . collectStms++-- | Add the statements of the body, then return the body result.+bodyBind :: MonadBuilder m => Body (Rep m) -> m Result+bodyBind (Body _ stms res) = do+ addStms stms+ pure res++-- | Add several bindings at the outermost level of a t'Body'.+insertStms :: Buildable rep => Stms rep -> Body rep -> Body rep+insertStms stms1 (Body _ stms2 res) = mkBody (stms1 <> stms2) res++-- | Add a single binding at the outermost level of a t'Body'.+insertStm :: Buildable rep => Stm rep -> Body rep -> Body rep+insertStm = insertStms . oneStm
src/Futhark/CLI/Bench.hs view
@@ -230,12 +230,7 @@ cell i | i' * step_size <= cur' = char 9 | otherwise =- char- ( floor- ( ((cur' - (i' -1) * step_size) * num_chars)- / step_size- )- )+ char (floor (((cur' - (i' -1) * step_size) * num_chars) / step_size)) where i' = fromIntegral i
src/Futhark/CLI/Dataset.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Strict #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} -- | @futhark dataset@ module Futhark.CLI.Dataset (main) where@@ -16,6 +17,7 @@ import Data.Word import qualified Futhark.Data as V import Futhark.Data.Reader (readValues)+import Futhark.Util (convFloat) import Futhark.Util.Options import Language.Futhark.Parser import Language.Futhark.Pretty ()@@ -29,7 +31,7 @@ ) import System.Exit import System.IO-import System.Random.PCG (Variate, initialize, uniformR)+import System.Random.PCG (Variate (..), initialize) -- | Run @futhark dataset@. main :: String -> [String] -> IO ()@@ -134,6 +136,7 @@ setRangeOption "u16" setu16Range, setRangeOption "u32" setu32Range, setRangeOption "u64" setu64Range,+ setRangeOption "f16" setf16Range, setRangeOption "f32" setf32Range, setRangeOption "f64" setf64Range ]@@ -217,6 +220,7 @@ u16Range :: Range Word16, u32Range :: Range Word32, u64Range :: Range Word64,+ f16Range :: Range Half, f32Range :: Range Float, f64Range :: Range Double }@@ -247,6 +251,9 @@ setu64Range :: Range Word64 -> RandomConfiguration -> RandomConfiguration setu64Range bounds config = config {u64Range = bounds} +setf16Range :: Range Half -> RandomConfiguration -> RandomConfiguration+setf16Range bounds config = config {f16Range = bounds}+ setf32Range :: Range Float -> RandomConfiguration -> RandomConfiguration setf32Range bounds config = config {f32Range = bounds} @@ -266,6 +273,7 @@ (minBound, maxBound) (0.0, 1.0) (0.0, 1.0)+ (0.0, 1.0) randomValue :: RandomConfiguration -> V.ValueType -> Word64 -> V.Value randomValue conf (V.ValueType ds t) seed =@@ -278,6 +286,7 @@ V.U16 -> gen u16Range V.U16Value V.U32 -> gen u32Range V.U32Value V.U64 -> gen u64Range V.U64Value+ V.F16 -> gen f16Range V.F16Value V.F32 -> gen f32Range V.F32Value V.F64 -> gen f64Range V.F64Value V.Bool -> gen (const (False, True)) V.BoolValue@@ -307,3 +316,12 @@ fill 0 where n = product ds++-- XXX: The following instance is an orphan. Maybe it could be+-- avoided with some newtype trickery or refactoring, but it's so+-- convenient this way.+instance Variate Half where+ uniformR (a, b) g = do+ (convFloat :: Float -> Half) <$> uniformR (convFloat a, convFloat b) g+ uniform = uniformR (0, 1)+ uniformB b = uniformR (0, b)
src/Futhark/CLI/Dev.hs view
@@ -14,7 +14,7 @@ import Futhark.Actions import qualified Futhark.Analysis.Alias as Alias import Futhark.Analysis.Metrics (OpMetrics)-import Futhark.Compiler.CLI+import Futhark.Compiler.CLI hiding (compilerMain) import Futhark.IR (ASTRep, Op, Prog, pretty) import qualified Futhark.IR.GPU as GPU import qualified Futhark.IR.GPUMem as GPUMem@@ -81,6 +81,7 @@ -- | Nothing is distinct from a empty pipeline - -- it means we don't even run the internaliser. futharkPipeline :: FutharkPipeline,+ futharkCompilerMode :: CompilerMode, futharkAction :: UntypedAction, -- | If true, prints programs as raw ASTs instead -- of their prettyprinted form.@@ -138,12 +139,14 @@ FutharkM UntypedPassState ) +type BackendAction rep = FutharkConfig -> CompilerMode -> FilePath -> Action rep+ data UntypedAction = SOACSAction (Action SOACS.SOACS) | GPUAction (Action GPU.GPU)- | GPUMemAction (FilePath -> Action GPUMem.GPUMem)- | MCMemAction (FilePath -> Action MCMem.MCMem)- | SeqMemAction (FilePath -> Action SeqMem.SeqMem)+ | GPUMemAction (BackendAction GPUMem.GPUMem)+ | MCMemAction (BackendAction MCMem.MCMem)+ | SeqMemAction (BackendAction SeqMem.SeqMem) | PolyAction ( forall rep. ( ASTRep rep,@@ -153,14 +156,6 @@ Action rep ) -untypedActionName :: UntypedAction -> String-untypedActionName (SOACSAction a) = actionName a-untypedActionName (GPUAction a) = actionName a-untypedActionName (SeqMemAction a) = actionName $ a ""-untypedActionName (GPUMemAction a) = actionName $ a ""-untypedActionName (MCMemAction a) = actionName $ a ""-untypedActionName (PolyAction a) = actionName (a :: Action SOACS.SOACS)- instance Representation UntypedAction where representation (SOACSAction _) = "SOACS" representation (GPUAction _) = "GPU"@@ -170,7 +165,7 @@ representation PolyAction {} = "<any>" newConfig :: Config-newConfig = Config newFutharkConfig (Pipeline []) action False+newConfig = Config newFutharkConfig (Pipeline []) ToExecutable action False where action = PolyAction printAction @@ -404,10 +399,31 @@ "Parse and pretty-print the AST of the given program.", Option []+ ["backend"]+ ( ReqArg+ ( \arg -> do+ action <- case arg of+ "c" -> Right $ SeqMemAction compileCAction+ "multicore" -> Right $ MCMemAction compileMulticoreAction+ "opencl" -> Right $ GPUMemAction compileOpenCLAction+ "cuda" -> Right $ GPUMemAction compileCUDAAction+ "wasm" -> Right $ SeqMemAction compileCtoWASMAction+ "wasm-multicore" -> Right $ MCMemAction compileMulticoreToWASMAction+ "python" -> Right $ SeqMemAction compilePythonAction+ "pyopencl" -> Right $ GPUMemAction compilePyOpenCLAction+ _ -> Left $ error $ "Invalid backend: " <> arg++ Right $ \opts -> opts {futharkAction = action}+ )+ "c|multicore|opencl|cuda|python|pyopencl"+ )+ "Run this compiler backend on pipeline result.",+ Option+ [] ["compile-imperative"] ( NoArg $ Right $ \opts ->- opts {futharkAction = SeqMemAction $ const impCodeGenAction}+ opts {futharkAction = SeqMemAction $ \_ _ _ -> impCodeGenAction} ) "Translate program into the imperative IL and write it on standard output.", Option@@ -415,7 +431,7 @@ ["compile-imperative-kernels"] ( NoArg $ Right $ \opts ->- opts {futharkAction = GPUMemAction $ const kernelImpCodeGenAction}+ opts {futharkAction = GPUMemAction $ \_ _ _ -> kernelImpCodeGenAction} ) "Translate program into the imperative IL with kernels and write it on standard output.", Option@@ -423,26 +439,10 @@ ["compile-imperative-multicore"] ( NoArg $ Right $ \opts ->- opts {futharkAction = MCMemAction $ const multicoreImpCodeGenAction}+ opts {futharkAction = MCMemAction $ \_ _ _ -> multicoreImpCodeGenAction} ) "Translate program into the imperative IL with kernels and write it on standard output.", Option- []- ["compile-opencl"]- ( NoArg $- Right $ \opts ->- opts {futharkAction = GPUMemAction $ compileOpenCLAction newFutharkConfig ToExecutable}- )- "Compile the program using the OpenCL backend.",- Option- []- ["compile-c"]- ( NoArg $- Right $ \opts ->- opts {futharkAction = SeqMemAction $ compileCAction newFutharkConfig ToExecutable}- )- "Compile the program using the C backend.",- Option "p" ["print"] (NoArg $ Right $ \opts -> opts {futharkAction = PolyAction printAction})@@ -453,6 +453,11 @@ (NoArg $ Right $ \opts -> opts {futharkAction = PolyAction printAliasesAction}) "Print the resulting IR with aliases.", Option+ []+ ["call-graph"]+ (NoArg $ Right $ \opts -> opts {futharkAction = SOACSAction callGraphAction})+ "Print the resulting call graph.",+ Option "m" ["metrics"] (NoArg $ Right $ \opts -> opts {futharkAction = PolyAction metricsAction})@@ -500,9 +505,26 @@ "NAME" ) "Treat this function as an additional entry point.",+ Option+ []+ ["library"]+ (NoArg $ Right $ \opts -> opts {futharkCompilerMode = ToLibrary})+ "Generate a library instead of an executable.",+ Option+ []+ ["executable"]+ (NoArg $ Right $ \opts -> opts {futharkCompilerMode = ToExecutable})+ "Generate an executable instead of a library (set by default).",+ Option+ []+ ["server"]+ (NoArg $ Right $ \opts -> opts {futharkCompilerMode = ToServer})+ "Generate a server executable.", typedPassOption soacsProg Seq firstOrderTransform "f", soacsPassOption fuseSOACs "o",- soacsPassOption inlineFunctions [],+ soacsPassOption inlineAggressively [],+ soacsPassOption inlineConservatively [],+ soacsPassOption removeDeadFunctions [], kernelsPassOption babysitKernels [], kernelsPassOption tileLoops [], kernelsPassOption unstreamGPU [],@@ -528,7 +550,7 @@ "Run the default optimised kernels pipeline" kernelsPipeline []- ["kernels"],+ ["gpu"], pipelineOption getSOACSProg "GPUMem"@@ -536,15 +558,15 @@ "Run the full GPU compilation pipeline" gpuPipeline []- ["gpu"],+ ["gpu-mem"], pipelineOption getSOACSProg- "GPUMem"+ "SeqMem" SeqMem "Run the sequential CPU compilation pipeline" sequentialCpuPipeline []- ["cpu"],+ ["seq-mem"], pipelineOption getSOACSProg "MCMem"@@ -552,7 +574,7 @@ "Run the multicore compilation pipeline" multicorePipeline []- ["multicore"]+ ["mc-mem"] ] incVerbosity :: Maybe FilePath -> FutharkConfig -> FutharkConfig@@ -654,8 +676,8 @@ (".fut_soacs", readCore parseSOACS SOACS), (".fut_seq", readCore parseSeq Seq), (".fut_seq_mem", readCore parseSeqMem SeqMem),- (".fut_kernels", readCore parseGPU GPU),- (".fut_kernels_mem", readCore parseGPUMem GPUMem),+ (".fut_gpu", readCore parseGPU GPU),+ (".fut_gpu_mem", readCore parseGPUMem GPUMem), (".fut_mc", readCore parseMC MC), (".fut_mc_mem", readCore parseMCMem MCMem) ]@@ -677,43 +699,48 @@ (runPolyPass pipeline_config) initial_prog (getFutharkPipeline config)- logMsg $ "Running action " ++ untypedActionName (futharkAction config) case (end_prog, futharkAction config) of (SOACS prog, SOACSAction action) ->- actionProcedure action prog+ otherAction action prog (GPU prog, GPUAction action) ->- actionProcedure action prog+ otherAction action prog (SeqMem prog, SeqMemAction action) ->- actionProcedure (action base) prog+ backendAction prog action (GPUMem prog, GPUMemAction action) ->- actionProcedure (action base) prog+ backendAction prog action (MCMem prog, MCMemAction action) ->- actionProcedure (action base) prog+ backendAction prog action (SOACS soacs_prog, PolyAction acs) ->- actionProcedure acs soacs_prog+ otherAction acs soacs_prog (GPU kernels_prog, PolyAction acs) ->- actionProcedure acs kernels_prog+ otherAction acs kernels_prog (MC mc_prog, PolyAction acs) ->- actionProcedure acs mc_prog+ otherAction acs mc_prog (Seq seq_prog, PolyAction acs) ->- actionProcedure acs seq_prog+ otherAction acs seq_prog (GPUMem mem_prog, PolyAction acs) ->- actionProcedure acs mem_prog+ otherAction acs mem_prog (SeqMem mem_prog, PolyAction acs) ->- actionProcedure acs mem_prog+ otherAction acs mem_prog (MCMem mem_prog, PolyAction acs) ->- actionProcedure acs mem_prog+ otherAction acs mem_prog (_, action) -> externalErrorS $- "Action "- <> untypedActionName action- <> " expects "+ "Action expects " ++ representation action ++ " representation, but got " ++ representation end_prog ++ "." logMsg ("Done." :: String) where+ backendAction prog actionf = do+ let action = actionf (futharkConfig config) (futharkCompilerMode config) base+ otherAction action prog++ otherAction action prog = do+ logMsg $ "Running action " ++ actionName action+ actionProcedure action prog+ pipeline_config = PipelineConfig { pipelineVerbose = fst (futharkVerbose $ futharkConfig config) > NotVerbose,
src/Futhark/CLI/Literate.hs view
@@ -14,7 +14,6 @@ import qualified Data.ByteString.Lazy as LBS import Data.Char import Data.Functor-import Data.Hashable (hash) import Data.Int (Int64) import Data.List (foldl', transpose) import qualified Data.Map as M@@ -34,7 +33,7 @@ import Futhark.Test.Values import Futhark.Util ( directoryContents,- hashIntText,+ hashText, nubOrd, runProgramWithExitCode, )@@ -504,36 +503,51 @@ data Env = Env { envImgDir :: FilePath,+ -- | Image dir relative to program.+ envRelImgDir :: FilePath, envOpts :: Options, envServer :: ScriptServer,- envHash :: Int+ envHash :: T.Text } -newFile :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM FilePath-newFile env template m = do- let fname =- envImgDir env- </> T.unpack (hashIntText (envHash env)) <> "-" <> template+newFileWorker :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM (FilePath, FilePath)+newFileWorker env template m = do+ let fname_base = T.unpack (envHash env) <> "-" <> template+ fname = envImgDir env </> fname_base+ fname_rel = envRelImgDir env </> fname_base exists <- liftIO $ doesFileExist fname liftIO $ createDirectoryIfMissing True $ envImgDir env when (exists && scriptVerbose (envOpts env) > 0) $ liftIO $ T.hPutStrLn stderr $ "Using existing file: " <> T.pack fname- unless exists $ m fname+ unless exists $ do+ when (scriptVerbose (envOpts env) > 0) $+ liftIO $ T.hPutStrLn stderr $ "Generating new file: " <> T.pack fname+ m fname modify $ \s -> s {stateFiles = S.insert fname $ stateFiles s}- pure fname+ pure (fname, fname_rel) +newFile :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM FilePath+newFile env template m = snd <$> newFileWorker env template m++newFileContents :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM T.Text+newFileContents env template m =+ liftIO . T.readFile . fst =<< newFileWorker env template m+ processDirective :: Env -> Directive -> ScriptM T.Text processDirective env (DirectiveBrief d) = processDirective env d processDirective env (DirectiveCovert d) = processDirective env d processDirective env (DirectiveRes e) = do- v <- either nope pure =<< evalExpToGround literateBuiltin (envServer env) e+ result <-+ newFileContents env "eval.txt" $ \resultf -> do+ v <- either nope pure =<< evalExpToGround literateBuiltin (envServer env) e+ liftIO $ T.writeFile resultf $ prettyText v pure $ T.unlines [ "", "```",- prettyText v,+ result, "```", "" ]@@ -542,40 +556,38 @@ throwError $ "Cannot show value of type " <> prettyText t -- processDirective env (DirectiveImg e) = do- maybe_v <- evalExpToGround literateBuiltin (envServer env) e- case maybe_v of- Right (ValueAtom v)- | Just bmp <- valueToBMP v -> do- pngfile <- withTempDir $ \dir -> do- let bmpfile = dir </> "img.bmp"- liftIO $ LBS.writeFile bmpfile bmp- newFile env "img.png" $ \pngfile ->+ fmap imgBlock . newFile env "img.png" $ \pngfile -> do+ maybe_v <- evalExpToGround literateBuiltin (envServer env) e+ case maybe_v of+ Right (ValueAtom v)+ | Just bmp <- valueToBMP v -> do+ withTempDir $ \dir -> do+ let bmpfile = dir </> "img.bmp"+ liftIO $ LBS.writeFile bmpfile bmp void $ system "convert" [bmpfile, pngfile] mempty- pure $ imgBlock pngfile- Right v ->- nope $ fmap valueType v- Left t ->- nope t+ Right v ->+ nope $ fmap valueType v+ Left t ->+ nope t where nope t = throwError $ "Cannot create image from value of type " <> prettyText t -- processDirective env (DirectivePlot e size) = do- maybe_v <- evalExpToGround literateBuiltin (envServer env) e- case maybe_v of- Right v- | Just vs <- plottable2d v -> do- pngfile <- newFile env "plot.png" $ plotWith [(Nothing, vs)]- pure $ imgBlock pngfile- Right (ValueRecord m)- | Just m' <- traverse plottable2d m -> do- pngfile <- newFile env "plot.png" $ plotWith $ map (first Just) $ M.toList m'- pure $ imgBlock pngfile- Right v ->- throwError $ "Cannot plot value of type " <> prettyText (fmap valueType v)- Left t ->- throwError $ "Cannot plot opaque value of type " <> prettyText t+ fmap imgBlock . newFile env "plot.png" $ \pngfile -> do+ maybe_v <- evalExpToGround literateBuiltin (envServer env) e+ case maybe_v of+ Right v+ | Just vs <- plottable2d v ->+ plotWith [(Nothing, vs)] pngfile+ Right (ValueRecord m)+ | Just m' <- traverse plottable2d m -> do+ plotWith (map (first Just) $ M.toList m') pngfile+ Right v ->+ throwError $ "Cannot plot value of type " <> prettyText (fmap valueType v)+ Left t ->+ throwError $ "Cannot plot opaque value of type " <> prettyText t where plottable2d v = do [x, y] <- plottable v@@ -607,16 +619,16 @@ void $ system "gnuplot" [] script -- processDirective env (DirectiveGnuplot e script) = do- maybe_v <- evalExpToGround literateBuiltin (envServer env) e- case maybe_v of- Right (ValueRecord m)- | Just m' <- traverse plottable m -> do- pngfile <- newFile env "plot.png" $ plotWith $ M.toList m'- pure $ imgBlock pngfile- Right v ->- throwError $ "Cannot plot value of type " <> prettyText (fmap valueType v)- Left t ->- throwError $ "Cannot plot opaque value of type " <> prettyText t+ fmap imgBlock . newFile env "plot.png" $ \pngfile -> do+ maybe_v <- evalExpToGround literateBuiltin (envServer env) e+ case maybe_v of+ Right (ValueRecord m)+ | Just m' <- traverse plottable m ->+ plotWith (M.toList m') pngfile+ Right v ->+ throwError $ "Cannot plot value of type " <> prettyText (fmap valueType v)+ Left t ->+ throwError $ "Cannot plot opaque value of type " <> prettyText t where plotWith xys pngfile = withGnuplotData [] xys $ \_ sets -> do let script' =@@ -632,12 +644,11 @@ when (format `notElem` ["webm", "gif"]) $ throwError $ "Unknown video format: " <> format - v <- evalExp literateBuiltin (envServer env) e- let nope =- throwError $- "Cannot produce video from value of type " <> prettyText (fmap scriptValueType v)-- videofile <- newFile env ("video" <.> T.unpack format) $ \videofile ->+ fmap (videoBlock params) . newFile env ("video" <.> T.unpack format) $ \videofile -> do+ v <- evalExp literateBuiltin (envServer env) e+ let nope =+ throwError $+ "Cannot produce video from value of type " <> prettyText (fmap scriptValueType v) case v of ValueAtom SValue {} -> do ValueAtom arr <- getExpValue (envServer env) v@@ -659,8 +670,6 @@ onWebM videofile =<< bmpsToVideo dir _ -> nope-- pure $ videoBlock params videofile where framerate = fromMaybe 30 $ videoFPS params format = fromMaybe "webm" $ videoFormat params@@ -742,7 +751,7 @@ "```\n" <> prettyText (pprDirective False directive) <> "\n```\n" _ -> "```\n" <> prettyText (pprDirective True directive) <> "\n```\n"- env' = env {envHash = hash (envHash env, prettyText directive)}+ env' = env {envHash = hashText (envHash env <> prettyText directive)} (r, files) <- runScriptM $ processDirective env' directive case r of Left err -> failed prompt err files@@ -873,11 +882,12 @@ T.hPutStrLn stderr err exitFailure proghash <-- either onError (pure . hash) <=< runExceptT $+ either onError pure <=< runExceptT $ system futhark ["hash", prog] mempty let mdfile = fromMaybe (prog `replaceExtension` "md") $ scriptOutput opts- imgdir = dropExtension mdfile <> "-img"+ imgdir_rel = dropExtension (takeFileName mdfile) <> "-img"+ imgdir = takeDirectory mdfile </> imgdir_rel run_options = scriptExtraOptions opts cfg = futharkServerCfg ("." </> dropExtension prog) run_options @@ -887,7 +897,8 @@ { envServer = server, envOpts = opts, envHash = proghash,- envImgDir = imgdir+ envImgDir = imgdir,+ envRelImgDir = imgdir_rel } (failure, md) <- processScript env script T.writeFile mdfile md
src/Futhark/CLI/Misc.hs view
@@ -11,12 +11,11 @@ import Control.Monad.State import qualified Data.ByteString.Lazy as BS import Data.Function (on)-import Data.Hashable (hash) import Data.List (isInfixOf, isPrefixOf, nubBy) import qualified Data.Text.IO as T import Futhark.Compiler import Futhark.Test-import Futhark.Util (hashIntText)+import Futhark.Util (hashText) import Futhark.Util.Options import Futhark.Util.Pretty (prettyText) import System.Environment (getExecutablePath)@@ -43,7 +42,9 @@ case args of [file] -> Just $ do prog <- filter (not . isBuiltin . fst) <$> readUntypedProgramOrDie file- liftIO $ T.putStrLn $ hashIntText $ hash $ prettyText prog+ -- The 'map snd' is an attempt to get rid of the file names so+ -- they won't affect the hashing.+ liftIO $ T.putStrLn $ hashText $ prettyText $ map snd prog _ -> Nothing -- | @futhark dataget@
+ src/Futhark/CLI/MulticoreWASM.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE FlexibleContexts #-}++-- | @futhark wasm-multicore@+module Futhark.CLI.MulticoreWASM (main) where++import Futhark.Actions (compileMulticoreToWASMAction)+import Futhark.Compiler.CLI+import Futhark.Passes (multicorePipeline)++-- | Run @futhark c@+main :: String -> [String] -> IO ()+main = compilerMain+ ()+ []+ "Compile to multicore WASM"+ "Generate multicore WASM with the multicore C backend code from optimised Futhark program."+ multicorePipeline+ $ \fcfg () mode outpath prog ->+ actionProcedure (compileMulticoreToWASMAction fcfg mode outpath) prog
src/Futhark/CLI/REPL.hs view
@@ -47,7 +47,7 @@ -- | Run @futhark repl@. main :: String -> [String] -> IO ()-main = mainWithOptions interpreterConfig options "options... [program.fut]" run+main = mainWithOptions () [] "options... [program.fut]" run where run [] _ = Just $ repl Nothing run [prog] _ = Just $ repl $ Just prog@@ -111,25 +111,6 @@ Just 'n' -> return False _ -> confirmQuit -newtype InterpreterConfig = InterpreterConfig {interpreterEntryPoint :: Name}--interpreterConfig :: InterpreterConfig-interpreterConfig = InterpreterConfig defaultEntryPoint--options :: [FunOptDescr InterpreterConfig]-options =- [ Option- "e"- ["entry-point"]- ( ReqArg- ( \entry -> Right $ \config ->- config {interpreterEntryPoint = nameFromString entry}- )- "NAME"- )- "The entry point to execute."- ]- -- | Representation of breaking at a breakpoint, to allow for -- navigating through the stack frames and such. data Breaking = Breaking@@ -346,9 +327,9 @@ intOp (I.ExtOpError err) = return $ Left err intOp (I.ExtOpTrace w v c) = do- liftIO $ putStrLn $ "Trace at " ++ locStr (srclocOf w) ++ ": " ++ v+ liftIO $ putStrLn $ w ++ ": " ++ v c- intOp (I.ExtOpBreak why callstack c) = do+ intOp (I.ExtOpBreak w why callstack c) = do s <- get let why' = case why of@@ -361,7 +342,7 @@ -- Are we supposed to respect this breakpoint? when (breakForReason s top why) $ do- liftIO $ putStrLn $ why' <> " at " ++ locStr top+ liftIO $ putStrLn $ why' <> " at " ++ locStr w liftIO $ putStrLn $ prettyBreaking breaking liftIO $ putStrLn "<Enter> to continue." @@ -398,9 +379,9 @@ where intOp (I.ExtOpError err) = return $ Left err intOp (I.ExtOpTrace w v c) = do- liftIO $ putStrLn $ "Trace at " ++ locStr w ++ ": " ++ v+ liftIO $ putStrLn $ w ++ ": " ++ v c- intOp (I.ExtOpBreak _ _ c) = c+ intOp (I.ExtOpBreak _ _ _ c) = c type Command = T.Text -> FutharkiM ()
src/Futhark/CLI/Run.hs view
@@ -154,6 +154,6 @@ where intOp (I.ExtOpError err) = return $ Left err intOp (I.ExtOpTrace w v c) = do- liftIO $ putStrLn $ "Trace at " ++ locStr w ++ ": " ++ v+ liftIO $ hPutStrLn stderr $ w ++ ": " ++ v c- intOp (I.ExtOpBreak _ _ c) = c+ intOp (I.ExtOpBreak _ _ _ c) = c
src/Futhark/CLI/Test.hs view
@@ -74,11 +74,12 @@ deriving (Eq, Show) pureTestResults :: IO [TestResult] -> TestM ()-pureTestResults m =- mapM_ check =<< liftIO m+pureTestResults m = do+ errs <- foldr collectErrors mempty <$> liftIO m+ unless (null errs) $ E.throwError $ concat errs where- check Success = pure ()- check (Failure err) = E.throwError err+ collectErrors Success errs = errs+ collectErrors (Failure err) errs = err : errs withProgramServer :: FilePath -> FilePath -> [String] -> (Server -> IO [TestResult]) -> TestM () withProgramServer program runner extra_options f = do@@ -125,11 +126,11 @@ SOACSPipeline -> check ["-s"] KernelsPipeline ->- check ["--kernels"]+ check ["--gpu"] SequentialCpuPipeline ->- check ["--cpu"]+ check ["--seq-mem"] GpuPipeline ->- check ["--gpu"]+ check ["--gpu-mem"] NoPipeline -> check [] where
+ src/Futhark/CLI/WASM.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE FlexibleContexts #-}++-- | @futhark wasm@+module Futhark.CLI.WASM (main) where++import Futhark.Actions (compileCtoWASMAction)+import Futhark.Compiler.CLI+import Futhark.Passes (sequentialCpuPipeline)++-- | Run @futhark c@+main :: String -> [String] -> IO ()+main = compilerMain+ ()+ []+ "Compile to WASM"+ "Generate WASM with the sequential C backend code from optimised Futhark program."+ sequentialCpuPipeline+ $ \fcfg () mode outpath prog ->+ actionProcedure (compileCtoWASMAction fcfg mode outpath) prog
src/Futhark/CodeGen/Backends/CCUDA.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TupleSections #-} @@ -12,7 +13,6 @@ where import Control.Monad-import Data.List (intercalate) import Data.Maybe (catMaybes) import Futhark.CodeGen.Backends.CCUDA.Boilerplate import Futhark.CodeGen.Backends.COpenCL.Boilerplate (commonOptions, sizeLoggingCode)@@ -27,6 +27,7 @@ ) import Futhark.MonadFreshNames import qualified Language.C.Quote.OpenCL as C+import NeatInterpolation (untrimming) -- | Compile the program to C with calls to CUDA. compileProg :: MonadFreshNames m => Prog GPUMem -> m (ImpGen.Warnings, GC.CParts)@@ -76,11 +77,11 @@ ) } cuda_includes =- unlines- [ "#include <cuda.h>",- "#include <cuda_runtime.h>",- "#include <nvrtc.h>"- ]+ [untrimming|+ #include <cuda.h>+ #include <cuda_runtime.h>+ #include <nvrtc.h>+ |] cliOptions :: [Option] cliOptions =@@ -173,7 +174,7 @@ allocateCUDABuffer :: GC.Allocate OpenCL () allocateCUDABuffer mem size tag "device" =- GC.stm [C.cstm|CUDA_SUCCEED_OR_RETURN(cuda_alloc(&ctx->cuda, $exp:size, $exp:tag, &$exp:mem));|]+ GC.stm [C.cstm|CUDA_SUCCEED_OR_RETURN(cuda_alloc(&ctx->cuda, (size_t)$exp:size, $exp:tag, &$exp:mem));|] allocateCUDABuffer _ _ _ space = error $ "Cannot allocate in '" ++ space ++ "' memory space." @@ -198,7 +199,7 @@ } |] where- memcpyFun DefaultSpace (Space "device") = ("cuMemcpyDtoH", copyDevToHost)+ memcpyFun DefaultSpace (Space "device") = ("cuMemcpyDtoH" :: String, copyDevToHost) memcpyFun (Space "device") DefaultSpace = ("cuMemcpyHtoD", copyHostToDev) memcpyFun (Space "device") (Space "device") = ("cuMemcpy", copyDevToDev) memcpyFun _ _ =@@ -214,7 +215,7 @@ name_realtype <- newVName $ baseString name ++ "_realtype" num_elems <- case vs of ArrayValues vs' -> do- let vs'' = [[C.cinit|$exp:v|] | v <- map GC.compilePrimValue vs']+ let vs'' = [[C.cinit|$exp:v|] | v <- vs'] GC.earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:(length vs'')] = {$inits:vs''};|] return $ length vs'' ArrayZeros n -> do@@ -322,11 +323,11 @@ void *$id:args_arr[] = { $inits:args'' }; typename int64_t $id:time_start = 0, $id:time_end = 0; if (ctx->debugging) {- fprintf(ctx->log, "Launching %s with grid size (", $string:(pretty kernel_name));- $stms:(printSizes [grid_x, grid_y, grid_z])- fprintf(ctx->log, ") and block size (");- $stms:(printSizes [block_x, block_y, block_z])- fprintf(ctx->log, ").\n");+ fprintf(ctx->log, "Launching %s with grid size [%ld, %ld, %ld] and block size [%ld, %ld, %ld]; shared memory: %d bytes.\n",+ $string:(pretty kernel_name),+ (long int)$exp:grid_x, (long int)$exp:grid_y, (long int)$exp:grid_z,+ (long int)$exp:block_x, (long int)$exp:block_y, (long int)$exp:block_z,+ (int)$exp:shared_tot); $id:time_start = get_wall_time(); } $items:bef@@ -371,8 +372,3 @@ offset <- newVName "shared_offset" GC.decl [C.cdecl|unsigned int $id:size = $exp:num_bytes;|] return (offset, Just (size, offset))-- printSizes =- intercalate [[C.cstm|fprintf(ctx->log, ", ");|]] . map printSize- printSize e =- [[C.cstm|fprintf(ctx->log, "%ld", (long int)$exp:e);|]]
src/Futhark/CodeGen/Backends/CCUDA/Boilerplate.hs view
@@ -9,9 +9,9 @@ ) where -import Data.FileEmbed (embedStringFile) import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T import Futhark.CodeGen.Backends.COpenCL.Boilerplate ( copyDevToDev, copyDevToHost,@@ -25,6 +25,7 @@ ) import qualified Futhark.CodeGen.Backends.GenericC as GC import Futhark.CodeGen.ImpCode.OpenCL+import Futhark.CodeGen.RTS.C (cudaH, freeListH) import Futhark.Util (chunk, zEncodeString) import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C@@ -54,8 +55,8 @@ -- | Called after most code has been generated to generate the bulk of -- the boilerplate. generateBoilerplate ::- String ->- String ->+ T.Text ->+ T.Text -> [Name] -> M.Map KernelName KernelSafety -> M.Map Name SizeClass ->@@ -68,8 +69,8 @@ $esc:("#include <cuda.h>") $esc:("#include <nvrtc.h>") $esc:("typedef CUdeviceptr fl_mem_t;")- $esc:free_list_h- $esc:cuda_h+ $esc:(T.unpack freeListH)+ $esc:(T.unpack cudaH) const char *cuda_program[] = {$inits:fragments, NULL}; |] @@ -80,11 +81,10 @@ GC.profileReport [C.citem|CUDA_SUCCEED_FATAL(cuda_tally_profiling_records(&ctx->cuda));|] mapM_ GC.profileReport $ costCentreReport $ cost_centres ++ M.keys kernels where- cuda_h = $(embedStringFile "rts/c/cuda.h")- free_list_h = $(embedStringFile "rts/c/free_list.h") fragments =- map (\s -> [C.cinit|$string:s|]) $- chunk 2000 (cuda_prelude ++ cuda_program)+ [ [C.cinit|$string:s|]+ | s <- chunk 2000 $ T.unpack $ cuda_prelude <> cuda_program+ ] generateSizeFuns :: M.Map Name SizeClass -> GC.CompilerM OpenCL () () generateSizeFuns sizes = do
src/Futhark/CodeGen/Backends/COpenCL.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TupleSections #-} @@ -27,6 +28,7 @@ import Futhark.MonadFreshNames import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C+import NeatInterpolation (untrimming) -- | Compile the program to C with calls to OpenCL. compileProg :: MonadFreshNames m => Prog GPUMem -> m (ImpGen.Warnings, GC.CParts)@@ -81,16 +83,16 @@ GC.opsFatMemory = True } include_opencl_h =- unlines- [ "#define CL_TARGET_OPENCL_VERSION 120",- "#define CL_USE_DEPRECATED_OPENCL_1_2_APIS",- "#ifdef __APPLE__",- "#define CL_SILENCE_DEPRECATION",- "#include <OpenCL/cl.h>",- "#else",- "#include <CL/cl.h>",- "#endif"- ]+ [untrimming|+ #define CL_TARGET_OPENCL_VERSION 120+ #define CL_USE_DEPRECATED_OPENCL_1_2_APIS+ #ifdef __APPLE__+ #define CL_SILENCE_DEPRECATION+ #include <OpenCL/cl.h>+ #else+ #include <CL/cl.h>+ #endif+ |] cliOptions :: [Option] cliOptions =@@ -208,7 +210,7 @@ allocateOpenCLBuffer :: GC.Allocate OpenCL () allocateOpenCLBuffer mem size tag "device" =- GC.stm [C.cstm|OPENCL_SUCCEED_OR_RETURN(opencl_alloc(&ctx->opencl, $exp:size, $exp:tag, &$exp:mem));|]+ GC.stm [C.cstm|OPENCL_SUCCEED_OR_RETURN(opencl_alloc(&ctx->opencl, (size_t)$exp:size, $exp:tag, &$exp:mem));|] allocateOpenCLBuffer _ _ _ space = error $ "Cannot allocate in '" ++ space ++ "' space." @@ -229,7 +231,7 @@ OPENCL_SUCCEED_OR_RETURN( clEnqueueReadBuffer(ctx->opencl.queue, $exp:srcmem, ctx->failure_is_an_option ? CL_FALSE : CL_TRUE,- $exp:srcidx, $exp:nbytes,+ (size_t)$exp:srcidx, (size_t)$exp:nbytes, $exp:destmem + $exp:destidx, 0, NULL, $exp:(profilingEvent copyHostToDev))); if (ctx->failure_is_an_option &&@@ -242,7 +244,7 @@ if ($exp:nbytes > 0) { OPENCL_SUCCEED_OR_RETURN( clEnqueueWriteBuffer(ctx->opencl.queue, $exp:destmem, CL_TRUE,- $exp:destidx, $exp:nbytes,+ (size_t)$exp:destidx, (size_t)$exp:nbytes, $exp:srcmem + $exp:srcidx, 0, NULL, $exp:(profilingEvent copyDevToHost))); }@@ -256,8 +258,8 @@ OPENCL_SUCCEED_OR_RETURN( clEnqueueCopyBuffer(ctx->opencl.queue, $exp:srcmem, $exp:destmem,- $exp:srcidx, $exp:destidx,- $exp:nbytes,+ (size_t)$exp:srcidx, (size_t)$exp:destidx,+ (size_t)$exp:nbytes, 0, NULL, $exp:(profilingEvent copyDevToDev))); if (ctx->debugging) { OPENCL_SUCCEED_FATAL(clFinish(ctx->opencl.queue));@@ -280,7 +282,7 @@ name_realtype <- newVName $ baseString name ++ "_realtype" num_elems <- case vs of ArrayValues vs' -> do- let vs'' = [[C.cinit|$exp:v|] | v <- map GC.compilePrimValue vs']+ let vs'' = [[C.cinit|$exp:v|] | v <- vs'] GC.earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:(length vs'')] = {$inits:vs''};|] return $ length vs'' ArrayZeros n -> do@@ -358,7 +360,7 @@ num_bytes' <- GC.compileExp $ unCount num_bytes GC.stm [C.cstm|- OPENCL_SUCCEED_OR_RETURN(clSetKernelArg(ctx->$id:name, $int:i, $exp:num_bytes', NULL));+ OPENCL_SUCCEED_OR_RETURN(clSetKernelArg(ctx->$id:name, $int:i, (size_t)$exp:num_bytes', NULL)); |] localBytes cur (SharedMemoryKArg num_bytes) = do@@ -380,6 +382,8 @@ time_diff <- newVName "time_diff" local_work_size <- newVName "local_work_size" + let (debug_str, debug_args) = debugPrint global_work_size local_work_size+ GC.stm [C.cstm| if ($exp:total_elements != 0) {@@ -387,11 +391,7 @@ const size_t $id:local_work_size[$int:kernel_rank] = {$inits:workgroup_dims'}; typename int64_t $id:time_start = 0, $id:time_end = 0; if (ctx->debugging) {- fprintf(ctx->log, "Launching %s with global work size [", $string:(pretty kernel_name));- $stms:(printKernelSize global_work_size)- fprintf(ctx->log, "] and local work size [");- $stms:(printKernelSize local_work_size)- fprintf(ctx->log, "]; local memory parameters sum to %d bytes.\n", (int)$exp:local_bytes);+ fprintf(ctx->log, $string:debug_str, $args:debug_args); $id:time_start = get_wall_time(); } OPENCL_SUCCEED_OR_RETURN(@@ -410,16 +410,25 @@ kernel_rank = length kernel_dims kernel_dims = zipWith multExp (map toSize num_workgroups) (map toSize workgroup_dims) kernel_dims' = map toInit kernel_dims- workgroup_dims' = map toInit workgroup_dims+ workgroup_dims' = map (toInit . toSize) workgroup_dims total_elements = foldl multExp [C.cexp|1|] kernel_dims toInit e = [C.cinit|$exp:e|] multExp x y = [C.cexp|$exp:x * $exp:y|] toSize e = [C.cexp|(size_t)$exp:e|] - printKernelSize :: VName -> [C.Stm]- printKernelSize work_size =- intercalate [[C.cstm|fprintf(ctx->log, ", ");|]] $- map (printKernelDim work_size) [0 .. kernel_rank -1]- printKernelDim global_work_size i =- [[C.cstm|fprintf(ctx->log, "%zu", $id:global_work_size[$int:i]);|]]+ debugPrint :: VName -> VName -> (String, [C.Exp])+ debugPrint global_work_size local_work_size =+ ( "Launching %s with global work size "+ ++ dims+ ++ " and local work size "+ ++ dims+ ++ "]; local memory: %d bytes.\n",+ [C.cexp|$string:(pretty kernel_name)|] :+ map (kernelDim global_work_size) [0 .. kernel_rank -1]+ ++ map (kernelDim local_work_size) [0 .. kernel_rank -1]+ ++ [[C.cexp|(int)$exp:local_bytes|]]+ )+ where+ dims = "[" ++ intercalate ", " (replicate kernel_rank "%zu") ++ "]"+ kernelDim arr i = [C.cexp|$id:arr[$int:i]|]
src/Futhark/CodeGen/Backends/COpenCL/Boilerplate.hs view
@@ -21,13 +21,14 @@ where import Control.Monad.State-import Data.FileEmbed import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericC as GC import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.ImpCode.OpenCL import Futhark.CodeGen.OpenCL.Heuristics+import Futhark.CodeGen.RTS.C (freeListH, openclH) import Futhark.Util (chunk, zEncodeString) import Futhark.Util.Pretty (prettyOneLine) import qualified Language.C.Quote.OpenCL as C@@ -43,8 +44,8 @@ escapeChar c = [c] in concatMap escapeChar onPart (ErrorString s) = printfEscape s- onPart ErrorInt32 {} = "%lld"- onPart ErrorInt64 {} = "%lld"+ -- FIXME: bogus for non-ints.+ onPart ErrorVal {} = "%lld" onFailure i (FailureMsg emsg@(ErrorMsg parts) backtrace) = let msg = concatMap onPart parts ++ "\n" ++ printfEscape backtrace msgargs = [[C.cexp|args[$int:j]|] | j <- [0 .. errorMsgNumArgs emsg -1]]@@ -70,8 +71,8 @@ -- | Called after most code has been generated to generate the bulk of -- the boilerplate. generateBoilerplate ::- String ->- String ->+ T.Text ->+ T.Text -> [Name] -> M.Map KernelName KernelSafety -> [PrimType] ->@@ -82,7 +83,7 @@ final_inits <- GC.contextFinalInits let (ctx_opencl_fields, ctx_opencl_inits, top_decls, later_top_decls) =- openClDecls cost_centres kernels opencl_code opencl_prelude+ openClDecls cost_centres kernels (opencl_prelude <> opencl_code) mapM_ GC.earlyDecl top_decls @@ -505,17 +506,18 @@ openClDecls :: [Name] -> M.Map KernelName KernelSafety ->- String ->- String ->+ T.Text -> ([C.FieldGroup], [C.Stm], [C.Definition], [C.Definition])-openClDecls cost_centres kernels opencl_program opencl_prelude =+openClDecls cost_centres kernels opencl_program = (ctx_fields, ctx_inits, openCL_boilerplate, openCL_load) where opencl_program_fragments = -- Some C compilers limit the size of literal strings, so -- chunk the entire program into small bits here, and -- concatenate it again at runtime.- [[C.cinit|$string:s|] | s <- chunk 2000 (opencl_prelude ++ opencl_program)]+ [ [C.cinit|$string:s|]+ | s <- chunk 2000 $ T.unpack opencl_program+ ] ctx_fields = [ [C.csdecl|int total_runs;|],@@ -549,15 +551,12 @@ }|] ] - free_list_h = $(embedStringFile "rts/c/free_list.h")- openCL_h = $(embedStringFile "rts/c/opencl.h")- program_fragments = opencl_program_fragments ++ [[C.cinit|NULL|]] openCL_boilerplate = [C.cunit| $esc:("typedef cl_mem fl_mem_t;")- $esc:free_list_h- $esc:openCL_h+ $esc:(T.unpack freeListH)+ $esc:(T.unpack openclH) static const char *opencl_program[] = {$inits:program_fragments};|] loadKernel :: (KernelName, KernelSafety) -> C.Stm
src/Futhark/CodeGen/Backends/GenericC.hs view
@@ -46,7 +46,6 @@ compileCode, compileExp, compilePrimExp,- compilePrimValue, compileExpToName, rawMem, item,@@ -85,19 +84,22 @@ import Control.Monad.State import Data.Bifunctor (first) import qualified Data.DList as DL-import Data.FileEmbed import Data.Loc import qualified Data.Map.Strict as M import Data.Maybe+import qualified Data.Text as T import Futhark.CodeGen.Backends.GenericC.CLI (cliDefs) import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.Backends.GenericC.Server (serverDefs) import Futhark.CodeGen.Backends.SimpleRep import Futhark.CodeGen.ImpCode+import Futhark.CodeGen.RTS.C (halfH, lockH, timingH, utilH) import Futhark.IR.Prop (isBuiltInFunction) import Futhark.MonadFreshNames+import Futhark.Util.Pretty (prettyText) import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C+import NeatInterpolation (untrimming) -- How public an array type definition sould be. Public types show up -- in the generated API, while private types are used only to@@ -223,16 +225,31 @@ opsCritical :: ([C.BlockItem], [C.BlockItem]) } +errorMsgString :: ErrorMsg Exp -> CompilerM op s (String, [C.Exp])+errorMsgString (ErrorMsg parts) = do+ let boolStr e = [C.cexp|($exp:e) ? "true" : "false"|]+ asLongLong e = [C.cexp|(long long int)$exp:e|]+ asDouble e = [C.cexp|(double)$exp:e|]+ onPart (ErrorString s) = return ("%s", [C.cexp|$string:s|])+ onPart (ErrorVal Bool x) = ("%s",) . boolStr <$> compileExp x+ onPart (ErrorVal Unit _) = pure ("%s", [C.cexp|"()"|])+ onPart (ErrorVal (IntType Int8) x) = ("%hhd",) <$> compileExp x+ onPart (ErrorVal (IntType Int16) x) = ("%hd",) <$> compileExp x+ onPart (ErrorVal (IntType Int32) x) = ("%d",) <$> compileExp x+ onPart (ErrorVal (IntType Int64) x) = ("%lld",) . asLongLong <$> compileExp x+ onPart (ErrorVal (FloatType Float16) x) = ("%f",) . asDouble <$> compileExp x+ onPart (ErrorVal (FloatType Float32) x) = ("%f",) . asDouble <$> compileExp x+ onPart (ErrorVal (FloatType Float64) x) = ("%f",) <$> compileExp x+ (formatstrs, formatargs) <- unzip <$> mapM onPart parts+ pure (mconcat formatstrs, formatargs)+ defError :: ErrorCompiler op s-defError (ErrorMsg parts) stacktrace = do+defError msg stacktrace = do free_all_mem <- collect $ mapM_ (uncurry unRefMem) =<< gets compDeclaredMem- let onPart (ErrorString s) = return ("%s", [C.cexp|$string:s|])- onPart (ErrorInt32 x) = ("%d",) <$> compileExp x- onPart (ErrorInt64 x) = ("%lld",) <$> compileExp x- (formatstrs, formatargs) <- unzip <$> mapM onPart parts- let formatstr = "Error: " ++ concat formatstrs ++ "\n\nBacktrace:\n%s"+ (formatstr, formatargs) <- errorMsgString msg+ let formatstr' = "Error: " <> formatstr <> "\n\nBacktrace:\n%s" items- [C.citems|ctx->error = msgprintf($string:formatstr, $args:formatargs, $string:stacktrace);+ [C.citems|ctx->error = msgprintf($string:formatstr', $args:formatargs, $string:stacktrace); $items:free_all_mem return 1;|] @@ -326,18 +343,27 @@ envFatMemory :: CompilerEnv op s -> Bool envFatMemory = opsFatMemory . envOperations -initDecls, arrayDecls, opaqueDecls, entryDecls, miscDecls :: CompilerState s -> [C.Definition]-initDecls = concatMap (DL.toList . snd) . filter ((== InitDecl) . fst) . M.toList . compHeaderDecls-arrayDecls = concatMap (DL.toList . snd) . filter (isArrayDecl . fst) . M.toList . compHeaderDecls+declsCode :: (HeaderSection -> Bool) -> CompilerState s -> T.Text+declsCode p =+ T.unlines+ . map prettyText+ . concatMap (DL.toList . snd)+ . filter (p . fst)+ . M.toList+ . compHeaderDecls++initDecls, arrayDecls, opaqueDecls, entryDecls, miscDecls :: CompilerState s -> T.Text+initDecls = declsCode (== InitDecl)+arrayDecls = declsCode isArrayDecl where isArrayDecl ArrayDecl {} = True isArrayDecl _ = False-opaqueDecls = concatMap (DL.toList . snd) . filter (isOpaqueDecl . fst) . M.toList . compHeaderDecls+opaqueDecls = declsCode isOpaqueDecl where isOpaqueDecl OpaqueDecl {} = True isOpaqueDecl _ = False-entryDecls = concatMap (DL.toList . snd) . filter ((== EntryDecl) . fst) . M.toList . compHeaderDecls-miscDecls = concatMap (DL.toList . snd) . filter ((== MiscDecl) . fst) . M.toList . compHeaderDecls+entryDecls = declsCode (== EntryDecl)+miscDecls = declsCode (== MiscDecl) contextContents :: CompilerM op s ([C.FieldGroup], [C.Stm]) contextContents = do@@ -567,7 +593,7 @@ <*> pure [C.cexp|$exp:desc|] <*> pure sid _ ->- stm [C.cstm|$exp:dest = (char*) malloc($exp:size);|]+ stm [C.cstm|$exp:dest = (unsigned char*) malloc((size_t)$exp:size);|] freeRawMem :: (C.ToExp a, C.ToExp b) =>@@ -783,9 +809,11 @@ CompilerM op s () copyMemoryDefaultSpace destmem destidx srcmem srcidx nbytes = stm- [C.cstm|memmove($exp:destmem + $exp:destidx,+ [C.cstm|if ($exp:nbytes > 0) {+ memmove($exp:destmem + $exp:destidx, $exp:srcmem + $exp:srcidx,- $exp:nbytes);|]+ $exp:nbytes);+ }|] --- Entry points. @@ -806,7 +834,7 @@ Int -> CompilerM op s [C.Definition] arrayLibraryFunctions pub space pt signed rank = do- let pt' = signedPrimTypeToCType signed pt+ let pt' = primAPIType signed pt name = arrayName pt signed rank arr_name = "futhark_" ++ name array_type = [C.cty|struct $id:arr_name|]@@ -830,7 +858,7 @@ resetMem [C.cexp|arr->mem|] space allocMem [C.cexp|arr->mem|]- [C.cexp|((size_t)$exp:arr_size) * $int:(primByteSize pt::Int)|]+ [C.cexp|$exp:arr_size * $int:(primByteSize pt::Int)|] space [C.cstm|return NULL;|] forM_ [0 .. rank -1] $ \i ->@@ -884,7 +912,7 @@ proto [C.cedecl|$ty:array_type* $id:new_array($ty:ctx_ty *ctx, const $ty:pt' *data, $params:shape_params);|] proto- [C.cedecl|$ty:array_type* $id:new_raw_array($ty:ctx_ty *ctx, const $ty:memty data, int offset, $params:shape_params);|]+ [C.cedecl|$ty:array_type* $id:new_raw_array($ty:ctx_ty *ctx, const $ty:memty data, typename int64_t offset, $params:shape_params);|] proto [C.cedecl|int $id:free_array($ty:ctx_ty *ctx, $ty:array_type *arr);|] proto@@ -906,7 +934,7 @@ return arr; } - $ty:array_type* $id:new_raw_array($ty:ctx_ty *ctx, const $ty:memty data, int offset,+ $ty:array_type* $id:new_raw_array($ty:ctx_ty *ctx, const $ty:memty data, typename int64_t offset, $params:shape_params) { $ty:array_type* bad = NULL; $ty:array_type *arr = ($ty:array_type*) malloc(sizeof($ty:array_type));@@ -1082,7 +1110,7 @@ valueDescToCType :: Publicness -> ValueDesc -> CompilerM op s C.Type valueDescToCType _ (ScalarValue pt signed _) =- return $ signedPrimTypeToCType signed pt+ return $ primAPIType signed pt valueDescToCType pub (ArrayValue _ space pt signed shape) = do let rank = length shape name <- publicName $ arrayName pt signed rank@@ -1130,7 +1158,7 @@ prepareEntryInputs :: [ExternalValue] ->- CompilerM op s ([(C.Param, C.Exp)], [C.BlockItem])+ CompilerM op s ([(C.Param, Maybe C.Exp)], [C.BlockItem]) prepareEntryInputs args = collect' $ zipWithM prepare [(0 :: Int) ..] args where arg_names = namesFromList $ concatMap evNames args@@ -1144,7 +1172,7 @@ (ty, check) <- prepareValue Public [C.cexp|$id:pname|] vd return ( [C.cparam|const $ty:ty $id:pname|],- allTrue check+ if null check then Nothing else Just $ allTrue check ) prepare pno (OpaqueValue _ desc vds) = do ty <- opaqueToCType desc vds@@ -1154,12 +1182,15 @@ checks <- map snd <$> zipWithM (prepareValue Private) (zipWith field [0 ..] vds) vds return ( [C.cparam|const $ty:ty *$id:pname|],- allTrue $ concat checks+ if null $ concat checks+ then Nothing+ else Just $ allTrue $ concat checks ) prepareValue _ src (ScalarValue pt signed name) = do- let pt' = signedPrimTypeToCType signed pt- stm [C.cstm|$id:name = $exp:src;|]+ let pt' = primAPIType signed pt+ src' = fromStorage pt $ C.toExp src mempty+ stm [C.cstm|$id:name = $exp:src';|] return (pt', []) prepareValue pub src vd@(ArrayValue mem _ _ _ shape) = do ty <- valueDescToCType pub vd@@ -1214,8 +1245,9 @@ return [C.cparam|$ty:ty **$id:pname|] - prepareValue dest (ScalarValue _ _ name) =- stm [C.cstm|$exp:dest = $id:name;|]+ prepareValue dest (ScalarValue t _ name) =+ let name' = toStorage t $ C.toExp name mempty+ in stm [C.cstm|$exp:dest = $exp:name';|] prepareValue dest (ArrayValue mem _ _ _ shape) = do stm [C.cstm|$exp:dest->mem = $id:mem;|] @@ -1256,18 +1288,25 @@ $params:entry_point_output_params, $params:entry_point_input_params);|] - let critical =- [C.citems|- $items:unpack_entry_inputs-- if (!($exp:(allTrue entry_point_input_checks))) {+ let checks = catMaybes entry_point_input_checks+ check_input =+ if null checks+ then []+ else+ [C.citems|+ if (!($exp:(allTrue (catMaybes entry_point_input_checks)))) { ret = 1; if (!ctx->error) { ctx->error = msgprintf("Error: entry point arguments have invalid sizes.\n"); }- } else {- ret = $id:(funName fname)(ctx, $args:out_args, $args:in_args);+ }|] + critical =+ [C.citems|+ $items:unpack_entry_inputs+ $items:check_input+ if (ret == 0) {+ ret = $id:(funName fname)(ctx, $args:out_args, $args:in_args); if (ret == 0) { $items:get_consts @@ -1305,26 +1344,25 @@ -- all of them, which yields a CLI program. Another is to compile the -- library part by itself, and use the header file to call into it. data CParts = CParts- { cHeader :: String,+ { cHeader :: T.Text, -- | Utility definitions that must be visible -- to both CLI and library parts.- cUtils :: String,- cCLI :: String,- cServer :: String,- cLib :: String+ cUtils :: T.Text,+ cCLI :: T.Text,+ cServer :: T.Text,+ cLib :: T.Text } -gnuSource :: String+gnuSource :: T.Text gnuSource =- pretty- [C.cunit|+ [untrimming| // We need to define _GNU_SOURCE before // _any_ headers files are imported to get // the usage statistics of a thread (i.e. have RUSAGE_THREAD) on GNU/Linux // https://manpages.courier-mta.org/htmlman2/getrusage.2.html-$esc:("#ifndef _GNU_SOURCE") // Avoid possible double-definition warning.-$esc:("#define _GNU_SOURCE")-$esc:("#endif")+#ifndef _GNU_SOURCE // Avoid possible double-definition warning.+#define _GNU_SOURCE+#endif |] -- We may generate variables that are never used (e.g. for@@ -1332,39 +1370,37 @@ -- intrinsics), and generated code may have other cosmetic issues that -- compilers warn about. We disable these warnings to not clutter the -- compilation logs.-disableWarnings :: String+disableWarnings :: T.Text disableWarnings =- pretty- [C.cunit|-$esc:("#ifdef __clang__")-$esc:("#pragma clang diagnostic ignored \"-Wunused-function\"")-$esc:("#pragma clang diagnostic ignored \"-Wunused-variable\"")-$esc:("#pragma clang diagnostic ignored \"-Wparentheses\"")-$esc:("#pragma clang diagnostic ignored \"-Wunused-label\"")-$esc:("#elif __GNUC__")-$esc:("#pragma GCC diagnostic ignored \"-Wunused-function\"")-$esc:("#pragma GCC diagnostic ignored \"-Wunused-variable\"")-$esc:("#pragma GCC diagnostic ignored \"-Wparentheses\"")-$esc:("#pragma GCC diagnostic ignored \"-Wunused-label\"")-$esc:("#pragma GCC diagnostic ignored \"-Wunused-but-set-variable\"")-$esc:("#endif")-+ [untrimming|+#ifdef __clang__+#pragma clang diagnostic ignored "-Wunused-function"+#pragma clang diagnostic ignored "-Wunused-variable"+#pragma clang diagnostic ignored "-Wparentheses"+#pragma clang diagnostic ignored "-Wunused-label"+#elif __GNUC__+#pragma GCC diagnostic ignored "-Wunused-function"+#pragma GCC diagnostic ignored "-Wunused-variable"+#pragma GCC diagnostic ignored "-Wparentheses"+#pragma GCC diagnostic ignored "-Wunused-label"+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"+#endif |] -- | Produce header and implementation files.-asLibrary :: CParts -> (String, String)+asLibrary :: CParts -> (T.Text, T.Text) asLibrary parts = ( "#pragma once\n\n" <> cHeader parts, gnuSource <> disableWarnings <> cHeader parts <> cUtils parts <> cLib parts ) -- | As executable with command-line interface.-asExecutable :: CParts -> String+asExecutable :: CParts -> T.Text asExecutable parts = gnuSource <> disableWarnings <> cHeader parts <> cUtils parts <> cCLI parts <> cLib parts -- | As server executable.-asServer :: CParts -> String+asServer :: CParts -> T.Text asServer parts = gnuSource <> disableWarnings <> cHeader parts <> cUtils parts <> cServer parts <> cLib parts @@ -1372,10 +1408,10 @@ -- function named "main" as entry point, so make sure it is defined. compileProg :: MonadFreshNames m =>- String ->+ T.Text -> Operations op () -> CompilerM op () () ->- String ->+ T.Text -> [Space] -> [Option] -> Definitions op ->@@ -1384,98 +1420,105 @@ src <- getNameSource let ((prototypes, definitions, entry_point_decls), endstate) = runCompilerM ops src () compileProg'+ initdecls = initDecls endstate+ entrydecls = entryDecls endstate+ arraydecls = arrayDecls endstate+ opaquedecls = opaqueDecls endstate+ miscdecls = miscDecls endstate let headerdefs =- [C.cunit|-$esc:("// Headers\n")-$esc:("#include <stdint.h>")-$esc:("#include <stddef.h>")-$esc:("#include <stdbool.h>")-$esc:("#include <stdio.h>")-$esc:("#include <float.h>")-$esc:(header_extra)--$esc:("#ifdef __cplusplus")-$esc:("extern \"C\" {")-$esc:("#endif")+ [untrimming|+// Headers\n")+#include <stdint.h>+#include <stddef.h>+#include <stdbool.h>+#include <stdio.h>+#include <float.h>+$header_extra+#ifdef __cplusplus+extern "C" {+#endif -$esc:("\n// Initialisation\n")-$edecls:(initDecls endstate)+// Initialisation+$initdecls -$esc:("\n// Arrays\n")-$edecls:(arrayDecls endstate)+// Arrays+$arraydecls -$esc:("\n// Opaque values\n")-$edecls:(opaqueDecls endstate)+// Opaque values+$opaquedecls -$esc:("\n// Entry points\n")-$edecls:(entryDecls endstate)+// Entry points+$entrydecls -$esc:("\n// Miscellaneous\n")-$edecls:(miscDecls endstate)-$esc:("#define FUTHARK_BACKEND_"++backend)+// Miscellaneous+$miscdecls+#define FUTHARK_BACKEND_$backend -$esc:("#ifdef __cplusplus")-$esc:("}")-$esc:("#endif")- |]+#ifdef __cplusplus+}+#endif+|] let utildefs =- [C.cunit|-$esc:("#include <stdio.h>")-$esc:("#include <stdlib.h>")-$esc:("#include <stdbool.h>")-$esc:("#include <math.h>")-$esc:("#include <stdint.h>")+ [untrimming|+#include <stdio.h>+#include <stdlib.h>+#include <stdbool.h>+#include <math.h>+#include <stdint.h> // If NDEBUG is set, the assert() macro will do nothing. Since Futhark // (unfortunately) makes use of assert() for error detection (and even some // side effects), we want to avoid that.-$esc:("#undef NDEBUG")-$esc:("#include <assert.h>")-$esc:("#include <stdarg.h>")--$esc:util_h--$esc:timing_h+#undef NDEBUG+#include <assert.h>+#include <stdarg.h>+$utilH+$halfH+$timingH |] - let early_decls = DL.toList $ compEarlyDecls endstate- let lib_decls = DL.toList $ compLibDecls endstate- let clidefs = cliDefs options $ Functions entry_funs- let serverdefs = serverDefs options $ Functions entry_funs- let libdefs =- [C.cunit|-$esc:("#ifdef _MSC_VER\n#define inline __inline\n#endif")-$esc:("#include <string.h>")-$esc:("#include <string.h>")-$esc:("#include <errno.h>")-$esc:("#include <assert.h>")-$esc:("#include <ctype.h>")+ let early_decls = T.unlines $ map prettyText $ DL.toList $ compEarlyDecls endstate+ lib_decls = T.unlines $ map prettyText $ DL.toList $ compLibDecls endstate+ clidefs = cliDefs options $ Functions entry_funs+ serverdefs = serverDefs options $ Functions entry_funs+ libdefs =+ [untrimming|+#ifdef _MSC_VER+#define inline __inline+#endif+#include <string.h>+#include <string.h>+#include <errno.h>+#include <assert.h>+#include <ctype.h> -$esc:header_extra+$header_extra -$esc:lock_h+$lockH -$edecls:builtin+#define FUTHARK_F64_ENABLED -$edecls:early_decls+$cScalarDefs -$edecls:prototypes+$early_decls -$edecls:lib_decls+$prototypes -$edecls:definitions+$lib_decls -$edecls:entry_point_decls+$definitions++$entry_point_decls |] - return $+ return CParts- { cHeader = pretty headerdefs,- cUtils = pretty utildefs,- cCLI = pretty clidefs,- cServer = pretty serverdefs,- cLib = pretty libdefs+ { cHeader = headerdefs,+ cUtils = utildefs,+ cCLI = clidefs,+ cServer = serverdefs,+ cLib = libdefs } where Definitions consts (Functions funs) = prog@@ -1501,7 +1544,11 @@ commonLibFuns memreport - return (prototypes, map funcToDef functions, entry_points)+ return+ ( T.unlines $ map prettyText prototypes,+ T.unlines $ map (prettyText . funcToDef) functions,+ T.unlines $ map prettyText entry_points+ ) funcToDef func = C.FuncDef func loc where@@ -1509,15 +1556,6 @@ C.OldFunc _ _ _ _ _ _ l -> l C.Func _ _ _ _ _ l -> l - builtin =- cIntOps ++ cFloat32Ops ++ cFloat64Ops ++ cFloatConvOps- ++ cFloat32Funs- ++ cFloat64Funs-- util_h = $(embedStringFile "rts/c/util.h")- timing_h = $(embedStringFile "rts/c/timing.h")- lock_h = $(embedStringFile "rts/c/lock.h")- commonLibFuns :: [C.BlockItem] -> CompilerM op s () commonLibFuns memreport = do generateAPITypes@@ -1748,33 +1786,6 @@ p_name <- newVName $ baseString name ++ "_p" return ([C.cparam|$ty:ty *$id:p_name|], [C.cexp|$id:p_name|]) -compilePrimValue :: PrimValue -> C.Exp-compilePrimValue (IntValue (Int8Value k)) = [C.cexp|(typename int8_t)$int:k|]-compilePrimValue (IntValue (Int16Value k)) = [C.cexp|(typename int16_t)$int:k|]-compilePrimValue (IntValue (Int32Value k)) = [C.cexp|$int:k|]-compilePrimValue (IntValue (Int64Value k)) = [C.cexp|(typename int64_t)$int:k|]-compilePrimValue (FloatValue (Float64Value x))- | isInfinite x =- if x > 0 then [C.cexp|INFINITY|] else [C.cexp|-INFINITY|]- | isNaN x =- [C.cexp|NAN|]- | otherwise =- [C.cexp|$double:x|]-compilePrimValue (FloatValue (Float32Value x))- | isInfinite x =- if x > 0 then [C.cexp|INFINITY|] else [C.cexp|-INFINITY|]- | isNaN x =- [C.cexp|NAN|]- | otherwise =- [C.cexp|$float:x|]-compilePrimValue (BoolValue b) =- [C.cexp|$int:b'|]- where- b' :: Int- b' = if b then 1 else 0-compilePrimValue UnitValue =- [C.cexp|0|]- derefPointer :: C.Exp -> C.Exp -> C.Type -> C.Exp derefPointer ptr i res_t = [C.cexp|(($ty:res_t)$exp:ptr)[$exp:i]|]@@ -1815,18 +1826,19 @@ compileLeaf (ScalarVar src) = return [C.cexp|$id:src|] compileLeaf (Index _ _ Unit __ _) =- return $ compilePrimValue UnitValue+ pure $ C.toExp UnitValue mempty compileLeaf (Index src (Count iexp) restype DefaultSpace vol) = do src' <- rawMem src- derefPointer src'- <$> compileExp (untyped iexp)- <*> pure [C.cty|$tyquals:(volQuals vol) $ty:(primTypeToCType restype)*|]+ fmap (fromStorage restype) $+ derefPointer src'+ <$> compileExp (untyped iexp)+ <*> pure [C.cty|$tyquals:(volQuals vol) $ty:(primStorageType restype)*|] compileLeaf (Index src (Count iexp) restype (Space space) vol) =- join $+ fmap (fromStorage restype) . join $ asks envReadScalar <*> rawMem src <*> compileExp (untyped iexp)- <*> pure (primTypeToCType restype)+ <*> pure (primStorageType restype) <*> pure space <*> pure vol compileLeaf (Index src (Count iexp) _ ScalarSpace {} _) = do@@ -1836,7 +1848,7 @@ -- | Tell me how to compile a @v@, and I'll Compile any @PrimExp v@ for you. compilePrimExp :: Monad m => (v -> m C.Exp) -> PrimExp v -> m C.Exp compilePrimExp _ (ValueExp val) =- return $ compilePrimValue val+ pure $ C.toExp val mempty compilePrimExp f (LeafExp v _) = f v compilePrimExp f (UnOpExp Complement {} x) = do@@ -1845,9 +1857,6 @@ compilePrimExp f (UnOpExp Not {} x) = do x' <- compilePrimExp f x return [C.cexp|!$exp:x'|]-compilePrimExp f (UnOpExp Abs {} x) = do- x' <- compilePrimExp f x- return [C.cexp|abs($exp:x')|] compilePrimExp f (UnOpExp (FAbs Float32) x) = do x' <- compilePrimExp f x return [C.cexp|(float)fabs($exp:x')|]@@ -1860,12 +1869,9 @@ compilePrimExp f (UnOpExp USignum {} x) = do x' <- compilePrimExp f x return [C.cexp|($exp:x' > 0) - ($exp:x' < 0) != 0|]-compilePrimExp f (UnOpExp (FSignum Float32) x) = do- x' <- compilePrimExp f x- return [C.cexp|fsignum32($exp:x')|]-compilePrimExp f (UnOpExp (FSignum Float64) x) = do+compilePrimExp f (UnOpExp op x) = do x' <- compilePrimExp f x- return [C.cexp|fsignum32($exp:x')|]+ return [C.cexp|$id:(pretty op)($exp:x')|] compilePrimExp f (CmpOpExp cmp x y) = do x' <- compilePrimExp f x y' <- compilePrimExp f y@@ -1898,7 +1904,6 @@ Xor {} -> [C.cexp|$exp:x' ^ $exp:y'|] And {} -> [C.cexp|$exp:x' & $exp:y'|] Or {} -> [C.cexp|$exp:x' | $exp:y'|]- Shl {} -> [C.cexp|$exp:x' << $exp:y'|] LogAnd {} -> [C.cexp|$exp:x' && $exp:y'|] LogOr {} -> [C.cexp|$exp:x' || $exp:y'|] _ -> [C.cexp|$id:(pretty bop)($exp:x', $exp:y')|]@@ -1924,6 +1929,9 @@ [C.cstm|$comment:comment { $items:xs } |]+compileCode (TracePrint msg) = do+ (formatstr, formatargs) <- errorMsgString msg+ stm [C.cstm|fprintf(ctx->log, $string:formatstr, $args:formatargs);|] compileCode (DebugPrint s (Just e)) = do e' <- compileExp e stm@@ -1956,9 +1964,8 @@ compileCode (Assert e msg (loc, locs)) = do e' <- compileExp e err <-- collect $- join $- asks (opsError . envOperations) <*> pure msg <*> pure stacktrace+ collect . join $+ asks (opsError . envOperations) <*> pure msg <*> pure stacktrace stm [C.cstm|if (!$exp:e') { $items:err }|] where stacktrace = prettyStacktrace 0 $ map locStr $ loc : locs@@ -2033,8 +2040,8 @@ deref <- derefPointer dest' <$> compileExp (untyped idx)- <*> pure [C.cty|$tyquals:(volQuals vol) $ty:(primTypeToCType elemtype)*|]- elemexp' <- compileExp elemexp+ <*> pure [C.cty|$tyquals:(volQuals vol) $ty:(primStorageType elemtype)*|]+ elemexp' <- toStorage elemtype <$> compileExp elemexp stm [C.cstm|$exp:deref = $exp:elemexp';|] compileCode (Write dest (Count idx) _ ScalarSpace {} _ elemexp) = do idx' <- compileExp (untyped idx)@@ -2045,10 +2052,10 @@ asks envWriteScalar <*> rawMem dest <*> compileExp (untyped idx)- <*> pure (primTypeToCType elemtype)+ <*> pure (primStorageType elemtype) <*> pure space <*> pure vol- <*> compileExp elemexp+ <*> (toStorage elemtype <$> compileExp elemexp) compileCode (DeclareMem name space) = declMem name space compileCode (DeclareScalar name vol t) = do@@ -2061,7 +2068,7 @@ let ct = primTypeToCType t case vs of ArrayValues vs' -> do- let vs'' = [[C.cinit|$exp:(compilePrimValue v)|] | v <- vs']+ let vs'' = [[C.cinit|$exp:v|] | v <- vs'] earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:(length vs')] = {$inits:vs''};|] ArrayZeros n -> earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:n];|]
src/Futhark/CodeGen/Backends/GenericC/CLI.hs view
@@ -12,12 +12,14 @@ ) where -import Data.FileEmbed import Data.List (unzip5) import Data.Maybe+import qualified Data.Text as T import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.Backends.SimpleRep import Futhark.CodeGen.ImpCode+import Futhark.CodeGen.RTS.C (tuningH, valuesH)+import Futhark.Util.Pretty (prettyText) import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C @@ -105,7 +107,7 @@ int value = atoi(value_str); if (equals != NULL) { *equals = 0;- if (futhark_context_config_set_size(cfg, name, value) != 0) {+ if (futhark_context_config_set_size(cfg, name, (size_t)value) != 0) { futhark_panic(1, "Unknown size: %s\n", name); } } else {@@ -145,7 +147,7 @@ valueDescToCType :: ValueDesc -> C.Type valueDescToCType (ScalarValue pt signed _) =- signedPrimTypeToCType signed pt+ primAPIType signed pt valueDescToCType (ArrayValue _ _ pt signed shape) = let name = "futhark_" ++ arrayName pt signed (length shape) in [C.cty|struct $id:name|]@@ -169,6 +171,7 @@ (Int16, _) -> [C.cexp|i16_info|] (Int32, _) -> [C.cexp|i32_info|] (Int64, _) -> [C.cexp|i64_info|]+primTypeInfo (FloatType Float16) _ = [C.cexp|f16_info|] primTypeInfo (FloatType Float32) _ = [C.cexp|f32_info|] primTypeInfo (FloatType Float64) _ = [C.cexp|f64_info|] primTypeInfo Bool _ = [C.cexp|bool_info|]@@ -193,12 +196,12 @@ ) readInput i (TransparentValue _ (ScalarValue t ept _)) = let dest = "read_value_" ++ show i- in ( [C.citems|$ty:(primTypeToCType t) $id:dest;+ in ( [C.citems|$ty:(primStorageType t) $id:dest; $stm:(readPrimStm dest i t ept);|], [C.cstm|;|], [C.cstm|;|], [C.cstm|;|],- [C.cexp|$id:dest|]+ fromStorage t [C.cexp|$id:dest|] ) readInput i (TransparentValue _ (ArrayValue _ _ t ept dims)) = let dest = "read_value_" ++ show i@@ -211,7 +214,7 @@ rank = length dims dims_exps = [[C.cexp|$id:shape[$int:j]|] | j <- [0 .. rank -1]] dims_s = concat $ replicate rank "[]"- t' = signedPrimTypeToCType ept t+ t' = primAPIType ept t new_array = "futhark_new_" ++ name free_array = "futhark_free_" ++ name@@ -295,7 +298,7 @@ }|] where rank = length shape- bt' = primTypeToCType bt+ bt' = primStorageType bt name = arrayName bt ept rank printResult :: [(ExternalValue, C.Exp)] -> [C.Stm]@@ -304,10 +307,8 @@ f (v, e) = [printStm v e, [C.cstm|printf("\n");|]] cliEntryPoint ::- Name ->- FunctionT a ->- Maybe (C.Definition, C.Initializer)-cliEntryPoint fname fun@(Function _ _ _ _ results args) = do+ FunctionT a -> Maybe (C.Definition, C.Initializer)+cliEntryPoint fun@(Function _ _ _ _ results args) = do entry_point_name <- nameToString <$> functionEntry fun let (input_items, pack_input, free_input, free_parsed, input_args) = unzip5 $ readInputs args@@ -376,7 +377,7 @@ $items:(mconcat input_items) if (end_of_input(stdin) != 0) {- futhark_panic(1, "Expected EOF on stdin after reading input for %s.\n", $string:(quote (pretty fname)));+ futhark_panic(1, "Expected EOF on stdin after reading input for \"%s\".\n", $string:(pretty entry_point_name)); } $items:output_decls@@ -415,21 +416,19 @@ {-# NOINLINE cliDefs #-} -- | Generate Futhark standalone executable code.-cliDefs :: [Option] -> Functions a -> [C.Definition]+cliDefs :: [Option] -> Functions a -> T.Text cliDefs options (Functions funs) =- let values_h = $(embedStringFile "rts/c/values.h")- tuning_h = $(embedStringFile "rts/c/tuning.h")-- option_parser =+ let option_parser = generateOptionParser "parse_options" $ genericOptions ++ options (cli_entry_point_decls, entry_point_inits) =- unzip $ mapMaybe (uncurry cliEntryPoint) funs- in [C.cunit|+ unzip $ mapMaybe (cliEntryPoint . snd) funs+ in prettyText+ [C.cunit| $esc:("#include <getopt.h>") $esc:("#include <ctype.h>") $esc:("#include <inttypes.h>") -$esc:values_h+$esc:(T.unpack valuesH) static int binary_output = 0; static typename FILE *runtime_file;@@ -438,7 +437,7 @@ // If the entry point is NULL, the program will terminate after doing initialisation and such. static const char *entry_point = "main"; -$esc:tuning_h+$esc:(T.unpack tuningH) $func:option_parser
src/Futhark/CodeGen/Backends/GenericC/Server.hs view
@@ -13,12 +13,14 @@ where import Data.Bifunctor (first, second)-import Data.FileEmbed import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.Backends.SimpleRep import Futhark.CodeGen.ImpCode+import Futhark.CodeGen.RTS.C (serverH, tuningH, valuesH)+import Futhark.Util.Pretty (prettyText) import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C @@ -275,16 +277,14 @@ {-# NOINLINE serverDefs #-} -- | Generate Futhark server executable code.-serverDefs :: [Option] -> Functions a -> [C.Definition]+serverDefs :: [Option] -> Functions a -> T.Text serverDefs options funs =- let server_h = $(embedStringFile "rts/c/server.h")- values_h = $(embedStringFile "rts/c/values.h")- tuning_h = $(embedStringFile "rts/c/tuning.h")- option_parser =+ let option_parser = generateOptionParser "parse_options" $ genericOptions ++ options (boilerplate_defs, type_inits, entry_point_inits) = mkBoilerplate funs- in [C.cunit|+ in prettyText+ [C.cunit| $esc:("#include <getopt.h>") $esc:("#include <ctype.h>") $esc:("#include <inttypes.h>")@@ -292,9 +292,9 @@ // If the entry point is NULL, the program will terminate after doing initialisation and such. It is not used for anything else in server mode. static const char *entry_point = "main"; -$esc:values_h-$esc:server_h-$esc:tuning_h+$esc:(T.unpack valuesH)+$esc:(T.unpack serverH)+$esc:(T.unpack tuningH) $edecls:boilerplate_defs
src/Futhark/CodeGen/Backends/GenericPython.hs view
@@ -22,6 +22,8 @@ compilePrimTypeExt, compilePrimToNp, compilePrimToExtNp,+ fromStorage,+ toStorage, Operations (..), defaultOperations, unpackDim,@@ -49,17 +51,18 @@ import Control.Monad.RWS import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T import Futhark.CodeGen.Backends.GenericPython.AST-import Futhark.CodeGen.Backends.GenericPython.Definitions import Futhark.CodeGen.Backends.GenericPython.Options import qualified Futhark.CodeGen.ImpCode as Imp+import Futhark.CodeGen.RTS.Python import Futhark.Compiler.CLI (CompilerMode (..)) import Futhark.IR.Primitive hiding (Bool) import Futhark.IR.Prop (isBuiltInFunction, subExpVars) import Futhark.IR.Syntax (Space (..)) import Futhark.MonadFreshNames import Futhark.Util (zEncodeString)-import Futhark.Util.Pretty (pretty)+import Futhark.Util.Pretty (pretty, prettyText) -- | A substitute expression compiler, tried before the main -- compilation function.@@ -362,27 +365,24 @@ [PyStmt] -> [Option] -> Imp.Definitions op ->- m String+ m T.Text compileProg mode class_name constructor imports defines ops userstate sync options prog = do src <- getNameSource let prog' = runCompilerM ops src userstate compileProg'- return $- pretty- ( PyProg $- imports- ++ [ Import "argparse" Nothing,- Assign (Var "sizes") $ Dict []- ]- ++ defines- ++ [ Escape pyValues,- Escape pyFunctions,- Escape pyPanic,- Escape pyTuning,- Escape pyUtility,- Escape pyServer- ]- ++ prog'- )+ pure . prettyText . PyProg $+ imports+ ++ [ Import "argparse" Nothing,+ Assign (Var "sizes") $ Dict []+ ]+ ++ defines+ ++ [ Escape valuesPy,+ Escape memoryPy,+ Escape panicPy,+ Escape tuningPy,+ Escape scalarPy,+ Escape serverPy+ ]+ ++ prog' where Imp.Definitions consts (Imp.Functions funs) = prog compileProg' = withConstantSubsts consts $ do@@ -551,10 +551,9 @@ pack_output <- asks envEntryOutput pack_output mem sid bt ept dims entryPointOutput (Imp.TransparentValue _ (Imp.ArrayValue mem _ bt ept dims)) = do- mem' <- compileVar mem- let cast = Cast mem' (compilePrimTypeExt bt ept)+ mem' <- Cast <$> compileVar mem <*> pure (compilePrimTypeExt bt ept) dims' <- mapM compileDim dims- return $ simpleCall "createArray" [cast, Tuple dims']+ return $ simpleCall "createArray" [mem', Tuple dims', Var $ compilePrimToExtNp bt ept] badInput :: Int -> PyExp -> String -> PyStmt badInput i e t =@@ -641,9 +640,14 @@ -- we first go through the corresponding ctypes type, which does -- not have this problem. ctobject = compilePrimType bt- ctcall = simpleCall ctobject [e] npobject = compilePrimToNp bt- npcall = simpleCall npobject [ctcall]+ npcall =+ simpleCall+ npobject+ [ case bt of+ IntType Int64 -> simpleCall ctobject [e]+ _ -> e+ ] stm $ Try [Assign vname' npcall]@@ -726,6 +730,7 @@ readTypeEnum (IntType Int16) Imp.TypeDirect = "i16" readTypeEnum (IntType Int32) Imp.TypeDirect = "i32" readTypeEnum (IntType Int64) Imp.TypeDirect = "i64"+readTypeEnum (FloatType Float16) _ = "f16" readTypeEnum (FloatType Float32) _ = "f32" readTypeEnum (FloatType Float64) _ = "f64" readTypeEnum Imp.Bool _ = "bool"@@ -1026,6 +1031,7 @@ IntType Int16 -> "ct.c_int16" IntType Int32 -> "ct.c_int32" IntType Int64 -> "ct.c_int64"+ FloatType Float16 -> "ct.c_uint16" FloatType Float32 -> "ct.c_float" FloatType Float64 -> "ct.c_double" Imp.Bool -> "ct.c_bool"@@ -1043,6 +1049,7 @@ (IntType Int16, _) -> "ct.c_int16" (IntType Int32, _) -> "ct.c_int32" (IntType Int64, _) -> "ct.c_int64"+ (FloatType Float16, _) -> "ct.c_uint16" (FloatType Float32, _) -> "ct.c_float" (FloatType Float64, _) -> "ct.c_double" (Imp.Bool, _) -> "ct.c_bool"@@ -1056,6 +1063,7 @@ IntType Int16 -> "np.int16" IntType Int32 -> "np.int32" IntType Int64 -> "np.int64"+ FloatType Float16 -> "np.float16" FloatType Float32 -> "np.float32" FloatType Float64 -> "np.float64" Imp.Bool -> "np.byte"@@ -1073,11 +1081,24 @@ (IntType Int16, _) -> "np.int16" (IntType Int32, _) -> "np.int32" (IntType Int64, _) -> "np.int64"+ (FloatType Float16, _) -> "np.float16" (FloatType Float32, _) -> "np.float32" (FloatType Float64, _) -> "np.float64" (Imp.Bool, _) -> "np.bool_" (Unit, _) -> "np.byte" +-- | Convert from scalar to storage representation for the given type.+toStorage :: PrimType -> PyExp -> PyExp+toStorage (FloatType Float16) e =+ simpleCall "ct.c_int16" [simpleCall "futhark_to_bits16" [e]]+toStorage t e = simpleCall (compilePrimType t) [e]++-- | Convert from storage to scalar representation for the given type.+fromStorage :: PrimType -> PyExp -> PyExp+fromStorage (FloatType Float16) e =+ simpleCall "futhark_from_bits16" [simpleCall "np.int16" [e]]+fromStorage t e = simpleCall (compilePrimToNp t) [e]+ compilePrimValue :: Imp.PrimValue -> PyExp compilePrimValue (IntValue (Int8Value v)) = simpleCall "np.int8" [Integer $ toInteger v]@@ -1087,6 +1108,12 @@ simpleCall "np.int32" [Integer $ toInteger v] compilePrimValue (IntValue (Int64Value v)) = simpleCall "np.int64" [Integer $ toInteger v]+compilePrimValue (FloatValue (Float16Value v))+ | isInfinite v =+ if v > 0 then Var "np.inf" else Var "-np.inf"+ | isNaN v =+ Var "np.nan"+ | otherwise = simpleCall "np.float16" [Float $ fromRational $ toRational v] compilePrimValue (FloatValue (Float32Value v)) | isInfinite v = if v > 0 then Var "np.inf" else Var "-np.inf"@@ -1162,13 +1189,24 @@ compileLeaf (Imp.Index src (Imp.Count iexp) bt _ _) = do iexp' <- compileExp $ Imp.untyped iexp let bt' = compilePrimType bt- nptype = compilePrimToNp bt src' <- compileVar src- return $ simpleCall "indexArray" [src', iexp', Var bt', Var nptype]+ return $ fromStorage bt $ simpleCall "indexArray" [src', iexp', Var bt'] +errorMsgString :: Imp.ErrorMsg Imp.Exp -> CompilerM op s (String, [PyExp])+errorMsgString (Imp.ErrorMsg parts) = do+ let onPart (Imp.ErrorString s) = return ("%s", String s)+ onPart (Imp.ErrorVal IntType {} x) = ("%d",) <$> compileExp x+ onPart (Imp.ErrorVal FloatType {} x) = ("%f",) <$> compileExp x+ onPart (Imp.ErrorVal Imp.Bool x) = ("%r",) <$> compileExp x+ onPart (Imp.ErrorVal Unit {} x) = ("%r",) <$> compileExp x+ (formatstrs, formatargs) <- unzip <$> mapM onPart parts+ pure (mconcat formatstrs, formatargs)+ compileCode :: Imp.Code op -> CompilerM op s () compileCode Imp.DebugPrint {} = return ()+compileCode Imp.TracePrint {} =+ return () compileCode (Imp.Op op) = join $ asks envOpCompiler <*> pure op compileCode (Imp.If cond tb fb) = do@@ -1236,18 +1274,15 @@ compileCode (Imp.Comment s code) = do code' <- collect $ compileCode code stm $ Comment s code'-compileCode (Imp.Assert e (Imp.ErrorMsg parts) (loc, locs)) = do+compileCode (Imp.Assert e msg (loc, locs)) = do e' <- compileExp e- let onPart (Imp.ErrorString s) = return ("%s", String s)- onPart (Imp.ErrorInt32 x) = ("%d",) <$> compileExp x- onPart (Imp.ErrorInt64 x) = ("%d",) <$> compileExp x- (formatstrs, formatargs) <- unzip <$> mapM onPart parts+ (formatstr, formatargs) <- errorMsgString msg stm $ Assert e' ( BinOp "%"- (String $ "Error: " ++ concat formatstrs ++ "\n\nBacktrace:\n" ++ stacktrace)+ (String $ "Error: " ++ formatstr ++ "\n\nBacktrace:\n" ++ stacktrace) (Tuple formatargs) ) where@@ -1314,9 +1349,7 @@ <*> compileExp elemexp compileCode (Imp.Write dest (Imp.Count idx) elemtype _ _ elemexp) = do idx' <- compileExp $ Imp.untyped idx- elemexp' <- compileExp elemexp+ elemexp' <- toStorage elemtype <$> compileExp elemexp dest' <- compileVar dest- let elemtype' = compilePrimType elemtype- ctype = simpleCall elemtype' [elemexp']- stm $ Exp $ simpleCall "writeScalarArray" [dest', idx', ctype]+ stm $ Exp $ simpleCall "writeScalarArray" [dest', idx', elemexp'] compileCode Imp.Skip = return ()
src/Futhark/CodeGen/Backends/GenericPython/AST.hs view
@@ -11,6 +11,7 @@ ) where +import qualified Data.Text as T import Futhark.Util.Pretty import Language.Futhark.Core @@ -30,7 +31,7 @@ | Bool Bool | Float Double | String String- | RawStringLiteral String+ | RawStringLiteral T.Text | Var String | BinOp String PyExp PyExp | UnOp String PyExp@@ -75,7 +76,7 @@ | FunDef PyFunDef | ClassDef PyClassDef | -- Some arbitrary string of Python code.- Escape String+ Escape T.Text deriving (Eq, Show) data PyExcept = Catch PyExp [PyStmt]@@ -105,7 +106,7 @@ | isInfinite x = text $ if x > 0 then "float('inf')" else "float('-inf')" | otherwise = ppr x ppr (String x) = text $ show x- ppr (RawStringLiteral s) = text "\"\"\"" <> text s <> text "\"\"\""+ ppr (RawStringLiteral s) = text "\"\"\"" <> strictText s <> text "\"\"\"" ppr (Var n) = text $ map (\x -> if x == '\'' then 'm' else x) n ppr (Field e s) = ppr e <> text "." <> text s ppr (BinOp s e1 e2) = parens (ppr e1 <+> text s <+> ppr e2)@@ -172,7 +173,7 @@ text "import" <+> text from ppr (FunDef d) = ppr d ppr (ClassDef d) = ppr d- ppr (Escape s) = stack $ map text $ lines s+ ppr (Escape s) = stack $ map strictText $ T.lines s instance Pretty PyFunDef where ppr (Def fname params body) =
− src/Futhark/CodeGen/Backends/GenericPython/Definitions.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Futhark.CodeGen.Backends.GenericPython.Definitions- ( pyFunctions,- pyUtility,- pyValues,- pyPanic,- pyTuning,- pyServer,- )-where--import Data.FileEmbed--pyFunctions :: String-pyFunctions = $(embedStringFile "rts/python/memory.py")--pyUtility :: String-pyUtility = $(embedStringFile "rts/python/scalar.py")--pyValues :: String-pyValues = $(embedStringFile "rts/python/values.py")--pyPanic :: String-pyPanic = $(embedStringFile "rts/python/panic.py")--pyTuning :: String-pyTuning = $(embedStringFile "rts/python/tuning.py")--pyServer :: String-pyServer = $(embedStringFile "rts/python/server.py")
+ src/Futhark/CodeGen/Backends/GenericWASM.hs view
@@ -0,0 +1,338 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Futhark.CodeGen.Backends.GenericWASM+ ( GC.CParts (..),+ GC.asLibrary,+ GC.asExecutable,+ GC.asServer,+ JSEntryPoint (..),+ emccExportNames,+ javascriptWrapper,+ extToString,+ runServer,+ libraryExports,+ )+where++import Data.List (intercalate, nub)+import qualified Data.Text as T+import qualified Futhark.CodeGen.Backends.GenericC as GC+import Futhark.CodeGen.Backends.SimpleRep (opaqueName)+import qualified Futhark.CodeGen.ImpCode.Sequential as Imp+import Futhark.CodeGen.RTS.JavaScript+import Futhark.IR.Primitive+import NeatInterpolation (text)++extToString :: Imp.ExternalValue -> String+extToString (Imp.TransparentValue u (Imp.ArrayValue vn _ pt s dimSize)) =+ concat (replicate (length dimSize) "[]") ++ extToString (Imp.TransparentValue u (Imp.ScalarValue pt s vn))+extToString (Imp.TransparentValue _ (Imp.ScalarValue (FloatType Float16) _ _)) = "f16"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (FloatType Float32) _ _)) = "f32"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (FloatType Float64) _ _)) = "f64"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int8) Imp.TypeDirect _)) = "i8"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int16) Imp.TypeDirect _)) = "i16"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int32) Imp.TypeDirect _)) = "i32"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int64) Imp.TypeDirect _)) = "i64"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int8) Imp.TypeUnsigned _)) = "u8"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int16) Imp.TypeUnsigned _)) = "u16"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int32) Imp.TypeUnsigned _)) = "u32"+extToString (Imp.TransparentValue _ (Imp.ScalarValue (IntType Int64) Imp.TypeUnsigned _)) = "u64"+extToString (Imp.TransparentValue _ (Imp.ScalarValue Bool _ _)) = "bool"+extToString (Imp.TransparentValue _ (Imp.ScalarValue Unit _ _)) = error "extToString: Unit"+extToString (Imp.OpaqueValue _ oname vds) = opaqueName oname vds++type EntryPointType = String++data JSEntryPoint = JSEntryPoint+ { name :: String,+ parameters :: [EntryPointType],+ ret :: [EntryPointType]+ }++emccExportNames :: [JSEntryPoint] -> [String]+emccExportNames jses =+ map (\jse -> "'_futhark_entry_" ++ name jse ++ "'") jses+ ++ map (\arg -> "'" ++ gfn "new" arg ++ "'") arrays+ ++ map (\arg -> "'" ++ gfn "free" arg ++ "'") arrays+ ++ map (\arg -> "'" ++ gfn "shape" arg ++ "'") arrays+ ++ map (\arg -> "'" ++ gfn "values_raw" arg ++ "'") arrays+ ++ map (\arg -> "'" ++ gfn "values" arg ++ "'") arrays+ ++ map (\arg -> "'" ++ "_futhark_free_" ++ arg ++ "'") opaques+ ++ [ "_futhark_context_config_new",+ "_futhark_context_config_free",+ "_futhark_context_new",+ "_futhark_context_free",+ "_futhark_context_get_error"+ ]+ where+ arrays = filter isArray typs+ opaques = filter isOpaque typs+ typs = nub $ concatMap (\jse -> parameters jse ++ ret jse) jses+ gfn typ str = "_futhark_" ++ typ ++ "_" ++ baseType str ++ "_" ++ show (dim str) ++ "d"++javascriptWrapper :: [JSEntryPoint] -> T.Text+javascriptWrapper entryPoints =+ T.unlines+ [ serverJs,+ valuesJs,+ wrapperclassesJs,+ classFutharkContext entryPoints+ ]++classFutharkContext :: [JSEntryPoint] -> T.Text+classFutharkContext entryPoints =+ T.unlines+ [ "class FutharkContext {",+ constructor entryPoints,+ getFreeFun,+ getEntryPointsFun,+ getErrorFun,+ T.unlines $ map toFutharkArray arrays,+ T.unlines $ map jsWrapEntryPoint entryPoints,+ "}",+ [text|+ async function newFutharkContext() {+ var wasm = await loadWASM();+ return new FutharkContext(wasm);+ }+ |]+ ]+ where+ arrays = filter isArray typs+ typs = nub $ concatMap (\jse -> parameters jse ++ ret jse) entryPoints++constructor :: [JSEntryPoint] -> T.Text+constructor jses =+ [text|+ constructor(wasm, num_threads) {+ this.wasm = wasm;+ this.cfg = this.wasm._futhark_context_config_new();+ if (num_threads) this.wasm._futhark_context_config_set_num_threads(this.cfg, num_threads);+ this.ctx = this.wasm._futhark_context_new(this.cfg);+ this.entry_points = {+ ${entries}+ };+ }+ |]+ where+ entries = T.intercalate "," $ map dicEntry jses++getFreeFun :: T.Text+getFreeFun =+ [text|+ free() {+ this.wasm._futhark_context_free(this.ctx);+ this.wasm._futhark_context_config_free(this.cfg);+ }+ |]++getEntryPointsFun :: T.Text+getEntryPointsFun =+ [text|+ get_entry_points() {+ return this.entry_points;+ }+ |]++getErrorFun :: T.Text+getErrorFun =+ [text|+ get_error() {+ var ptr = this.wasm._futhark_context_get_error(this.ctx);+ var len = HEAP8.subarray(ptr).indexOf(0);+ var str = String.fromCharCode(...HEAP8.subarray(ptr, ptr + len));+ this.wasm._free(ptr);+ return str;+ }+ |]++dicEntry :: JSEntryPoint -> T.Text+dicEntry jse =+ [text|+ '${ename}' : [${params}, ${rets}]+ |]+ where+ ename = T.pack $ name jse+ params = T.pack $ show $ parameters jse+ rets = T.pack $ show $ ret jse++jsWrapEntryPoint :: JSEntryPoint -> T.Text+jsWrapEntryPoint jse =+ [text|+ ${func_name}(${inparams}) {+ var out = [${outparams}].map(n => this.wasm._malloc(n));+ var to_free = [];+ var do_free = () => { out.forEach(this.wasm._free); to_free.forEach(f => f.free()); };+ ${paramsToPtr}+ if (this.wasm._futhark_entry_${func_name}(this.ctx, ...out, ${ins}) > 0) {+ do_free();+ throw this.get_error();+ }+ ${results}+ do_free();+ return ${res};+ }+ |]+ where+ func_name = T.pack $ name jse++ alp = [0 .. length (parameters jse) - 1]+ inparams = T.pack $ intercalate ", " ["in" ++ show i | i <- alp]+ ins = T.pack $ intercalate ", " [maybeDerefence ("in" ++ show i) $ parameters jse !! i | i <- alp]+ paramsToPtr = T.pack $ unlines $ filter ("" /=) [arrayPointer ("in" ++ show i) $ parameters jse !! i | i <- alp]++ alr = [0 .. length (ret jse) - 1]+ outparams = T.pack $ intercalate ", " [show $ typeSize $ ret jse !! i | i <- alr]+ results = T.pack $ unlines [makeResult i $ ret jse !! i | i <- alr]+ res_array = intercalate ", " ["result" ++ show i | i <- alr]+ res = T.pack $ if length (ret jse) == 1 then "result0" else "[" ++ res_array ++ "]"++maybeDerefence :: String -> String -> String+maybeDerefence arg typ =+ if isScalar typ then arg else arg ++ ".ptr"++arrayPointer :: String -> String -> String+arrayPointer arg typ =+ if isArray typ+ then " if (" ++ arg ++ " instanceof Array) { " ++ reassign ++ "; to_free.push(" ++ arg ++ "); }"+ else ""+ where+ reassign = arg ++ " = this.new_" ++ signature ++ "_from_jsarray(" ++ arg ++ ")"+ signature = baseType typ ++ "_" ++ show (dim typ) ++ "d"++makeResult :: Int -> String -> String+makeResult i typ =+ " var result" ++ show i ++ " = "+ ++ if isArray typ+ then "this.new_" ++ signature ++ "_from_ptr(" ++ readout ++ ");"+ else+ if isOpaque typ+ then "new FutharkOpaque(this, " ++ readout ++ ", this.wasm._futhark_free_" ++ typ ++ ");"+ else readout ++ if typ == "bool" then "!==0;" else ";"+ where+ res = "out[" ++ show i ++ "]"+ readout = typeHeap typ ++ "[" ++ res ++ " >> " ++ show (typeShift typ) ++ "]"+ signature = baseType typ ++ "_" ++ show (dim typ) ++ "d"++baseType :: String -> String+baseType ('[' : ']' : end) = baseType end+baseType typ = typ++dim :: String -> Int+dim ('[' : ']' : end) = dim end + 1+dim _ = 0++isArray :: String -> Bool+isArray typ = take 2 typ == "[]"++isOpaque :: String -> Bool+isOpaque typ = take 6 typ == "opaque"++isScalar :: String -> Bool+isScalar typ = not (isArray typ || isOpaque typ)++typeSize :: String -> Integer+typeSize typ =+ case typ of+ "i8" -> 1+ "i16" -> 2+ "i32" -> 4+ "i64" -> 8+ "u8" -> 1+ "u16" -> 2+ "u32" -> 4+ "u64" -> 8+ "f16" -> 2+ "f32" -> 4+ "f64" -> 8+ "bool" -> 1+ _ -> 4++typeShift :: String -> Integer+typeShift typ =+ case typ of+ "i8" -> 0+ "i16" -> 1+ "i32" -> 2+ "i64" -> 3+ "u8" -> 0+ "u16" -> 1+ "u32" -> 2+ "u64" -> 3+ "f16" -> 1+ "f32" -> 2+ "f64" -> 3+ "bool" -> 0+ _ -> 2++typeHeap :: String -> String+typeHeap typ =+ case typ of+ "i8" -> "this.wasm.HEAP8"+ "i16" -> "this.wasm.HEAP16"+ "i32" -> "this.wasm.HEAP32"+ "i64" -> "this.wasm.HEAP64"+ "u8" -> "this.wasm.HEAPU8"+ "u16" -> "this.wasm.HEAPU16"+ "u32" -> "this.wasm.HEAPU32"+ "u64" -> "(new BigUint64Array(this.wasm.HEAP64.buffer))"+ "f16" -> "this.wasm.HEAPU16"+ "f32" -> "this.wasm.HEAPF32"+ "f64" -> "this.wasm.HEAPF64"+ "bool" -> "this.wasm.HEAP8"+ _ -> "this.wasm.HEAP32"++toFutharkArray :: String -> T.Text+toFutharkArray typ =+ [text|+ ${new}_from_jsarray(${arraynd_p}) {+ return this.${new}(${arraynd_flat_p}, ${arraynd_dims_p});+ }+ ${new}(array, ${dims}) {+ console.assert(array.length === ${dims_multiplied}, 'len=%s,dims=%s', array.length, [${dims}].toString());+ var copy = this.wasm._malloc(array.length << ${shift});+ ${heapType}.set(array, copy >> ${shift});+ var ptr = ${fnew}(this.ctx, copy, ${bigint_dims});+ this.wasm._free(copy);+ return this.${new}_from_ptr(ptr);+ }++ ${new}_from_ptr(ptr) {+ return new FutharkArray(this, ptr, ${args});+ }+ |]+ where+ d = dim typ+ ftype = baseType typ+ heap = typeHeap ftype+ signature = ftype ++ "_" ++ show d ++ "d"+ new = T.pack $ "new_" ++ signature+ fnew = T.pack $ "this.wasm._futhark_new_" ++ signature+ fshape = "this.wasm._futhark_shape_" ++ signature+ fvalues = "this.wasm._futhark_values_raw_" ++ signature+ ffree = "this.wasm._futhark_free_" ++ signature+ arraynd = "array" ++ show d ++ "d"+ shift = T.pack $ show (typeShift ftype)+ heapType = T.pack heap+ arraynd_flat = if d > 1 then arraynd ++ ".flat()" else arraynd+ arraynd_dims = intercalate ", " [arraynd ++ mult i "[0]" ++ ".length" | i <- [0 .. d -1]]+ dims = T.pack $ intercalate ", " ["d" ++ show i | i <- [0 .. d -1]]+ dims_multiplied = T.pack $ intercalate "*" ["Number(d" ++ show i ++ ")" | i <- [0 .. d -1]]+ bigint_dims = T.pack $ intercalate ", " ["BigInt(d" ++ show i ++ ")" | i <- [0 .. d -1]]+ mult i s = concat $ replicate i s+ (arraynd_p, arraynd_flat_p, arraynd_dims_p) = (T.pack arraynd, T.pack arraynd_flat, T.pack arraynd_dims)+ args = T.pack $ intercalate ", " ["'" ++ ftype ++ "'", show d, heap, fshape, fvalues, ffree]++runServer :: T.Text+runServer =+ [text|+ Module.onRuntimeInitialized = () => {+ var context = new FutharkContext(Module);+ var server = new Server(context);+ server.run();+ }|]++libraryExports :: T.Text+libraryExports = "export {newFutharkContext, FutharkContext, FutharkArray, FutharkOpaque};"
src/Futhark/CodeGen/Backends/MulticoreC.hs view
@@ -6,22 +6,26 @@ -- program to an equivalent C program. module Futhark.CodeGen.Backends.MulticoreC ( compileProg,+ generateContext, GC.CParts (..), GC.asLibrary, GC.asExecutable, GC.asServer,+ operations,+ cliOptions, ) where import Control.Monad-import Data.FileEmbed import qualified Data.Map as M import Data.Maybe+import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericC as GC import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.Backends.SimpleRep import Futhark.CodeGen.ImpCode.Multicore import qualified Futhark.CodeGen.ImpGen.Multicore as ImpGen+import Futhark.CodeGen.RTS.C (schedulerH) import Futhark.IR.MCMem (MCMem, Prog) import Futhark.MonadFreshNames import qualified Language.C.Quote.OpenCL as C@@ -43,165 +47,165 @@ cliOptions ) <=< ImpGen.compileProg- where- generateContext = do- let scheduler_h = $(embedStringFile "rts/c/scheduler.h")- mapM_ GC.earlyDecl [C.cunit|$esc:scheduler_h|] - cfg <- GC.publicDef "context_config" GC.InitDecl $ \s ->- ( [C.cedecl|struct $id:s;|],- [C.cedecl|struct $id:s { int debugging;- int profiling;- int num_threads;- };|]- )+generateContext :: GC.CompilerM op () ()+generateContext = do+ mapM_ GC.earlyDecl [C.cunit|$esc:(T.unpack schedulerH)|] - GC.publicDef_ "context_config_new" GC.InitDecl $ \s ->- ( [C.cedecl|struct $id:cfg* $id:s(void);|],- [C.cedecl|struct $id:cfg* $id:s(void) {- struct $id:cfg *cfg = (struct $id:cfg*) malloc(sizeof(struct $id:cfg));- if (cfg == NULL) {- return NULL;- }- cfg->debugging = 0;- cfg->profiling = 0;- cfg->num_threads = 0;- return cfg;- }|]- )+ cfg <- GC.publicDef "context_config" GC.InitDecl $ \s ->+ ( [C.cedecl|struct $id:s;|],+ [C.cedecl|struct $id:s { int debugging;+ int profiling;+ int num_threads;+ };|]+ ) - GC.publicDef_ "context_config_free" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:cfg* cfg);|],- [C.cedecl|void $id:s(struct $id:cfg* cfg) {- free(cfg);- }|]- )+ GC.publicDef_ "context_config_new" GC.InitDecl $ \s ->+ ( [C.cedecl|struct $id:cfg* $id:s(void);|],+ [C.cedecl|struct $id:cfg* $id:s(void) {+ struct $id:cfg *cfg = (struct $id:cfg*) malloc(sizeof(struct $id:cfg));+ if (cfg == NULL) {+ return NULL;+ }+ cfg->debugging = 0;+ cfg->profiling = 0;+ cfg->num_threads = 0;+ return cfg;+ }|]+ ) - GC.publicDef_ "context_config_set_debugging" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],- [C.cedecl|void $id:s(struct $id:cfg* cfg, int detail) {- cfg->debugging = detail;- }|]- )+ GC.publicDef_ "context_config_free" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:cfg* cfg);|],+ [C.cedecl|void $id:s(struct $id:cfg* cfg) {+ free(cfg);+ }|]+ ) - GC.publicDef_ "context_config_set_profiling" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],- [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag) {- cfg->profiling = flag;- }|]- )+ GC.publicDef_ "context_config_set_debugging" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],+ [C.cedecl|void $id:s(struct $id:cfg* cfg, int detail) {+ cfg->debugging = detail;+ }|]+ ) - GC.publicDef_ "context_config_set_logging" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],- [C.cedecl|void $id:s(struct $id:cfg* cfg, int detail) {- /* Does nothing for this backend. */- (void)cfg; (void)detail;- }|]- )+ GC.publicDef_ "context_config_set_profiling" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],+ [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag) {+ cfg->profiling = flag;+ }|]+ ) - GC.publicDef_ "context_config_set_num_threads" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:cfg *cfg, int n);|],- [C.cedecl|void $id:s(struct $id:cfg *cfg, int n) {- cfg->num_threads = n;- }|]- )+ GC.publicDef_ "context_config_set_logging" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|],+ [C.cedecl|void $id:s(struct $id:cfg* cfg, int detail) {+ // Does nothing for this backend.+ (void)cfg; (void)detail;+ }|]+ ) - (fields, init_fields) <- GC.contextContents+ GC.publicDef_ "context_config_set_num_threads" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:cfg *cfg, int n);|],+ [C.cedecl|void $id:s(struct $id:cfg *cfg, int n) {+ cfg->num_threads = n;+ }|]+ ) - ctx <- GC.publicDef "context" GC.InitDecl $ \s ->- ( [C.cedecl|struct $id:s;|],- [C.cedecl|struct $id:s {- struct scheduler scheduler;- int detail_memory;- int debugging;- int profiling;- int profiling_paused;- int logging;- typename lock_t lock;- char *error;- typename FILE *log;- int total_runs;- long int total_runtime;- $sdecls:fields+ (fields, init_fields) <- GC.contextContents - // Tuning parameters- typename int64_t tuning_timing;- typename int64_t tuning_iter;- };|]- )+ ctx <- GC.publicDef "context" GC.InitDecl $ \s ->+ ( [C.cedecl|struct $id:s;|],+ [C.cedecl|struct $id:s {+ struct scheduler scheduler;+ int detail_memory;+ int debugging;+ int profiling;+ int profiling_paused;+ int logging;+ typename lock_t lock;+ char *error;+ typename FILE *log;+ int total_runs;+ long int total_runtime;+ $sdecls:fields - GC.publicDef_ "context_new" GC.InitDecl $ \s ->- ( [C.cedecl|struct $id:ctx* $id:s(struct $id:cfg* cfg);|],- [C.cedecl|struct $id:ctx* $id:s(struct $id:cfg* cfg) {- struct $id:ctx* ctx = (struct $id:ctx*) malloc(sizeof(struct $id:ctx));- if (ctx == NULL) {- return NULL;- }+ // Tuning parameters+ typename int64_t tuning_timing;+ typename int64_t tuning_iter;+ };|]+ ) - // Initialize rand()- fast_srand(time(0));- ctx->detail_memory = cfg->debugging;- ctx->debugging = cfg->debugging;- ctx->profiling = cfg->profiling;- ctx->profiling_paused = 0;- ctx->logging = 0;- ctx->error = NULL;- ctx->log = stderr;- create_lock(&ctx->lock);+ GC.publicDef_ "context_new" GC.InitDecl $ \s ->+ ( [C.cedecl|struct $id:ctx* $id:s(struct $id:cfg* cfg);|],+ [C.cedecl|struct $id:ctx* $id:s(struct $id:cfg* cfg) {+ struct $id:ctx* ctx = (struct $id:ctx*) malloc(sizeof(struct $id:ctx));+ if (ctx == NULL) {+ return NULL;+ } - int tune_kappa = 0;- double kappa = 5.1f * 1000;+ // Initialize rand()+ fast_srand(time(0));+ ctx->detail_memory = cfg->debugging;+ ctx->debugging = cfg->debugging;+ ctx->profiling = cfg->profiling;+ ctx->profiling_paused = 0;+ ctx->logging = 0;+ ctx->error = NULL;+ ctx->log = stderr;+ create_lock(&ctx->lock); - if (tune_kappa) {- if (determine_kappa(&kappa) != 0) {- return NULL;- }- }+ int tune_kappa = 0;+ double kappa = 5.1f * 1000; - if (scheduler_init(&ctx->scheduler,- cfg->num_threads > 0 ?- cfg->num_threads : num_processors(),- kappa) != 0) {- return NULL;- }+ if (tune_kappa) {+ if (determine_kappa(&kappa) != 0) {+ return NULL;+ }+ } - $stms:init_fields+ if (scheduler_init(&ctx->scheduler,+ cfg->num_threads > 0 ?+ cfg->num_threads : num_processors(),+ kappa) != 0) {+ return NULL;+ } - init_constants(ctx);+ $stms:init_fields - return ctx;- }|]- )+ init_constants(ctx); - GC.publicDef_ "context_free" GC.InitDecl $ \s ->- ( [C.cedecl|void $id:s(struct $id:ctx* ctx);|],- [C.cedecl|void $id:s(struct $id:ctx* ctx) {- free_constants(ctx);- (void)scheduler_destroy(&ctx->scheduler);- free_lock(&ctx->lock);- free(ctx);- }|]- )+ return ctx;+ }|]+ ) - GC.publicDef_ "context_sync" GC.InitDecl $ \s ->- ( [C.cedecl|int $id:s(struct $id:ctx* ctx);|],- [C.cedecl|int $id:s(struct $id:ctx* ctx) {- (void)ctx;- return 0;- }|]- )+ GC.publicDef_ "context_free" GC.InitDecl $ \s ->+ ( [C.cedecl|void $id:s(struct $id:ctx* ctx);|],+ [C.cedecl|void $id:s(struct $id:ctx* ctx) {+ free_constants(ctx);+ (void)scheduler_destroy(&ctx->scheduler);+ free_lock(&ctx->lock);+ free(ctx);+ }|]+ ) - GC.earlyDecl [C.cedecl|static const char *size_names[0];|]- GC.earlyDecl [C.cedecl|static const char *size_vars[0];|]- GC.earlyDecl [C.cedecl|static const char *size_classes[0];|]+ GC.publicDef_ "context_sync" GC.InitDecl $ \s ->+ ( [C.cedecl|int $id:s(struct $id:ctx* ctx);|],+ [C.cedecl|int $id:s(struct $id:ctx* ctx) {+ (void)ctx;+ return 0;+ }|]+ ) - GC.publicDef_ "context_config_set_size" GC.InitDecl $ \s ->- ( [C.cedecl|int $id:s(struct $id:cfg* cfg, const char *size_name, size_t size_value);|],- [C.cedecl|int $id:s(struct $id:cfg* cfg, const char *size_name, size_t size_value) {- (void)cfg; (void)size_name; (void)size_value;- return 1;- }|]- )+ GC.earlyDecl [C.cedecl|static const char *size_names[0];|]+ GC.earlyDecl [C.cedecl|static const char *size_vars[0];|]+ GC.earlyDecl [C.cedecl|static const char *size_classes[0];|]++ GC.publicDef_ "context_config_set_size" GC.InitDecl $ \s ->+ ( [C.cedecl|int $id:s(struct $id:cfg* cfg, const char *size_name, size_t size_value);|],+ [C.cedecl|int $id:s(struct $id:cfg* cfg, const char *size_name, size_t size_value) {+ (void)cfg; (void)size_name; (void)size_value;+ return 1;+ }|]+ ) cliOptions :: [Option] cliOptions =
+ src/Futhark/CodeGen/Backends/MulticoreWASM.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++-- | C code generator. This module can convert a correct ImpCode+-- program to an equivalent C program. This C program is expected to+-- be converted to WebAssembly, so we also produce the intended+-- JavaScript wrapper.+module Futhark.CodeGen.Backends.MulticoreWASM+ ( compileProg,+ runServer,+ libraryExports,+ GC.CParts (..),+ GC.asLibrary,+ GC.asExecutable,+ GC.asServer,+ )+where++import Data.Maybe+import qualified Data.Text as T+import qualified Futhark.CodeGen.Backends.GenericC as GC+import Futhark.CodeGen.Backends.GenericWASM+import qualified Futhark.CodeGen.Backends.MulticoreC as MC+import qualified Futhark.CodeGen.ImpCode.Multicore as Imp+import qualified Futhark.CodeGen.ImpGen.Multicore as ImpGen+import Futhark.IR.MCMem+import Futhark.MonadFreshNames++compileProg :: MonadFreshNames m => Prog MCMem -> m (ImpGen.Warnings, (GC.CParts, T.Text, [String]))+compileProg prog = do+ (ws, prog') <- ImpGen.compileProg prog++ prog'' <-+ GC.compileProg+ "wasm_multicore"+ MC.operations+ MC.generateContext+ ""+ [DefaultSpace]+ MC.cliOptions+ prog'++ pure+ ( ws,+ ( prog'',+ javascriptWrapper (fRepMyRep prog'),+ "_futhark_context_config_set_num_threads" : emccExportNames (fRepMyRep prog')+ )+ )++fRepMyRep :: Imp.Definitions Imp.Multicore -> [JSEntryPoint]+fRepMyRep prog =+ let Imp.Functions fs = Imp.defFuns prog+ function (Imp.Function entry _ _ _ res args) = do+ n <- entry+ Just $+ JSEntryPoint+ { name = nameToString n,+ parameters = map extToString args,+ ret = map extToString res+ }+ in mapMaybe (function . snd) fs
src/Futhark/CodeGen/Backends/PyOpenCL.hs view
@@ -9,12 +9,14 @@ import Control.Monad import qualified Data.Map as M+import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericPython as Py import Futhark.CodeGen.Backends.GenericPython.AST import Futhark.CodeGen.Backends.GenericPython.Options import Futhark.CodeGen.Backends.PyOpenCL.Boilerplate import qualified Futhark.CodeGen.ImpCode.OpenCL as Imp import qualified Futhark.CodeGen.ImpGen.OpenCL as ImpGen+import Futhark.CodeGen.RTS.Python (openclPy) import Futhark.IR.GPUMem (GPUMem, Prog) import Futhark.MonadFreshNames import Futhark.Util (zEncodeString)@@ -26,7 +28,7 @@ Py.CompilerMode -> String -> Prog GPUMem ->- m (ImpGen.Warnings, String)+ m (ImpGen.Warnings, T.Text) compileProg mode class_name prog = do ( ws, Imp.Program@@ -60,14 +62,14 @@ Assign (Var "default_num_groups") None, Assign (Var "default_tile_size") None, Assign (Var "default_reg_tile_size") None,- Assign (Var "fut_opencl_src") $ RawStringLiteral $ opencl_prelude ++ opencl_code+ Assign (Var "fut_opencl_src") $ RawStringLiteral $ opencl_prelude <> opencl_code ] let imports = [ Import "sys" Nothing, Import "numpy" $ Just "np", Import "ctypes" $ Just "ct",- Escape openClPrelude,+ Escape openclPy, Import "pyopencl.array" Nothing, Import "time" Nothing ]@@ -424,7 +426,7 @@ (Var "cl.array.Array") [ Arg $ Var "self.queue", Arg $ Tuple dims',- Arg $ Var $ Py.compilePrimTypeExt bt ept,+ Arg $ Var $ Py.compilePrimToExtNp bt ept, ArgKeyword "data" mem' ] packArrayOutput _ sid _ _ _ =
src/Futhark/CodeGen/Backends/PyOpenCL/Boilerplate.hs view
@@ -5,12 +5,10 @@ -- | Various boilerplate definitions for the PyOpenCL backend. module Futhark.CodeGen.Backends.PyOpenCL.Boilerplate ( openClInit,- openClPrelude, ) where import Control.Monad.Identity-import Data.FileEmbed import qualified Data.Map as M import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericPython as Py@@ -32,17 +30,12 @@ errorMsgNumArgs :: ErrorMsg a -> Int errorMsgNumArgs = length . errorMsgArgTypes --- | @rts/python/opencl.py@ embedded as a string.-openClPrelude :: String-openClPrelude = $(embedStringFile "rts/python/opencl.py")- -- | Python code (as a string) that calls the -- @initiatialize_opencl_object@ procedure. Should be put in the -- class constructor.-openClInit :: [PrimType] -> String -> M.Map Name SizeClass -> [FailureMsg] -> String+openClInit :: [PrimType] -> String -> M.Map Name SizeClass -> [FailureMsg] -> T.Text openClInit types assign sizes failures =- T.unpack- [text|+ [text| size_heuristics=$size_heuristics self.global_failure_args_max = $max_num_args self.failure_msgs=$failure_msgs@@ -82,8 +75,7 @@ in concatMap escapeChar onPart (ErrorString s) = formatEscape s- onPart ErrorInt32 {} = "{}"- onPart ErrorInt64 {} = "{}"+ onPart ErrorVal {} = "{}" sizeClassesToPython :: M.Map Name SizeClass -> PyExp sizeClassesToPython = Dict . map f . M.toList
src/Futhark/CodeGen/Backends/SequentialC.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE OverloadedStrings #-}+ -- | C code generator. This module can convert a correct ImpCode -- program to an equivalent C program. The C code is strictly -- sequential, but can handle the full Futhark language.@@ -22,7 +24,7 @@ compileProg :: MonadFreshNames m => Prog SeqMem -> m (ImpGen.Warnings, GC.CParts) compileProg = traverse- (GC.compileProg "c" operations generateBoilerplate "" [DefaultSpace] [])+ (GC.compileProg "c" operations generateBoilerplate mempty [DefaultSpace] []) <=< ImpGen.compileProg where operations :: GC.Operations Imp.Sequential ()
src/Futhark/CodeGen/Backends/SequentialC/Boilerplate.hs view
@@ -41,7 +41,7 @@ GC.publicDef_ "context_config_set_logging" GC.InitDecl $ \s -> ( [C.cedecl|void $id:s(struct $id:cfg* cfg, int flag);|], [C.cedecl|void $id:s(struct $id:cfg* cfg, int detail) {- /* Does nothing for this backend. */+ // Does nothing for this backend. (void)cfg; (void)detail; }|] )
src/Futhark/CodeGen/Backends/SequentialPython.hs view
@@ -5,6 +5,7 @@ where import Control.Monad+import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericPython as GenericPython import Futhark.CodeGen.Backends.GenericPython.AST import qualified Futhark.CodeGen.ImpCode.Sequential as Imp@@ -18,7 +19,7 @@ GenericPython.CompilerMode -> String -> Prog SeqMem ->- m (ImpGen.Warnings, String)+ m (ImpGen.Warnings, T.Text) compileProg mode class_name = ImpGen.compileProg >=> traverse
+ src/Futhark/CodeGen/Backends/SequentialWASM.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}++-- | C code generator. This module can convert a correct ImpCode+-- program to an equivalent C program. This C program is expected to+-- be converted to WebAssembly, so we also produce the intended+-- JavaScript wrapper.+module Futhark.CodeGen.Backends.SequentialWASM+ ( compileProg,+ runServer,+ libraryExports,+ GC.CParts (..),+ GC.asLibrary,+ GC.asExecutable,+ GC.asServer,+ )+where++import Data.Maybe+import qualified Data.Text as T+import qualified Futhark.CodeGen.Backends.GenericC as GC+import Futhark.CodeGen.Backends.GenericWASM+import Futhark.CodeGen.Backends.SequentialC.Boilerplate+import qualified Futhark.CodeGen.ImpCode.Sequential as Imp+import qualified Futhark.CodeGen.ImpGen.Sequential as ImpGen+import Futhark.IR.SeqMem+import Futhark.MonadFreshNames++-- | Compile the program to sequential C with a JavaScript wrapper.+compileProg :: MonadFreshNames m => Prog SeqMem -> m (ImpGen.Warnings, (GC.CParts, T.Text, [String]))+compileProg prog = do+ (ws, prog') <- ImpGen.compileProg prog++ prog'' <-+ GC.compileProg+ "wasm"+ operations+ generateBoilerplate+ ""+ [DefaultSpace]+ []+ prog'+ pure (ws, (prog'', javascriptWrapper (fRepMyRep prog'), emccExportNames (fRepMyRep prog')))+ where+ operations :: GC.Operations Imp.Sequential ()+ operations =+ GC.defaultOperations+ { GC.opsCompiler = const $ return ()+ }++fRepMyRep :: Imp.Program -> [JSEntryPoint]+fRepMyRep prog =+ let Imp.Functions fs = Imp.defFuns prog+ function (Imp.Function entry _ _ _ res args) = do+ n <- entry+ Just $+ JSEntryPoint+ { name = nameToString n,+ parameters = map extToString args,+ ret = map extToString res+ }+ in mapMaybe (function . snd) fs
src/Futhark/CodeGen/Backends/SimpleRep.hs view
@@ -1,28 +1,33 @@ {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE Trustworthy #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Simple C runtime representation.+--+-- Most types use the same memory and scalar variable representation.+-- For those that do not (as of this writing, only `Float16`), we use+-- 'primStorageType' for the array element representation, and+-- 'primTypeToCType' for their scalar representation. Use 'toStorage'+-- and 'fromStorage' to convert back and forth. module Futhark.CodeGen.Backends.SimpleRep ( tupleField, funName, defaultMemBlockType, intTypeToCType, primTypeToCType,- signedPrimTypeToCType,+ primStorageType,+ primAPIType, arrayName, opaqueName, externalValueType,+ toStorage,+ fromStorage, cproduct, csum, -- * Primitive value operations- cIntOps,- cFloat32Ops,- cFloat32Funs,- cFloat64Ops,- cFloat64Funs,- cFloatConvOps,+ cScalarDefs, -- * Storing/restoring values in byte sequences storageSize,@@ -33,9 +38,10 @@ import Data.Bits (shiftR, xor) import Data.Char (isAlphaNum, isDigit, ord)+import qualified Data.Text as T import Futhark.CodeGen.ImpCode+import Futhark.CodeGen.RTS.C (scalarF16H, scalarH) import Futhark.Util (zEncodeString)-import Futhark.Util.Pretty (prettyOneLine) import qualified Language.C.Quote.C as C import qualified Language.C.Syntax as C import Text.Printf@@ -54,26 +60,38 @@ uintTypeToCType Int32 = [C.cty|typename uint32_t|] uintTypeToCType Int64 = [C.cty|typename uint64_t|] --- | The C type corresponding to a float type.-floatTypeToCType :: FloatType -> C.Type-floatTypeToCType Float32 = [C.cty|float|]-floatTypeToCType Float64 = [C.cty|double|]- -- | The C type corresponding to a primitive type. Integers are -- assumed to be unsigned. primTypeToCType :: PrimType -> C.Type primTypeToCType (IntType t) = intTypeToCType t-primTypeToCType (FloatType t) = floatTypeToCType t+primTypeToCType (FloatType Float16) = [C.cty|typename f16|]+primTypeToCType (FloatType Float32) = [C.cty|float|]+primTypeToCType (FloatType Float64) = [C.cty|double|] primTypeToCType Bool = [C.cty|typename bool|] primTypeToCType Unit = [C.cty|typename bool|] --- | The C type corresponding to a primitive type. Integers are+-- | The C storage type for arrays of this primitive type.+primStorageType :: PrimType -> C.Type+primStorageType (FloatType Float16) = [C.cty|typename uint16_t|]+primStorageType t = primTypeToCType t++-- | The C API corresponding to a primitive type. Integers are -- assumed to have the specified sign.-signedPrimTypeToCType :: Signedness -> PrimType -> C.Type-signedPrimTypeToCType TypeUnsigned (IntType t) = uintTypeToCType t-signedPrimTypeToCType TypeDirect (IntType t) = intTypeToCType t-signedPrimTypeToCType _ t = primTypeToCType t+primAPIType :: Signedness -> PrimType -> C.Type+primAPIType TypeUnsigned (IntType t) = uintTypeToCType t+primAPIType TypeDirect (IntType t) = intTypeToCType t+primAPIType _ t = primStorageType t +-- | Convert from scalar to storage representation for the given type.+toStorage :: PrimType -> C.Exp -> C.Exp+toStorage (FloatType Float16) e = [C.cexp|futrts_to_bits16($exp:e)|]+toStorage _ e = e++-- | Convert from storage to scalar representation for the given type.+fromStorage :: PrimType -> C.Exp -> C.Exp+fromStorage (FloatType Float16) e = [C.cexp|futrts_from_bits16($exp:e)|]+fromStorage _ e = e+ -- | @tupleField i@ is the name of field number @i@ in a tuple. tupleField :: Int -> String tupleField i = "v" ++ show i@@ -83,12 +101,9 @@ funName :: Name -> String funName = ("futrts_" ++) . zEncodeString . nameToString -funName' :: String -> String-funName' = funName . nameFromString- -- | The type of memory blocks in the default memory space. defaultMemBlockType :: C.Type-defaultMemBlockType = [C.cty|char*|]+defaultMemBlockType = [C.cty|unsigned char*|] -- | The name of exposed array type structs. arrayName :: PrimType -> Signedness -> Int -> String@@ -132,7 +147,7 @@ externalValueType (TransparentValue _ (ArrayValue _ _ pt signed shape)) = [C.cty|struct $id:("futhark_" ++ arrayName pt signed (length shape))*|] externalValueType (TransparentValue _ (ScalarValue pt signed _)) =- signedPrimTypeToCType signed pt+ primAPIType signed pt -- | Return an expression multiplying together the given expressions. -- If an empty list is given, the expression @1@ is returned.@@ -160,923 +175,48 @@ toExp v _ = [C.cexp|$id:v|] instance C.ToExp IntValue where- toExp (Int8Value v) = C.toExp v- toExp (Int16Value v) = C.toExp v- toExp (Int32Value v) = C.toExp v- toExp (Int64Value v) = C.toExp v+ toExp (Int8Value k) _ = [C.cexp|(typename int8_t)$int:k|]+ toExp (Int16Value k) _ = [C.cexp|(typename int16_t)$int:k|]+ toExp (Int32Value k) _ = [C.cexp|$int:k|]+ toExp (Int64Value k) _ = [C.cexp|(typename int64_t)$int:k|] instance C.ToExp FloatValue where- toExp (Float32Value v) = C.toExp v- toExp (Float64Value v) = C.toExp v+ toExp (Float16Value x) _+ | isInfinite x =+ if x > 0 then [C.cexp|INFINITY|] else [C.cexp|-INFINITY|]+ | isNaN x =+ [C.cexp|NAN|]+ | otherwise =+ [C.cexp|$float:(fromRational (toRational x))|]+ toExp (Float32Value x) _+ | isInfinite x =+ if x > 0 then [C.cexp|INFINITY|] else [C.cexp|-INFINITY|]+ | isNaN x =+ [C.cexp|NAN|]+ | otherwise =+ [C.cexp|$float:x|]+ toExp (Float64Value x) _+ | isInfinite x =+ if x > 0 then [C.cexp|INFINITY|] else [C.cexp|-INFINITY|]+ | isNaN x =+ [C.cexp|NAN|]+ | otherwise =+ [C.cexp|$double:x|] instance C.ToExp PrimValue where toExp (IntValue v) = C.toExp v toExp (FloatValue v) = C.toExp v toExp (BoolValue True) = C.toExp (1 :: Int8) toExp (BoolValue False) = C.toExp (0 :: Int8)- toExp UnitValue = C.toExp (1 :: Int8)+ toExp UnitValue = C.toExp (0 :: Int8) instance C.ToExp SubExp where toExp (Var v) = C.toExp v toExp (Constant c) = C.toExp c -cIntOps :: [C.Definition]-cIntOps =- concatMap (`map` [minBound .. maxBound]) ops- ++ cIntPrimFuns- where- ops =- [ mkAdd,- mkSub,- mkMul,- mkUDiv,- mkUDivUp,- mkUMod,- mkUDivSafe,- mkUDivUpSafe,- mkUModSafe,- mkSDiv,- mkSDivUp,- mkSMod,- mkSDivSafe,- mkSDivUpSafe,- mkSModSafe,- mkSQuot,- mkSRem,- mkSQuotSafe,- mkSRemSafe,- mkSMin,- mkUMin,- mkSMax,- mkUMax,- mkShl,- mkLShr,- mkAShr,- mkAnd,- mkOr,- mkXor,- mkUlt,- mkUle,- mkSlt,- mkSle,- mkPow,- mkIToB,- mkBToI- ]- ++ map mkSExt [minBound .. maxBound]- ++ map mkZExt [minBound .. maxBound]-- taggedI s Int8 = s ++ "8"- taggedI s Int16 = s ++ "16"- taggedI s Int32 = s ++ "32"- taggedI s Int64 = s ++ "64"-- -- Use unsigned types for add/sub/mul so we can do- -- well-defined overflow.- mkAdd = simpleUintOp "add" [C.cexp|x + y|]- mkSub = simpleUintOp "sub" [C.cexp|x - y|]- mkMul = simpleUintOp "mul" [C.cexp|x * y|]- mkUDiv = simpleUintOp "udiv" [C.cexp|x / y|]- mkUDivUp = simpleUintOp "udiv_up" [C.cexp|(x+y-1) / y|]- mkUMod = simpleUintOp "umod" [C.cexp|x % y|]- mkUDivSafe = simpleUintOp "udiv_safe" [C.cexp|y == 0 ? 0 : x / y|]- mkUDivUpSafe = simpleUintOp "udiv_up_safe" [C.cexp|y == 0 ? 0 : (x+y-1) / y|]- mkUModSafe = simpleUintOp "umod_safe" [C.cexp|y == 0 ? 0 : x % y|]- mkUMax = simpleUintOp "umax" [C.cexp|x < y ? y : x|]- mkUMin = simpleUintOp "umin" [C.cexp|x < y ? x : y|]-- mkSDiv t =- let ct = intTypeToCType t- in [C.cedecl|static inline $ty:ct $id:(taggedI "sdiv" t)($ty:ct x, $ty:ct y) {- $ty:ct q = x / y;- $ty:ct r = x % y;- return q -- (((r != 0) && ((r < 0) != (y < 0))) ? 1 : 0);- }|]- mkSDivUp t =- simpleIntOp "sdiv_up" [C.cexp|$id:(taggedI "sdiv" t)(x+y-1,y)|] t- mkSMod t =- let ct = intTypeToCType t- in [C.cedecl|static inline $ty:ct $id:(taggedI "smod" t)($ty:ct x, $ty:ct y) {- $ty:ct r = x % y;- return r +- ((r == 0 || (x > 0 && y > 0) || (x < 0 && y < 0)) ? 0 : y);- }|]- mkSDivSafe t =- simpleIntOp "sdiv_safe" [C.cexp|y == 0 ? 0 : $id:(taggedI "sdiv" t)(x,y)|] t- mkSDivUpSafe t =- simpleIntOp "sdiv_up_safe" [C.cexp|$id:(taggedI "sdiv_safe" t)(x+y-1,y)|] t- mkSModSafe t =- simpleIntOp "smod_safe" [C.cexp|y == 0 ? 0 : $id:(taggedI "smod" t)(x,y)|] t-- mkSQuot = simpleIntOp "squot" [C.cexp|x / y|]- mkSRem = simpleIntOp "srem" [C.cexp|x % y|]- mkSQuotSafe = simpleIntOp "squot_safe" [C.cexp|y == 0 ? 0 : x / y|]- mkSRemSafe = simpleIntOp "srem_safe" [C.cexp|y == 0 ? 0 : x % y|]- mkSMax = simpleIntOp "smax" [C.cexp|x < y ? y : x|]- mkSMin = simpleIntOp "smin" [C.cexp|x < y ? x : y|]- mkShl = simpleUintOp "shl" [C.cexp|x << y|]- mkLShr = simpleUintOp "lshr" [C.cexp|x >> y|]- mkAShr = simpleIntOp "ashr" [C.cexp|x >> y|]- mkAnd = simpleUintOp "and" [C.cexp|x & y|]- mkOr = simpleUintOp "or" [C.cexp|x | y|]- mkXor = simpleUintOp "xor" [C.cexp|x ^ y|]- mkUlt = uintCmpOp "ult" [C.cexp|x < y|]- mkUle = uintCmpOp "ule" [C.cexp|x <= y|]- mkSlt = intCmpOp "slt" [C.cexp|x < y|]- mkSle = intCmpOp "sle" [C.cexp|x <= y|]-- -- We define some operations as macros rather than functions,- -- because this allows us to use them as constant expressions- -- in things like array sizes and static initialisers.- macro name rhs =- [C.cedecl|$esc:("#define " ++ name ++ "(x) (" ++ prettyOneLine rhs ++ ")")|]-- mkPow t =- let ct = intTypeToCType t- in [C.cedecl|static inline $ty:ct $id:(taggedI "pow" t)($ty:ct x, $ty:ct y) {- $ty:ct res = 1, rem = y;- while (rem != 0) {- if (rem & 1) {- res *= x;- }- rem >>= 1;- x *= x;- }- return res;- }|]-- mkSExt from_t to_t = macro name [C.cexp|($ty:to_ct)(($ty:from_ct)x)|]- where- name = "sext_" ++ pretty from_t ++ "_" ++ pretty to_t- from_ct = intTypeToCType from_t- to_ct = intTypeToCType to_t-- mkZExt from_t to_t = macro name [C.cexp|($ty:to_ct)(($ty:from_ct)x)|]- where- name = "zext_" ++ pretty from_t ++ "_" ++ pretty to_t- from_ct = uintTypeToCType from_t- to_ct = intTypeToCType to_t-- mkBToI to_t =- [C.cedecl|static inline $ty:to_ct- $id:name($ty:from_ct x) { return x; } |]- where- name = "btoi_bool_" ++ pretty to_t- from_ct = primTypeToCType Bool- to_ct = intTypeToCType to_t-- mkIToB from_t =- [C.cedecl|static inline $ty:to_ct- $id:name($ty:from_ct x) { return x; } |]- where- name = "itob_" ++ pretty from_t ++ "_bool"- to_ct = primTypeToCType Bool- from_ct = intTypeToCType from_t-- simpleUintOp s e t =- [C.cedecl|static inline $ty:ct $id:(taggedI s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = uintTypeToCType t- simpleIntOp s e t =- [C.cedecl|static inline $ty:ct $id:(taggedI s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = intTypeToCType t- intCmpOp s e t =- [C.cedecl|static inline typename bool $id:(taggedI s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = intTypeToCType t- uintCmpOp s e t =- [C.cedecl|static inline typename bool $id:(taggedI s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = uintTypeToCType t--cIntPrimFuns :: [C.Definition]-cIntPrimFuns =- [C.cunit|-$esc:("#if defined(__OPENCL_VERSION__)")- static typename int32_t $id:(funName' "popc8") (typename int8_t x) {- return popcount(x);- }- static typename int32_t $id:(funName' "popc16") (typename int16_t x) {- return popcount(x);- }- static typename int32_t $id:(funName' "popc32") (typename int32_t x) {- return popcount(x);- }- static typename int32_t $id:(funName' "popc64") (typename int64_t x) {- return popcount(x);- }-$esc:("#elif defined(__CUDA_ARCH__)")- static typename int32_t $id:(funName' "popc8") (typename int8_t x) {- return __popc(zext_i8_i32(x));- }- static typename int32_t $id:(funName' "popc16") (typename int16_t x) {- return __popc(zext_i16_i32(x));- }- static typename int32_t $id:(funName' "popc32") (typename int32_t x) {- return __popc(x);- }- static typename int32_t $id:(funName' "popc64") (typename int64_t x) {- return __popcll(x);- }-$esc:("#else")- static typename int32_t $id:(funName' "popc8") (typename int8_t x) {- int c = 0;- for (; x; ++c) {- x &= x - 1;- }- return c;- }- static typename int32_t $id:(funName' "popc16") (typename int16_t x) {- int c = 0;- for (; x; ++c) {- x &= x - 1;- }- return c;- }- static typename int32_t $id:(funName' "popc32") (typename int32_t x) {- int c = 0;- for (; x; ++c) {- x &= x - 1;- }- return c;- }- static typename int32_t $id:(funName' "popc64") (typename int64_t x) {- int c = 0;- for (; x; ++c) {- x &= x - 1;- }- return c;- }-$esc:("#endif")--$esc:("#if defined(__OPENCL_VERSION__)")- static typename uint8_t $id:(funName' "mul_hi8") (typename uint8_t a, typename uint8_t b) {- return mul_hi(a, b);- }- static typename uint16_t $id:(funName' "mul_hi16") (typename uint16_t a, typename uint16_t b) {- return mul_hi(a, b);- }- static typename uint32_t $id:(funName' "mul_hi32") (typename uint32_t a, typename uint32_t b) {- return mul_hi(a, b);- }- static typename uint64_t $id:(funName' "mul_hi64") (typename uint64_t a, typename uint64_t b) {- return mul_hi(a, b);- }-$esc:("#elif defined(__CUDA_ARCH__)")- static typename uint8_t $id:(funName' "mul_hi8") (typename uint8_t a, typename uint8_t b) {- typename uint16_t aa = a;- typename uint16_t bb = b;- return (aa * bb) >> 8;- }- static typename uint16_t $id:(funName' "mul_hi16") (typename uint16_t a, typename uint16_t b) {- typename uint32_t aa = a;- typename uint32_t bb = b;- return (aa * bb) >> 16;- }- static typename uint32_t $id:(funName' "mul_hi32") (typename uint32_t a, typename uint32_t b) {- return mulhi(a, b);- }- static typename uint64_t $id:(funName' "mul_hi64") (typename uint64_t a, typename uint64_t b) {- return mul64hi(a, b);- }-$esc:("#else")- static typename uint8_t $id:(funName' "mul_hi8") (typename uint8_t a, typename uint8_t b) {- typename uint16_t aa = a;- typename uint16_t bb = b;- return (aa * bb) >> 8;- }- static typename uint16_t $id:(funName' "mul_hi16") (typename uint16_t a, typename uint16_t b) {- typename uint32_t aa = a;- typename uint32_t bb = b;- return (aa * bb) >> 16;- }- static typename uint32_t $id:(funName' "mul_hi32") (typename uint32_t a, typename uint32_t b) {- typename uint64_t aa = a;- typename uint64_t bb = b;- return (aa * bb) >> 32;- }- static typename uint64_t $id:(funName' "mul_hi64") (typename uint64_t a, typename uint64_t b) {- typename __uint128_t aa = a;- typename __uint128_t bb = b;- return (aa * bb) >> 64;- }-$esc:("#endif")--$esc:("#if defined(__OPENCL_VERSION__)")- static typename uint8_t $id:(funName' "mad_hi8") (typename uint8_t a, typename uint8_t b, typename uint8_t c) {- return mad_hi(a, b, c);- }- static typename uint16_t $id:(funName' "mad_hi16") (typename uint16_t a, typename uint16_t b, typename uint16_t c) {- return mad_hi(a, b, c);- }- static typename uint32_t $id:(funName' "mad_hi32") (typename uint32_t a, typename uint32_t b, typename uint32_t c) {- return mad_hi(a, b, c);- }- static typename uint64_t $id:(funName' "mad_hi64") (typename uint64_t a, typename uint64_t b, typename uint64_t c) {- return mad_hi(a, b, c);- }-$esc:("#else")- static typename uint8_t $id:(funName' "mad_hi8") (typename uint8_t a, typename uint8_t b, typename uint8_t c) {- return futrts_mul_hi8(a, b) + c;- }- static typename uint16_t $id:(funName' "mad_hi16") (typename uint16_t a, typename uint16_t b, typename uint16_t c) {- return futrts_mul_hi16(a, b) + c;- }- static typename uint32_t $id:(funName' "mad_hi32") (typename uint32_t a, typename uint32_t b, typename uint32_t c) {- return futrts_mul_hi32(a, b) + c;- }- static typename uint64_t $id:(funName' "mad_hi64") (typename uint64_t a, typename uint64_t b, typename uint64_t c) {- return futrts_mul_hi64(a, b) + c;- }-$esc:("#endif")---$esc:("#if defined(__OPENCL_VERSION__)")- static typename int32_t $id:(funName' "clz8") (typename int8_t x) {- return clz(x);- }- static typename int32_t $id:(funName' "clz16") (typename int16_t x) {- return clz(x);- }- static typename int32_t $id:(funName' "clz32") (typename int32_t x) {- return clz(x);- }- static typename int32_t $id:(funName' "clz64") (typename int64_t x) {- return clz(x);- }-$esc:("#elif defined(__CUDA_ARCH__)")- static typename int32_t $id:(funName' "clz8") (typename int8_t x) {- return __clz(zext_i8_i32(x))-24;- }- static typename int32_t $id:(funName' "clz16") (typename int16_t x) {- return __clz(zext_i16_i32(x))-16;- }- static typename int32_t $id:(funName' "clz32") (typename int32_t x) {- return __clz(x);- }- static typename int32_t $id:(funName' "clz64") (typename int64_t x) {- return __clzll(x);- }-$esc:("#else")- static typename int32_t $id:(funName' "clz8") (typename int8_t x) {- int n = 0;- int bits = sizeof(x) * 8;- for (int i = 0; i < bits; i++) {- if (x < 0) break;- n++;- x <<= 1;- }- return n;- }- static typename int32_t $id:(funName' "clz16") (typename int16_t x) {- int n = 0;- int bits = sizeof(x) * 8;- for (int i = 0; i < bits; i++) {- if (x < 0) break;- n++;- x <<= 1;- }- return n;- }- static typename int32_t $id:(funName' "clz32") (typename int32_t x) {- int n = 0;- int bits = sizeof(x) * 8;- for (int i = 0; i < bits; i++) {- if (x < 0) break;- n++;- x <<= 1;- }- return n;- }- static typename int32_t $id:(funName' "clz64") (typename int64_t x) {- int n = 0;- int bits = sizeof(x) * 8;- for (int i = 0; i < bits; i++) {- if (x < 0) break;- n++;- x <<= 1;- }- return n;- }-$esc:("#endif")--$esc:("#if defined(__OPENCL_VERSION__)")- // OpenCL has ctz, but only from version 2.0, which we cannot assume we are using.- static typename int32_t $id:(funName' "ctz8") (typename int8_t x) {- int i = 0;- for (; i < 8 && (x&1)==0; i++, x>>=1);- return i;- }- static typename int32_t $id:(funName' "ctz16") (typename int16_t x) {- int i = 0;- for (; i < 16 && (x&1)==0; i++, x>>=1);- return i;- }- static typename int32_t $id:(funName' "ctz32") (typename int32_t x) {- int i = 0;- for (; i < 32 && (x&1)==0; i++, x>>=1);- return i;- }- static typename int32_t $id:(funName' "ctz64") (typename int64_t x) {- int i = 0;- for (; i < 64 && (x&1)==0; i++, x>>=1);- return i;- }-$esc:("#elif defined(__CUDA_ARCH__)")- static typename int32_t $id:(funName' "ctz8") (typename int8_t x) {- int y = __ffs(x);- return y == 0 ? 8 : y-1;- }- static typename int32_t $id:(funName' "ctz16") (typename int16_t x) {- int y = __ffs(x);- return y == 0 ? 16 : y-1;- }- static typename int32_t $id:(funName' "ctz32") (typename int32_t x) {- int y = __ffs(x);- return y == 0 ? 32 : y-1;- }- static typename int32_t $id:(funName' "ctz64") (typename int64_t x) {- int y = __ffsll(x);- return y == 0 ? 64 : y-1;- }-$esc:("#else")-// FIXME: assumes GCC or clang.- static typename int32_t $id:(funName' "ctz8") (typename int8_t x) {- return x == 0 ? 8 : __builtin_ctz((typename uint32_t)x);- }- static typename int32_t $id:(funName' "ctz16") (typename int16_t x) {- return x == 0 ? 16 : __builtin_ctz((typename uint32_t)x);- }- static typename int32_t $id:(funName' "ctz32") (typename int32_t x) {- return x == 0 ? 32 : __builtin_ctz(x);- }- static typename int32_t $id:(funName' "ctz64") (typename int64_t x) {- return x == 0 ? 64 : __builtin_ctzll(x);- }-$esc:("#endif")- |]--cFloat32Ops :: [C.Definition]-cFloat64Ops :: [C.Definition]-cFloatConvOps :: [C.Definition]-(cFloat32Ops, cFloat64Ops, cFloatConvOps) =- ( map ($ Float32) mkOps,- map ($ Float64) mkOps,- [ mkFPConvFF "fpconv" from to- | from <- [minBound .. maxBound],- to <- [minBound .. maxBound]- ]- )- where- taggedF s Float32 = s ++ "32"- taggedF s Float64 = s ++ "64"- convOp s from to = s ++ "_" ++ pretty from ++ "_" ++ pretty to-- mkOps =- [mkFDiv, mkFAdd, mkFSub, mkFMul, mkFMin, mkFMax, mkPow, mkCmpLt, mkCmpLe]- ++ map (mkFPConvIF "sitofp") [minBound .. maxBound]- ++ map (mkFPConvUF "uitofp") [minBound .. maxBound]- ++ map (flip $ mkFPConvFI "fptosi") [minBound .. maxBound]- ++ map (flip $ mkFPConvFU "fptoui") [minBound .. maxBound]-- mkFDiv = simpleFloatOp "fdiv" [C.cexp|x / y|]- mkFAdd = simpleFloatOp "fadd" [C.cexp|x + y|]- mkFSub = simpleFloatOp "fsub" [C.cexp|x - y|]- mkFMul = simpleFloatOp "fmul" [C.cexp|x * y|]- mkFMin = simpleFloatOp "fmin" [C.cexp|fmin(x, y)|]- mkFMax = simpleFloatOp "fmax" [C.cexp|fmax(x, y)|]- mkCmpLt = floatCmpOp "cmplt" [C.cexp|x < y|]- mkCmpLe = floatCmpOp "cmple" [C.cexp|x <= y|]-- mkPow Float32 =- [C.cedecl|static inline float fpow32(float x, float y) { return pow(x, y); }|]- mkPow Float64 =- [C.cedecl|static inline double fpow64(double x, double y) { return pow(x, y); }|]-- mkFPConv from_f to_f s from_t to_t =- [C.cedecl|static inline $ty:to_ct- $id:(convOp s from_t to_t)($ty:from_ct x) { return ($ty:to_ct)x;} |]- where- from_ct = from_f from_t- to_ct = to_f to_t-- mkFPConvFF = mkFPConv floatTypeToCType floatTypeToCType- mkFPConvFI = mkFPConv floatTypeToCType intTypeToCType- mkFPConvIF = mkFPConv intTypeToCType floatTypeToCType- mkFPConvFU = mkFPConv floatTypeToCType uintTypeToCType- mkFPConvUF = mkFPConv uintTypeToCType floatTypeToCType-- simpleFloatOp s e t =- [C.cedecl|static inline $ty:ct $id:(taggedF s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = floatTypeToCType t- floatCmpOp s e t =- [C.cedecl|static inline typename bool $id:(taggedF s t)($ty:ct x, $ty:ct y) { return $exp:e; }|]- where- ct = floatTypeToCType t--cFloat32Funs :: [C.Definition]-cFloat32Funs =- [C.cunit|- static inline typename bool $id:(funName' "isnan32")(float x) {- return isnan(x);- }-- static inline typename bool $id:(funName' "isinf32")(float x) {- return isinf(x);- }--$esc:("#ifdef __OPENCL_VERSION__")- static inline float $id:(funName' "log32")(float x) {- return log(x);- }-- static inline float $id:(funName' "log2_32")(float x) {- return log2(x);- }-- static inline float $id:(funName' "log10_32")(float x) {- return log10(x);- }-- static inline float $id:(funName' "sqrt32")(float x) {- return sqrt(x);- }-- static inline float $id:(funName' "exp32")(float x) {- return exp(x);- }-- static inline float $id:(funName' "cos32")(float x) {- return cos(x);- }-- static inline float $id:(funName' "sin32")(float x) {- return sin(x);- }-- static inline float $id:(funName' "tan32")(float x) {- return tan(x);- }-- static inline float $id:(funName' "acos32")(float x) {- return acos(x);- }-- static inline float $id:(funName' "asin32")(float x) {- return asin(x);- }-- static inline float $id:(funName' "atan32")(float x) {- return atan(x);- }-- static inline float $id:(funName' "cosh32")(float x) {- return cosh(x);- }-- static inline float $id:(funName' "sinh32")(float x) {- return sinh(x);- }-- static inline float $id:(funName' "tanh32")(float x) {- return tanh(x);- }-- static inline float $id:(funName' "acosh32")(float x) {- return acosh(x);- }-- static inline float $id:(funName' "asinh32")(float x) {- return asinh(x);- }-- static inline float $id:(funName' "atanh32")(float x) {- return atanh(x);- }-- static inline float $id:(funName' "atan2_32")(float x, float y) {- return atan2(x,y);- }-- static inline float $id:(funName' "hypot32")(float x, float y) {- return hypot(x,y);- }-- static inline float $id:(funName' "gamma32")(float x) {- return tgamma(x);- }-- static inline float $id:(funName' "lgamma32")(float x) {- return lgamma(x);- }-- static inline float fmod32(float x, float y) {- return fmod(x, y);- }- static inline float $id:(funName' "round32")(float x) {- return rint(x);- }- static inline float $id:(funName' "floor32")(float x) {- return floor(x);- }- static inline float $id:(funName' "ceil32")(float x) {- return ceil(x);- }- static inline float $id:(funName' "lerp32")(float v0, float v1, float t) {- return mix(v0, v1, t);- }- static inline float $id:(funName' "mad32")(float a, float b, float c) {- return mad(a,b,c);- }- static inline float $id:(funName' "fma32")(float a, float b, float c) {- return fma(a,b,c);- }-$esc:("#else")- static inline float $id:(funName' "log32")(float x) {- return logf(x);- }-- static inline float $id:(funName' "log2_32")(float x) {- return log2f(x);- }-- static inline float $id:(funName' "log10_32")(float x) {- return log10f(x);- }-- static inline float $id:(funName' "sqrt32")(float x) {- return sqrtf(x);- }-- static inline float $id:(funName' "exp32")(float x) {- return expf(x);- }-- static inline float $id:(funName' "cos32")(float x) {- return cosf(x);- }-- static inline float $id:(funName' "sin32")(float x) {- return sinf(x);- }-- static inline float $id:(funName' "tan32")(float x) {- return tanf(x);- }-- static inline float $id:(funName' "acos32")(float x) {- return acosf(x);- }-- static inline float $id:(funName' "asin32")(float x) {- return asinf(x);- }-- static inline float $id:(funName' "atan32")(float x) {- return atanf(x);- }-- static inline float $id:(funName' "cosh32")(float x) {- return coshf(x);- }-- static inline float $id:(funName' "sinh32")(float x) {- return sinhf(x);- }-- static inline float $id:(funName' "tanh32")(float x) {- return tanhf(x);- }-- static inline float $id:(funName' "acosh32")(float x) {- return acoshf(x);- }-- static inline float $id:(funName' "asinh32")(float x) {- return asinhf(x);- }-- static inline float $id:(funName' "atanh32")(float x) {- return atanhf(x);- }-- static inline float $id:(funName' "atan2_32")(float x, float y) {- return atan2f(x,y);- }-- static inline float $id:(funName' "hypot32")(float x, float y) {- return hypotf(x,y);- }-- static inline float $id:(funName' "gamma32")(float x) {- return tgammaf(x);- }-- static inline float $id:(funName' "lgamma32")(float x) {- return lgammaf(x);- }-- static inline float fmod32(float x, float y) {- return fmodf(x, y);- }- static inline float $id:(funName' "round32")(float x) {- return rintf(x);- }- static inline float $id:(funName' "floor32")(float x) {- return floorf(x);- }- static inline float $id:(funName' "ceil32")(float x) {- return ceilf(x);- }- static inline float $id:(funName' "lerp32")(float v0, float v1, float t) {- return v0 + (v1-v0)*t;- }- static inline float $id:(funName' "mad32")(float a, float b, float c) {- return a*b+c;- }- static inline float $id:(funName' "fma32")(float a, float b, float c) {- return fmaf(a,b,c);- }-$esc:("#endif")- static inline typename int32_t $id:(funName' "to_bits32")(float x) {- union {- float f;- typename int32_t t;- } p;- p.f = x;- return p.t;- }-- static inline float $id:(funName' "from_bits32")(typename int32_t x) {- union {- typename int32_t f;- float t;- } p;- p.f = x;- return p.t;- }-- static inline float fsignum32(float x) {- return $id:(funName' "isnan32")(x) ? x : ((x > 0) - (x < 0));- }-|]--cFloat64Funs :: [C.Definition]-cFloat64Funs =- [C.cunit|- static inline double $id:(funName' "log64")(double x) {- return log(x);- }-- static inline double $id:(funName' "log2_64")(double x) {- return log2(x);- }-- static inline double $id:(funName' "log10_64")(double x) {- return log10(x);- }-- static inline double $id:(funName' "sqrt64")(double x) {- return sqrt(x);- }-- static inline double $id:(funName' "exp64")(double x) {- return exp(x);- }-- static inline double $id:(funName' "cos64")(double x) {- return cos(x);- }-- static inline double $id:(funName' "sin64")(double x) {- return sin(x);- }-- static inline double $id:(funName' "tan64")(double x) {- return tan(x);- }-- static inline double $id:(funName' "acos64")(double x) {- return acos(x);- }-- static inline double $id:(funName' "asin64")(double x) {- return asin(x);- }-- static inline double $id:(funName' "atan64")(double x) {- return atan(x);- }-- static inline double $id:(funName' "cosh64")(double x) {- return cosh(x);- }-- static inline double $id:(funName' "sinh64")(double x) {- return sinh(x);- }-- static inline double $id:(funName' "tanh64")(double x) {- return tanh(x);- }-- static inline double $id:(funName' "acosh64")(double x) {- return acosh(x);- }-- static inline double $id:(funName' "asinh64")(double x) {- return asinh(x);- }-- static inline double $id:(funName' "atanh64")(double x) {- return atanh(x);- }-- static inline double $id:(funName' "atan2_64")(double x, double y) {- return atan2(x,y);- }-- static inline double $id:(funName' "hypot64")(double x, double y) {- return hypot(x,y);- }-- static inline double $id:(funName' "gamma64")(double x) {- return tgamma(x);- }-- static inline double $id:(funName' "lgamma64")(double x) {- return lgamma(x);- }-- static inline double $id:(funName' "fma64")(double a, double b, double c) {- return fma(a,b,c);- }-- static inline double $id:(funName' "round64")(double x) {- return rint(x);- }-- static inline double $id:(funName' "ceil64")(double x) {- return ceil(x);- }-- static inline double $id:(funName' "floor64")(double x) {- return floor(x);- }-- static inline typename bool $id:(funName' "isnan64")(double x) {- return isnan(x);- }-- static inline typename bool $id:(funName' "isinf64")(double x) {- return isinf(x);- }-- static inline typename int64_t $id:(funName' "to_bits64")(double x) {- union {- double f;- typename int64_t t;- } p;- p.f = x;- return p.t;- }-- static inline double $id:(funName' "from_bits64")(typename int64_t x) {- union {- typename int64_t f;- double t;- } p;- p.f = x;- return p.t;- }-- static inline double fmod64(double x, double y) {- return fmod(x, y);- }-- static inline double fsignum64(double x) {- return $id:(funName' "isnan64")(x) ? x : ((x > 0) - (x < 0));- }--$esc:("#ifdef __OPENCL_VERSION__")- static inline double $id:(funName' "lerp64")(double v0, double v1, double t) {- return mix(v0, v1, t);- }- static inline double $id:(funName' "mad64")(double a, double b, double c) {- return mad(a,b,c);- }-$esc:("#else")- static inline double $id:(funName' "lerp64")(double v0, double v1, double t) {- return v0 + (v1-v0)*t;- }- static inline double $id:(funName' "mad64")(double a, double b, double c) {- return a*b+c;- }-$esc:("#endif")-|]+-- | Implementations of scalar operations.+cScalarDefs :: T.Text+cScalarDefs = scalarH <> scalarF16H storageSize :: PrimType -> Int -> C.Exp -> C.Exp storageSize pt rank shape =@@ -1094,6 +234,7 @@ case (sign, pt) of (_, Bool) -> "bool" (_, Unit) -> "bool"+ (_, FloatType Float16) -> " f16" (_, FloatType Float32) -> " f32" (_, FloatType Float64) -> " f64" (TypeDirect, IntType Int8) -> " i8"
src/Futhark/CodeGen/ImpCode.hs view
@@ -70,7 +70,7 @@ import Futhark.IR.Pretty () import Futhark.IR.Primitive import Futhark.IR.Prop.Names-import Futhark.IR.Syntax+import Futhark.IR.Syntax.Core ( ErrorMsg (..), ErrorMsgPart (..), Space (..),@@ -105,6 +105,9 @@ } deriving (Show) +instance Functor Definitions where+ fmap f (Definitions consts funs) = Definitions (fmap f consts) (fmap f funs)+ -- | A collection of imperative functions. newtype Functions a = Functions [(Name, Function a)] deriving (Show)@@ -125,6 +128,9 @@ } deriving (Show) +instance Functor Constants where+ fmap f (Constants params code) = Constants params (fmap f code)+ -- | Since the core language does not care for signedness, but the -- source language does, entry point input/output information has -- metadata for integer types (and arrays containing these) that@@ -264,6 +270,9 @@ -- debugging. Code generators are free to ignore this -- statement. DebugPrint String (Maybe Exp)+ | -- | Log the given message, *without* a trailing linebreak (unless+ -- part of the mssage).+ TracePrint (ErrorMsg Exp) | -- | Perform an extensible operation. Op a deriving (Show)@@ -517,6 +526,8 @@ text "debug" <+> parens (commasep [text (show desc), ppr e]) ppr (DebugPrint desc Nothing) = text "debug" <+> parens (text (show desc))+ ppr (TracePrint msg) =+ text "trace" <+> parens (ppr msg) instance Pretty Arg where ppr (MemArg m) = ppr m@@ -599,6 +610,8 @@ Comment s <$> traverse f code traverse _ (DebugPrint s v) = pure $ DebugPrint s v+ traverse _ (TracePrint msg) =+ pure $ TracePrint msg -- | The names declared with 'DeclareMem', 'DeclareScalar', and -- 'DeclareArray' in the given code.@@ -670,6 +683,8 @@ freeIn' code freeIn' (DebugPrint _ v) = maybe mempty freeIn' v+ freeIn' (TracePrint msg) =+ foldMap freeIn' msg instance FreeIn ExpLeaf where freeIn' (Index v e _ _ _) = freeIn' v <> freeIn' e
src/Futhark/CodeGen/ImpCode/OpenCL.hs view
@@ -24,6 +24,7 @@ where import qualified Data.Map as M+import qualified Data.Text as T import Futhark.CodeGen.ImpCode hiding (Code, Function) import qualified Futhark.CodeGen.ImpCode as Imp import Futhark.IR.GPU.Sizes@@ -31,9 +32,9 @@ -- | An program calling OpenCL kernels. data Program = Program- { openClProgram :: String,+ { openClProgram :: T.Text, -- | Must be prepended to the program.- openClPrelude :: String,+ openClPrelude :: T.Text, openClKernelNames :: M.Map KernelName KernelSafety, -- | So we can detect whether the device is capable. openClUsedTypes :: [PrimType],
src/Futhark/CodeGen/ImpGen.hs view
@@ -21,7 +21,8 @@ AllocCompiler, Operations (..), defaultOperations,- MemLocation (..),+ MemLoc (..),+ sliceMemLoc, MemEntry (..), ScalarEntry (..), @@ -92,6 +93,7 @@ dPrimV, dPrimVE, dIndexSpace,+ dIndexSpace', sFor, sWhile, sComment,@@ -125,7 +127,7 @@ import Data.Bifunctor (first) import qualified Data.DList as DL import Data.Either-import Data.List (find, genericLength, sortOn)+import Data.List (find) import qualified Data.Map.Strict as M import Data.Maybe import qualified Data.Set as S@@ -151,20 +153,18 @@ import Prelude hiding (quot) -- | How to compile an t'Op'.-type OpCompiler rep r op = Pattern rep -> Op rep -> ImpM rep r op ()+type OpCompiler rep r op = Pat rep -> Op rep -> ImpM rep r op () -- | How to compile some 'Stms'. type StmsCompiler rep r op = Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op () -- | How to compile an 'Exp'.-type ExpCompiler rep r op = Pattern rep -> Exp rep -> ImpM rep r op ()+type ExpCompiler rep r op = Pat rep -> Exp rep -> ImpM rep r op () type CopyCompiler rep r op = PrimType ->- MemLocation ->- Slice (Imp.TExp Int64) ->- MemLocation ->- Slice (Imp.TExp Int64) ->+ MemLoc ->+ MemLoc -> ImpM rep r op () -- | An alternate way of compiling an allocation.@@ -181,7 +181,7 @@ -- | An operations set for which the expression compiler always -- returns 'defCompileExp'. defaultOperations ::- (Mem rep, FreeIn op) =>+ (Mem rep inner, FreeIn op) => OpCompiler rep r op -> Operations rep r op defaultOperations opc =@@ -194,21 +194,29 @@ } -- | When an array is dared, this is where it is stored.-data MemLocation = MemLocation- { memLocationName :: VName,- memLocationShape :: [Imp.DimSize],- memLocationIxFun :: IxFun.IxFun (Imp.TExp Int64)+data MemLoc = MemLoc+ { memLocName :: VName,+ memLocShape :: [Imp.DimSize],+ memLocIxFun :: IxFun.IxFun (Imp.TExp Int64) } deriving (Eq, Show) +sliceMemLoc :: MemLoc -> Slice (Imp.TExp Int64) -> MemLoc+sliceMemLoc (MemLoc mem shape ixfun) slice =+ MemLoc mem shape $ IxFun.slice ixfun slice++flatSliceMemLoc :: MemLoc -> FlatSlice (Imp.TExp Int64) -> MemLoc+flatSliceMemLoc (MemLoc mem shape ixfun) slice =+ MemLoc mem shape $ IxFun.flatSlice ixfun slice+ data ArrayEntry = ArrayEntry- { entryArrayLocation :: MemLocation,+ { entryArrayLoc :: MemLoc, entryArrayElemType :: PrimType } deriving (Show) entryArrayShape :: ArrayEntry -> [Imp.DimSize]-entryArrayShape = memLocationShape . entryArrayLocation+entryArrayShape = memLocShape . entryArrayLoc newtype MemEntry = MemEntry {entryMemSpace :: Imp.Space} deriving (Show)@@ -226,25 +234,14 @@ | AccVar (Maybe (Exp rep)) (VName, Shape, [Type]) deriving (Show) --- | When compiling an expression, this is a description of where the--- result should end up. The integer is a reference to the construct--- that gave rise to this destination (for patterns, this will be the--- tag of the first name in the pattern). This can be used to make--- the generated code easier to relate to the original code.-data Destination = Destination- { destinationTag :: Maybe Int,- valueDestinations :: [ValueDestination]- }- deriving (Show)- data ValueDestination = ScalarDestination VName | MemoryDestination VName- | -- | The 'MemLocation' is 'Just' if a copy if+ | -- | The 'MemLoc' is 'Just' if a copy if -- required. If it is 'Nothing', then a -- copy/assignment of a memory block somewhere -- takes care of this array.- ArrayDestination (Maybe MemLocation)+ ArrayDestination (Maybe MemLoc) deriving (Show) data Env rep r op = Env@@ -425,16 +422,16 @@ let Imp.Functions fs = stateFunctions s in isJust $ lookup fname fs -constsVTable :: Mem rep => Stms rep -> VTable rep+constsVTable :: Mem rep inner => Stms rep -> VTable rep constsVTable = foldMap stmVtable where stmVtable (Let pat _ e) =- foldMap (peVtable e) $ patternElements pat+ foldMap (peVtable e) $ patElems pat peVtable e (PatElem name dec) =- M.singleton name $ memBoundToVarEntry (Just e) dec+ M.singleton name $ memBoundToVarEntry (Just e) $ letDecMem dec compileProg ::- (Mem rep, FreeIn op, MonadFreshNames m) =>+ (Mem rep inner, FreeIn op, MonadFreshNames m) => r -> Operations rep r op -> Imp.Space ->@@ -496,7 +493,7 @@ (mempty, s) compileInParam ::- Mem rep =>+ Mem rep inner => FParam rep -> ImpM rep r op (Either Imp.Param ArrayDecl) compileInParam fparam = case paramDec fparam of@@ -508,16 +505,16 @@ return $ Right $ ArrayDecl name bt $- MemLocation mem (shapeDims shape) $ fmap (fmap Imp.ScalarVar) ixfun+ MemLoc mem (shapeDims shape) $ fmap (fmap Imp.ScalarVar) ixfun MemAcc {} -> error "Functions may not have accumulator parameters." where name = paramName fparam -data ArrayDecl = ArrayDecl VName PrimType MemLocation+data ArrayDecl = ArrayDecl VName PrimType MemLoc compileInParams ::- Mem rep =>+ Mem rep inner => [FParam rep] -> [EntryPointType] -> ImpM rep r op ([Imp.Param], [ArrayDecl], [Imp.ExternalValue])@@ -540,7 +537,7 @@ mkValueDesc fparam signedness = case (findArray $ paramName fparam, paramType fparam) of- (Just (ArrayDecl _ bt (MemLocation mem shape _)), _) -> do+ (Just (ArrayDecl _ bt (MemLoc mem shape _)), _) -> do memspace <- findMemInfo mem Just $ Imp.ArrayValue mem memspace bt signedness shape (_, Prim bt) ->@@ -567,87 +564,81 @@ where isArrayDecl x (ArrayDecl y _ _) = x == y -compileOutParams ::- Mem rep =>+compileOutParam ::+ FunReturns -> ImpM rep r op (Maybe Imp.Param, ValueDestination)+compileOutParam (MemPrim t) = do+ name <- newVName "prim_out"+ pure (Just $ Imp.ScalarParam name t, ScalarDestination name)+compileOutParam (MemMem space) = do+ name <- newVName "mem_out"+ pure (Just $ Imp.MemParam name space, MemoryDestination name)+compileOutParam MemArray {} =+ pure (Nothing, ArrayDestination Nothing)+compileOutParam MemAcc {} =+ error "Functions may not return accumulators."++compileExternalValues ::+ Mem rep inner => [RetType rep] -> [EntryPointType] ->- ImpM rep r op ([Imp.ExternalValue], [Imp.Param], Destination)-compileOutParams orig_rts orig_epts = do- ((extvs, dests), (outparams, ctx_dests)) <-- runWriterT $ evalStateT (mkExts orig_epts orig_rts) (M.empty, M.empty)- let ctx_dests' = map snd $ sortOn fst $ M.toList ctx_dests- return (extvs, outparams, Destination Nothing $ ctx_dests' <> dests)- where- imp = lift . lift+ [Maybe Imp.Param] ->+ ImpM rep r op [Imp.ExternalValue]+compileExternalValues orig_rts orig_epts maybe_params = do+ let (ctx_rts, val_rts) =+ splitAt (length orig_rts - sum (map entryPointSize orig_epts)) orig_rts - mkExts (TypeOpaque u desc n : epts) rts = do- let (rts', rest) = splitAt n rts- (evs, dests) <- unzip <$> zipWithM mkParam rts' (repeat Imp.TypeDirect)- (more_values, more_dests) <- mkExts epts rest- return- ( Imp.OpaqueValue u desc evs : more_values,- dests ++ more_dests- )- mkExts (TypeUnsigned u : epts) (rt : rts) = do- (ev, dest) <- mkParam rt Imp.TypeUnsigned- (more_values, more_dests) <- mkExts epts rts- return- ( Imp.TransparentValue u ev : more_values,- dest : more_dests- )- mkExts (TypeDirect u : epts) (rt : rts) = do- (ev, dest) <- mkParam rt Imp.TypeDirect- (more_values, more_dests) <- mkExts epts rts- return- ( Imp.TransparentValue u ev : more_values,- dest : more_dests- )- mkExts _ _ = return ([], [])+ let nthOut i = case maybeNth i maybe_params of+ Just (Just p) -> Imp.paramName p+ Just Nothing -> error $ "Output " ++ show i ++ " not a param."+ Nothing -> error $ "Param " ++ show i ++ " does not exist." - mkParam MemMem {} _ =- error "Functions may not explicitly return memory blocks."- mkParam MemAcc {} _ =- error "Functions may not return accumulators."- mkParam (MemPrim t) ept = do- out <- imp $ newVName "scalar_out"- tell ([Imp.ScalarParam out t], mempty)- return (Imp.ScalarValue t ept out, ScalarDestination out)- mkParam (MemArray t shape _ dec) ept = do- space <- asks envDefaultSpace- memout <- case dec of- ReturnsNewBlock _ x _ixfun -> do- memout <- imp $ newVName "out_mem"- tell- ( [Imp.MemParam memout space],- M.singleton x $ MemoryDestination memout- )- return memout- ReturnsInBlock memout _ ->- return memout- resultshape <- mapM inspectExtSize $ shapeDims shape- return- ( Imp.ArrayValue memout space t ept resultshape,- ArrayDestination Nothing- )+ mkValueDesc _ signedness (MemArray t shape _ ret) = do+ (mem, space) <-+ case ret of+ ReturnsNewBlock space j _ixfun ->+ pure (nthOut j, space)+ ReturnsInBlock mem _ixfun -> do+ space <- entryMemSpace <$> lookupMemory mem+ pure (mem, space)+ pure $ Imp.ArrayValue mem space t signedness $ map f $ shapeDims shape+ where+ f (Free v) = v+ f (Ext i) = Var $ nthOut i+ mkValueDesc i signedness (MemPrim bt) =+ pure $ Imp.ScalarValue bt signedness $ nthOut i+ mkValueDesc _ _ MemAcc {} =+ error "mkValueDesc: unexpected MemAcc output."+ mkValueDesc _ _ MemMem {} =+ error "mkValueDesc: unexpected MemMem output." - inspectExtSize (Ext x) = do- (memseen, arrseen) <- get- case M.lookup x arrseen of- Nothing -> do- out <- imp $ newVName "out_arrsize"- tell- ( [Imp.ScalarParam out int64],- M.singleton x $ ScalarDestination out- )- put (memseen, M.insert x out arrseen)- return $ Var out- Just out ->- return $ Var out- inspectExtSize (Free se) =- return se+ mkExts i (TypeOpaque u desc n : epts) rets = do+ let (rets', rest) = splitAt n rets+ vds <- zipWithM (`mkValueDesc` Imp.TypeDirect) [i ..] rets'+ (Imp.OpaqueValue u desc vds :) <$> mkExts (i + n) epts rest+ mkExts i (TypeUnsigned u : epts) (ret : rets) = do+ vd <- mkValueDesc i Imp.TypeUnsigned ret+ (Imp.TransparentValue u vd :) <$> mkExts (i + 1) epts rets+ mkExts i (TypeDirect u : epts) (ret : rets) = do+ vd <- mkValueDesc i Imp.TypeDirect ret+ (Imp.TransparentValue u vd :) <$> mkExts (i + 1) epts rets+ mkExts _ _ _ = pure [] + mkExts (length ctx_rts) orig_epts val_rts++compileOutParams ::+ Mem rep inner =>+ [RetType rep] ->+ Maybe [EntryPointType] ->+ ImpM rep r op ([Imp.ExternalValue], [Imp.Param], [ValueDestination])+compileOutParams orig_rts maybe_orig_epts = do+ (maybe_params, dests) <- unzip <$> mapM compileOutParam orig_rts+ evs <- case maybe_orig_epts of+ Just orig_epts -> compileExternalValues orig_rts orig_epts maybe_params+ Nothing -> pure []+ return (evs, catMaybes maybe_params, dests)+ compileFunDef ::- Mem rep =>+ Mem rep inner => FunDef rep -> ImpM rep r op () compileFunDef (FunDef entry _ fname rettype params body) =@@ -659,31 +650,31 @@ Nothing -> ( Nothing, replicate (length params) (TypeDirect mempty),- replicate (length rettype) (TypeDirect mempty)+ Nothing )- Just (x, y, z) -> (Just x, y, z)+ Just (x, y, z) -> (Just x, y, Just z) compile = do (inparams, arrayds, args) <- compileInParams params params_entry- (results, outparams, Destination _ dests) <- compileOutParams rettype ret_entry+ (results, outparams, dests) <- compileOutParams rettype ret_entry addFParams params addArrays arrayds let Body _ stms ses = body compileStms (freeIn ses) stms $- forM_ (zip dests ses) $ \(d, se) -> copyDWIMDest d [] se []+ forM_ (zip dests ses) $ \(d, SubExpRes _ se) -> copyDWIMDest d [] se [] return (outparams, inparams, results, args) -compileBody :: (Mem rep) => Pattern rep -> Body rep -> ImpM rep r op ()+compileBody :: Pat rep -> Body rep -> ImpM rep r op () compileBody pat (Body _ bnds ses) = do- Destination _ dests <- destinationFromPattern pat+ dests <- destinationFromPat pat compileStms (freeIn ses) bnds $- forM_ (zip dests ses) $ \(d, se) -> copyDWIMDest d [] se []+ forM_ (zip dests ses) $ \(d, SubExpRes _ se) -> copyDWIMDest d [] se [] compileBody' :: [Param dec] -> Body rep -> ImpM rep r op () compileBody' params (Body _ bnds ses) = compileStms (freeIn ses) bnds $- forM_ (zip params ses) $ \(param, se) -> copyDWIM (paramName param) [] se []+ forM_ (zip params ses) $ \(param, SubExpRes _ se) -> copyDWIM (paramName param) [] se [] compileLoopBody :: Typed dec => [Param dec] -> Body rep -> ImpM rep r op () compileLoopBody mergeparams (Body _ bnds ses) = do@@ -695,7 +686,7 @@ -- operations are all scalar operations. tmpnames <- mapM (newVName . (++ "_tmp") . baseString . paramName) mergeparams compileStms (freeIn ses) bnds $ do- copy_to_merge_params <- forM (zip3 mergeparams tmpnames ses) $ \(p, tmp, se) ->+ copy_to_merge_params <- forM (zip3 mergeparams tmpnames ses) $ \(p, tmp, SubExpRes _ se) -> case typeOf p of Prim pt -> do emit $ Imp.DeclareScalar tmp Imp.Nonvolatile pt@@ -714,7 +705,7 @@ cb alive_after_stms all_stms m defCompileStms ::- (Mem rep, FreeIn op) =>+ (Mem rep inner, FreeIn op) => Names -> Stms rep -> ImpM rep r op () ->@@ -727,7 +718,7 @@ void $ compileStms' mempty $ stmsToList all_stms where compileStms' allocs (Let pat aux e : bs) = do- dVars (Just e) (patternElements pat)+ dVars (Just e) (patElems pat) e_code <- localAttrs (stmAuxAttrs aux) $@@ -748,25 +739,25 @@ emit code return $ freeIn code <> alive_after_stms - patternAllocs = S.fromList . mapMaybe isMemPatElem . patternElements+ patternAllocs = S.fromList . mapMaybe isMemPatElem . patElems isMemPatElem pe = case patElemType pe of Mem space -> Just (patElemName pe, space) _ -> Nothing -compileExp :: Pattern rep -> Exp rep -> ImpM rep r op ()+compileExp :: Pat rep -> Exp rep -> ImpM rep r op () compileExp pat e = do ec <- asks envExpCompiler ec pat e defCompileExp ::- (Mem rep) =>- Pattern rep ->+ (Mem rep inner) =>+ Pat rep -> Exp rep -> ImpM rep r op () defCompileExp pat (If cond tbranch fbranch _) = sIf (toBoolExp cond) (compileBody pat tbranch) (compileBody pat fbranch) defCompileExp pat (Apply fname args _ _) = do- dest <- destinationFromPattern pat+ dest <- destinationFromPat pat targets <- funcallTargets dest args' <- catMaybes <$> mapM compileArg args emit $ Imp.Call targets fname args'@@ -778,16 +769,16 @@ (Var v, Mem {}) -> return $ Just $ Imp.MemArg v _ -> return Nothing defCompileExp pat (BasicOp op) = defCompileBasicOp pat op-defCompileExp pat (DoLoop ctx val form body) = do+defCompileExp pat (DoLoop merge form body) = do attrs <- askAttrs when ("unroll" `inAttrs` attrs) $ warn (noLoc :: SrcLoc) [] "#[unroll] on loop with unknown number of iterations." -- FIXME: no location.- dFParams mergepat+ dFParams params forM_ merge $ \(p, se) -> when ((== 0) $ arrayRank $ paramType p) $ copyDWIM (paramName p) [] se [] - let doBody = compileLoopBody mergepat body+ let doBody = compileLoopBody params body case form of ForLoop i _ bound loopvars -> do@@ -805,12 +796,11 @@ WhileLoop cond -> sWhile (TPrimExp $ Imp.var cond Bool) doBody - Destination _ pat_dests <- destinationFromPattern pat+ pat_dests <- destinationFromPat pat forM_ (zip pat_dests $ map (Var . paramName . fst) merge) $ \(d, r) -> copyDWIMDest d [] r [] where- merge = ctx ++ val- mergepat = map fst merge+ params = map fst merge defCompileExp pat (WithAcc inputs lam) = do dLParams $ lambdaParams lam forM_ (zip inputs $ lambdaParams lam) $ \((_, arrs, op), p) ->@@ -818,8 +808,8 @@ s {stateAccs = M.insert (paramName p) (arrs, op) $ stateAccs s} compileStms mempty (bodyStms $ lambdaBody lam) $ do let nonacc_res = drop num_accs (bodyResult (lambdaBody lam))- nonacc_pat_names = takeLast (length nonacc_res) (patternNames pat)- forM_ (zip nonacc_pat_names nonacc_res) $ \(v, se) ->+ nonacc_pat_names = takeLast (length nonacc_res) (patNames pat)+ forM_ (zip nonacc_pat_names nonacc_res) $ \(v, SubExpRes _ se) -> copyDWIM v [] se [] where num_accs = length inputs@@ -827,26 +817,50 @@ opc <- asks envOpCompiler opc pat op +tracePrim :: String -> PrimType -> SubExp -> ImpM rep r op ()+tracePrim s t se =+ emit . Imp.TracePrint $+ ErrorMsg [ErrorString (s <> ": "), ErrorVal t (toExp' t se), ErrorString "\n"]++traceArray :: String -> PrimType -> Shape -> SubExp -> ImpM rep r op ()+traceArray s t shape se = do+ emit . Imp.TracePrint $ ErrorMsg [ErrorString (s <> ": ")]+ sLoopNest shape $ \is -> do+ arr_elem <- dPrim "arr_elem" t+ copyDWIMFix (tvVar arr_elem) [] se is+ emit . Imp.TracePrint $ ErrorMsg [ErrorVal t (untyped (tvExp arr_elem)), " "]+ emit . Imp.TracePrint $ ErrorMsg ["\n"]+ defCompileBasicOp ::- Mem rep =>- Pattern rep ->+ Mem rep inner =>+ Pat rep -> BasicOp -> ImpM rep r op ()-defCompileBasicOp (Pattern _ [pe]) (SubExp se) =+defCompileBasicOp (Pat [pe]) (SubExp se) = copyDWIM (patElemName pe) [] se []-defCompileBasicOp (Pattern _ [pe]) (Opaque se) =+defCompileBasicOp (Pat [pe]) (Opaque op se) = do copyDWIM (patElemName pe) [] se []-defCompileBasicOp (Pattern _ [pe]) (UnOp op e) = do+ case op of+ OpaqueNil -> pure ()+ OpaqueTrace s -> comment ("Trace: " <> s) $ do+ se_t <- subExpType se+ case se_t of+ Prim t -> tracePrim s t se+ Array t shape _ -> traceArray s t shape se+ _ ->+ warn [mempty :: SrcLoc] mempty $+ s ++ ": cannot trace value of this (core) type: " <> pretty se_t+defCompileBasicOp (Pat [pe]) (UnOp op e) = do e' <- toExp e patElemName pe <~~ Imp.UnOpExp op e'-defCompileBasicOp (Pattern _ [pe]) (ConvOp conv e) = do+defCompileBasicOp (Pat [pe]) (ConvOp conv e) = do e' <- toExp e patElemName pe <~~ Imp.ConvOpExp conv e'-defCompileBasicOp (Pattern _ [pe]) (BinOp bop x y) = do+defCompileBasicOp (Pat [pe]) (BinOp bop x y) = do x' <- toExp x y' <- toExp y patElemName pe <~~ Imp.BinOpExp bop x' y'-defCompileBasicOp (Pattern _ [pe]) (CmpOp bop x y) = do+defCompileBasicOp (Pat [pe]) (CmpOp bop x y) = do x' <- toExp x y' <- toExp y patElemName pe <~~ Imp.CmpOpExp bop x' y'@@ -858,21 +872,35 @@ attrs <- askAttrs when (AttrComp "warn" ["safety_checks"] `inAttrs` attrs) $ uncurry warn loc "Safety check required at run-time."-defCompileBasicOp (Pattern _ [pe]) (Index src slice)+defCompileBasicOp (Pat [pe]) (Index src slice) | Just idxs <- sliceIndices slice = copyDWIM (patElemName pe) [] (Var src) $ map (DimFix . toInt64Exp) idxs defCompileBasicOp _ Index {} = return ()-defCompileBasicOp (Pattern _ [pe]) (Update _ slice se) =- sUpdate (patElemName pe) (map (fmap toInt64Exp) slice) se-defCompileBasicOp (Pattern _ [pe]) (Replicate (Shape ds) se) = do+defCompileBasicOp (Pat [pe]) (Update safety _ slice se) =+ case safety of+ Unsafe -> write+ Safe -> sWhen (inBounds slice' dims) write+ where+ slice' = fmap toInt64Exp slice+ dims = map toInt64Exp $ arrayDims $ patElemType pe+ write = sUpdate (patElemName pe) slice' se+defCompileBasicOp _ FlatIndex {} =+ pure ()+defCompileBasicOp (Pat [pe]) (FlatUpdate _ slice v) = do+ pe_loc <- entryArrayLoc <$> lookupArray (patElemName pe)+ v_loc <- entryArrayLoc <$> lookupArray v+ copy (elemType (patElemType pe)) (flatSliceMemLoc pe_loc slice') v_loc+ where+ slice' = fmap toInt64Exp slice+defCompileBasicOp (Pat [pe]) (Replicate (Shape ds) se) = do ds' <- mapM toExp ds is <- replicateM (length ds) (newVName "i") copy_elem <- collect $ copyDWIM (patElemName pe) (map (DimFix . Imp.vi64) is) se [] emit $ foldl (.) id (zipWith Imp.For is ds') copy_elem defCompileBasicOp _ Scratch {} = return ()-defCompileBasicOp (Pattern [] [pe]) (Iota n e s it) = do+defCompileBasicOp (Pat [pe]) (Iota n e s it) = do e' <- toExp e s' <- toExp s sFor "i" (toInt64Exp n) $ \i -> do@@ -883,11 +911,11 @@ BinOpExp (Add it OverflowUndef) e' $ BinOpExp (Mul it OverflowUndef) i' s' copyDWIM (patElemName pe) [DimFix i] (Var (tvVar x)) []-defCompileBasicOp (Pattern _ [pe]) (Copy src) =+defCompileBasicOp (Pat [pe]) (Copy src) = copyDWIM (patElemName pe) [] (Var src) []-defCompileBasicOp (Pattern _ [pe]) (Manifest _ src) =+defCompileBasicOp (Pat [pe]) (Manifest _ src) = copyDWIM (patElemName pe) [] (Var src) []-defCompileBasicOp (Pattern _ [pe]) (Concat i x ys _) = do+defCompileBasicOp (Pat [pe]) (Concat i x ys _) = do offs_glb <- dPrimV "tmp_offs" 0 forM_ (x : ys) $ \y -> do@@ -901,20 +929,19 @@ destslice = skip_slices ++ [DimSlice (tvExp offs_glb) rows 1] copyDWIM (patElemName pe) destslice (Var y) [] offs_glb <-- tvExp offs_glb + rows-defCompileBasicOp (Pattern [] [pe]) (ArrayLit es _)+defCompileBasicOp (Pat [pe]) (ArrayLit es _) | Just vs@(v : _) <- mapM isLiteral es = do- dest_mem <- entryArrayLocation <$> lookupArray (patElemName pe)- dest_space <- entryMemSpace <$> lookupMemory (memLocationName dest_mem)+ dest_mem <- entryArrayLoc <$> lookupArray (patElemName pe)+ dest_space <- entryMemSpace <$> lookupMemory (memLocName dest_mem) let t = primValueType v static_array <- newVNameForFun "static_array" emit $ Imp.DeclareArray static_array dest_space t $ Imp.ArrayValues vs let static_src =- MemLocation static_array [intConst Int64 $ fromIntegral $ length es] $+ MemLoc static_array [intConst Int64 $ fromIntegral $ length es] $ IxFun.iota [fromIntegral $ length es] entry = MemVar Nothing $ MemEntry dest_space addVar static_array entry- let slice = [DimSlice 0 (genericLength es) 1]- copy t dest_mem slice static_src slice+ copy t dest_mem static_src | otherwise = forM_ (zip [0 ..] es) $ \(i, e) -> copyDWIM (patElemName pe) [DimFix $ fromInteger i] e []@@ -940,7 +967,7 @@ -- index parameters. (_, _, arrs, dims, op) <- lookupAcc acc is' - sWhen (inBounds (map DimFix is') dims) $+ sWhen (inBounds (Slice (map DimFix is')) dims) $ case op of Nothing -> -- Scatter-like.@@ -958,7 +985,7 @@ copyDWIM yp [] v [] compileStms mempty (bodyStms $ lambdaBody lam) $- forM_ (zip arrs (bodyResult (lambdaBody lam))) $ \(arr, se) ->+ forM_ (zip arrs (bodyResult (lambdaBody lam))) $ \(arr, SubExpRes _ se) -> copyDWIMFix arr is' se [] defCompileBasicOp pat e = error $@@ -976,13 +1003,13 @@ ArrayVar Nothing ArrayEntry- { entryArrayLocation = location,+ { entryArrayLoc = location, entryArrayElemType = bt } -- | Like 'dFParams', but does not create new declarations. -- Note: a hack to be used only for functions.-addFParams :: Mem rep => [FParam rep] -> ImpM rep r op ()+addFParams :: Mem rep inner => [FParam rep] -> ImpM rep r op () addFParams = mapM_ addFParam where addFParam fparam =@@ -994,7 +1021,7 @@ addLoopVar i it = addVar i $ ScalarVar Nothing $ ScalarEntry $ IntType it dVars ::- Mem rep =>+ Mem rep inner => Maybe (Exp rep) -> [PatElem rep] -> ImpM rep r op ()@@ -1002,10 +1029,10 @@ where dVar = dScope e . scopeOfPatElem -dFParams :: Mem rep => [FParam rep] -> ImpM rep r op ()+dFParams :: Mem rep inner => [FParam rep] -> ImpM rep r op () dFParams = dScope Nothing . scopeOfFParams -dLParams :: Mem rep => [LParam rep] -> ImpM rep r op ()+dLParams :: Mem rep inner => [LParam rep] -> ImpM rep r op () dLParams = dScope Nothing . scopeOfLParams dPrimVol :: String -> PrimType -> Imp.TExp t -> ImpM rep r op (TV t)@@ -1060,25 +1087,25 @@ memBoundToVarEntry e (MemAcc acc ispace ts _) = AccVar e (acc, ispace, ts) memBoundToVarEntry e (MemArray bt shape _ (ArrayIn mem ixfun)) =- let location = MemLocation mem (shapeDims shape) $ fmap (fmap Imp.ScalarVar) ixfun+ let location = MemLoc mem (shapeDims shape) $ fmap (fmap Imp.ScalarVar) ixfun in ArrayVar e ArrayEntry- { entryArrayLocation = location,+ { entryArrayLoc = location, entryArrayElemType = bt } infoDec ::- Mem rep =>+ Mem rep inner => NameInfo rep -> MemInfo SubExp NoUniqueness MemBind-infoDec (LetName dec) = dec+infoDec (LetName dec) = letDecMem dec infoDec (FParamName dec) = noUniquenessReturns dec infoDec (LParamName dec) = dec infoDec (IndexName it) = MemPrim $ IntType it dInfo ::- Mem rep =>+ Mem rep inner => Maybe (Exp rep) -> VName -> NameInfo rep ->@@ -1097,7 +1124,7 @@ addVar name entry dScope ::- Mem rep =>+ Mem rep inner => Maybe (Exp rep) -> Scope rep -> ImpM rep r op ()@@ -1112,8 +1139,8 @@ everythingVolatile = local $ \env -> env {envVolatility = Imp.Volatile} -- | Remove the array targets.-funcallTargets :: Destination -> ImpM rep r op [VName]-funcallTargets (Destination _ dests) =+funcallTargets :: [ValueDestination] -> ImpM rep r op [VName]+funcallTargets dests = concat <$> mapM funcallTarget dests where funcallTarget (ScalarDestination name) =@@ -1267,7 +1294,7 @@ lookupArraySpace :: VName -> ImpM rep r op Space lookupArraySpace = fmap entryMemSpace . lookupMemory- <=< fmap (memLocationName . entryArrayLocation) . lookupArray+ <=< fmap (memLocName . entryArrayLoc) . lookupArray -- | In the case of a histogram-like accumulator, also sets the index -- parameters.@@ -1301,16 +1328,14 @@ error $ "ImpGen.lookupAcc: unlisted accumulator: " ++ pretty name _ -> error $ "ImpGen.lookupAcc: not an accumulator: " ++ pretty name -destinationFromPattern :: Mem rep => Pattern rep -> ImpM rep r op Destination-destinationFromPattern pat =- fmap (Destination (baseTag <$> maybeHead (patternNames pat))) . mapM inspect $- patternElements pat+destinationFromPat :: Pat rep -> ImpM rep r op [ValueDestination]+destinationFromPat = mapM inspect . patElems where- inspect patElem = do- let name = patElemName patElem+ inspect pe = do+ let name = patElemName pe entry <- lookupVar name case entry of- ArrayVar _ (ArrayEntry MemLocation {} _) ->+ ArrayVar _ (ArrayEntry MemLoc {} _) -> return $ ArrayDestination Nothing MemVar {} -> return $ MemoryDestination name@@ -1325,13 +1350,13 @@ ImpM rep r op (VName, Imp.Space, Count Elements (Imp.TExp Int64)) fullyIndexArray name indices = do arr <- lookupArray name- fullyIndexArray' (entryArrayLocation arr) indices+ fullyIndexArray' (entryArrayLoc arr) indices fullyIndexArray' ::- MemLocation ->+ MemLoc -> [Imp.TExp Int64] -> ImpM rep r op (VName, Imp.Space, Count Elements (Imp.TExp Int64))-fullyIndexArray' (MemLocation mem _ ixfun) indices = do+fullyIndexArray' (MemLoc mem _ ixfun) indices = do space <- entryMemSpace <$> lookupMemory mem return ( mem,@@ -1342,17 +1367,15 @@ -- More complicated read/write operations that use index functions. copy :: CopyCompiler rep r op-copy bt dest destslice src srcslice = do+copy bt dest src = do cc <- asks envCopyCompiler- cc bt dest destslice src srcslice+ cc bt dest src -- | Is this copy really a mapping with transpose? isMapTransposeCopy :: PrimType ->- MemLocation ->- Slice (Imp.TExp Int64) ->- MemLocation ->- Slice (Imp.TExp Int64) ->+ MemLoc ->+ MemLoc -> Maybe ( Imp.TExp Int64, Imp.TExp Int64,@@ -1360,45 +1383,37 @@ Imp.TExp Int64, Imp.TExp Int64 )-isMapTransposeCopy- bt- (MemLocation _ _ destIxFun)- destslice- (MemLocation _ _ srcIxFun)- srcslice- | Just (dest_offset, perm_and_destshape) <- IxFun.rearrangeWithOffset destIxFun' bt_size,- (perm, destshape) <- unzip perm_and_destshape,- Just src_offset <- IxFun.linearWithOffset srcIxFun' bt_size,- Just (r1, r2, _) <- isMapTranspose perm =- isOk destshape swap r1 r2 dest_offset src_offset- | Just dest_offset <- IxFun.linearWithOffset destIxFun' bt_size,- Just (src_offset, perm_and_srcshape) <- IxFun.rearrangeWithOffset srcIxFun' bt_size,- (perm, srcshape) <- unzip perm_and_srcshape,- Just (r1, r2, _) <- isMapTranspose perm =- isOk srcshape id r1 r2 dest_offset src_offset- | otherwise =- Nothing- where- bt_size = primByteSize bt- swap (x, y) = (y, x)-- destIxFun' = IxFun.slice destIxFun destslice- srcIxFun' = IxFun.slice srcIxFun srcslice+isMapTransposeCopy bt (MemLoc _ _ destIxFun) (MemLoc _ _ srcIxFun)+ | Just (dest_offset, perm_and_destshape) <- IxFun.rearrangeWithOffset destIxFun bt_size,+ (perm, destshape) <- unzip perm_and_destshape,+ Just src_offset <- IxFun.linearWithOffset srcIxFun bt_size,+ Just (r1, r2, _) <- isMapTranspose perm =+ isOk destshape swap r1 r2 dest_offset src_offset+ | Just dest_offset <- IxFun.linearWithOffset destIxFun bt_size,+ Just (src_offset, perm_and_srcshape) <- IxFun.rearrangeWithOffset srcIxFun bt_size,+ (perm, srcshape) <- unzip perm_and_srcshape,+ Just (r1, r2, _) <- isMapTranspose perm =+ isOk srcshape id r1 r2 dest_offset src_offset+ | otherwise =+ Nothing+ where+ bt_size = primByteSize bt+ swap (x, y) = (y, x) - isOk shape f r1 r2 dest_offset src_offset = do- let (num_arrays, size_x, size_y) = getSizes shape f r1 r2- return- ( dest_offset,- src_offset,- num_arrays,- size_x,- size_y- )+ isOk shape f r1 r2 dest_offset src_offset = do+ let (num_arrays, size_x, size_y) = getSizes shape f r1 r2+ return+ ( dest_offset,+ src_offset,+ num_arrays,+ size_x,+ size_y+ ) - getSizes shape f r1 r2 =- let (mapped, notmapped) = splitAt r1 shape- (pretrans, posttrans) = f $ splitAt r2 notmapped- in (product mapped, product pretrans, product posttrans)+ getSizes shape f r1 r2 =+ let (mapped, notmapped) = splitAt r1 shape+ (pretrans, posttrans) = f $ splitAt r2 notmapped+ in (product mapped, product pretrans, product posttrans) mapTransposeName :: PrimType -> String mapTransposeName bt = "map_transpose_" ++ pretty bt@@ -1414,15 +1429,9 @@ -- | Use an 'Imp.Copy' if possible, otherwise 'copyElementWise'. defaultCopy :: CopyCompiler rep r op-defaultCopy pt dest destslice src srcslice- | Just- ( destoffset,- srcoffset,- num_arrays,- size_x,- size_y- ) <-- isMapTransposeCopy pt dest destslice src srcslice = do+defaultCopy pt dest src+ | Just (destoffset, srcoffset, num_arrays, size_x, size_y) <-+ isMapTransposeCopy pt dest src = do fname <- mapTransposeForType pt emit $ Imp.Call@@ -1438,13 +1447,13 @@ size_x size_y | Just destoffset <-- IxFun.linearWithOffset (IxFun.slice dest_ixfun destslice) pt_size,+ IxFun.linearWithOffset dest_ixfun pt_size, Just srcoffset <-- IxFun.linearWithOffset (IxFun.slice src_ixfun srcslice) pt_size = do+ IxFun.linearWithOffset src_ixfun pt_size = do srcspace <- entryMemSpace <$> lookupMemory srcmem destspace <- entryMemSpace <$> lookupMemory destmem if isScalarSpace srcspace || isScalarSpace destspace- then copyElementWise pt dest destslice src srcslice+ then copyElementWise pt dest src else emit $ Imp.Copy@@ -1456,26 +1465,24 @@ srcspace $ num_elems `withElemType` pt | otherwise =- copyElementWise pt dest destslice src srcslice+ copyElementWise pt dest src where pt_size = primByteSize pt- num_elems = Imp.elements $ product $ sliceDims srcslice+ num_elems = Imp.elements $ product $ IxFun.shape $ memLocIxFun src - MemLocation destmem _ dest_ixfun = dest- MemLocation srcmem _ src_ixfun = src+ MemLoc destmem _ dest_ixfun = dest+ MemLoc srcmem _ src_ixfun = src isScalarSpace ScalarSpace {} = True isScalarSpace _ = False copyElementWise :: CopyCompiler rep r op-copyElementWise bt dest destslice src srcslice = do- let bounds = sliceDims srcslice+copyElementWise bt dest src = do+ let bounds = IxFun.shape $ memLocIxFun src is <- replicateM (length bounds) (newVName "i") let ivars = map Imp.vi64 is- (destmem, destspace, destidx) <-- fullyIndexArray' dest $ fixSlice destslice ivars- (srcmem, srcspace, srcidx) <-- fullyIndexArray' src $ fixSlice srcslice ivars+ (destmem, destspace, destidx) <- fullyIndexArray' dest ivars+ (srcmem, srcspace, srcidx) <- fullyIndexArray' src ivars vol <- asks envVolatility emit $ foldl (.) id (zipWith Imp.For is $ map untyped bounds) $@@ -1486,16 +1493,16 @@ -- indexeded. copyArrayDWIM :: PrimType ->- MemLocation ->+ MemLoc -> [DimIndex (Imp.TExp Int64)] ->- MemLocation ->+ MemLoc -> [DimIndex (Imp.TExp Int64)] -> ImpM rep r op (Imp.Code op) copyArrayDWIM bt- destlocation@(MemLocation _ destshape _)+ destlocation@(MemLoc _ destshape _) destslice- srclocation@(MemLocation _ srcshape _)+ srclocation@(MemLoc _ srcshape _) srcslice | Just destis <- mapM dimFix destslice, Just srcis <- mapM dimFix srcslice,@@ -1510,28 +1517,28 @@ Imp.Write targetmem targetoffset bt destspace vol $ Imp.index srcmem srcoffset bt srcspace vol | otherwise = do- let destslice' =- fullSliceNum (map toInt64Exp destshape) destslice- srcslice' =- fullSliceNum (map toInt64Exp srcshape) srcslice+ let destslice' = fullSliceNum (map toInt64Exp destshape) destslice+ srcslice' = fullSliceNum (map toInt64Exp srcshape) srcslice destrank = length $ sliceDims destslice' srcrank = length $ sliceDims srcslice'+ destlocation' = sliceMemLoc destlocation destslice'+ srclocation' = sliceMemLoc srclocation srcslice' if destrank /= srcrank then error $ "copyArrayDWIM: cannot copy to "- ++ pretty (memLocationName destlocation)+ ++ pretty (memLocName destlocation) ++ " from "- ++ pretty (memLocationName srclocation)+ ++ pretty (memLocName srclocation) ++ " because ranks do not match (" ++ pretty destrank ++ " vs " ++ pretty srcrank ++ ")" else- if destlocation == srclocation && destslice' == srcslice'- then return mempty -- Copy would be no-op.- else collect $ copy bt destlocation destslice' srclocation srcslice'+ if destlocation' == srclocation'+ then pure mempty -- Copy would be no-op.+ else collect $ copy bt destlocation' srclocation' -- | Like 'copyDWIM', but the target is a 'ValueDestination' -- instead of a variable name.@@ -1591,7 +1598,7 @@ length src_slice == length (entryArrayShape arr) -> do let bt = entryArrayElemType arr (mem, space, i) <-- fullyIndexArray' (entryArrayLocation arr) src_is+ fullyIndexArray' (entryArrayLoc arr) src_is vol <- asks envVolatility emit $ Imp.SetScalar name $ Imp.index mem i bt space vol | otherwise ->@@ -1605,7 +1612,7 @@ pretty src_slice ] (ArrayDestination (Just dest_loc), ArrayVar _ src_arr) -> do- let src_loc = entryArrayLocation src_arr+ let src_loc = entryArrayLoc src_arr bt = entryArrayElemType src_arr emit =<< copyArrayDWIM bt dest_loc dest_slice src_loc src_slice (ArrayDestination (Just dest_loc), ScalarVar _ (ScalarEntry bt))@@ -1643,8 +1650,8 @@ case dest_entry of ScalarVar _ _ -> ScalarDestination dest- ArrayVar _ (ArrayEntry (MemLocation mem shape ixfun) _) ->- ArrayDestination $ Just $ MemLocation mem shape ixfun+ ArrayVar _ (ArrayEntry (MemLoc mem shape ixfun) _) ->+ ArrayDestination $ Just $ MemLoc mem shape ixfun MemVar _ _ -> MemoryDestination dest AccVar {} ->@@ -1666,12 +1673,8 @@ -- writing the result to @dest@, which must be a single -- 'MemoryDestination', compileAlloc ::- Mem rep =>- Pattern rep ->- SubExp ->- Space ->- ImpM rep r op ()-compileAlloc (Pattern [] [mem]) e space = do+ Mem rep inner => Pat rep -> SubExp -> Space -> ImpM rep r op ()+compileAlloc (Pat [mem]) e space = do let e' = Imp.bytes $ toInt64Exp e allocator <- asks $ M.lookup space . envAllocCompilers case allocator of@@ -1690,11 +1693,11 @@ -- is useful for things like scatter, which ignores out-of-bounds -- writes. inBounds :: Slice (Imp.TExp Int64) -> [Imp.TExp Int64] -> Imp.TExp Bool-inBounds slice dims =+inBounds (Slice slice) dims = let condInBounds (DimFix i) d = 0 .<=. i .&&. i .<. d condInBounds (DimSlice i n s) d =- 0 .<=. i .&&. i + n * s .<. d+ 0 .<=. i .&&. i + (n -1) * s .<. d in foldl1 (.&&.) $ zipWith condInBounds slice dims --- Building blocks for constructing code.@@ -1805,7 +1808,7 @@ emit $ Imp.Write mem offset (primExpType v) space vol v sUpdate :: VName -> Slice (Imp.TExp Int64) -> SubExp -> ImpM rep r op ()-sUpdate arr slice v = copyDWIM arr slice v []+sUpdate arr slice v = copyDWIM arr (unSlice slice) v [] sLoopNest :: Shape ->@@ -1875,3 +1878,15 @@ i' <- dPrimVE "remnant" $ i - Imp.vi64 v * size loop rest i' loop _ _ = pure ()++-- | Like 'dIndexSpace', but invent some new names for the indexes+-- based on the given template.+dIndexSpace' ::+ String ->+ [Imp.TExp Int64] ->+ Imp.TExp Int64 ->+ ImpM rep r op [Imp.TExp Int64]+dIndexSpace' desc ds j = do+ ivs <- replicateM (length ds) (newVName desc)+ dIndexSpace (zip ivs ds) j+ pure $ map Imp.vi64 ivs
src/Futhark/CodeGen/ImpGen/GPU.hs view
@@ -83,8 +83,19 @@ Prog GPUMem -> m (Warnings, Imp.Program) compileProg env prog =- second (setDefaultSpace (Imp.Space "device"))- <$> Futhark.CodeGen.ImpGen.compileProg env callKernelOperations (Imp.Space "device") prog+ second (fmap setOpSpace . setDefsSpace)+ <$> Futhark.CodeGen.ImpGen.compileProg env callKernelOperations device_space prog+ where+ device_space = Imp.Space "device"+ global_space = Imp.Space "global"+ setDefsSpace = setDefaultSpace device_space+ setOpSpace (Imp.CallKernel kernel) =+ Imp.CallKernel+ kernel+ { Imp.kernelBody =+ setDefaultCodeSpace global_space $ Imp.kernelBody kernel+ }+ setOpSpace op = op -- | Compile a 'GPUMem' program to low-level parallel code, with -- either CUDA or OpenCL characteristics.@@ -95,24 +106,24 @@ compileProgCUDA = compileProg $ HostEnv cudaAtomics CUDA mempty opCompiler ::- Pattern GPUMem ->+ Pat GPUMem -> Op GPUMem -> CallKernelGen () opCompiler dest (Alloc e space) = compileAlloc dest e space-opCompiler (Pattern _ [pe]) (Inner (SizeOp (GetSize key size_class))) = do+opCompiler (Pat [pe]) (Inner (SizeOp (GetSize key size_class))) = do fname <- askFunction sOp $ Imp.GetSize (patElemName pe) (keyWithEntryPoint fname key) $ sizeClassWithEntryPoint fname size_class-opCompiler (Pattern _ [pe]) (Inner (SizeOp (CmpSizeLe key size_class x))) = do+opCompiler (Pat [pe]) (Inner (SizeOp (CmpSizeLe key size_class x))) = do fname <- askFunction let size_class' = sizeClassWithEntryPoint fname size_class sOp . Imp.CmpSizeLe (patElemName pe) (keyWithEntryPoint fname key) size_class' =<< toExp x-opCompiler (Pattern _ [pe]) (Inner (SizeOp (GetSizeMax size_class))) =+opCompiler (Pat [pe]) (Inner (SizeOp (GetSizeMax size_class))) = sOp $ Imp.GetSizeMax (patElemName pe) size_class-opCompiler (Pattern _ [pe]) (Inner (SizeOp (CalcNumGroups w64 max_num_groups_key group_size))) = do+opCompiler (Pat [pe]) (Inner (SizeOp (CalcNumGroups w64 max_num_groups_key group_size))) = do fname <- askFunction max_num_groups :: TV Int32 <- dPrim "max_num_groups" int32 sOp $@@ -147,7 +158,7 @@ sizeClassWithEntryPoint _ size_class = size_class segOpCompiler ::- Pattern GPUMem ->+ Pat GPUMem -> SegOp SegLevel GPUMem -> CallKernelGen () segOpCompiler pat (SegMap lvl space _ kbody) =@@ -200,7 +211,7 @@ alignedSize x = x + ((8 - (x `rem` 8)) `rem` 8) withAcc ::- Pattern GPUMem ->+ Pat GPUMem -> [(Shape, [VName], Maybe (Lambda GPUMem, [SubExp]))] -> Lambda GPUMem -> CallKernelGen ()@@ -226,12 +237,12 @@ expCompiler :: ExpCompiler GPUMem HostEnv Imp.HostOp -- We generate a simple kernel for itoa and replicate.-expCompiler (Pattern _ [pe]) (BasicOp (Iota n x s et)) = do+expCompiler (Pat [pe]) (BasicOp (Iota n x s et)) = do x' <- toExp x s' <- toExp s sIota (patElemName pe) (toInt64Exp n) x' s' et-expCompiler (Pattern _ [pe]) (BasicOp (Replicate _ se)) =+expCompiler (Pat [pe]) (BasicOp (Replicate _ se)) = sReplicate (patElemName pe) se -- Allocation in the "local" space is just a placeholder. expCompiler _ (Op (Alloc _ (Space "local"))) =@@ -255,51 +266,38 @@ defCompileExp dest e callKernelCopy :: CopyCompiler GPUMem HostEnv Imp.HostOp-callKernelCopy- bt- destloc@(MemLocation destmem _ destIxFun)- destslice- srcloc@(MemLocation srcmem srcshape srcIxFun)- srcslice- | Just- ( destoffset,- srcoffset,- num_arrays,- size_x,- size_y- ) <-- isMapTransposeCopy bt destloc destslice srcloc srcslice = do- fname <- mapTransposeForType bt- emit $- Imp.Call- []- fname- [ Imp.MemArg destmem,- Imp.ExpArg $ untyped destoffset,- Imp.MemArg srcmem,- Imp.ExpArg $ untyped srcoffset,- Imp.ExpArg $ untyped num_arrays,- Imp.ExpArg $ untyped size_x,- Imp.ExpArg $ untyped size_y- ]- | bt_size <- primByteSize bt,- Just destoffset <-- IxFun.linearWithOffset (IxFun.slice destIxFun destslice) bt_size,- Just srcoffset <-- IxFun.linearWithOffset (IxFun.slice srcIxFun srcslice) bt_size = do- let num_elems = Imp.elements $ product $ map toInt64Exp srcshape- srcspace <- entryMemSpace <$> lookupMemory srcmem- destspace <- entryMemSpace <$> lookupMemory destmem- emit $- Imp.Copy- destmem- (bytes $ sExt64 destoffset)- destspace- srcmem- (bytes $ sExt64 srcoffset)- srcspace- $ num_elems `Imp.withElemType` bt- | otherwise = sCopy bt destloc destslice srcloc srcslice+callKernelCopy bt destloc@(MemLoc destmem _ destIxFun) srcloc@(MemLoc srcmem srcshape srcIxFun)+ | Just (destoffset, srcoffset, num_arrays, size_x, size_y) <-+ isMapTransposeCopy bt destloc srcloc = do+ fname <- mapTransposeForType bt+ emit $+ Imp.Call+ []+ fname+ [ Imp.MemArg destmem,+ Imp.ExpArg $ untyped destoffset,+ Imp.MemArg srcmem,+ Imp.ExpArg $ untyped srcoffset,+ Imp.ExpArg $ untyped num_arrays,+ Imp.ExpArg $ untyped size_x,+ Imp.ExpArg $ untyped size_y+ ]+ | bt_size <- primByteSize bt,+ Just destoffset <- IxFun.linearWithOffset destIxFun bt_size,+ Just srcoffset <- IxFun.linearWithOffset srcIxFun bt_size = do+ let num_elems = Imp.elements $ product $ map toInt64Exp srcshape+ srcspace <- entryMemSpace <$> lookupMemory srcmem+ destspace <- entryMemSpace <$> lookupMemory destmem+ emit $+ Imp.Copy+ destmem+ (bytes $ sExt64 destoffset)+ destspace+ srcmem+ (bytes $ sExt64 srcoffset)+ srcspace+ $ num_elems `Imp.withElemType` bt+ | otherwise = sCopy bt destloc srcloc mapTransposeForType :: PrimType -> CallKernelGen Name mapTransposeForType bt = do
src/Futhark/CodeGen/ImpGen/GPU/Base.hs view
@@ -104,7 +104,7 @@ S.singleton $ map snd $ unSegSpace $ segSpace op onExp (If _ tbranch fbranch _) = onStms (bodyStms tbranch) <> onStms (bodyStms fbranch)- onExp (DoLoop _ _ _ body) =+ onExp (DoLoop _ _ body) = onStms (bodyStms body) onExp _ = mempty @@ -120,9 +120,9 @@ localEnv f m where mkMap ltid dims = do- let dims' = map (sExt32 . toInt64Exp) dims- ids' <- mapM (dPrimVE "ltid_pre") $ unflattenIndex dims' ltid- return (dims, ids')+ let dims' = map toInt64Exp dims+ ids' <- dIndexSpace' "ltid_pre" dims' (sExt64 ltid)+ return (dims, map sExt32 ids') keyWithEntryPoint :: Maybe Name -> Name -> Name keyWithEntryPoint fname key =@@ -133,30 +133,30 @@ sOp $ Imp.LocalAlloc mem size kernelAlloc ::- Pattern GPUMem ->+ Pat GPUMem -> SubExp -> Space -> InKernelGen ()-kernelAlloc (Pattern _ [_]) _ ScalarSpace {} =+kernelAlloc (Pat [_]) _ ScalarSpace {} = -- Handled by the declaration of the memory block, which is then -- translated to an actual scalar variable during C code generation. return ()-kernelAlloc (Pattern _ [mem]) size (Space "local") =+kernelAlloc (Pat [mem]) size (Space "local") = allocLocal (patElemName mem) $ Imp.bytes $ toInt64Exp size-kernelAlloc (Pattern _ [mem]) _ _ =+kernelAlloc (Pat [mem]) _ _ = compilerLimitationS $ "Cannot allocate memory block " ++ pretty mem ++ " in kernel." kernelAlloc dest _ _ = error $ "Invalid target for in-kernel allocation: " ++ show dest splitSpace :: (ToExp w, ToExp i, ToExp elems_per_thread) =>- Pattern GPUMem ->+ Pat GPUMem -> SplitOrdering -> w -> i -> elems_per_thread -> ImpM rep r op ()-splitSpace (Pattern [] [size]) o w i elems_per_thread = do+splitSpace (Pat [size]) o w i elems_per_thread = do num_elements <- Imp.elements . TPrimExp <$> toExp w let i' = toInt64Exp i elems_per_thread' <- Imp.elements . TPrimExp <$> toExp elems_per_thread@@ -169,7 +169,7 @@ -- See the ImpGen implementation of UpdateAcc for general notes. let is' = map toInt64Exp is (c, space, arrs, dims, op) <- lookupAcc acc is'- sWhen (inBounds (map DimFix is') dims) $+ sWhen (inBounds (Slice (map DimFix is')) dims) $ case op of Nothing -> forM_ (zip arrs vs) $ \(arr, v) -> copyDWIMFix arr is' v []@@ -194,7 +194,10 @@ error $ "Missing locks for " ++ pretty acc compileThreadExp :: ExpCompiler GPUMem KernelEnv Imp.KernelOp-compileThreadExp (Pattern _ [dest]) (BasicOp (ArrayLit es _)) =+compileThreadExp (Pat [pe]) (BasicOp (Opaque _ se)) =+ -- Cannot print in GPU code.+ copyDWIM (patElemName pe) [] se []+compileThreadExp (Pat [dest]) (BasicOp (ArrayLit es _)) = forM_ (zip [0 ..] es) $ \(i, e) -> copyDWIMFix (patElemName dest) [fromIntegral (i :: Int64)] e [] compileThreadExp _ (BasicOp (UpdateAcc acc is vs)) =@@ -250,18 +253,21 @@ groupLoop (product ds) $ f . unflattenIndex ds compileGroupExp :: ExpCompiler GPUMem KernelEnv Imp.KernelOp+compileGroupExp (Pat [pe]) (BasicOp (Opaque _ se)) =+ -- Cannot print in GPU code.+ copyDWIM (patElemName pe) [] se [] -- The static arrays stuff does not work inside kernels.-compileGroupExp (Pattern _ [dest]) (BasicOp (ArrayLit es _)) =+compileGroupExp (Pat [dest]) (BasicOp (ArrayLit es _)) = forM_ (zip [0 ..] es) $ \(i, e) -> copyDWIMFix (patElemName dest) [fromIntegral (i :: Int64)] e [] compileGroupExp _ (BasicOp (UpdateAcc acc is vs)) = updateAcc acc is vs-compileGroupExp (Pattern _ [dest]) (BasicOp (Replicate ds se)) = do+compileGroupExp (Pat [dest]) (BasicOp (Replicate ds se)) = do let ds' = map toInt64Exp $ shapeDims ds groupCoverSpace ds' $ \is -> copyDWIMFix (patElemName dest) is se (drop (shapeRank ds) is) sOp $ Imp.Barrier Imp.FenceLocal-compileGroupExp (Pattern _ [dest]) (BasicOp (Iota n e s it)) = do+compileGroupExp (Pat [dest]) (BasicOp (Iota n e s it)) = do n' <- toExp n e' <- toExp e s' <- toExp s@@ -278,13 +284,19 @@ -- sure that only one thread performs the write. When writing an -- array, the group-level copy code will take care of doing the right -- thing.-compileGroupExp (Pattern _ [pe]) (BasicOp (Update _ slice se))+compileGroupExp (Pat [pe]) (BasicOp (Update safety _ slice se)) | null $ sliceDims slice = do sOp $ Imp.Barrier Imp.FenceLocal ltid <- kernelLocalThreadId . kernelConstants <$> askEnv sWhen (ltid .==. 0) $- copyDWIM (patElemName pe) (map (fmap toInt64Exp) slice) se []+ case safety of+ Unsafe -> write+ Safe -> sWhen (inBounds slice' dims) write sOp $ Imp.Barrier Imp.FenceLocal+ where+ slice' = fmap toInt64Exp slice+ dims = map toInt64Exp $ arrayDims $ patElemType pe+ write = copyDWIM (patElemName pe) (unSlice slice') se [] compileGroupExp dest e = defCompileExp dest e @@ -371,7 +383,7 @@ whenActive lvl space $ localOps threadOperations $ compileStms mempty (kernelBodyStms body) $- zipWithM_ (compileThreadResult space) (patternElements pat) $+ zipWithM_ (compileThreadResult space) (patElems pat) $ kernelBodyResult body sOp $ Imp.ErrorSync Imp.FenceLocal@@ -382,7 +394,7 @@ whenActive lvl space $ compileStms mempty (kernelBodyStms body) $- forM_ (zip (patternNames pat) $ kernelBodyResult body) $ \(dest, res) ->+ forM_ (zip (patNames pat) $ kernelBodyResult body) $ \(dest, res) -> copyDWIMFix dest (map Imp.vi64 ltids)@@ -401,8 +413,8 @@ -- row-major, but does not actually verify it. dims_flat <- dPrimV "dims_flat" $ product dims' let flattened pe = do- MemLocation mem _ _ <-- entryArrayLocation <$> lookupArray (patElemName pe)+ MemLoc mem _ _ <-+ entryArrayLoc <$> lookupArray (patElemName pe) let pe_t = typeOf pe arr_dims = Var (tvVar dims_flat) : drop (length dims') (arrayDims pe_t) sArray@@ -413,7 +425,7 @@ num_scan_results = sum $ map (length . segBinOpNeutral) scans - arrs_flat <- mapM flattened $ take num_scan_results $ patternElements pat+ arrs_flat <- mapM flattened $ take num_scan_results $ patElems pat forM_ scans $ \scan -> do let scan_op = segBinOpLambda scan@@ -423,7 +435,7 @@ let (ltids, dims) = unzip $ unSegSpace space (red_pes, map_pes) =- splitAt (segBinOpResults ops) $ patternElements pat+ splitAt (segBinOpResults ops) $ patElems pat dims' = map toInt64Exp dims @@ -468,9 +480,9 @@ let flat_shape = Shape $ Var (tvVar dims_flat) :- drop (length ltids) (memLocationShape arr_loc)+ drop (length ltids) (memLocShape arr_loc) sArray "red_arr_flat" pt flat_shape $- ArrayIn (memLocationName arr_loc) $+ ArrayIn (memLocName arr_loc) $ IxFun.iota $ map pe64 $ shapeDims flat_shape let segment_size = last dims'@@ -505,7 +517,7 @@ -- the ops. let num_red_res = length ops + sum (map (length . histNeutral) ops) (_red_pes, map_pes) =- splitAt num_red_res $ patternElements pat+ splitAt num_red_res $ patElems pat ops' <- prepareIntraGroupSegHist (segGroupSize lvl) ops @@ -1397,27 +1409,35 @@ f copyInGroup :: CopyCompiler GPUMem KernelEnv Imp.KernelOp-copyInGroup pt destloc destslice srcloc srcslice = do- dest_space <- entryMemSpace <$> lookupMemory (memLocationName destloc)- src_space <- entryMemSpace <$> lookupMemory (memLocationName srcloc)+copyInGroup pt destloc srcloc = do+ dest_space <- entryMemSpace <$> lookupMemory (memLocName destloc)+ src_space <- entryMemSpace <$> lookupMemory (memLocName srcloc) + let src_ixfun = memLocIxFun srcloc+ dims = IxFun.shape src_ixfun+ rank = length dims+ case (dest_space, src_space) of (ScalarSpace destds _, ScalarSpace srcds _) -> do- let destslice' =- replicate (length destslice - length destds) (DimFix 0)- ++ takeLast (length destds) destslice+ let fullDim d = DimSlice 0 d 1+ destslice' =+ Slice $+ replicate (rank - length destds) (DimFix 0)+ ++ takeLast (length destds) (map fullDim dims) srcslice' =- replicate (length srcslice - length srcds) (DimFix 0)- ++ takeLast (length srcds) srcslice- copyElementWise pt destloc destslice' srcloc srcslice'+ Slice $+ replicate (rank - length srcds) (DimFix 0)+ ++ takeLast (length srcds) (map fullDim dims)+ copyElementWise+ pt+ (sliceMemLoc destloc destslice')+ (sliceMemLoc srcloc srcslice') _ -> do- groupCoverSpace (sliceDims destslice) $ \is ->+ groupCoverSpace dims $ \is -> copyElementWise pt- destloc- (map DimFix $ fixSlice destslice is)- srcloc- (map DimFix $ fixSlice srcslice is)+ (sliceMemLoc destloc (Slice $ map DimFix is))+ (sliceMemLoc srcloc (Slice $ map DimFix is)) sOp $ Imp.Barrier Imp.FenceLocal threadOperations, groupOperations :: Operations GPUMem KernelEnv Imp.KernelOp@@ -1453,10 +1473,10 @@ keyWithEntryPoint fname $ nameFromString $ "replicate_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)- is' = unflattenIndex dims $ sExt64 $ kernelGlobalThreadId constants sKernelFailureTolerant True threadOperations constants name $ do set_constants+ is' <- dIndexSpace' "rep_i" dims $ sExt64 $ kernelGlobalThreadId constants sWhen (kernelThreadActive constants) $ copyDWIMFix arr is' se $ drop (length ds) is' @@ -1491,7 +1511,7 @@ replicateIsFill :: VName -> SubExp -> CallKernelGen (Maybe (CallKernelGen ())) replicateIsFill arr v = do- ArrayEntry (MemLocation arr_mem arr_shape arr_ixfun) _ <- lookupArray arr+ ArrayEntry (MemLoc arr_mem arr_shape arr_ixfun) _ <- lookupArray arr v_t <- subExpType v case v_t of Prim v_t'@@ -1528,7 +1548,7 @@ IntType -> CallKernelGen () sIotaKernel arr n x s et = do- destloc <- entryArrayLocation <$> lookupArray arr+ destloc <- entryArrayLoc <$> lookupArray arr (constants, set_constants) <- simpleKernelConstants n "iota" fname <- askFunction@@ -1595,7 +1615,7 @@ IntType -> CallKernelGen () sIota arr n x s et = do- ArrayEntry (MemLocation arr_mem _ arr_ixfun) _ <- lookupArray arr+ ArrayEntry (MemLoc arr_mem _ arr_ixfun) _ <- lookupArray arr if IxFun.isLinear arr_ixfun then do fname <- iotaForType et@@ -1607,49 +1627,40 @@ else sIotaKernel arr n x s et sCopy :: CopyCompiler GPUMem HostEnv Imp.HostOp-sCopy- bt- destloc@(MemLocation destmem _ _)- destslice- srcloc@(MemLocation srcmem _ _)- srcslice =- do- -- Note that the shape of the destination and the source are- -- necessarily the same.- let shape = sliceDims srcslice- kernel_size = product shape+sCopy bt destloc@(MemLoc destmem _ _) srcloc@(MemLoc srcmem srcdims _) = do+ -- Note that the shape of the destination and the source are+ -- necessarily the same.+ let shape = map toInt64Exp srcdims+ kernel_size = product shape - (constants, set_constants) <- simpleKernelConstants kernel_size "copy"+ (constants, set_constants) <- simpleKernelConstants kernel_size "copy" - fname <- askFunction- let name =- keyWithEntryPoint fname $- nameFromString $- "copy_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)+ fname <- askFunction+ let name =+ keyWithEntryPoint fname $+ nameFromString $+ "copy_" ++ show (baseTag $ kernelGlobalThreadIdVar constants) - sKernelFailureTolerant True threadOperations constants name $ do- set_constants+ sKernelFailureTolerant True threadOperations constants name $ do+ set_constants - let gtid = sExt64 $ kernelGlobalThreadId constants- dest_is = unflattenIndex shape gtid- src_is = dest_is+ let gtid = sExt64 $ kernelGlobalThreadId constants+ is <- dIndexSpace' "copy_i" shape gtid - (_, destspace, destidx) <-- fullyIndexArray' destloc $ fixSlice destslice dest_is- (_, srcspace, srcidx) <-- fullyIndexArray' srcloc $ fixSlice srcslice src_is+ (_, destspace, destidx) <- fullyIndexArray' destloc is+ (_, srcspace, srcidx) <- fullyIndexArray' srcloc is - sWhen (gtid .<. kernel_size) $- emit $- Imp.Write destmem destidx bt destspace Imp.Nonvolatile $- Imp.index srcmem srcidx bt srcspace Imp.Nonvolatile+ sWhen (gtid .<. kernel_size) $+ emit $+ Imp.Write destmem destidx bt destspace Imp.Nonvolatile $+ Imp.index srcmem srcidx bt srcspace Imp.Nonvolatile compileGroupResult :: SegSpace -> PatElem GPUMem -> KernelResult -> InKernelGen ()-compileGroupResult _ pe (TileReturns [(w, per_group_elems)] what) = do+compileGroupResult _ pe (TileReturns _ [(w, per_group_elems)] what) = do n <- toInt64Exp . arraySize 0 <$> lookupType what constants <- kernelConstants <$> askEnv@@ -1669,7 +1680,7 @@ j <- dPrimVE "j" $ kernelGroupSize constants * i + ltid sWhen (j + offset .<. toInt64Exp w) $ copyDWIMFix (patElemName pe) [j + offset] (Var what) [j]-compileGroupResult space pe (TileReturns dims what) = do+compileGroupResult space pe (TileReturns _ dims what) = do let gids = map fst $ unSegSpace space out_tile_sizes = map (toInt64Exp . snd) dims group_is = zipWith (*) (map Imp.vi64 gids) out_tile_sizes@@ -1681,7 +1692,7 @@ localOps threadOperations $ sWhen (isActive $ zip (map tvVar is_for_thread) $ map fst dims) $ copyDWIMFix (patElemName pe) (map tvExp is_for_thread) (Var what) local_is-compileGroupResult space pe (RegTileReturns dims_n_tiles what) = do+compileGroupResult space pe (RegTileReturns _ dims_n_tiles what) = do constants <- kernelConstants <$> askEnv let gids = map fst $ unSegSpace space@@ -1695,8 +1706,7 @@ -- Within the group tile, which register tile is this thread -- responsible for? reg_tile_is <-- mapM (dPrimVE "reg_tile_i") $- unflattenIndex group_tiles' $ sExt64 $ kernelLocalThreadId constants+ dIndexSpace' "reg_tile_i" group_tiles' $ sExt64 $ kernelLocalThreadId constants -- Compute output array slice for the register tile belonging to -- this thread.@@ -1706,10 +1716,11 @@ reg_tile * (group_tile * group_tile_i + reg_tile_i) return $ DimSlice tile_dim_start reg_tile 1 reg_tile_slices <-- zipWithM- regTileSliceDim- (zip group_tiles' group_tile_is)- (zip reg_tiles' reg_tile_is)+ Slice+ <$> zipWithM+ regTileSliceDim+ (zip group_tiles' group_tile_is)+ (zip reg_tiles' reg_tile_is) localOps threadOperations $ sLoopNest (Shape reg_tiles) $ \is_in_reg_tile -> do@@ -1717,7 +1728,7 @@ src_is = reg_tile_is ++ is_in_reg_tile sWhen (foldl1 (.&&.) $ zipWith (.<.) dest_is $ map toInt64Exp dims) $ copyDWIMFix (patElemName pe) dest_is (Var what) src_is-compileGroupResult space pe (Returns _ what) = do+compileGroupResult space pe (Returns _ _ what) = do constants <- kernelConstants <$> askEnv in_local_memory <- arrayInLocalMemory what let gids = map (Imp.vi64 . fst) $ unSegSpace space@@ -1744,33 +1755,27 @@ InKernelGen () compileThreadResult _ _ RegTileReturns {} = compilerLimitationS "compileThreadResult: RegTileReturns not yet handled."-compileThreadResult space pe (Returns _ what) = do+compileThreadResult space pe (Returns _ _ what) = do let is = map (Imp.vi64 . fst) $ unSegSpace space copyDWIMFix (patElemName pe) is what []-compileThreadResult _ pe (ConcatReturns SplitContiguous _ per_thread_elems what) = do+compileThreadResult _ pe (ConcatReturns _ SplitContiguous _ per_thread_elems what) = do constants <- kernelConstants <$> askEnv let offset = toInt64Exp per_thread_elems * sExt64 (kernelGlobalThreadId constants) n <- toInt64Exp . arraySize 0 <$> lookupType what copyDWIM (patElemName pe) [DimSlice offset n 1] (Var what) []-compileThreadResult _ pe (ConcatReturns (SplitStrided stride) _ _ what) = do+compileThreadResult _ pe (ConcatReturns _ (SplitStrided stride) _ _ what) = do offset <- sExt64 . kernelGlobalThreadId . kernelConstants <$> askEnv n <- toInt64Exp . arraySize 0 <$> lookupType what copyDWIM (patElemName pe) [DimSlice offset n $ toInt64Exp stride] (Var what) []-compileThreadResult _ pe (WriteReturns (Shape rws) _arr dests) = do+compileThreadResult _ pe (WriteReturns _ (Shape rws) _arr dests) = do constants <- kernelConstants <$> askEnv let rws' = map toInt64Exp rws forM_ dests $ \(slice, e) -> do- let slice' = map (fmap toInt64Exp) slice- condInBounds (DimFix i) rw =- 0 .<=. i .&&. i .<. rw- condInBounds (DimSlice i n s) rw =- 0 .<=. i .&&. i + n * s .<. rw- write =- foldl (.&&.) (kernelThreadActive constants) $- zipWith condInBounds slice' rws'- sWhen write $ copyDWIM (patElemName pe) slice' e []+ let slice' = fmap toInt64Exp slice+ write = kernelThreadActive constants .&&. inBounds slice' rws'+ sWhen write $ copyDWIM (patElemName pe) (unSlice slice') e [] compileThreadResult _ _ TileReturns {} = compilerBugS "compileThreadResult: TileReturns unhandled." @@ -1780,6 +1785,6 @@ case res of ArrayVar _ entry -> (Space "local" ==) . entryMemSpace- <$> lookupMemory (memLocationName (entryArrayLocation entry))+ <$> lookupMemory (memLocName (entryArrayLoc entry)) _ -> return False arrayInLocalMemory Constant {} = return False
src/Futhark/CodeGen/ImpGen/GPU/SegHist.hs view
@@ -99,7 +99,7 @@ num_subhistos <- dPrim "num_subhistos" int32 subhisto_infos <- forM (zip (histDest op) (histNeutral op)) $ \(dest, ne) -> do dest_t <- lookupType dest- dest_mem <- entryArrayLocation <$> lookupArray dest+ dest_mem <- entryArrayLoc <$> lookupArray dest subhistos_mem <- sDeclareMem (baseString dest ++ "_subhistos_mem") (Space "device")@@ -122,7 +122,7 @@ SubhistosInfo subhistos $ do let unitHistoCase = emit $- Imp.SetMem subhistos_mem (memLocationName dest_mem) $+ Imp.SetMem subhistos_mem (memLocName dest_mem) $ Space "device" multiHistoCase = do@@ -360,16 +360,16 @@ -- destination. The idea is to avoid a copy if we are writing a -- small number of values into a very large prior histogram. dests <- forM (zip (histDest op) subhisto_info) $ \(dest, info) -> do- dest_mem <- entryArrayLocation <$> lookupArray dest+ dest_mem <- entryArrayLoc <$> lookupArray dest sub_mem <-- fmap memLocationName $- entryArrayLocation+ fmap memLocName $+ entryArrayLoc <$> lookupArray (subhistosArray info) let unitHistoCase = emit $- Imp.SetMem sub_mem (memLocationName dest_mem) $+ Imp.SetMem sub_mem (memLocName dest_mem) $ Space "device" multiHistoCase = subhistosAlloc info@@ -1023,14 +1023,14 @@ -- | Generate code for a segmented histogram called from the host. compileSegHist ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [HistOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()-compileSegHist (Pattern _ pes) num_groups group_size space ops kbody = do+compileSegHist (Pat pes) num_groups group_size space ops kbody = do -- Most of this function is not the histogram part itself, but -- rather figuring out whether to use a local or global memory -- strategy, as well as collapsing the subhistograms produced (which@@ -1107,10 +1107,10 @@ -- large as the ones we are supposed to use for the result. forM_ (zip red_pes subhistos) $ \(pe, subhisto) -> do pe_mem <-- memLocationName . entryArrayLocation+ memLocName . entryArrayLoc <$> lookupArray (patElemName pe) subhisto_mem <-- memLocationName . entryArrayLocation+ memLocName . entryArrayLoc <$> lookupArray subhisto emit $ Imp.SetMem pe_mem subhisto_mem $ Space "device" @@ -1138,7 +1138,7 @@ ++ [(subhistogram_id, Var $ tvVar num_histos)] let segred_op = SegBinOp Commutative (histOp op) (histNeutral op) mempty- compileSegRed' (Pattern [] red_pes) lvl segred_space [segred_op] $ \red_cont ->+ compileSegRed' (Pat red_pes) lvl segred_space [segred_op] $ \red_cont -> red_cont $ flip map subhistos $ \subhisto -> ( Var subhisto,
src/Futhark/CodeGen/ImpGen/GPU/SegMap.hs view
@@ -17,7 +17,7 @@ -- | Compile 'SegMap' instance code. compileSegMap ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> KernelBody GPUMem ->@@ -46,7 +46,7 @@ sWhen (isActive $ unSegSpace space) $ compileStms mempty (kernelBodyStms kbody) $- zipWithM_ (compileThreadResult space) (patternElements pat) $+ zipWithM_ (compileThreadResult space) (patElems pat) $ kernelBodyResult kbody SegGroup {} -> sKernelGroup "segmap_intragroup" num_groups' group_size' (segFlat space) $ do@@ -56,6 +56,6 @@ dIndexSpace (zip is dims') $ sExt64 group_id compileStms mempty (kernelBodyStms kbody) $- zipWithM_ (compileGroupResult space) (patternElements pat) $+ zipWithM_ (compileGroupResult space) (patElems pat) $ kernelBodyResult kbody emit $ Imp.DebugPrint "" Nothing
src/Futhark/CodeGen/ImpGen/GPU/SegRed.hs view
@@ -77,7 +77,7 @@ -- | Compile 'SegRed' instance to host-level code with calls to -- various kernels. compileSegRed ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] ->@@ -89,14 +89,14 @@ let (red_res, map_res) = splitAt (segBinOpResults reds) $ kernelBodyResult body sComment "save map-out results" $ do- let map_arrs = drop (segBinOpResults reds) $ patternElements pat+ let map_arrs = drop (segBinOpResults reds) $ patElems pat zipWithM_ (compileThreadResult space) map_arrs map_res red_cont $ zip (map kernelResultSubExp red_res) $ repeat [] -- | Like 'compileSegRed', but where the body is a monadic action. compileSegRed' ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] ->@@ -171,7 +171,7 @@ sAllocArrayPerm "segred_tmp" pt full_shape (Space "device") perm nonsegmentedReduction ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace ->@@ -228,7 +228,7 @@ let segred_pes = chunks (map (length . segBinOpNeutral) reds) $- patternElements segred_pat+ patElems segred_pat forM_ (zip7 reds reds_arrs reds_group_res_arrs segred_pes slugs reds_op_renamed [0 ..]) $ \(SegBinOp _ red_op nes _, red_arrs, group_res_arrs, pes, slug, red_op_renamed, i) -> do let (red_x_params, red_y_params) = splitAt (length nes) $ lambdaParams red_op@@ -255,14 +255,14 @@ emit $ Imp.DebugPrint "" Nothing smallSegmentsReduction ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [SegBinOp GPUMem] -> DoSegBody -> CallKernelGen ()-smallSegmentsReduction (Pattern _ segred_pes) num_groups group_size space reds body = do+smallSegmentsReduction (Pat segred_pes) num_groups group_size space reds body = do let (gtids, dims) = unzip $ unSegSpace space dims' = map toInt64Exp dims segment_size = last dims'@@ -364,7 +364,7 @@ emit $ Imp.DebugPrint "" Nothing largeSegmentsReduction ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace ->@@ -466,7 +466,7 @@ let segred_pes = chunks (map (length . segBinOpNeutral) reds) $- patternElements segred_pat+ patElems segred_pat multiple_groups_per_segment = forM_ (zip7 reds reds_arrs reds_group_res_arrs segred_pes slugs reds_op_renamed [0 ..]) $@@ -661,7 +661,7 @@ forM_ ( zip (slugAccs slug)- (bodyResult $ slugBody slug)+ (map resSubExp $ bodyResult $ slugBody slug) ) $ \((acc, acc_is), se) -> copyDWIMFix acc (acc_is ++ vec_is) se []@@ -820,7 +820,7 @@ ([0, index_of_group_res] ++ vec_is) compileStms mempty (bodyStms $ slugBody slug) $- forM_ (zip red_x_params (bodyResult $ slugBody slug)) $ \(p, se) ->+ forM_ (zip red_x_params $ map resSubExp $ bodyResult $ slugBody slug) $ \(p, se) -> copyDWIMFix (paramName p) [] se [] forM_ (zip red_x_params red_arrs) $ \(p, arr) ->
src/Futhark/CodeGen/ImpGen/GPU/SegScan.hs view
@@ -35,10 +35,9 @@ (concatMap (bodyResult . lambdaBody) lams) } -canBeSinglePass :: SegSpace -> [SegBinOp GPUMem] -> Maybe (SegBinOp GPUMem)-canBeSinglePass space ops- | [_] <- unSegSpace space,- all ok ops =+canBeSinglePass :: [SegBinOp GPUMem] -> Maybe (SegBinOp GPUMem)+canBeSinglePass ops+ | all ok ops = Just $ combineScans ops | otherwise = Nothing@@ -50,7 +49,7 @@ -- | Compile 'SegScan' instance to host-level code with calls to -- various kernels. compileSegScan ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] ->@@ -61,7 +60,7 @@ target <- hostTarget <$> askEnv case target of CUDA- | Just scan' <- canBeSinglePass space scans ->+ | Just scan' <- canBeSinglePass scans -> SinglePass.compileSegScan pat lvl space scan' kbody _ -> TwoPass.compileSegScan pat lvl space scans kbody where
src/Futhark/CodeGen/ImpGen/GPU/SegScan/SinglePass.hs view
@@ -103,14 +103,14 @@ -- | Compile 'SegScan' instance to host-level code with calls to a -- single-pass kernel. compileSegScan ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> SegBinOp GPUMem -> KernelBody GPUMem -> CallKernelGen () compileSegScan pat lvl space scanOp kbody = do- let Pattern _ all_pes = pat+ let Pat all_pes = pat group_size = toInt64Exp <$> segGroupSize lvl n = product $ map toInt64Exp $ segSpaceDims space num_groups = Count (n `divUp` (unCount group_size * m))@@ -272,7 +272,7 @@ copyDWIMFix y [] (Var src) [i + 1] compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scanOp) $- forM_ (zip privateArrays $ bodyResult $ lambdaBody $ segBinOpLambda scanOp) $ \(dest, res) ->+ forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody $ segBinOpLambda scanOp) $ \(dest, res) -> copyDWIMFix dest [i + 1] res [] sComment "Publish results in shared memory" $ do@@ -437,7 +437,7 @@ ( do used1 <-- tvExp used1 + tvExp used2 compileStms mempty (bodyStms $ lambdaBody scanOp'') $- forM_ (zip3 agg1s tys $ bodyResult $ lambdaBody scanOp'') $+ forM_ (zip3 agg1s tys $ map resSubExp $ bodyResult $ lambdaBody scanOp'') $ \(agg1, ty, res) -> agg1 <~~ toExp' ty res ) flag <-- tvExp flag1@@ -460,7 +460,7 @@ forM_ (zip xs aggrs) $ \(x, aggr) -> dPrimV_ x (tvExp aggr) forM_ (zip ys prefixes) $ \(y, prefix) -> dPrimV_ y (tvExp prefix) compileStms mempty (bodyStms $ lambdaBody scanOp''') $- forM_ (zip3 prefixes tys $ bodyResult $ lambdaBody scanOp''') $+ forM_ (zip3 prefixes tys $ map resSubExp $ bodyResult $ lambdaBody scanOp''') $ \(prefix, ty, res) -> prefix <-- TPrimExp (toExp' ty res) -- end sWhen sOp localFence@@ -477,7 +477,7 @@ forM_ (zip ys accs) $ \(y, acc) -> dPrimV_ y $ tvExp acc compileStms mempty (bodyStms $ lambdaBody scanOp'''') $ everythingVolatile $- forM_ (zip incprefixArrays $ bodyResult $ lambdaBody scanOp'''') $+ forM_ (zip incprefixArrays $ map resSubExp $ bodyResult $ lambdaBody scanOp'''') $ \(incprefixArray, res) -> copyDWIMFix incprefixArray [tvExp dynamicId] res [] sOp globalFence everythingVolatile $ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []@@ -513,7 +513,7 @@ sIf (kernelLocalThreadId constants * m .<. boundary .&&. bNot blockNewSgm) ( compileStms mempty (bodyStms $ lambdaBody scanOp'''''') $- forM_ (zip3 xs tys $ bodyResult $ lambdaBody scanOp'''''') $+ forM_ (zip3 xs tys $ map resSubExp $ bodyResult $ lambdaBody scanOp'''''') $ \(x, ty, res) -> x <~~ toExp' ty res ) (forM_ (zip xs accs) $ \(x, acc) -> copyDWIMFix x [] (Var $ tvVar acc) [])@@ -528,7 +528,7 @@ -- only include prefix for the first segment part per thread copyDWIMFix y [] (Var src) [i] compileStms mempty (bodyStms $ lambdaBody scanOp''''') $- forM_ (zip privateArrays $ bodyResult $ lambdaBody scanOp''''') $+ forM_ (zip privateArrays $ map resSubExp $ bodyResult $ lambdaBody scanOp''''') $ \(dest, res) -> copyDWIMFix dest [i] res []
src/Futhark/CodeGen/ImpGen/GPU/SegScan/TwoPass.hs view
@@ -146,14 +146,14 @@ -- | Produce partially scanned intervals; one per workgroup. scanStage1 ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen (TV Int32, Imp.TExp Int64, CrossesSegment)-scanStage1 (Pattern _ all_pes) num_groups group_size space scans kbody = do+scanStage1 (Pat all_pes) num_groups group_size space scans kbody = do let num_groups' = fmap toInt64Exp num_groups group_size' = fmap toInt64Exp group_size num_threads <- dPrimV "num_threads" $ sExt32 $ unCount num_groups' * unCount group_size'@@ -241,7 +241,7 @@ sComment "combine with carry and write to local memory" $ compileStms mempty (bodyStms $ lambdaBody scan_op) $- forM_ (zip3 rets local_arrs (bodyResult $ lambdaBody scan_op)) $+ forM_ (zip3 rets local_arrs $ map resSubExp $ bodyResult $ lambdaBody scan_op) $ \(t, arr, se) -> copyDWIMFix arr [localArrayIndex constants t] se [] @@ -314,7 +314,7 @@ return (num_threads, elems_per_group, crossesSegment) scanStage2 ::- Pattern GPUMem ->+ Pat GPUMem -> TV Int32 -> Imp.TExp Int64 -> Count NumGroups SubExp ->@@ -322,7 +322,7 @@ SegSpace -> [SegBinOp GPUMem] -> CallKernelGen ()-scanStage2 (Pattern _ all_pes) stage1_num_threads elems_per_group num_groups crossesSegment space scans = do+scanStage2 (Pat all_pes) stage1_num_threads elems_per_group num_groups crossesSegment space scans = do let (gtids, dims) = unzip $ unSegSpace space dims' = map toInt64Exp dims @@ -391,7 +391,7 @@ [localArrayIndex constants t] scanStage3 ::- Pattern GPUMem ->+ Pat GPUMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> Imp.TExp Int64 ->@@ -399,7 +399,7 @@ SegSpace -> [SegBinOp GPUMem] -> CallKernelGen ()-scanStage3 (Pattern _ all_pes) num_groups group_size elems_per_group crossesSegment space scans = do+scanStage3 (Pat all_pes) num_groups group_size elems_per_group crossesSegment space scans = do let num_groups' = fmap toInt64Exp num_groups group_size' = fmap toInt64Exp group_size (gtids, dims) = unzip $ unSegSpace space@@ -478,7 +478,7 @@ -- | Compile 'SegScan' instance to host-level code with calls to -- various kernels. compileSegScan ::- Pattern GPUMem ->+ Pat GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] ->
src/Futhark/CodeGen/ImpGen/GPU/ToOpenCL.hs view
@@ -13,24 +13,25 @@ import Control.Monad.Identity import Control.Monad.Reader import Control.Monad.State-import Data.FileEmbed import qualified Data.Map.Strict as M import Data.Maybe import qualified Data.Set as S+import qualified Data.Text as T import qualified Futhark.CodeGen.Backends.GenericC as GC import Futhark.CodeGen.Backends.SimpleRep import Futhark.CodeGen.ImpCode.GPU hiding (Program) import qualified Futhark.CodeGen.ImpCode.GPU as ImpGPU import Futhark.CodeGen.ImpCode.OpenCL hiding (Program) import qualified Futhark.CodeGen.ImpCode.OpenCL as ImpOpenCL+import Futhark.CodeGen.RTS.C (atomicsH, halfH) import Futhark.Error (compilerLimitationS) import Futhark.IR.Prop (isBuiltInFunction) import Futhark.MonadFreshNames import Futhark.Util (zEncodeString)-import Futhark.Util.Pretty (prettyOneLine)-import qualified Language.C.Quote.CUDA as CUDAC+import Futhark.Util.Pretty (prettyOneLine, prettyText) import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C+import NeatInterpolation (untrimming) kernelsToCUDA, kernelsToOpenCL :: ImpGPU.Program -> ImpOpenCL.Program kernelsToCUDA = translateGPU TargetCUDA@@ -63,10 +64,10 @@ opencl_code = openClCode $ map snd $ M.elems kernels opencl_prelude =- unlines- [ pretty $ genPrelude target used_types,- unlines $ map pretty device_prototypes,- unlines $ map pretty device_defs+ T.unlines+ [ genPrelude target used_types,+ T.unlines $ map prettyText device_prototypes,+ T.unlines $ map prettyText device_defs ] in ImpOpenCL.Program opencl_code@@ -357,14 +358,14 @@ return ( Just $ SharedMemoryKArg size, Just [C.cparam|__local volatile typename int64_t* $id:mem_aligned|],- [C.citem|__local volatile char* restrict $id:mem = (__local volatile char*)$id:mem_aligned;|]+ [C.citem|__local volatile unsigned char* restrict $id:mem = (__local volatile unsigned char*) $id:mem_aligned;|] ) prepareLocalMemory TargetCUDA (mem, size) = do param <- newVName $ baseString mem ++ "_offset" return ( Just $ SharedMemoryKArg size, Just [C.cparam|uint $id:param|],- [C.citem|volatile char *$id:mem = &shared_mem[$id:param];|]+ [C.citem|volatile $ty:defaultMemBlockType $id:mem = &shared_mem[$id:param];|] ) useAsParam :: KernelUse -> Maybe C.Param@@ -376,7 +377,7 @@ _ -> GC.primTypeToCType bt in Just [C.cparam|$ty:ctp $id:name|] useAsParam (MemoryUse name) =- Just [C.cparam|__global unsigned char *$id:name|]+ Just [C.cparam|__global $ty:defaultMemBlockType $id:name|] useAsParam ConstUse {} = Nothing @@ -395,42 +396,34 @@ undef = "#undef " ++ pretty (C.toIdent v mempty) constDef _ = Nothing -openClCode :: [C.Func] -> String+openClCode :: [C.Func] -> T.Text openClCode kernels =- pretty [C.cunit|$edecls:funcs|]+ prettyText [C.cunit|$edecls:funcs|] where funcs = [ [C.cedecl|$func:kernel_func|] | kernel_func <- kernels ] -atomicsDefs :: String-atomicsDefs = $(embedStringFile "rts/c/atomics.h")--genOpenClPrelude :: S.Set PrimType -> [C.Definition]+genOpenClPrelude :: S.Set PrimType -> T.Text genOpenClPrelude ts =- -- Clang-based OpenCL implementations need this for 'static' to work.- [ [C.cedecl|$esc:("#ifdef cl_clang_storage_class_specifiers")|],- [C.cedecl|$esc:("#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable")|],- [C.cedecl|$esc:("#endif")|],- [C.cedecl|$esc:("#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable")|]- ]- ++ concat- [ [C.cunit|$esc:("#pragma OPENCL EXTENSION cl_khr_fp64 : enable")- $esc:("#define FUTHARK_F64_ENABLED")|]- | uses_float64- ]- ++ [C.cunit|-/* Some OpenCL programs dislike empty progams, or programs with no kernels.- * Declare a dummy kernel to ensure they remain our friends. */+ [untrimming|+// Clang-based OpenCL implementations need this for 'static' to work.+#ifdef cl_clang_storage_class_specifiers+#pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable+#endif+#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable+$enable_f64+// Some OpenCL programs dislike empty progams, or programs with no kernels.+// Declare a dummy kernel to ensure they remain our friends. __kernel void dummy_kernel(__global unsigned char *dummy, int n) { const int thread_gid = get_global_id(0); if (thread_gid >= n) return; } -$esc:("#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable")-$esc:("#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable")+#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable+#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable typedef char int8_t; typedef short int16_t;@@ -444,40 +437,36 @@ // NVIDIAs OpenCL does not create device-wide memory fences (see #734), so we // use inline assembly if we detect we are on an NVIDIA GPU.-$esc:("#ifdef cl_nv_pragma_unroll")+#ifdef cl_nv_pragma_unroll static inline void mem_fence_global() { asm("membar.gl;"); }-$esc:("#else")+#else static inline void mem_fence_global() { mem_fence(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); }-$esc:("#endif")+#endif static inline void mem_fence_local() { mem_fence(CLK_LOCAL_MEM_FENCE); } |]- ++ cIntOps- ++ cFloat32Ops- ++ cFloat32Funs- ++ (if uses_float64 then cFloat64Ops ++ cFloat64Funs ++ cFloatConvOps else [])- ++ [[C.cedecl|$esc:atomicsDefs|]]+ <> halfH+ <> cScalarDefs+ <> atomicsH where- uses_float64 = FloatType Float64 `S.member` ts+ enable_f64+ | FloatType Float64 `S.member` ts =+ [untrimming|+ #pragma OPENCL EXTENSION cl_khr_fp64 : enable+ #define FUTHARK_F64_ENABLED+ |]+ | otherwise = mempty -genCUDAPrelude :: [C.Definition]+genCUDAPrelude :: T.Text genCUDAPrelude =- cudafy ++ ops- where- ops =- cIntOps ++ cFloat32Ops ++ cFloat32Funs ++ cFloat64Ops- ++ cFloat64Funs- ++ cFloatConvOps- ++ [[C.cedecl|$esc:atomicsDefs|]]- cudafy =- [CUDAC.cunit|-$esc:("#define FUTHARK_CUDA")-$esc:("#define FUTHARK_F64_ENABLED")+ [untrimming|+#define FUTHARK_CUDA+#define FUTHARK_F64_ENABLED typedef char int8_t; typedef short int16_t;@@ -491,16 +480,15 @@ typedef uint16_t ushort; typedef uint32_t uint; typedef uint64_t ulong;-$esc:("#define __kernel extern \"C\" __global__ __launch_bounds__(MAX_THREADS_PER_BLOCK)")-$esc:("#define __global")-$esc:("#define __local")-$esc:("#define __private")-$esc:("#define __constant")-$esc:("#define __write_only")-$esc:("#define __read_only")+#define __kernel extern "C" __global__ __launch_bounds__(MAX_THREADS_PER_BLOCK)+#define __global+#define __local+#define __private+#define __constant+#define __write_only+#define __read_only -static inline int get_group_id_fn(int block_dim0, int block_dim1, int block_dim2, int d)-{+static inline int get_group_id_fn(int block_dim0, int block_dim1, int block_dim2, int d) { switch (d) { case 0: d = block_dim0; break; case 1: d = block_dim1; break;@@ -513,10 +501,9 @@ default: return 0; } }-$esc:("#define get_group_id(d) get_group_id_fn(block_dim0, block_dim1, block_dim2, d)")+#define get_group_id(d) get_group_id_fn(block_dim0, block_dim1, block_dim2, d) -static inline int get_num_groups_fn(int block_dim0, int block_dim1, int block_dim2, int d)-{+static inline int get_num_groups_fn(int block_dim0, int block_dim1, int block_dim2, int d) { switch (d) { case 0: d = block_dim0; break; case 1: d = block_dim1; break;@@ -529,10 +516,9 @@ default: return 0; } }-$esc:("#define get_num_groups(d) get_num_groups_fn(block_dim0, block_dim1, block_dim2, d)")+#define get_num_groups(d) get_num_groups_fn(block_dim0, block_dim1, block_dim2, d) -static inline int get_local_id(int d)-{+static inline int get_local_id(int d) { switch (d) { case 0: return threadIdx.x; case 1: return threadIdx.y;@@ -541,8 +527,7 @@ } } -static inline int get_local_size(int d)-{+static inline int get_local_size(int d) { switch (d) { case 0: return blockDim.x; case 1: return blockDim.y;@@ -551,21 +536,18 @@ } } -static inline int get_global_id_fn(int block_dim0, int block_dim1, int block_dim2, int d)-{+static inline int get_global_id_fn(int block_dim0, int block_dim1, int block_dim2, int d) { return get_group_id(d) * get_local_size(d) + get_local_id(d); }-$esc:("#define get_global_id(d) get_global_id_fn(block_dim0, block_dim1, block_dim2, d)")+#define get_global_id(d) get_global_id_fn(block_dim0, block_dim1, block_dim2, d) -static inline int get_global_size(int block_dim0, int block_dim1, int block_dim2, int d)-{+static inline int get_global_size(int block_dim0, int block_dim1, int block_dim2, int d) { return get_num_groups(d) * get_local_size(d); } -$esc:("#define CLK_LOCAL_MEM_FENCE 1")-$esc:("#define CLK_GLOBAL_MEM_FENCE 2")-static inline void barrier(int x)-{+#define CLK_LOCAL_MEM_FENCE 1+#define CLK_GLOBAL_MEM_FENCE 2+static inline void barrier(int x) { __syncthreads(); } static inline void mem_fence_local() {@@ -575,10 +557,13 @@ __threadfence(); } -$esc:("#define NAN (0.0/0.0)")-$esc:("#define INFINITY (1.0/0.0)")-extern volatile __shared__ char shared_mem[];+#define NAN (0.0/0.0)+#define INFINITY (1.0/0.0)+extern volatile __shared__ unsigned char shared_mem[]; |]+ <> halfH+ <> cScalarDefs+ <> atomicsH compilePrimExp :: PrimExp KernelConst -> C.Exp compilePrimExp e = runIdentity $ GC.compilePrimExp compileKernelConst e@@ -666,7 +651,7 @@ name' <- newVName $ pretty name ++ "_backing" GC.modifyUserState $ \s -> s {kernelLocalMemory = (name', fmap untyped size) : kernelLocalMemory s}- GC.stm [C.cstm|$id:name = (__local char*) $id:name';|]+ GC.stm [C.cstm|$id:name = (__local unsigned char*) $id:name';|] kernelOps (ErrorSync f) = do label <- nextErrorLabel pending <- kernelSyncPending <$> GC.getUserState@@ -738,8 +723,8 @@ -- atomicOps s (AtomicAdd t old arr ind val) = doAtomic s t old arr ind val "atomic_add" [C.cty|int|]- atomicOps s (AtomicFAdd Float32 old arr ind val) =- doAtomic s Float32 old arr ind val "atomic_fadd" [C.cty|float|]+ atomicOps s (AtomicFAdd t old arr ind val) =+ doAtomic s t old arr ind val "atomic_fadd" [C.cty|float|] atomicOps s (AtomicSMax t old arr ind val) = doAtomic s t old arr ind val "atomic_smax" [C.cty|int|] atomicOps s (AtomicSMin t old arr ind val) =@@ -816,14 +801,11 @@ s {kernelFailures = kernelFailures s ++ [FailureMsg msg backtrace]} let setArgs _ [] = return [] setArgs i (ErrorString {} : parts') = setArgs i parts'- setArgs i (ErrorInt32 x : parts') = do+ -- FIXME: bogus for non-ints.+ setArgs i (ErrorVal _ x : parts') = do x' <- GC.compileExp x stms <- setArgs (i + 1) parts' return $ [C.cstm|global_failure_args[$int:i] = (typename int64_t)$exp:x';|] : stms- setArgs i (ErrorInt64 x : parts') = do- x' <- GC.compileExp x- stms <- setArgs (i + 1) parts'- return $ [C.cstm|global_failure_args[$int:i] = $exp:x';|] : stms argstms <- setArgs (0 :: Int) parts what_next <- whatNext@@ -873,6 +855,7 @@ typesInCode (Assert e _ _) = typesInExp e typesInCode (Comment _ c) = typesInCode c typesInCode (DebugPrint _ v) = maybe mempty typesInExp v+typesInCode (TracePrint msg) = foldMap typesInExp msg typesInCode Op {} = mempty typesInExp :: Exp -> S.Set PrimType
src/Futhark/CodeGen/ImpGen/Multicore.hs view
@@ -58,7 +58,7 @@ -- See the ImpGen implementation of UpdateAcc for general notes. let is' = map toInt64Exp is (c, _space, arrs, dims, op) <- lookupAcc acc is'- sWhen (inBounds (map DimFix is') dims) $+ sWhen (inBounds (Slice (map DimFix is')) dims) $ case op of Nothing -> forM_ (zip arrs vs) $ \(arr, v) -> copyDWIMFix arr is' v []@@ -83,7 +83,7 @@ error $ "Missing locks for " ++ pretty acc withAcc ::- Pattern MCMem ->+ Pat MCMem -> [(Shape, [VName], Maybe (Lambda MCMem, [SubExp]))] -> Lambda MCMem -> MulticoreGen ()@@ -116,7 +116,7 @@ defCompileExp dest e compileMCOp ::- Pattern MCMem ->+ Pat MCMem -> MCOp MCMem () -> ImpM MCMem HostEnv Imp.Multicore () compileMCOp _ (OtherOp ()) = pure ()@@ -156,7 +156,7 @@ emit $ Imp.Op $ Imp.Segop s free_params seq_task par_task retvals $ scheduling_info (decideScheduling' op seq_code) compileSegOp ::- Pattern MCMem ->+ Pat MCMem -> SegOp () MCMem -> TV Int32 -> ImpM MCMem HostEnv Imp.Multicore Imp.Code
src/Futhark/CodeGen/ImpGen/Multicore/Base.hs view
@@ -60,7 +60,7 @@ arrParam arr = do name_entry <- lookupVar arr case name_entry of- ArrayVar _ (ArrayEntry (MemLocation mem _ _) _) ->+ ArrayVar _ (ArrayEntry (MemLoc mem _ _) _) -> return $ Imp.MemParam mem DefaultSpace _ -> error $ "arrParam: could not handle array " ++ show arr @@ -93,9 +93,9 @@ -- When the SegRed's return value is a scalar -- we perform a call by value-result in the segop function-getReturnParams :: Pattern MCMem -> SegOp () MCMem -> MulticoreGen [Imp.Param]+getReturnParams :: Pat MCMem -> SegOp () MCMem -> MulticoreGen [Imp.Param] getReturnParams pat SegRed {} = do- let retvals = map patElemName $ patternElements pat+ let retvals = map patElemName $ patElems pat retvals_ts <- mapM lookupType retvals concat <$> zipWithM toParam retvals retvals_ts getReturnParams _ _ = return mempty@@ -111,7 +111,7 @@ PatElem MCMem -> KernelResult -> MulticoreGen ()-compileThreadResult space pe (Returns _ what) = do+compileThreadResult space pe (Returns _ _ what) = do let is = map (Imp.vi64 . fst) $ unSegSpace space copyDWIMFix (patElemName pe) is what [] compileThreadResult _ _ ConcatReturns {} =
src/Futhark/CodeGen/ImpGen/Multicore/SegHist.hs view
@@ -16,7 +16,7 @@ import Prelude hiding (quot, rem) compileSegHist ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem ->@@ -34,7 +34,7 @@ segHistOpChunks = chunks . map (length . histNeutral) nonsegmentedHist ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem ->@@ -91,7 +91,7 @@ return $ f l' atomicHistogram ::- Pattern MCMem ->+ Pat MCMem -> TV Int64 -> SegSpace -> [HistOp MCMem] ->@@ -101,7 +101,7 @@ let (is, ns) = unzip $ unSegSpace space ns_64 = map toInt64Exp ns let num_red_res = length histops + sum (map (length . histNeutral) histops)- (all_red_pes, map_pes) = splitAt num_red_res $ patternValueElements pat+ (all_red_pes, map_pes) = splitAt num_red_res $ patElems pat atomicOps <- mapM onOpAtomic histops @@ -144,7 +144,7 @@ copyDWIMFix (paramName acc_p) [] (Var arr) bucket op_body = compileBody' [] $ lambdaBody $ histOp op writeArray arr val = copyDWIMFix arr bucket val []- do_hist = zipWithM_ writeArray arrs $ bodyResult $ lambdaBody $ histOp op+ do_hist = zipWithM_ writeArray arrs $ map resSubExp $ bodyResult $ lambdaBody $ histOp op sComment "Start of body" $ do dLParams acc_params@@ -159,7 +159,7 @@ -- across the histogram indicies. -- This is expected to be fast if len(histDest) is small subHistogram ::- Pattern MCMem ->+ Pat MCMem -> TV Int64 -> SegSpace -> [HistOp MCMem] ->@@ -172,10 +172,10 @@ let (is, ns) = unzip $ unSegSpace space ns_64 = map toInt64Exp ns - let pes = patternElements pat+ let pes = patElems pat num_red_res = length histops + sum (map (length . histNeutral) histops) map_pes = drop num_red_res pes- per_red_pes = segHistOpChunks histops $ patternValueElements pat+ per_red_pes = segHistOpChunks histops $ patElems pat -- Allocate array of subhistograms in the calling thread. Each -- tasks will work in its own private allocations (to avoid false@@ -270,7 +270,7 @@ segred_op = SegBinOp Noncommutative (histOp op) (histNeutral op) (histShape op) nsubtasks_red <- dPrim "num_tasks" $ IntType Int32- red_code <- compileSegRed' (Pattern [] red_pes) segred_space [segred_op] nsubtasks_red $ \red_cont ->+ red_code <- compileSegRed' (Pat red_pes) segred_space [segred_op] nsubtasks_red $ \red_cont -> red_cont $ flip map hists $ \subhisto -> ( Var subhisto,@@ -291,7 +291,7 @@ -- parallelize over the segments, -- where each segment is updated sequentially. segmentedHist ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem ->@@ -308,7 +308,7 @@ compileSegHistBody :: Imp.TExp Int64 ->- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [HistOp MCMem] -> KernelBody MCMem ->@@ -318,8 +318,8 @@ ns_64 = map toInt64Exp ns let num_red_res = length histops + sum (map (length . histNeutral) histops)- map_pes = drop num_red_res $ patternValueElements pat- per_red_pes = segHistOpChunks histops $ patternValueElements pat+ map_pes = drop num_red_res $ patElems pat+ per_red_pes = segHistOpChunks histops $ patElems pat collect $ do let inner_bound = last ns_64@@ -357,5 +357,5 @@ forM_ (zip vs_params vs') $ \(p, v) -> copyDWIMFix (paramName p) [] v vec_is compileStms mempty (bodyStms $ lambdaBody lam) $- forM_ (zip red_pes $ bodyResult $ lambdaBody lam) $+ forM_ (zip red_pes $ map resSubExp $ bodyResult $ lambdaBody lam) $ \(pe, se) -> copyDWIMFix (patElemName pe) (map Imp.vi64 (init is) ++ [buck] ++ vec_is) se []
src/Futhark/CodeGen/ImpGen/Multicore/SegMap.hs view
@@ -16,26 +16,21 @@ PatElemT dec -> KernelResult -> MulticoreGen ()-writeResult is pe (Returns _ se) =+writeResult is pe (Returns _ _ se) = copyDWIMFix (patElemName pe) (map Imp.vi64 is) se []-writeResult _ pe (WriteReturns (Shape rws) _ idx_vals) = do+writeResult _ pe (WriteReturns _ (Shape rws) _ idx_vals) = do let (iss, vs) = unzip idx_vals rws' = map toInt64Exp rws forM_ (zip iss vs) $ \(slice, v) -> do- let slice' = map (fmap toInt64Exp) slice- condInBounds (DimFix i) rw =- 0 .<=. i .&&. i .<. rw- condInBounds (DimSlice i n s) rw =- 0 .<=. i .&&. i + n * s .<. rw- in_bounds = foldl1 (.&&.) $ zipWith condInBounds slice' rws'- when_in_bounds = copyDWIM (patElemName pe) slice' v []- sWhen in_bounds when_in_bounds+ let slice' = fmap toInt64Exp slice+ when_in_bounds = copyDWIM (patElemName pe) (unSlice slice') v []+ sWhen (inBounds slice' rws') when_in_bounds writeResult _ _ res = error $ "writeResult: cannot handle " ++ pretty res compileSegMapBody :: TV Int64 ->- Pattern MCMem ->+ Pat MCMem -> SegSpace -> KernelBody MCMem -> MulticoreGen Imp.Code@@ -47,10 +42,10 @@ emit $ Imp.DebugPrint "SegMap fbody" Nothing dIndexSpace (zip is ns') $ tvExp flat_idx compileStms (freeIn kres) kstms' $- zipWithM_ (writeResult is) (patternElements pat) kres+ zipWithM_ (writeResult is) (patElems pat) kres compileSegMap ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> KernelBody MCMem -> MulticoreGen Imp.Code
src/Futhark/CodeGen/ImpGen/Multicore/SegRed.hs view
@@ -16,7 +16,7 @@ -- | Generate code for a SegRed construct compileSegRed ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -28,14 +28,14 @@ let (red_res, map_res) = splitAt (segBinOpResults reds) $ kernelBodyResult kbody sComment "save map-out results" $ do- let map_arrs = drop (segBinOpResults reds) $ patternElements pat+ let map_arrs = drop (segBinOpResults reds) $ patElems pat zipWithM_ (compileThreadResult space) map_arrs map_res red_cont $ zip (map kernelResultSubExp red_res) $ repeat [] -- | Like 'compileSegRed', but where the body is a monadic action. compileSegRed' ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> TV Int32 ->@@ -72,7 +72,7 @@ nextParams slug = drop (length (slugNeutral slug)) $ slugParams slug nonsegmentedReduction ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> TV Int32 ->@@ -149,7 +149,7 @@ sComment "Red body" $ compileStms mempty (bodyStms $ slugBody slug) $- forM_ (zip local_accs (bodyResult $ slugBody slug)) $+ forM_ (zip local_accs $ map resSubExp $ bodyResult $ slugBody slug) $ \(local_acc, se) -> copyDWIMFix local_acc vec_is se [] @@ -163,13 +163,13 @@ emit $ Imp.Op $ Imp.ParLoop "segred_stage_1" (tvVar flat_idx) (body_allocs <> prebody) fbody' postbody free_params $ segFlat space reductionStage2 ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> Imp.TExp Int32 -> [SegBinOpSlug] -> MulticoreGen () reductionStage2 pat space nsubtasks slugs = do- let per_red_pes = segBinOpChunks (map slugOp slugs) $ patternValueElements pat+ let per_red_pes = segBinOpChunks (map slugOp slugs) $ patElems pat phys_id = Imp.vi64 (segFlat space) sComment "neutral-initialise the output" $ forM_ (zip (map slugOp slugs) per_red_pes) $ \(red, red_res) ->@@ -192,7 +192,7 @@ copyDWIMFix (paramName p) [] (Var acc) (phys_id : vec_is) sComment "red body" $ compileStms mempty (bodyStms $ slugBody slug) $- forM_ (zip red_res (bodyResult $ slugBody slug)) $+ forM_ (zip red_res $ map resSubExp $ bodyResult $ slugBody slug) $ \(pe, se') -> copyDWIMFix (patElemName pe) vec_is se' [] -- Each thread reduces over the number of segments@@ -200,7 +200,7 @@ -- Maybe we should select the work of the inner loop -- based on n_segments and dimensions etc. segmentedReduction ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> DoSegBody ->@@ -215,7 +215,7 @@ compileSegRedBody :: TV Int64 ->- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> DoSegBody ->@@ -226,7 +226,7 @@ inner_bound = last ns_64 n_segments' = tvExp n_segments - let per_red_pes = segBinOpChunks reds $ patternValueElements pat+ let per_red_pes = segBinOpChunks reds $ patElems pat -- Perform sequential reduce on inner most dimension collect $ do flat_idx <- dPrimVE "flat_idx" $ n_segments' * inner_bound@@ -263,5 +263,5 @@ let lbody = (lambdaBody . segBinOpLambda) red compileStms mempty (bodyStms lbody) $ sComment "write back to res" $- forM_ (zip pes (bodyResult lbody)) $+ forM_ (zip pes $ map resSubExp $ bodyResult lbody) $ \(pe, se') -> copyDWIMFix (patElemName pe) (map Imp.vi64 (init is) ++ vec_is) se' []
src/Futhark/CodeGen/ImpGen/Multicore/SegScan.hs view
@@ -14,7 +14,7 @@ -- Compile a SegScan construct compileSegScan ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -45,7 +45,7 @@ sAllocArray s pt full_shape DefaultSpace nonsegmentedScan ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -64,7 +64,7 @@ scanStage3 pat space scan_ops3 kbody scanStage1 ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -72,7 +72,7 @@ scanStage1 pat space scan_ops kbody = do let (all_scan_res, map_res) = splitAt (segBinOpResults scan_ops) $ kernelBodyResult kbody per_scan_res = segBinOpChunks scan_ops all_scan_res- per_scan_pes = segBinOpChunks scan_ops $ patternValueElements pat+ per_scan_pes = segBinOpChunks scan_ops $ patElems pat let (is, ns) = unzip $ unSegSpace space ns' = map toInt64Exp ns iter <- dPrim "iter" $ IntType Int64@@ -103,7 +103,7 @@ sComment "stage 1 scan body" $ compileStms mempty (kernelBodyStms kbody) $ do sComment "write mapped values results to memory" $ do- let map_arrs = drop (segBinOpResults scan_ops) $ patternElements pat+ let map_arrs = drop (segBinOpResults scan_ops) $ patElems pat zipWithM_ (compileThreadResult space) map_arrs map_res forM_ (zip4 per_scan_pes scan_ops per_scan_res local_accs) $ \(pes, scan_op, scan_res, acc) ->@@ -118,7 +118,7 @@ copyDWIMFix (paramName p) [] (kernelResultSubExp se) vec_is compileStms mempty (bodyStms $ lamBody scan_op) $- forM_ (zip3 acc pes (bodyResult $ lamBody scan_op)) $+ forM_ (zip3 acc pes $ map resSubExp $ bodyResult $ lamBody scan_op) $ \(acc', pe, se) -> do copyDWIMFix (patElemName pe) (map Imp.vi64 is ++ vec_is) se [] copyDWIMFix acc' vec_is se []@@ -128,7 +128,7 @@ emit $ Imp.Op $ Imp.ParLoop "scan_stage_1" (tvVar iter) (body_allocs <> prebody) body' mempty free_params $ segFlat space scanStage2 ::- Pattern MCMem ->+ Pat MCMem -> TV Int32 -> SegSpace -> [SegBinOp MCMem] ->@@ -138,7 +138,7 @@ emit $ Imp.DebugPrint "nonsegmentedScan stage 2" Nothing let (is, ns) = unzip $ unSegSpace space ns_64 = map toInt64Exp ns- per_scan_pes = segBinOpChunks scan_ops $ patternValueElements pat+ per_scan_pes = segBinOpChunks scan_ops $ patElems pat nsubtasks' = tvExp nsubtasks dScope Nothing $ scopeOfLParams $ concatMap (lambdaParams . segBinOpLambda) scan_ops@@ -178,7 +178,7 @@ copyDWIMFix (paramName p) [] (Var $ patElemName pe) ((offset_index' - 1) : vec_is) compileStms mempty (bodyStms $ lamBody scan_op) $- forM_ (zip3 acc pes (bodyResult $ lamBody scan_op)) $+ forM_ (zip3 acc pes $ map resSubExp $ bodyResult $ lamBody scan_op) $ \(acc', pe, se) -> do copyDWIMFix (patElemName pe) ((offset_index' - 1) : vec_is) se [] copyDWIMFix acc' vec_is se []@@ -186,7 +186,7 @@ -- Stage 3 : Finally each thread partially scans a chunk of the input -- reading its corresponding carry-in scanStage3 ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -195,7 +195,7 @@ let (is, ns) = unzip $ unSegSpace space all_scan_res = take (segBinOpResults scan_ops) $ kernelBodyResult kbody per_scan_res = segBinOpChunks scan_ops all_scan_res- per_scan_pes = segBinOpChunks scan_ops $ patternValueElements pat+ per_scan_pes = segBinOpChunks scan_ops $ patElems pat ns' = map toInt64Exp ns iter <- dPrimV "iter" (0 :: Imp.TExp Int64)@@ -238,7 +238,7 @@ copyDWIMFix (paramName p) [] (kernelResultSubExp se) vec_is compileStms mempty (bodyStms $ lamBody scan_op) $- forM_ (zip3 pes (bodyResult $ lamBody scan_op) acc) $+ forM_ (zip3 pes (map resSubExp $ bodyResult $ lamBody scan_op) acc) $ \(pe, se, acc') -> do copyDWIMFix (patElemName pe) (map Imp.vi64 is ++ vec_is) se [] copyDWIMFix acc' vec_is se []@@ -251,7 +251,7 @@ -- parallelize over the segments and each segment is -- scanned sequentially. segmentedScan ::- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -267,7 +267,7 @@ compileSegScanBody :: Imp.TExp Int64 ->- Pattern MCMem ->+ Pat MCMem -> SegSpace -> [SegBinOp MCMem] -> KernelBody MCMem ->@@ -276,7 +276,7 @@ let (is, ns) = unzip $ unSegSpace space ns_64 = map toInt64Exp ns - let per_scan_pes = segBinOpChunks scan_ops $ patternValueElements pat+ let per_scan_pes = segBinOpChunks scan_ops $ patElems pat collect $ forM_ (zip scan_ops per_scan_pes) $ \(scan_op, scan_pes) -> do dScope Nothing $ scopeOfLParams $ lambdaParams $ segBinOpLambda scan_op@@ -297,11 +297,11 @@ copyDWIMFix (paramName p) [] (kernelResultSubExp se) [] sComment "write mapped values results to memory" $- forM_ (zip (drop (length $ segBinOpNeutral scan_op) $ patternElements pat) map_res) $ \(pe, se) ->+ forM_ (zip (drop (length $ segBinOpNeutral scan_op) $ patElems pat) map_res) $ \(pe, se) -> copyDWIMFix (patElemName pe) (map Imp.vi64 is) (kernelResultSubExp se) [] sComment "combine with carry and write to memory" $ compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scan_op) $- forM_ (zip3 scan_x_params scan_pes (bodyResult $ lambdaBody $ segBinOpLambda scan_op)) $ \(p, pe, se) -> do+ forM_ (zip3 scan_x_params scan_pes $ map resSubExp $ bodyResult $ lambdaBody $ segBinOpLambda scan_op) $ \(p, pe, se) -> do copyDWIMFix (patElemName pe) (map Imp.vi64 is) se [] copyDWIMFix (paramName p) [] se []
+ src/Futhark/CodeGen/RTS/C.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE TemplateHaskell #-}++-- | Code snippets used by the C backends.+module Futhark.CodeGen.RTS.C+ ( atomicsH,+ chaselevH,+ cudaH,+ freeListH,+ halfH,+ lockH,+ openclH,+ scalarF16H,+ scalarH,+ schedulerH,+ serverH,+ timingH,+ tuningH,+ utilH,+ valuesH,+ )+where++import Data.FileEmbed+import qualified Data.Text as T++-- We mark everything here NOINLINE so that the dependent modules+-- don't have to be recompiled just because we change the RTS files.++-- | @rts/c/atomics.h@+atomicsH :: T.Text+atomicsH = $(embedStringFile "rts/c/atomics.h")+{-# NOINLINE atomicsH #-}++-- | @rts/c/chaselev.h@+chaselevH :: T.Text+chaselevH = $(embedStringFile "rts/c/chaselev.h")+{-# NOINLINE chaselevH #-}++-- | @rts/c/cuda.h@+cudaH :: T.Text+cudaH = $(embedStringFile "rts/c/cuda.h")+{-# NOINLINE cudaH #-}++-- | @rts/c/free_list.h@+freeListH :: T.Text+freeListH = $(embedStringFile "rts/c/free_list.h")+{-# NOINLINE freeListH #-}++-- | @rts/c/half.h@+halfH :: T.Text+halfH = $(embedStringFile "rts/c/half.h")+{-# NOINLINE halfH #-}++-- | @rts/c/lock.h@+lockH :: T.Text+lockH = $(embedStringFile "rts/c/lock.h")+{-# NOINLINE lockH #-}++-- | @rts/c/opencl.h@+openclH :: T.Text+openclH = $(embedStringFile "rts/c/opencl.h")+{-# NOINLINE openclH #-}++-- | @rts/c/scalar_f16.h@+scalarF16H :: T.Text+scalarF16H = $(embedStringFile "rts/c/scalar_f16.h")+{-# NOINLINE scalarF16H #-}++-- | @rts/c/scalar.h@+scalarH :: T.Text+scalarH = $(embedStringFile "rts/c/scalar.h")+{-# NOINLINE scalarH #-}++-- | @rts/c/scheduler.h@+schedulerH :: T.Text+schedulerH = $(embedStringFile "rts/c/scheduler.h")+{-# NOINLINE schedulerH #-}++-- | @rts/c/server.h@+serverH :: T.Text+serverH = $(embedStringFile "rts/c/server.h")+{-# NOINLINE serverH #-}++-- | @rts/c/timing.h@+timingH :: T.Text+timingH = $(embedStringFile "rts/c/timing.h")+{-# NOINLINE timingH #-}++-- | @rts/c/tuning.h@+tuningH :: T.Text+tuningH = $(embedStringFile "rts/c/tuning.h")+{-# NOINLINE tuningH #-}++-- | @rts/c/util.h@+utilH :: T.Text+utilH = $(embedStringFile "rts/c/util.h")+{-# NOINLINE utilH #-}++-- | @rts/c/values.h@+valuesH :: T.Text+valuesH = $(embedStringFile "rts/c/values.h")+{-# NOINLINE valuesH #-}
+ src/Futhark/CodeGen/RTS/JavaScript.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}++-- | Code snippets used by the JS backends.+module Futhark.CodeGen.RTS.JavaScript+ ( serverJs,+ valuesJs,+ wrapperclassesJs,+ )+where++import Data.FileEmbed+import qualified Data.Text as T++-- | @rts/javascript/server.js@+serverJs :: T.Text+serverJs = $(embedStringFile "rts/javascript/server.js")++-- | @rts/javascript/values.js@+valuesJs :: T.Text+valuesJs = $(embedStringFile "rts/javascript/values.js")++-- | @rts/javascript/wrapperclasses.js@+wrapperclassesJs :: T.Text+wrapperclassesJs = $(embedStringFile "rts/javascript/wrapperclasses.js")
+ src/Futhark/CodeGen/RTS/Python.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE TemplateHaskell #-}++-- | Code snippets used by the Python backends.+module Futhark.CodeGen.RTS.Python+ ( memoryPy,+ openclPy,+ panicPy,+ scalarPy,+ serverPy,+ tuningPy,+ valuesPy,+ )+where++import Data.FileEmbed+import qualified Data.Text as T++-- | @rts/python/memory.py@+memoryPy :: T.Text+memoryPy = $(embedStringFile "rts/python/memory.py")++-- | @rts/python/opencl.py@+openclPy :: T.Text+openclPy = $(embedStringFile "rts/python/opencl.py")++-- | @rts/python/panic.py@+panicPy :: T.Text+panicPy = $(embedStringFile "rts/python/panic.py")++-- | @rts/python/scalar.py@+scalarPy :: T.Text+scalarPy = $(embedStringFile "rts/python/scalar.py")++-- | @rts/python/server.py@+serverPy :: T.Text+serverPy = $(embedStringFile "rts/python/server.py")++-- | @rts/python/tuning.py@+tuningPy :: T.Text+tuningPy = $(embedStringFile "rts/python/tuning.py")++-- | @rts/python/values.py@+valuesPy :: T.Text+valuesPy = $(embedStringFile "rts/python/values.py")
src/Futhark/CodeGen/SetDefaultSpace.hs view
@@ -4,6 +4,7 @@ -- assumes that 'DefaultSpace' is CPU memory. module Futhark.CodeGen.SetDefaultSpace ( setDefaultSpace,+ setDefaultCodeSpace, ) where @@ -14,20 +15,24 @@ setDefaultSpace :: Space -> Definitions op -> Definitions op setDefaultSpace space (Definitions (Constants ps consts) (Functions fundecs)) = Definitions- (Constants (map (setParamSpace space) ps) (setBodySpace space consts))+ (Constants (map (setParamSpace space) ps) (setCodeSpace space consts)) ( Functions [ (fname, setFunctionSpace space func) | (fname, func) <- fundecs ] ) +-- | Like 'setDefaultSpace', but for 'Code'.+setDefaultCodeSpace :: Space -> Code op -> Code op+setDefaultCodeSpace = setCodeSpace+ setFunctionSpace :: Space -> Function op -> Function op setFunctionSpace space (Function entry outputs inputs body results args) = Function entry (map (setParamSpace space) outputs) (map (setParamSpace space) inputs)- (setBodySpace space body)+ (setCodeSpace space body) (map (setExtValueSpace space) results) (map (setExtValueSpace space) args) @@ -49,16 +54,16 @@ setValueSpace _ (ScalarValue bt ept v) = ScalarValue bt ept v -setBodySpace :: Space -> Code op -> Code op-setBodySpace space (Allocate v e old_space) =+setCodeSpace :: Space -> Code op -> Code op+setCodeSpace space (Allocate v e old_space) = Allocate v (fmap (setTExpSpace space) e) $ setSpace space old_space-setBodySpace space (Free v old_space) =+setCodeSpace space (Free v old_space) = Free v $ setSpace space old_space-setBodySpace space (DeclareMem name old_space) =+setCodeSpace space (DeclareMem name old_space) = DeclareMem name $ setSpace space old_space-setBodySpace space (DeclareArray name _ t vs) =+setCodeSpace space (DeclareArray name _ t vs) = DeclareArray name space t vs-setBodySpace space (Copy dest dest_offset dest_space src src_offset src_space n) =+setCodeSpace space (Copy dest dest_offset dest_space src src_offset src_space n) = Copy dest (fmap (setTExpSpace space) dest_offset)@@ -70,7 +75,7 @@ where dest_space' = setSpace space dest_space src_space' = setSpace space src_space-setBodySpace space (Write dest dest_offset bt dest_space vol e) =+setCodeSpace space (Write dest dest_offset bt dest_space vol e) = Write dest (fmap (setTExpSpace space) dest_offset)@@ -78,34 +83,36 @@ (setSpace space dest_space) vol (setExpSpace space e)-setBodySpace space (c1 :>>: c2) =- setBodySpace space c1 :>>: setBodySpace space c2-setBodySpace space (For i e body) =- For i (setExpSpace space e) $ setBodySpace space body-setBodySpace space (While e body) =- While (setTExpSpace space e) $ setBodySpace space body-setBodySpace space (If e c1 c2) =- If (setTExpSpace space e) (setBodySpace space c1) (setBodySpace space c2)-setBodySpace space (Comment s c) =- Comment s $ setBodySpace space c-setBodySpace _ Skip =+setCodeSpace space (c1 :>>: c2) =+ setCodeSpace space c1 :>>: setCodeSpace space c2+setCodeSpace space (For i e body) =+ For i (setExpSpace space e) $ setCodeSpace space body+setCodeSpace space (While e body) =+ While (setTExpSpace space e) $ setCodeSpace space body+setCodeSpace space (If e c1 c2) =+ If (setTExpSpace space e) (setCodeSpace space c1) (setCodeSpace space c2)+setCodeSpace space (Comment s c) =+ Comment s $ setCodeSpace space c+setCodeSpace _ Skip = Skip-setBodySpace _ (DeclareScalar name vol bt) =+setCodeSpace _ (DeclareScalar name vol bt) = DeclareScalar name vol bt-setBodySpace space (SetScalar name e) =+setCodeSpace space (SetScalar name e) = SetScalar name $ setExpSpace space e-setBodySpace space (SetMem to from old_space) =+setCodeSpace space (SetMem to from old_space) = SetMem to from $ setSpace space old_space-setBodySpace space (Call dests fname args) =+setCodeSpace space (Call dests fname args) = Call dests fname $ map setArgSpace args where setArgSpace (MemArg m) = MemArg m setArgSpace (ExpArg e) = ExpArg $ setExpSpace space e-setBodySpace space (Assert e msg loc) =- Assert (setExpSpace space e) msg loc-setBodySpace space (DebugPrint s v) =+setCodeSpace space (Assert e msg loc) =+ Assert (setExpSpace space e) (fmap (setExpSpace space) msg) loc+setCodeSpace space (DebugPrint s v) = DebugPrint s $ fmap (setExpSpace space) v-setBodySpace _ (Op op) =+setCodeSpace space (TracePrint msg) =+ TracePrint $ fmap (setExpSpace space) msg+setCodeSpace _ (Op op) = Op op setExpSpace :: Space -> Exp -> Exp
src/Futhark/Construct.hs view
@@ -16,29 +16,29 @@ -- own bespoke source of unique names) to manually construct -- expressions, statements, and entire ASTs. In practice, this would -- be very tedious. Instead, we have defined a collection of building--- blocks (centered around the 'MonadBinder' type class) that permits+-- blocks (centered around the 'MonadBuilder' type class) that permits -- a more abstract way of generating code. -- -- Constructing ASTs with these building blocks requires you to ensure -- that all free variables are in scope. See -- "Futhark.IR.Prop.Scope". ----- == 'MonadBinder'+-- == 'MonadBuilder' ----- A monad that implements 'MonadBinder' tracks the statements added+-- A monad that implements 'MonadBuilder' tracks the statements added -- so far, the current names in scope, and allows you to add -- additional statements with 'addStm'. Any monad that implements--- 'MonadBinder' also implements the t'REp' type family, which--- indicates which rep it works with. Inside a 'MonadBinder' we can+-- 'MonadBuilder' also implements the t'Rep' type family, which+-- indicates which rep it works with. Inside a 'MonadBuilder' we can -- use 'collectStms' to gather up the 'Stms' added with 'addStm' in -- some nested computation. ----- The 'BinderT' monad (and its convenient 'Binder' version) provides--- the simplest implementation of 'MonadBinder'.+-- The 'BuilderT' monad (and its convenient 'Builder' version) provides+-- the simplest implementation of 'MonadBuilder'. -- -- == Higher-level building blocks ----- On top of the raw facilities provided by 'MonadBinder', we have+-- On top of the raw facilities provided by 'MonadBuilder', we have -- more convenient facilities. For example, 'letSubExp' lets us -- conveniently create a 'Stm' for an 'Exp' that produces a /single/ -- value, and returns the (fresh) name for the resulting variable:@@ -60,6 +60,7 @@ letTupExp', letInPlace, eSubExp,+ eParam, eIf, eIf', eBinOp,@@ -74,7 +75,6 @@ eBlank, eAll, eOutOfBounds,- eWriteArray, asIntZ, asIntS, resultBody,@@ -93,7 +93,7 @@ isFullSlice, sliceAt, ifCommon,- module Futhark.Binder,+ module Futhark.Builder, -- * Result types instantiateShapes,@@ -109,15 +109,15 @@ import Control.Monad.Identity import Control.Monad.State-import Control.Monad.Writer-import Data.Bifunctor (second) import Data.List (sortOn) import qualified Data.Map.Strict as M-import Futhark.Binder+import qualified Data.Set as S+import Futhark.Builder import Futhark.IR+import Futhark.Util (maybeNth) letSubExp ::- MonadBinder m =>+ MonadBuilder m => String -> Exp (Rep m) -> m SubExp@@ -125,7 +125,7 @@ letSubExp desc e = Var <$> letExp desc e letExp ::- MonadBinder m =>+ MonadBuilder m => String -> Exp (Rep m) -> m VName@@ -140,7 +140,7 @@ _ -> error $ "letExp: tuple-typed expression given:\n" ++ pretty e letInPlace ::- MonadBinder m =>+ MonadBuilder m => String -> VName -> Slice SubExp ->@@ -148,30 +148,33 @@ m VName letInPlace desc src slice e = do tmp <- letSubExp (desc ++ "_tmp") e- letExp desc $ BasicOp $ Update src slice tmp+ letExp desc $ BasicOp $ Update Unsafe src slice tmp letSubExps ::- MonadBinder m =>+ MonadBuilder m => String -> [Exp (Rep m)] -> m [SubExp] letSubExps desc = mapM $ letSubExp desc +-- | Only returns those pattern names that are not used in the pattern+-- itself (the "non-existential" part, you could say). letTupExp ::- (MonadBinder m) =>+ (MonadBuilder m) => String -> Exp (Rep m) -> m [VName] letTupExp _ (BasicOp (SubExp (Var v))) = return [v] letTupExp name e = do- numValues <- length <$> expExtType e- names <- replicateM numValues $ newVName name+ e_t <- expExtType e+ names <- replicateM (length e_t) $ newVName name letBindNames names e- return names+ let ctx = shapeContext e_t+ pure $ map fst $ filter ((`S.notMember` ctx) . snd) $ zip names [0 ..] letTupExp' ::- (MonadBinder m) =>+ (MonadBuilder m) => String -> Exp (Rep m) -> m [SubExp]@@ -179,13 +182,19 @@ letTupExp' name ses = map Var <$> letTupExp name ses eSubExp ::- MonadBinder m =>+ MonadBuilder m => SubExp -> m (Exp (Rep m)) eSubExp = pure . BasicOp . SubExp +eParam ::+ MonadBuilder m =>+ Param t ->+ m (Exp (Rep m))+eParam = eSubExp . Var . paramName+ eIf ::- (MonadBinder m, BranchType (Rep m) ~ ExtType) =>+ (MonadBuilder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) ->@@ -194,7 +203,7 @@ -- | As 'eIf', but an 'IfSort' can be given. eIf' ::- (MonadBinder m, BranchType (Rep m) ~ ExtType) =>+ (MonadBuilder m, BranchType (Rep m) ~ ExtType) => m (Exp (Rep m)) -> m (Body (Rep m)) -> m (Body (Rep m)) ->@@ -208,15 +217,14 @@ ts <- generaliseExtTypes <$> bodyExtType te' <*> bodyExtType fe' te'' <- addContextForBranch ts te' fe'' <- addContextForBranch ts fe'- return $ If ce' te'' fe'' $ IfDec ts if_sort+ let ts' = replicate (length (shapeContext ts)) (Prim int64) ++ ts+ return $ If ce' te'' fe'' $ IfDec ts' if_sort where addContextForBranch ts (Body _ stms val_res) = do- body_ts <- extendedScope (traverse subExpType val_res) stmsscope+ body_ts <- extendedScope (traverse subExpResType val_res) stmsscope let ctx_res =- map snd $- sortOn fst $- M.toList $ shapeExtMapping ts body_ts- mkBodyM stms $ ctx_res ++ val_res+ map snd $ sortOn fst $ M.toList $ shapeExtMapping ts body_ts+ mkBodyM stms $ subExpsRes ctx_res ++ val_res where stmsscope = scopeOf stms @@ -225,12 +233,12 @@ bodyExtType :: (HasScope rep m, Monad m) => Body rep -> m [ExtType] bodyExtType (Body _ stms res) = existentialiseExtTypes (M.keys stmsscope) . staticShapes- <$> extendedScope (traverse subExpType res) stmsscope+ <$> extendedScope (traverse subExpResType res) stmsscope where stmsscope = scopeOf stms eBinOp ::- MonadBinder m =>+ MonadBuilder m => BinOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) ->@@ -241,7 +249,7 @@ return $ BasicOp $ BinOp op x' y' eCmpOp ::- MonadBinder m =>+ MonadBuilder m => CmpOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) ->@@ -252,7 +260,7 @@ return $ BasicOp $ CmpOp op x' y' eConvOp ::- MonadBinder m =>+ MonadBuilder m => ConvOp -> m (Exp (Rep m)) -> m (Exp (Rep m))@@ -261,7 +269,7 @@ return $ BasicOp $ ConvOp op x' eSignum ::- MonadBinder m =>+ MonadBuilder m => m (Exp (Rep m)) -> m (Exp (Rep m)) eSignum em = do@@ -275,25 +283,25 @@ error $ "eSignum: operand " ++ pretty e ++ " has invalid type." eCopy ::- MonadBinder m =>+ MonadBuilder m => m (Exp (Rep m)) -> m (Exp (Rep m)) eCopy e = BasicOp . Copy <$> (letExp "copy_arg" =<< e) eBody ::- (MonadBinder m) =>+ (MonadBuilder m) => [m (Exp (Rep m))] -> m (Body (Rep m)) eBody es = buildBody_ $ do es' <- sequence es xs <- mapM (letTupExp "x") es'- pure $ map Var $ concat xs+ pure $ varsRes $ concat xs eLambda ::- MonadBinder m =>+ MonadBuilder m => Lambda (Rep m) -> [m (Exp (Rep m))] ->- m [SubExp]+ m [SubExpRes] eLambda lam args = do zipWithM_ bindParam (lambdaParams lam) args bodyBind $ lambdaBody lam@@ -301,7 +309,7 @@ bindParam param arg = letBindNames [paramName param] =<< arg eRoundToMultipleOf ::- MonadBinder m =>+ MonadBuilder m => IntType -> m (Exp (Rep m)) -> m (Exp (Rep m)) ->@@ -315,7 +323,7 @@ -- | Construct an 'Index' expressions that slices an array with unit stride. eSliceArray ::- MonadBinder m =>+ MonadBuilder m => Int -> VName -> m (Exp (Rep m)) ->@@ -332,7 +340,7 @@ -- | Are these indexes out-of-bounds for the array? eOutOfBounds ::- MonadBinder m =>+ MonadBuilder m => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m))@@ -351,52 +359,23 @@ BasicOp $ BinOp LogOr less_than_zero greater_than_size foldBinOp LogOr (constant False) =<< zipWithM checkDim ws is' --- | Write to an index of the array, if within bounds. Otherwise,--- nothing. Produces the updated array.-eWriteArray ::- (MonadBinder m, BranchType (Rep m) ~ ExtType) =>- VName ->- [m (Exp (Rep m))] ->- m (Exp (Rep m)) ->- m (Exp (Rep m))-eWriteArray arr is v = do- arr_t <- lookupType arr- is' <- mapM (letSubExp "write_i") =<< sequence is- v' <- letSubExp "write_v" =<< v-- outside_bounds <- letSubExp "outside_bounds" =<< eOutOfBounds arr is-- outside_bounds_branch <- buildBody_ $ pure [Var arr]-- in_bounds_branch <-- buildBody_ . fmap (pure . Var) $- letInPlace- "write_out_inside_bounds"- arr- (fullSlice arr_t (map DimFix is'))- (BasicOp $ SubExp v')-- return $- If outside_bounds outside_bounds_branch in_bounds_branch $- ifCommon [arr_t]- -- | Construct an unspecified value of the given type.-eBlank :: MonadBinder m => Type -> m (Exp (Rep m))+eBlank :: MonadBuilder m => Type -> m (Exp (Rep m)) eBlank (Prim t) = return $ BasicOp $ SubExp $ Constant $ blankPrimValue t eBlank (Array t shape _) = return $ BasicOp $ Scratch t $ shapeDims shape eBlank Acc {} = error "eBlank: cannot create blank accumulator" eBlank Mem {} = error "eBlank: cannot create blank memory" -- | Sign-extend to the given integer type.-asIntS :: MonadBinder m => IntType -> SubExp -> m SubExp+asIntS :: MonadBuilder m => IntType -> SubExp -> m SubExp asIntS = asInt SExt -- | Zero-extend to the given integer type.-asIntZ :: MonadBinder m => IntType -> SubExp -> m SubExp+asIntZ :: MonadBuilder m => IntType -> SubExp -> m SubExp asIntZ = asInt ZExt asInt ::- MonadBinder m =>+ MonadBuilder m => (IntType -> IntType -> ConvOp) -> IntType -> SubExp ->@@ -415,7 +394,7 @@ -- | Apply a binary operator to several subexpressions. A left-fold. foldBinOp ::- MonadBinder m =>+ MonadBuilder m => BinOp -> SubExp -> [SubExp] ->@@ -426,7 +405,7 @@ eBinOp bop (pure $ BasicOp $ SubExp e) (foldBinOp bop ne es) -- | True if all operands are true.-eAll :: MonadBinder m => [SubExp] -> m (Exp (Rep m))+eAll :: MonadBuilder m => [SubExp] -> m (Exp (Rep m)) eAll [] = pure $ BasicOp $ SubExp $ constant True eAll (x : xs) = foldBinOp LogAnd x xs @@ -435,7 +414,7 @@ -- result types are the same. (This assumption should be fixed at -- some point.) binOpLambda ::- (MonadBinder m, Bindable (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m)) => BinOp -> PrimType -> m (Lambda (Rep m))@@ -443,13 +422,13 @@ -- | As 'binOpLambda', but for t'CmpOp's. cmpOpLambda ::- (MonadBinder m, Bindable (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m)) => CmpOp -> m (Lambda (Rep m)) cmpOpLambda cop = binLambda (CmpOp cop) (cmpOpType cop) Bool binLambda ::- (MonadBinder m, Bindable (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m)) => (SubExp -> SubExp -> BasicOp) -> PrimType -> PrimType ->@@ -458,7 +437,7 @@ x <- newVName "x" y <- newVName "y" body <-- buildBody_ . fmap pure $+ buildBody_ . fmap (pure . subExpRes) $ letSubExp "binlam_res" $ BasicOp $ bop (Var x) (Var y) return Lambda@@ -470,16 +449,16 @@ lambdaBody = body } --- | Easily construct a 'Lambda' within a 'MonadBinder'.+-- | Easily construct a 'Lambda' within a 'MonadBuilder'. mkLambda ::- MonadBinder m =>+ MonadBuilder m => [LParam (Rep m)] -> m Result -> m (Lambda (Rep m)) mkLambda params m = do (body, ret) <- buildBody . localScope (scopeOfLParams params) $ do res <- m- ret <- mapM subExpType res+ ret <- mapM subExpResType res pure (res, ret) pure $ Lambda params body ret @@ -493,7 +472,7 @@ -- by 'Index'. fullSlice :: Type -> [DimIndex SubExp] -> Slice SubExp fullSlice t slice =- slice ++ map sliceDim (drop (length slice) $ arrayDims t)+ Slice $ slice ++ map sliceDim (drop (length slice) $ arrayDims t) -- | @ sliceAt t n slice@ returns @slice@ but with 'DimSlice's of the -- outer @n@ dimensions prepended, and as many appended as to make it@@ -505,13 +484,13 @@ -- | Like 'fullSlice', but the dimensions are simply numeric. fullSliceNum :: Num d => [d] -> [DimIndex d] -> Slice d fullSliceNum dims slice =- slice ++ map (\d -> DimSlice 0 d 1) (drop (length slice) dims)+ Slice $ slice ++ map (\d -> DimSlice 0 d 1) (drop (length slice) dims) -- | Does the slice describe the full size of the array? The most -- obvious such slice is one that 'DimSlice's the full span of every -- dimension, but also one that fixes all unit dimensions. isFullSlice :: Shape -> Slice SubExp -> Bool-isFullSlice shape slice = and $ zipWith allOfIt (shapeDims shape) slice+isFullSlice shape slice = and $ zipWith allOfIt (shapeDims shape) (unSlice slice) where allOfIt (Constant v) DimFix {} = oneIsh v allOfIt d (DimSlice _ n _) = d == n@@ -521,21 +500,18 @@ ifCommon ts = IfDec (staticShapes ts) IfNormal -- | Conveniently construct a body that contains no bindings.-resultBody :: Bindable rep => [SubExp] -> Body rep-resultBody = mkBody mempty+resultBody :: Buildable rep => [SubExp] -> Body rep+resultBody = mkBody mempty . subExpsRes -- | Conveniently construct a body that contains no bindings - but -- this time, monadically!-resultBodyM ::- MonadBinder m =>- [SubExp] ->- m (Body (Rep m))-resultBodyM = mkBodyM mempty+resultBodyM :: MonadBuilder m => [SubExp] -> m (Body (Rep m))+resultBodyM = mkBodyM mempty . subExpsRes -- | Evaluate the action, producing a body, then wrap it in all the -- bindings it created using 'addStm'. insertStmsM ::- (MonadBinder m) =>+ (MonadBuilder m) => m (Body (Rep m)) -> m (Body (Rep m)) insertStmsM m = do@@ -546,7 +522,7 @@ -- value, then return the body constructed from the 'Result' and any -- statements added during the action, along the auxiliary value. buildBody ::- MonadBinder m =>+ MonadBuilder m => m (Result, a) -> m (Body (Rep m), a) buildBody m = do@@ -556,7 +532,7 @@ -- | As 'buildBody', but there is no auxiliary value. buildBody_ ::- MonadBinder m =>+ MonadBuilder m => m Result -> m (Body (Rep m)) buildBody_ m = fst <$> buildBody ((,()) <$> m)@@ -564,7 +540,7 @@ -- | Change that result where evaluation of the body would stop. Also -- change type annotations at branches. mapResult ::- Bindable rep =>+ Buildable rep => (Result -> Body rep) -> Body rep -> Body rep@@ -596,20 +572,16 @@ return se instantiate' (Free se) = return se -instantiateShapes' ::- MonadFreshNames m =>- [TypeBase ExtShape u] ->- m ([TypeBase Shape u], [Ident])-instantiateShapes' ts =+instantiateShapes' :: [VName] -> [TypeBase ExtShape u] -> [TypeBase Shape u]+instantiateShapes' names ts = -- Carefully ensure that the order of idents we produce corresponds -- to their existential index.- second (map snd . sortOn fst)- <$> runWriterT (instantiateShapes instantiate ts)+ runIdentity $ instantiateShapes instantiate ts where- instantiate x = do- v <- lift $ newIdent "size" $ Prim int64- tell [(x, v)]- return $ Var $ identName v+ instantiate x =+ case maybeNth x names of+ Nothing -> error $ "instantiateShapes': " ++ pretty names ++ ", " ++ show x+ Just name -> pure $ Var name removeExistentials :: ExtType -> Type -> Type removeExistentials t1 t2 =@@ -622,7 +594,7 @@ nonExistential (Ext _) dim = dim nonExistential (Free dim) _ = dim --- | Can be used as the definition of 'mkLetNames' for a 'Bindable'+-- | Can be used as the definition of 'mkLetNames' for a 'Buildable' -- instance for simple representations. simpleMkLetNames :: ( ExpDec rep ~ (),@@ -636,15 +608,13 @@ m (Stm rep) simpleMkLetNames names e = do et <- expExtType e- (ts, shapes) <- instantiateShapes' et- let shapeElems = [PatElem shape shapet | Ident shape shapet <- shapes]- let valElems = zipWith PatElem names ts- return $ Let (Pattern shapeElems valElems) (defAux ()) e+ let ts = instantiateShapes' names et+ return $ Let (Pat $ zipWith PatElem names ts) (defAux ()) e -- | Instances of this class can be converted to Futhark expressions--- within a 'MonadBinder'.+-- within a 'MonadBuilder'. class ToExp a where- toExp :: MonadBinder m => a -> m (Exp (Rep m))+ toExp :: MonadBuilder m => a -> m (Exp (Rep m)) instance ToExp SubExp where toExp = return . BasicOp . SubExp@@ -653,5 +623,5 @@ toExp = return . BasicOp . SubExp . Var -- | A convenient composition of 'letSubExp' and 'toExp'.-toSubExp :: (MonadBinder m, ToExp a) => String -> a -> m SubExp+toSubExp :: (MonadBuilder m, ToExp a) => String -> a -> m SubExp toSubExp s e = letSubExp s =<< toExp e
src/Futhark/Doc/Generator.hs view
@@ -401,7 +401,7 @@ noLink' = noLink $ map typeParamName tparams- ++ map identName (S.toList $ mconcat $ map patternIdents params)+ ++ map identName (S.toList $ mconcat $ map patIdents params) rettype' <- noLink' $ maybe (typeHtml rettype) typeExpHtml retdecl params' <- noLink' $ mapM patternHtml params return@@ -666,7 +666,7 @@ typeNameHtml :: TypeName -> DocM Html typeNameHtml = qualNameHtml . qualNameFromTypeName -patternHtml :: Pattern -> DocM Html+patternHtml :: Pat -> DocM Html patternHtml pat = do let (pat_param, t) = patternParam pat t' <- typeHtml t
src/Futhark/IR/Aliases.hs view
@@ -23,10 +23,10 @@ module Futhark.IR.Syntax, -- * Adding aliases- addAliasesToPattern,+ addAliasesToPat, mkAliasedLetStm, mkAliasedBody,- mkPatternAliases,+ mkPatAliases, mkBodyAliases, -- * Removing aliases@@ -35,7 +35,7 @@ removeExpAliases, removeStmAliases, removeLambdaAliases,- removePatternAliases,+ removePatAliases, removeScopeAliases, -- * Tracking aliases@@ -50,7 +50,7 @@ import qualified Data.Map.Strict as M import Data.Maybe import Futhark.Analysis.Rephrase-import Futhark.Binder+import Futhark.Builder import Futhark.IR.Pretty import Futhark.IR.Prop import Futhark.IR.Prop.Aliases@@ -126,8 +126,8 @@ runReaderT m scope instance (ASTRep rep, CanBeAliased (Op rep)) => ASTRep (Aliases rep) where- expTypesFromPattern =- withoutAliases . expTypesFromPattern . removePatternAliases+ expTypesFromPat =+ withoutAliases . expTypesFromPat . removePatAliases instance (ASTRep rep, CanBeAliased (Op rep)) => Aliased (Aliases rep) where bodyAliases = map unAliases . fst . fst . bodyDec@@ -135,25 +135,20 @@ instance (ASTRep rep, CanBeAliased (Op rep)) => PrettyRep (Aliases rep) where ppExpDec (consumed, inner) e =- maybeComment $- catMaybes- [ exp_dec,- merge_dec,- ppExpDec inner $ removeExpAliases e- ]+ maybeComment . catMaybes $+ [exp_dec, merge_dec, ppExpDec inner $ removeExpAliases e] where merge_dec = case e of- DoLoop _ merge _ body ->+ DoLoop merge _ body -> let mergeParamAliases fparam als | primType (paramType fparam) = Nothing | otherwise = resultAliasComment (paramName fparam) als- in maybeComment $- catMaybes $- zipWith mergeParamAliases (map fst merge) $- bodyAliases body+ in maybeComment . catMaybes $+ zipWith mergeParamAliases (map fst merge) $+ bodyAliases body _ -> Nothing exp_dec = case namesToList $ unAliases consumed of@@ -228,18 +223,18 @@ Lambda rep removeLambdaAliases = runIdentity . rephraseLambda removeAliases -removePatternAliases ::- PatternT (AliasDec, a) ->- PatternT a-removePatternAliases = runIdentity . rephrasePattern (return . snd)+removePatAliases ::+ PatT (AliasDec, a) ->+ PatT a+removePatAliases = runIdentity . rephrasePat (return . snd) -addAliasesToPattern ::+addAliasesToPat :: (ASTRep rep, CanBeAliased (Op rep), Typed dec) =>- PatternT dec ->+ PatT dec -> Exp (Aliases rep) ->- PatternT (VarAliases, dec)-addAliasesToPattern pat e =- uncurry Pattern $ mkPatternAliases pat e+ PatT (VarAliases, dec)+addAliasesToPat pat e =+ Pat $ mkPatAliases pat e mkAliasedBody :: (ASTRep rep, CanBeAliased (Op rep)) =>@@ -250,26 +245,19 @@ mkAliasedBody dec bnds res = Body (mkBodyAliases bnds res, dec) bnds res -mkPatternAliases ::+mkPatAliases :: (Aliased rep, Typed dec) =>- PatternT dec ->+ PatT dec -> Exp rep ->- ( [PatElemT (VarAliases, dec)],- [PatElemT (VarAliases, dec)]- )-mkPatternAliases pat e =- -- Some part of the pattern may be the context. This does not have- -- aliases from expAliases, so we use a hack to compute aliases of- -- the context.- let als = expAliases e ++ repeat mempty -- In case the pattern has- -- more elements (this- -- implies a type error).- context_als = mkContextAliases pat e- in ( zipWith annotateBindee (patternContextElements pat) context_als,- zipWith annotateBindee (patternValueElements pat) als- )+ [PatElemT (VarAliases, dec)]+mkPatAliases pat e =+ let als = expAliases e ++ repeat mempty+ in -- In case the pattern has+ -- more elements (this+ -- implies a type error).+ zipWith annotatePatElem (patElems pat) als where- annotateBindee bindee names =+ annotatePatElem bindee names = bindee `setPatElemDec` (AliasDec names', patElemDec bindee) where names' =@@ -278,31 +266,6 @@ Mem _ -> names _ -> mempty -mkContextAliases ::- Aliased rep =>- PatternT dec ->- Exp rep ->- [Names]-mkContextAliases pat (DoLoop ctxmerge valmerge _ body) =- let ctx = map fst ctxmerge- init_als = zip mergenames $ map (subExpAliases . snd) $ ctxmerge ++ valmerge- expand als = als <> mconcat (mapMaybe (`lookup` init_als) (namesToList als))- merge_als =- zip mergenames $- map ((`namesSubtract` mergenames_set) . expand) $- bodyAliases body- in if length ctx == length (patternContextElements pat)- then map (fromMaybe mempty . flip lookup merge_als . paramName) ctx- else map (const mempty) $ patternContextElements pat- where- mergenames = map (paramName . fst) $ ctxmerge ++ valmerge- mergenames_set = namesFromList mergenames-mkContextAliases pat (If _ tbranch fbranch _) =- take (length $ patternContextNames pat) $- zipWith (<>) (bodyAliases tbranch) (bodyAliases fbranch)-mkContextAliases pat _ =- replicate (length $ patternContextElements pat) mempty- mkBodyAliases :: Aliased rep => Stms rep ->@@ -314,8 +277,7 @@ -- closure of the alias map (within bnds), then removing anything -- bound in bnds. let (aliases, consumed) = mkStmsAliases bnds res- boundNames =- foldMap (namesFromList . patternNames . stmPattern) bnds+ boundNames = foldMap (namesFromList . patNames . stmPat) bnds aliases' = map (`namesSubtract` boundNames) aliases consumed' = consumed `namesSubtract` boundNames in (map AliasDec aliases', AliasDec consumed')@@ -325,12 +287,12 @@ mkStmsAliases :: Aliased rep => Stms rep ->- [SubExp] ->+ Result -> ([Names], Names) mkStmsAliases bnds res = delve mempty $ stmsToList bnds where delve (aliasmap, consumed) [] =- ( map (aliasClosure aliasmap . subExpAliases) res,+ ( map (aliasClosure aliasmap . subExpAliases . resSubExp) res, consumed ) delve (aliasmap, consumed) (bnd : bnds') =@@ -351,9 +313,9 @@ Stm rep -> AliasesAndConsumed trackAliases (aliasmap, consumed) stm =- let pat = stmPattern stm+ let pat = stmPat stm pe_als =- zip (patternNames pat) $ map addAliasesOfAliases $ patternAliases pat+ zip (patNames pat) $ map addAliasesOfAliases $ patAliases pat als = M.fromList pe_als rev_als = foldMap revAls pe_als revAls (v, v_als) =@@ -369,23 +331,23 @@ mkAliasedLetStm :: (ASTRep rep, CanBeAliased (Op rep)) =>- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> Exp (Aliases rep) -> Stm (Aliases rep) mkAliasedLetStm pat (StmAux cs attrs dec) e = Let- (addAliasesToPattern pat e)+ (addAliasesToPat pat e) (StmAux cs attrs (AliasDec $ consumedInExp e, dec)) e -instance (Bindable rep, CanBeAliased (Op rep)) => Bindable (Aliases rep) where+instance (Buildable rep, CanBeAliased (Op rep)) => Buildable (Aliases rep) where mkExpDec pat e =- let dec = mkExpDec (removePatternAliases pat) $ removeExpAliases e+ let dec = mkExpDec (removePatAliases pat) $ removeExpAliases e in (AliasDec $ consumedInExp e, dec) - mkExpPat ctx val e =- addAliasesToPattern (mkExpPat ctx val $ removeExpAliases e) e+ mkExpPat ids e =+ addAliasesToPat (mkExpPat ids $ removeExpAliases e) e mkLetNames names e = do env <- asksScope removeScopeAliases@@ -397,4 +359,4 @@ let Body bodyrep _ _ = mkBody (fmap removeStmAliases bnds) res in mkAliasedBody bodyrep bnds res -instance (ASTRep (Aliases rep), Bindable (Aliases rep)) => BinderOps (Aliases rep)+instance (ASTRep (Aliases rep), Buildable (Aliases rep)) => BuilderOps (Aliases rep)
src/Futhark/IR/GPU.hs view
@@ -10,15 +10,15 @@ module Futhark.IR.Traversals, module Futhark.IR.Pretty, module Futhark.IR.Syntax,- module Futhark.IR.GPU.Kernel,+ module Futhark.IR.GPU.Op, module Futhark.IR.GPU.Sizes, module Futhark.IR.SOACS.SOAC, ) where -import Futhark.Binder+import Futhark.Builder import Futhark.Construct-import Futhark.IR.GPU.Kernel+import Futhark.IR.GPU.Op import Futhark.IR.GPU.Sizes import Futhark.IR.Pretty import Futhark.IR.Prop@@ -34,7 +34,7 @@ type Op GPU = HostOp GPU (SOAC GPU) instance ASTRep GPU where- expTypesFromPattern = return . expExtTypesFromPattern+ expTypesFromPat = return . expExtTypesFromPat instance TypeCheck.CheckableOp GPU where checkOp = typeCheckGPUOp Nothing@@ -44,13 +44,13 @@ instance TypeCheck.Checkable GPU -instance Bindable GPU where+instance Buildable GPU where mkBody = Body ()- mkExpPat ctx val _ = basicPattern ctx val+ mkExpPat idents _ = basicPat idents mkExpDec _ _ = () mkLetNames = simpleMkLetNames -instance BinderOps GPU+instance BuilderOps GPU instance PrettyRep GPU
− src/Futhark/IR/GPU/Kernel.hs
@@ -1,346 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--module Futhark.IR.GPU.Kernel- ( -- * Size operations- SizeOp (..),-- -- * Host operations- HostOp (..),- typeCheckHostOp,-- -- * SegOp refinements- SegLevel (..),-- -- * Reexports- module Futhark.IR.GPU.Sizes,- module Futhark.IR.SegOp,- )-where--import Futhark.Analysis.Metrics-import qualified Futhark.Analysis.SymbolTable as ST-import Futhark.IR-import Futhark.IR.Aliases (Aliases)-import Futhark.IR.GPU.Sizes-import Futhark.IR.Prop.Aliases-import Futhark.IR.SegOp-import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Rep-import Futhark.Transform.Rename-import Futhark.Transform.Substitute-import qualified Futhark.TypeCheck as TC-import Futhark.Util.Pretty- ( commasep,- parens,- ppr,- text,- (<+>),- )-import qualified Futhark.Util.Pretty as PP-import Prelude hiding (id, (.))---- | At which level the *body* of a t'SegOp' executes.-data SegLevel- = SegThread- { segNumGroups :: Count NumGroups SubExp,- segGroupSize :: Count GroupSize SubExp,- segVirt :: SegVirt- }- | SegGroup- { segNumGroups :: Count NumGroups SubExp,- segGroupSize :: Count GroupSize SubExp,- segVirt :: SegVirt- }- deriving (Eq, Ord, Show)--instance PP.Pretty SegLevel where- ppr lvl =- PP.parens- ( lvl' <> PP.semi- <+> text "#groups=" <> ppr (segNumGroups lvl) <> PP.semi- <+> text "groupsize=" <> ppr (segGroupSize lvl) <> virt- )- where- lvl' = case lvl of- SegThread {} -> "thread"- SegGroup {} -> "group"- virt = case segVirt lvl of- SegNoVirt -> mempty- SegNoVirtFull -> PP.semi <+> text "full"- SegVirt -> PP.semi <+> text "virtualise"--instance Engine.Simplifiable SegLevel where- simplify (SegThread num_groups group_size virt) =- SegThread <$> traverse Engine.simplify num_groups- <*> traverse Engine.simplify group_size- <*> pure virt- simplify (SegGroup num_groups group_size virt) =- SegGroup <$> traverse Engine.simplify num_groups- <*> traverse Engine.simplify group_size- <*> pure virt--instance Substitute SegLevel where- substituteNames substs (SegThread num_groups group_size virt) =- SegThread- (substituteNames substs num_groups)- (substituteNames substs group_size)- virt- substituteNames substs (SegGroup num_groups group_size virt) =- SegGroup- (substituteNames substs num_groups)- (substituteNames substs group_size)- virt--instance Rename SegLevel where- rename = substituteRename--instance FreeIn SegLevel where- freeIn' (SegThread num_groups group_size _) =- freeIn' num_groups <> freeIn' group_size- freeIn' (SegGroup num_groups group_size _) =- freeIn' num_groups <> freeIn' group_size---- | A simple size-level query or computation.-data SizeOp- = -- | @SplitSpace o w i elems_per_thread@.- --- -- Computes how to divide array elements to- -- threads in a kernel. Returns the number of- -- elements in the chunk that the current thread- -- should take.- --- -- @w@ is the length of the outer dimension in- -- the array. @i@ is the current thread- -- index. Each thread takes at most- -- @elems_per_thread@ elements.- --- -- If the order @o@ is 'SplitContiguous', thread with index @i@- -- should receive elements- -- @i*elems_per_tread, i*elems_per_thread + 1,- -- ..., i*elems_per_thread + (elems_per_thread-1)@.- --- -- If the order @o@ is @'SplitStrided' stride@,- -- the thread will receive elements @i,- -- i+stride, i+2*stride, ...,- -- i+(elems_per_thread-1)*stride@.- SplitSpace SplitOrdering SubExp SubExp SubExp- | -- | Produce some runtime-configurable size.- GetSize Name SizeClass- | -- | The maximum size of some class.- GetSizeMax SizeClass- | -- | Compare size (likely a threshold) with some integer value.- CmpSizeLe Name SizeClass SubExp- | -- | @CalcNumGroups w max_num_groups group_size@ calculates the- -- number of GPU workgroups to use for an input of the given size.- -- The @Name@ is a size name. Note that @w@ is an i64 to avoid- -- overflow issues.- CalcNumGroups SubExp Name SubExp- deriving (Eq, Ord, Show)--instance Substitute SizeOp where- substituteNames subst (SplitSpace o w i elems_per_thread) =- SplitSpace- (substituteNames subst o)- (substituteNames subst w)- (substituteNames subst i)- (substituteNames subst elems_per_thread)- substituteNames substs (CmpSizeLe name sclass x) =- CmpSizeLe name sclass (substituteNames substs x)- substituteNames substs (CalcNumGroups w max_num_groups group_size) =- CalcNumGroups- (substituteNames substs w)- max_num_groups- (substituteNames substs group_size)- substituteNames _ op = op--instance Rename SizeOp where- rename (SplitSpace o w i elems_per_thread) =- SplitSpace- <$> rename o- <*> rename w- <*> rename i- <*> rename elems_per_thread- rename (CmpSizeLe name sclass x) =- CmpSizeLe name sclass <$> rename x- rename (CalcNumGroups w max_num_groups group_size) =- CalcNumGroups <$> rename w <*> pure max_num_groups <*> rename group_size- rename x = pure x--instance IsOp SizeOp where- safeOp _ = True- cheapOp _ = True--instance TypedOp SizeOp where- opType SplitSpace {} = pure [Prim int64]- opType (GetSize _ _) = pure [Prim int64]- opType (GetSizeMax _) = pure [Prim int64]- opType CmpSizeLe {} = pure [Prim Bool]- opType CalcNumGroups {} = pure [Prim int64]--instance AliasedOp SizeOp where- opAliases _ = [mempty]- consumedInOp _ = mempty--instance FreeIn SizeOp where- freeIn' (SplitSpace o w i elems_per_thread) =- freeIn' o <> freeIn' [w, i, elems_per_thread]- freeIn' (CmpSizeLe _ _ x) = freeIn' x- freeIn' (CalcNumGroups w _ group_size) = freeIn' w <> freeIn' group_size- freeIn' _ = mempty--instance PP.Pretty SizeOp where- ppr (SplitSpace SplitContiguous w i elems_per_thread) =- text "split_space"- <> parens (commasep [ppr w, ppr i, ppr elems_per_thread])- ppr (SplitSpace (SplitStrided stride) w i elems_per_thread) =- text "split_space_strided"- <> parens (commasep [ppr stride, ppr w, ppr i, ppr elems_per_thread])- ppr (GetSize name size_class) =- text "get_size" <> parens (commasep [ppr name, ppr size_class])- ppr (GetSizeMax size_class) =- text "get_size_max" <> parens (commasep [ppr size_class])- ppr (CmpSizeLe name size_class x) =- text "cmp_size" <> parens (commasep [ppr name, ppr size_class])- <+> text "<="- <+> ppr x- ppr (CalcNumGroups w max_num_groups group_size) =- text "calc_num_groups" <> parens (commasep [ppr w, ppr max_num_groups, ppr group_size])--instance OpMetrics SizeOp where- opMetrics SplitSpace {} = seen "SplitSpace"- opMetrics GetSize {} = seen "GetSize"- opMetrics GetSizeMax {} = seen "GetSizeMax"- opMetrics CmpSizeLe {} = seen "CmpSizeLe"- opMetrics CalcNumGroups {} = seen "CalcNumGroups"--typeCheckSizeOp :: TC.Checkable rep => SizeOp -> TC.TypeM rep ()-typeCheckSizeOp (SplitSpace o w i elems_per_thread) = do- case o of- SplitContiguous -> return ()- SplitStrided stride -> TC.require [Prim int64] stride- mapM_ (TC.require [Prim int64]) [w, i, elems_per_thread]-typeCheckSizeOp GetSize {} = return ()-typeCheckSizeOp GetSizeMax {} = return ()-typeCheckSizeOp (CmpSizeLe _ _ x) = TC.require [Prim int64] x-typeCheckSizeOp (CalcNumGroups w _ group_size) = do- TC.require [Prim int64] w- TC.require [Prim int64] group_size---- | A host-level operation; parameterised by what else it can do.-data HostOp rep op- = -- | A segmented operation.- SegOp (SegOp SegLevel rep)- | SizeOp SizeOp- | OtherOp op- deriving (Eq, Ord, Show)--instance (ASTRep rep, Substitute op) => Substitute (HostOp rep op) where- substituteNames substs (SegOp op) =- SegOp $ substituteNames substs op- substituteNames substs (OtherOp op) =- OtherOp $ substituteNames substs op- substituteNames substs (SizeOp op) =- SizeOp $ substituteNames substs op--instance (ASTRep rep, Rename op) => Rename (HostOp rep op) where- rename (SegOp op) = SegOp <$> rename op- rename (OtherOp op) = OtherOp <$> rename op- rename (SizeOp op) = SizeOp <$> rename op--instance (ASTRep rep, IsOp op) => IsOp (HostOp rep op) where- safeOp (SegOp op) = safeOp op- safeOp (OtherOp op) = safeOp op- safeOp (SizeOp op) = safeOp op-- cheapOp (SegOp op) = cheapOp op- cheapOp (OtherOp op) = cheapOp op- cheapOp (SizeOp op) = cheapOp op--instance TypedOp op => TypedOp (HostOp rep op) where- opType (SegOp op) = opType op- opType (OtherOp op) = opType op- opType (SizeOp op) = opType op--instance (Aliased rep, AliasedOp op, ASTRep rep) => AliasedOp (HostOp rep op) where- opAliases (SegOp op) = opAliases op- opAliases (OtherOp op) = opAliases op- opAliases (SizeOp op) = opAliases op-- consumedInOp (SegOp op) = consumedInOp op- consumedInOp (OtherOp op) = consumedInOp op- consumedInOp (SizeOp op) = consumedInOp op--instance (ASTRep rep, FreeIn op) => FreeIn (HostOp rep op) where- freeIn' (SegOp op) = freeIn' op- freeIn' (OtherOp op) = freeIn' op- freeIn' (SizeOp op) = freeIn' op--instance (CanBeAliased (Op rep), CanBeAliased op, ASTRep rep) => CanBeAliased (HostOp rep op) where- type OpWithAliases (HostOp rep op) = HostOp (Aliases rep) (OpWithAliases op)-- addOpAliases aliases (SegOp op) = SegOp $ addOpAliases aliases op- addOpAliases aliases (OtherOp op) = OtherOp $ addOpAliases aliases op- addOpAliases _ (SizeOp op) = SizeOp op-- removeOpAliases (SegOp op) = SegOp $ removeOpAliases op- removeOpAliases (OtherOp op) = OtherOp $ removeOpAliases op- removeOpAliases (SizeOp op) = SizeOp op--instance (CanBeWise (Op rep), CanBeWise op, ASTRep rep) => CanBeWise (HostOp rep op) where- type OpWithWisdom (HostOp rep op) = HostOp (Wise rep) (OpWithWisdom op)-- removeOpWisdom (SegOp op) = SegOp $ removeOpWisdom op- removeOpWisdom (OtherOp op) = OtherOp $ removeOpWisdom op- removeOpWisdom (SizeOp op) = SizeOp op--instance (ASTRep rep, ST.IndexOp op) => ST.IndexOp (HostOp rep op) where- indexOp vtable k (SegOp op) is = ST.indexOp vtable k op is- indexOp vtable k (OtherOp op) is = ST.indexOp vtable k op is- indexOp _ _ _ _ = Nothing--instance (PrettyRep rep, PP.Pretty op) => PP.Pretty (HostOp rep op) where- ppr (SegOp op) = ppr op- ppr (OtherOp op) = ppr op- ppr (SizeOp op) = ppr op--instance (OpMetrics (Op rep), OpMetrics op) => OpMetrics (HostOp rep op) where- opMetrics (SegOp op) = opMetrics op- opMetrics (OtherOp op) = opMetrics op- opMetrics (SizeOp op) = opMetrics op--checkSegLevel ::- TC.Checkable rep =>- Maybe SegLevel ->- SegLevel ->- TC.TypeM rep ()-checkSegLevel Nothing lvl = do- TC.require [Prim int64] $ unCount $ segNumGroups lvl- TC.require [Prim int64] $ unCount $ segGroupSize lvl-checkSegLevel (Just SegThread {}) _ =- TC.bad $ TC.TypeError "SegOps cannot occur when already at thread level."-checkSegLevel (Just x) y- | x == y = TC.bad $ TC.TypeError $ "Already at at level " ++ pretty x- | segNumGroups x /= segNumGroups y || segGroupSize x /= segGroupSize y =- TC.bad $ TC.TypeError "Physical layout for SegLevel does not match parent SegLevel."- | otherwise =- return ()--typeCheckHostOp ::- TC.Checkable rep =>- (SegLevel -> OpWithAliases (Op rep) -> TC.TypeM rep ()) ->- Maybe SegLevel ->- (op -> TC.TypeM rep ()) ->- HostOp (Aliases rep) op ->- TC.TypeM rep ()-typeCheckHostOp checker lvl _ (SegOp op) =- TC.checkOpWith (checker $ segLevel op) $- typeCheckSegOp (checkSegLevel lvl) op-typeCheckHostOp _ _ f (OtherOp op) = f op-typeCheckHostOp _ _ _ (SizeOp op) = typeCheckSizeOp op
+ src/Futhark/IR/GPU/Op.hs view
@@ -0,0 +1,346 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++module Futhark.IR.GPU.Op+ ( -- * Size operations+ SizeOp (..),++ -- * Host operations+ HostOp (..),+ typeCheckHostOp,++ -- * SegOp refinements+ SegLevel (..),++ -- * Reexports+ module Futhark.IR.GPU.Sizes,+ module Futhark.IR.SegOp,+ )+where++import Futhark.Analysis.Metrics+import qualified Futhark.Analysis.SymbolTable as ST+import Futhark.IR+import Futhark.IR.Aliases (Aliases)+import Futhark.IR.GPU.Sizes+import Futhark.IR.Prop.Aliases+import Futhark.IR.SegOp+import qualified Futhark.Optimise.Simplify.Engine as Engine+import Futhark.Optimise.Simplify.Rep+import Futhark.Transform.Rename+import Futhark.Transform.Substitute+import qualified Futhark.TypeCheck as TC+import Futhark.Util.Pretty+ ( commasep,+ parens,+ ppr,+ text,+ (<+>),+ )+import qualified Futhark.Util.Pretty as PP+import Prelude hiding (id, (.))++-- | At which level the *body* of a t'SegOp' executes.+data SegLevel+ = SegThread+ { segNumGroups :: Count NumGroups SubExp,+ segGroupSize :: Count GroupSize SubExp,+ segVirt :: SegVirt+ }+ | SegGroup+ { segNumGroups :: Count NumGroups SubExp,+ segGroupSize :: Count GroupSize SubExp,+ segVirt :: SegVirt+ }+ deriving (Eq, Ord, Show)++instance PP.Pretty SegLevel where+ ppr lvl =+ PP.parens+ ( lvl' <> PP.semi+ <+> text "#groups=" <> ppr (segNumGroups lvl) <> PP.semi+ <+> text "groupsize=" <> ppr (segGroupSize lvl) <> virt+ )+ where+ lvl' = case lvl of+ SegThread {} -> "thread"+ SegGroup {} -> "group"+ virt = case segVirt lvl of+ SegNoVirt -> mempty+ SegNoVirtFull -> PP.semi <+> text "full"+ SegVirt -> PP.semi <+> text "virtualise"++instance Engine.Simplifiable SegLevel where+ simplify (SegThread num_groups group_size virt) =+ SegThread <$> traverse Engine.simplify num_groups+ <*> traverse Engine.simplify group_size+ <*> pure virt+ simplify (SegGroup num_groups group_size virt) =+ SegGroup <$> traverse Engine.simplify num_groups+ <*> traverse Engine.simplify group_size+ <*> pure virt++instance Substitute SegLevel where+ substituteNames substs (SegThread num_groups group_size virt) =+ SegThread+ (substituteNames substs num_groups)+ (substituteNames substs group_size)+ virt+ substituteNames substs (SegGroup num_groups group_size virt) =+ SegGroup+ (substituteNames substs num_groups)+ (substituteNames substs group_size)+ virt++instance Rename SegLevel where+ rename = substituteRename++instance FreeIn SegLevel where+ freeIn' (SegThread num_groups group_size _) =+ freeIn' num_groups <> freeIn' group_size+ freeIn' (SegGroup num_groups group_size _) =+ freeIn' num_groups <> freeIn' group_size++-- | A simple size-level query or computation.+data SizeOp+ = -- | @SplitSpace o w i elems_per_thread@.+ --+ -- Computes how to divide array elements to+ -- threads in a kernel. Returns the number of+ -- elements in the chunk that the current thread+ -- should take.+ --+ -- @w@ is the length of the outer dimension in+ -- the array. @i@ is the current thread+ -- index. Each thread takes at most+ -- @elems_per_thread@ elements.+ --+ -- If the order @o@ is 'SplitContiguous', thread with index @i@+ -- should receive elements+ -- @i*elems_per_tread, i*elems_per_thread + 1,+ -- ..., i*elems_per_thread + (elems_per_thread-1)@.+ --+ -- If the order @o@ is @'SplitStrided' stride@,+ -- the thread will receive elements @i,+ -- i+stride, i+2*stride, ...,+ -- i+(elems_per_thread-1)*stride@.+ SplitSpace SplitOrdering SubExp SubExp SubExp+ | -- | Produce some runtime-configurable size.+ GetSize Name SizeClass+ | -- | The maximum size of some class.+ GetSizeMax SizeClass+ | -- | Compare size (likely a threshold) with some integer value.+ CmpSizeLe Name SizeClass SubExp+ | -- | @CalcNumGroups w max_num_groups group_size@ calculates the+ -- number of GPU workgroups to use for an input of the given size.+ -- The @Name@ is a size name. Note that @w@ is an i64 to avoid+ -- overflow issues.+ CalcNumGroups SubExp Name SubExp+ deriving (Eq, Ord, Show)++instance Substitute SizeOp where+ substituteNames subst (SplitSpace o w i elems_per_thread) =+ SplitSpace+ (substituteNames subst o)+ (substituteNames subst w)+ (substituteNames subst i)+ (substituteNames subst elems_per_thread)+ substituteNames substs (CmpSizeLe name sclass x) =+ CmpSizeLe name sclass (substituteNames substs x)+ substituteNames substs (CalcNumGroups w max_num_groups group_size) =+ CalcNumGroups+ (substituteNames substs w)+ max_num_groups+ (substituteNames substs group_size)+ substituteNames _ op = op++instance Rename SizeOp where+ rename (SplitSpace o w i elems_per_thread) =+ SplitSpace+ <$> rename o+ <*> rename w+ <*> rename i+ <*> rename elems_per_thread+ rename (CmpSizeLe name sclass x) =+ CmpSizeLe name sclass <$> rename x+ rename (CalcNumGroups w max_num_groups group_size) =+ CalcNumGroups <$> rename w <*> pure max_num_groups <*> rename group_size+ rename x = pure x++instance IsOp SizeOp where+ safeOp _ = True+ cheapOp _ = True++instance TypedOp SizeOp where+ opType SplitSpace {} = pure [Prim int64]+ opType (GetSize _ _) = pure [Prim int64]+ opType (GetSizeMax _) = pure [Prim int64]+ opType CmpSizeLe {} = pure [Prim Bool]+ opType CalcNumGroups {} = pure [Prim int64]++instance AliasedOp SizeOp where+ opAliases _ = [mempty]+ consumedInOp _ = mempty++instance FreeIn SizeOp where+ freeIn' (SplitSpace o w i elems_per_thread) =+ freeIn' o <> freeIn' [w, i, elems_per_thread]+ freeIn' (CmpSizeLe _ _ x) = freeIn' x+ freeIn' (CalcNumGroups w _ group_size) = freeIn' w <> freeIn' group_size+ freeIn' _ = mempty++instance PP.Pretty SizeOp where+ ppr (SplitSpace SplitContiguous w i elems_per_thread) =+ text "split_space"+ <> parens (commasep [ppr w, ppr i, ppr elems_per_thread])+ ppr (SplitSpace (SplitStrided stride) w i elems_per_thread) =+ text "split_space_strided"+ <> parens (commasep [ppr stride, ppr w, ppr i, ppr elems_per_thread])+ ppr (GetSize name size_class) =+ text "get_size" <> parens (commasep [ppr name, ppr size_class])+ ppr (GetSizeMax size_class) =+ text "get_size_max" <> parens (commasep [ppr size_class])+ ppr (CmpSizeLe name size_class x) =+ text "cmp_size" <> parens (commasep [ppr name, ppr size_class])+ <+> text "<="+ <+> ppr x+ ppr (CalcNumGroups w max_num_groups group_size) =+ text "calc_num_groups" <> parens (commasep [ppr w, ppr max_num_groups, ppr group_size])++instance OpMetrics SizeOp where+ opMetrics SplitSpace {} = seen "SplitSpace"+ opMetrics GetSize {} = seen "GetSize"+ opMetrics GetSizeMax {} = seen "GetSizeMax"+ opMetrics CmpSizeLe {} = seen "CmpSizeLe"+ opMetrics CalcNumGroups {} = seen "CalcNumGroups"++typeCheckSizeOp :: TC.Checkable rep => SizeOp -> TC.TypeM rep ()+typeCheckSizeOp (SplitSpace o w i elems_per_thread) = do+ case o of+ SplitContiguous -> return ()+ SplitStrided stride -> TC.require [Prim int64] stride+ mapM_ (TC.require [Prim int64]) [w, i, elems_per_thread]+typeCheckSizeOp GetSize {} = return ()+typeCheckSizeOp GetSizeMax {} = return ()+typeCheckSizeOp (CmpSizeLe _ _ x) = TC.require [Prim int64] x+typeCheckSizeOp (CalcNumGroups w _ group_size) = do+ TC.require [Prim int64] w+ TC.require [Prim int64] group_size++-- | A host-level operation; parameterised by what else it can do.+data HostOp rep op+ = -- | A segmented operation.+ SegOp (SegOp SegLevel rep)+ | SizeOp SizeOp+ | OtherOp op+ deriving (Eq, Ord, Show)++instance (ASTRep rep, Substitute op) => Substitute (HostOp rep op) where+ substituteNames substs (SegOp op) =+ SegOp $ substituteNames substs op+ substituteNames substs (OtherOp op) =+ OtherOp $ substituteNames substs op+ substituteNames substs (SizeOp op) =+ SizeOp $ substituteNames substs op++instance (ASTRep rep, Rename op) => Rename (HostOp rep op) where+ rename (SegOp op) = SegOp <$> rename op+ rename (OtherOp op) = OtherOp <$> rename op+ rename (SizeOp op) = SizeOp <$> rename op++instance (ASTRep rep, IsOp op) => IsOp (HostOp rep op) where+ safeOp (SegOp op) = safeOp op+ safeOp (OtherOp op) = safeOp op+ safeOp (SizeOp op) = safeOp op++ cheapOp (SegOp op) = cheapOp op+ cheapOp (OtherOp op) = cheapOp op+ cheapOp (SizeOp op) = cheapOp op++instance TypedOp op => TypedOp (HostOp rep op) where+ opType (SegOp op) = opType op+ opType (OtherOp op) = opType op+ opType (SizeOp op) = opType op++instance (Aliased rep, AliasedOp op, ASTRep rep) => AliasedOp (HostOp rep op) where+ opAliases (SegOp op) = opAliases op+ opAliases (OtherOp op) = opAliases op+ opAliases (SizeOp op) = opAliases op++ consumedInOp (SegOp op) = consumedInOp op+ consumedInOp (OtherOp op) = consumedInOp op+ consumedInOp (SizeOp op) = consumedInOp op++instance (ASTRep rep, FreeIn op) => FreeIn (HostOp rep op) where+ freeIn' (SegOp op) = freeIn' op+ freeIn' (OtherOp op) = freeIn' op+ freeIn' (SizeOp op) = freeIn' op++instance (CanBeAliased (Op rep), CanBeAliased op, ASTRep rep) => CanBeAliased (HostOp rep op) where+ type OpWithAliases (HostOp rep op) = HostOp (Aliases rep) (OpWithAliases op)++ addOpAliases aliases (SegOp op) = SegOp $ addOpAliases aliases op+ addOpAliases aliases (OtherOp op) = OtherOp $ addOpAliases aliases op+ addOpAliases _ (SizeOp op) = SizeOp op++ removeOpAliases (SegOp op) = SegOp $ removeOpAliases op+ removeOpAliases (OtherOp op) = OtherOp $ removeOpAliases op+ removeOpAliases (SizeOp op) = SizeOp op++instance (CanBeWise (Op rep), CanBeWise op, ASTRep rep) => CanBeWise (HostOp rep op) where+ type OpWithWisdom (HostOp rep op) = HostOp (Wise rep) (OpWithWisdom op)++ removeOpWisdom (SegOp op) = SegOp $ removeOpWisdom op+ removeOpWisdom (OtherOp op) = OtherOp $ removeOpWisdom op+ removeOpWisdom (SizeOp op) = SizeOp op++instance (ASTRep rep, ST.IndexOp op) => ST.IndexOp (HostOp rep op) where+ indexOp vtable k (SegOp op) is = ST.indexOp vtable k op is+ indexOp vtable k (OtherOp op) is = ST.indexOp vtable k op is+ indexOp _ _ _ _ = Nothing++instance (PrettyRep rep, PP.Pretty op) => PP.Pretty (HostOp rep op) where+ ppr (SegOp op) = ppr op+ ppr (OtherOp op) = ppr op+ ppr (SizeOp op) = ppr op++instance (OpMetrics (Op rep), OpMetrics op) => OpMetrics (HostOp rep op) where+ opMetrics (SegOp op) = opMetrics op+ opMetrics (OtherOp op) = opMetrics op+ opMetrics (SizeOp op) = opMetrics op++checkSegLevel ::+ TC.Checkable rep =>+ Maybe SegLevel ->+ SegLevel ->+ TC.TypeM rep ()+checkSegLevel Nothing lvl = do+ TC.require [Prim int64] $ unCount $ segNumGroups lvl+ TC.require [Prim int64] $ unCount $ segGroupSize lvl+checkSegLevel (Just SegThread {}) _ =+ TC.bad $ TC.TypeError "SegOps cannot occur when already at thread level."+checkSegLevel (Just x) y+ | x == y = TC.bad $ TC.TypeError $ "Already at at level " ++ pretty x+ | segNumGroups x /= segNumGroups y || segGroupSize x /= segGroupSize y =+ TC.bad $ TC.TypeError "Physical layout for SegLevel does not match parent SegLevel."+ | otherwise =+ return ()++typeCheckHostOp ::+ TC.Checkable rep =>+ (SegLevel -> OpWithAliases (Op rep) -> TC.TypeM rep ()) ->+ Maybe SegLevel ->+ (op -> TC.TypeM rep ()) ->+ HostOp (Aliases rep) op ->+ TC.TypeM rep ()+typeCheckHostOp checker lvl _ (SegOp op) =+ TC.checkOpWith (checker $ segLevel op) $+ typeCheckSegOp (checkSegLevel lvl) op+typeCheckHostOp _ _ f (OtherOp op) = f op+typeCheckHostOp _ _ _ (SizeOp op) = typeCheckSizeOp op
src/Futhark/IR/GPU/Simplify.hs view
@@ -75,7 +75,7 @@ w' <- Engine.simplify w return (SizeOp $ CalcNumGroups w' max_num_groups group_size, mempty) -instance BinderOps (Wise GPU)+instance BuilderOps (Wise GPU) instance HasSegOp (Wise GPU) where type SegOpLevel (Wise GPU) = SegLevel
src/Futhark/IR/GPUMem.hs view
@@ -14,20 +14,20 @@ -- * Module re-exports module Futhark.IR.Mem,- module Futhark.IR.GPU.Kernel,+ module Futhark.IR.GPU.Op, ) where import Futhark.Analysis.PrimExp.Convert import qualified Futhark.Analysis.UsageTable as UT-import Futhark.IR.GPU.Kernel+import Futhark.IR.GPU.Op import Futhark.IR.GPU.Simplify (simplifyKernelOp) import Futhark.IR.Mem import Futhark.IR.Mem.Simplify import Futhark.MonadFreshNames import qualified Futhark.Optimise.Simplify.Engine as Engine import Futhark.Pass-import Futhark.Pass.ExplicitAllocations (BinderOps (..), mkLetNamesB', mkLetNamesB'')+import Futhark.Pass.ExplicitAllocations (BuilderOps (..), mkLetNamesB', mkLetNamesB'') import qualified Futhark.TypeCheck as TC data GPUMem@@ -41,14 +41,16 @@ type Op GPUMem = MemOp (HostOp GPUMem ()) instance ASTRep GPUMem where- expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern+ expTypesFromPat = return . map snd . bodyReturnsFromPat -instance OpReturns GPUMem where- opReturns (Alloc _ space) =- return [MemMem space]- opReturns (Inner (SegOp op)) = segOpReturns op+instance OpReturns (HostOp GPUMem ()) where+ opReturns (SegOp op) = segOpReturns op opReturns k = extReturns <$> opType k +instance OpReturns (HostOp (Engine.Wise GPUMem) ()) where+ opReturns (SegOp op) = segOpReturns op+ opReturns k = extReturns <$> opType k+ instance PrettyRep GPUMem instance TC.CheckableOp GPUMem where@@ -65,17 +67,17 @@ checkLetBoundDec = checkMemInfo checkRetType = mapM_ $ TC.checkExtType . declExtTypeOf primFParam name t = return $ Param name (MemPrim t)- matchPattern = matchPatternToExp+ matchPat = matchPatToExp matchReturnType = matchFunctionReturnType matchBranchType = matchBranchReturnType matchLoopResult = matchLoopResultMem -instance BinderOps GPUMem where+instance BuilderOps GPUMem where mkExpDecB _ _ = return () mkBodyB stms res = return $ Body () stms res mkLetNamesB = mkLetNamesB' () -instance BinderOps (Engine.Wise GPUMem) where+instance BuilderOps (Engine.Wise GPUMem) where mkExpDecB pat e = return $ Engine.mkWiseExpDec pat () e mkBodyB stms res = return $ Engine.mkWiseBody () stms res mkLetNamesB = mkLetNamesB''
src/Futhark/IR/MC.hs view
@@ -20,7 +20,7 @@ ) where -import Futhark.Binder+import Futhark.Builder import Futhark.Construct import Futhark.IR.MC.Op import Futhark.IR.Pretty@@ -42,22 +42,22 @@ type Op MC = MCOp MC (SOAC MC) instance ASTRep MC where- expTypesFromPattern = return . expExtTypesFromPattern+ expTypesFromPat = return . expExtTypesFromPat instance TypeCheck.CheckableOp MC where checkOp = typeCheckMCOp typeCheckSOAC instance TypeCheck.Checkable MC -instance Bindable MC where+instance Buildable MC where mkBody = Body ()- mkExpPat ctx val _ = basicPattern ctx val+ mkExpPat idents _ = basicPat idents mkExpDec _ _ = () mkLetNames = simpleMkLetNames -instance BinderOps MC+instance BuilderOps MC -instance BinderOps (Engine.Wise MC)+instance BuilderOps (Engine.Wise MC) instance PrettyRep MC
src/Futhark/IR/MCMem.hs view
@@ -24,7 +24,7 @@ import Futhark.IR.SegOp import qualified Futhark.Optimise.Simplify.Engine as Engine import Futhark.Pass-import Futhark.Pass.ExplicitAllocations (BinderOps (..), mkLetNamesB', mkLetNamesB'')+import Futhark.Pass.ExplicitAllocations (BuilderOps (..), mkLetNamesB', mkLetNamesB'') import qualified Futhark.TypeCheck as TC data MCMem@@ -38,13 +38,16 @@ type Op MCMem = MemOp (MCOp MCMem ()) instance ASTRep MCMem where- expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern+ expTypesFromPat = return . map snd . bodyReturnsFromPat -instance OpReturns MCMem where- opReturns (Alloc _ space) = return [MemMem space]- opReturns (Inner (ParOp _ op)) = segOpReturns op- opReturns (Inner (OtherOp ())) = pure []+instance OpReturns (MCOp MCMem ()) where+ opReturns (ParOp _ op) = segOpReturns op+ opReturns (OtherOp ()) = pure [] +instance OpReturns (MCOp (Engine.Wise MCMem) ()) where+ opReturns (ParOp _ op) = segOpReturns op+ opReturns k = extReturns <$> opType k+ instance PrettyRep MCMem instance TC.CheckableOp MCMem where@@ -61,17 +64,17 @@ checkLetBoundDec = checkMemInfo checkRetType = mapM_ (TC.checkExtType . declExtTypeOf) primFParam name t = return $ Param name (MemPrim t)- matchPattern = matchPatternToExp+ matchPat = matchPatToExp matchReturnType = matchFunctionReturnType matchBranchType = matchBranchReturnType matchLoopResult = matchLoopResultMem -instance BinderOps MCMem where+instance BuilderOps MCMem where mkExpDecB _ _ = return () mkBodyB stms res = return $ Body () stms res mkLetNamesB = mkLetNamesB' () -instance BinderOps (Engine.Wise MCMem) where+instance BuilderOps (Engine.Wise MCMem) where mkExpDecB pat e = return $ Engine.mkWiseExpDec pat () e mkBodyB stms res = return $ Engine.mkWiseBody () stms res mkLetNamesB = mkLetNamesB''
src/Futhark/IR/Mem.hs view
@@ -75,7 +75,7 @@ noUniquenessReturns, bodyReturnsToExpReturns, Mem,- AllocOp (..),+ HasLetDecMem (..), OpReturns (..), varReturns, expReturns,@@ -87,10 +87,10 @@ -- * Type checking parts matchBranchReturnType,- matchPatternToExp,+ matchPatToExp, matchFunctionReturnType, matchLoopResultMem,- bodyReturnsFromPattern,+ bodyReturnsFromPat, checkMemInfo, -- * Module re-exports@@ -106,11 +106,11 @@ import Control.Monad.Except import Control.Monad.Reader import Control.Monad.State-import Data.Foldable (toList, traverse_)+import Data.Foldable (traverse_)+import Data.Function ((&)) import Data.List (elemIndex, find) import qualified Data.Map.Strict as M import Data.Maybe-import qualified Data.Set as S import Futhark.Analysis.Metrics import Futhark.Analysis.PrimExp.Convert import Futhark.Analysis.PrimExp.Simplify@@ -118,7 +118,7 @@ import Futhark.IR.Aliases ( Aliases, removeExpAliases,- removePatternAliases,+ removePatAliases, removeScopeAliases, ) import qualified Futhark.IR.Mem.IxFun as IxFun@@ -147,19 +147,26 @@ type BranchTypeMem = BodyReturns --- | The class of ops that have memory allocation.-class AllocOp op where- allocOp :: SubExp -> Space -> op+-- | The class of pattern element decorators that contain memory+-- information.+class HasLetDecMem t where+ letDecMem :: t -> LetDecMem -type Mem rep =- ( AllocOp (Op rep),- FParamInfo rep ~ FParamMem,+instance HasLetDecMem LetDecMem where+ letDecMem = id++instance HasLetDecMem b => HasLetDecMem (a, b) where+ letDecMem = letDecMem . snd++type Mem rep inner =+ ( FParamInfo rep ~ FParamMem, LParamInfo rep ~ LParamMem,- LetDec rep ~ LetDecMem,+ HasLetDecMem (LetDec rep), RetType rep ~ RetTypeMem, BranchType rep ~ BranchTypeMem, ASTRep rep,- OpReturns rep+ OpReturns inner,+ Op rep ~ MemOp inner ) instance IsRetType FunReturns where@@ -170,15 +177,11 @@ primBodyType = MemPrim data MemOp inner- = -- | Allocate a memory block. This really should not be an- -- expression, but what are you gonna do...+ = -- | Allocate a memory block. Alloc SubExp Space | Inner inner deriving (Eq, Ord, Show) -instance AllocOp (MemOp inner) where- allocOp = Alloc- instance FreeIn inner => FreeIn (MemOp inner) where freeIn' (Alloc size _) = freeIn' size freeIn' (Inner k) = freeIn' k@@ -531,24 +534,32 @@ bodyReturnsToExpReturns :: BodyReturns -> ExpReturns bodyReturnsToExpReturns = noUniquenessReturns . maybeReturns +varInfoToExpReturns :: MemInfo SubExp NoUniqueness MemBind -> ExpReturns+varInfoToExpReturns (MemArray et shape u (ArrayIn mem ixfun)) =+ MemArray et (fmap Free shape) u $+ Just $ ReturnsInBlock mem $ existentialiseIxFun [] ixfun+varInfoToExpReturns (MemPrim pt) = MemPrim pt+varInfoToExpReturns (MemAcc acc ispace ts u) = MemAcc acc ispace ts u+varInfoToExpReturns (MemMem space) = MemMem space+ matchRetTypeToResult ::- (Mem rep, TC.Checkable rep) =>+ (Mem rep inner, TC.Checkable rep) => [FunReturns] -> Result -> TC.TypeM rep () matchRetTypeToResult rettype result = do scope <- askScope- result_ts <- runReaderT (mapM subExpMemInfo result) $ removeScopeAliases scope- matchReturnType rettype result result_ts+ result_ts <- runReaderT (mapM (subExpMemInfo . resSubExp) result) $ removeScopeAliases scope+ matchReturnType rettype (map resSubExp result) result_ts matchFunctionReturnType ::- (Mem rep, TC.Checkable rep) =>+ (Mem rep inner, TC.Checkable rep) => [FunReturns] -> Result -> TC.TypeM rep () matchFunctionReturnType rettype result = do matchRetTypeToResult rettype result- mapM_ checkResultSubExp result+ mapM_ (checkResultSubExp . resSubExp) result where checkResultSubExp Constant {} = return ()@@ -569,21 +580,20 @@ ++ pretty ixfun matchLoopResultMem ::- (Mem rep, TC.Checkable rep) =>- [FParam (Aliases rep)] ->+ (Mem rep inner, TC.Checkable rep) => [FParam (Aliases rep)] ->- [SubExp] ->+ Result -> TC.TypeM rep ()-matchLoopResultMem ctx val = matchRetTypeToResult rettype+matchLoopResultMem params = matchRetTypeToResult rettype where- ctx_names = map paramName ctx+ param_names = map paramName params -- Invent a ReturnType so we can pretend that the loop body is -- actually returning from a function.- rettype = map (toRet . paramDec) val+ rettype = map (toRet . paramDec) params toExtV v- | Just i <- v `elemIndex` ctx_names = Ext i+ | Just i <- v `elemIndex` param_names = Ext i | otherwise = Free v toExtSE (Var v) = Var <$> toExtV v@@ -596,24 +606,24 @@ toRet (MemAcc acc ispace ts u) = MemAcc acc ispace ts u toRet (MemArray pt shape u (ArrayIn mem ixfun))- | Just i <- mem `elemIndex` ctx_names,- Param _ (MemMem space) : _ <- drop i ctx =+ | Just i <- mem `elemIndex` param_names,+ Param _ (MemMem space) : _ <- drop i params = MemArray pt shape' u $ ReturnsNewBlock space i ixfun' | otherwise = MemArray pt shape' u $ ReturnsInBlock mem ixfun' where shape' = fmap toExtSE shape- ixfun' = existentialiseIxFun ctx_names ixfun+ ixfun' = existentialiseIxFun param_names ixfun matchBranchReturnType ::- (Mem rep, TC.Checkable rep) =>+ (Mem rep inner, TC.Checkable rep) => [BodyReturns] -> Body (Aliases rep) -> TC.TypeM rep () matchBranchReturnType rettype (Body _ stms res) = do scope <- askScope- ts <- runReaderT (mapM subExpMemInfo res) $ removeScopeAliases (scope <> scopeOf stms)- matchReturnType rettype res ts+ ts <- runReaderT (mapM (subExpMemInfo . resSubExp) res) $ removeScopeAliases (scope <> scopeOf stms)+ matchReturnType rettype (map resSubExp res) ts -- | Helper function for index function unification. --@@ -650,19 +660,14 @@ [MemInfo SubExp NoUniqueness MemBind] -> TC.TypeM rep () matchReturnType rettype res ts = do- let (ctx_ts, val_ts) = splitFromEnd (length rettype) ts- (ctx_res, _val_res) = splitFromEnd (length rettype) res+ let (ctx_res, _val_res) = splitFromEnd (length rettype) res existentialiseIxFun0 :: IxFun -> ExtIxFun existentialiseIxFun0 = fmap $ fmap Free - fetchCtx i = case maybeNth i $ zip ctx_res ctx_ts of+ fetchCtx i = case maybeNth i $ zip res ts of Nothing ->- throwError $- "Cannot find context variable "- ++ show i- ++ " in context results: "- ++ pretty ctx_res+ throwError $ "Cannot find variable #" ++ show i ++ " in results: " ++ pretty res Just (se, t) -> return (se, t) checkReturn (MemPrim x) (MemPrim y)@@ -685,88 +690,56 @@ checkDim (Free x) y | x == y = return () | otherwise =- throwError $- unwords- [ "Expected dim",- pretty x,- "but got",- pretty y- ]+ throwError $ unwords ["Expected dim", pretty x, "but got", pretty y] checkDim (Ext i) y = do (x, _) <- fetchCtx i- unless (x == y) $- throwError $- unwords- [ "Expected ext dim",- pretty i,- "=>",- pretty x,- "but got",- pretty y- ]-- extsInMemInfo :: MemInfo ExtSize u MemReturn -> S.Set Int- extsInMemInfo (MemArray _ shp _ ret) =- extInShape shp <> extInMemReturn ret- extsInMemInfo _ = S.empty+ unless (x == y) . throwError . unwords $+ ["Expected ext dim", pretty i, "=>", pretty x, "but got", pretty y] checkMemReturn (ReturnsInBlock x_mem x_ixfun) (ArrayIn y_mem y_ixfun) | x_mem == y_mem = unless (IxFun.closeEnough x_ixfun $ existentialiseIxFun0 y_ixfun) $- throwError $- unwords- [ "Index function unification failed (ReturnsInBlock)",- "\nixfun of body result: ",- pretty y_ixfun,- "\nixfun of return type: ",- pretty x_ixfun,- "\nand context elements: ",- pretty ctx_res- ]+ throwError . unwords $+ [ "Index function unification failed (ReturnsInBlock)",+ "\nixfun of body result: ",+ pretty y_ixfun,+ "\nixfun of return type: ",+ pretty x_ixfun,+ "\nand context elements: ",+ pretty ctx_res+ ] checkMemReturn (ReturnsNewBlock x_space x_ext x_ixfun) (ArrayIn y_mem y_ixfun) = do (x_mem, x_mem_type) <- fetchCtx x_ext unless (IxFun.closeEnough x_ixfun $ existentialiseIxFun0 y_ixfun) $- throwError $- pretty $- "Index function unification failed (ReturnsNewBlock)"- </> "Ixfun of body result:"- </> indent 2 (ppr y_ixfun)- </> "Ixfun of return type:"- </> indent 2 (ppr x_ixfun)- </> "Context elements: "- </> indent 2 (ppr ctx_res)+ throwError . pretty $+ "Index function unification failed (ReturnsNewBlock)"+ </> "Ixfun of body result:"+ </> indent 2 (ppr y_ixfun)+ </> "Ixfun of return type:"+ </> indent 2 (ppr x_ixfun)+ </> "Context elements: "+ </> indent 2 (ppr ctx_res) case x_mem_type of MemMem y_space ->- unless (x_space == y_space) $- throwError $- unwords- [ "Expected memory",- pretty y_mem,- "in space",- pretty x_space,- "but actually in space",- pretty y_space- ]+ unless (x_space == y_space) . throwError . unwords $+ [ "Expected memory",+ pretty y_mem,+ "in space",+ pretty x_space,+ "but actually in space",+ pretty y_space+ ] t ->- throwError $- unwords- [ "Expected memory",- pretty x_ext,- "=>",- pretty x_mem,- "but but has type",- pretty t- ]+ throwError . unwords $+ ["Expected memory", pretty x_ext, "=>", pretty x_mem, "but but has type", pretty t] checkMemReturn x y =- throwError $- unwords- [ "Expected array in",- pretty x,- "but array returned in",- pretty y- ]+ throwError . pretty $+ "Expected array in"+ </> indent 2 (ppr x)+ </> "but array returned in"+ </> indent 2 (ppr y) bad :: String -> TC.TypeM rep a bad s =@@ -779,46 +752,29 @@ </> indent 2 (ppTuple' ts) </> text s - unless (length (S.unions $ map extsInMemInfo rettype) == length ctx_res) $- TC.bad $- TC.TypeError $- "Too many context parameters for the number of "- ++ "existentials in the return type! type:\n "- ++ prettyTuple rettype- ++ "\ncannot match context parameters:\n "- ++ prettyTuple ctx_res-- either bad return =<< runExceptT (zipWithM_ checkReturn rettype val_ts)+ either bad return =<< runExceptT (zipWithM_ checkReturn rettype ts) -matchPatternToExp ::- (Mem rep, TC.Checkable rep) =>- Pattern (Aliases rep) ->+matchPatToExp ::+ (Mem rep inner, LetDec rep ~ LetDecMem, TC.Checkable rep) =>+ Pat (Aliases rep) -> Exp (Aliases rep) -> TC.TypeM rep ()-matchPatternToExp pat e = do+matchPatToExp pat e = do scope <- asksScope removeScopeAliases rt <- runReaderT (expReturns $ removeExpAliases e) scope - let (ctxs, vals) = bodyReturnsFromPattern $ removePatternAliases pat- (ctx_ids, _ctx_ts) = unzip ctxs- (_val_ids, val_ts) = unzip vals- (ctx_map_ids, ctx_map_exts) =- getExtMaps $ zip ctx_ids [0 .. length ctx_ids - 1]-- let rt_exts = foldMap extInExpReturns rt+ let (ctx_ids, val_ts) = unzip $ bodyReturnsFromPat $ removePatAliases pat+ (ctx_map_ids, ctx_map_exts) = getExtMaps $ zip ctx_ids [0 .. 1] unless ( length val_ts == length rt && and (zipWith (matches ctx_map_ids ctx_map_exts) val_ts rt)- && M.keysSet ctx_map_exts `S.isSubsetOf` S.map Ext rt_exts ) $ TC.bad $ TC.TypeError $ "Expression type:\n " ++ prettyTuple rt ++ "\ncannot match pattern type:\n " ++ prettyTuple val_ts- ++ "\nwith context elements: "- ++ pretty ctx_ids where matches _ _ (MemPrim x) (MemPrim y) = x == y matches _ _ (MemMem x_space) (MemMem y_space) =@@ -848,58 +804,42 @@ _ -> False matches _ _ _ _ = False - extInExpReturns :: ExpReturns -> S.Set Int- extInExpReturns (MemArray _ shape _ mem_return) =- extInShape shape <> maybe S.empty extInMemReturn mem_return- extInExpReturns _ = mempty--extInShape :: ShapeBase (Ext SubExp) -> S.Set Int-extInShape shape = S.fromList $ mapMaybe isExt $ shapeDims shape--extInMemReturn :: MemReturn -> S.Set Int-extInMemReturn (ReturnsInBlock _ extixfn) = extInIxFn extixfn-extInMemReturn (ReturnsNewBlock _ i extixfn) =- S.singleton i <> extInIxFn extixfn--extInIxFn :: ExtIxFun -> S.Set Int-extInIxFn ixfun = S.fromList $ concatMap (mapMaybe isExt . toList) ixfun- varMemInfo ::- Mem rep =>+ Mem rep inner => VName -> TC.TypeM rep (MemInfo SubExp NoUniqueness MemBind) varMemInfo name = do dec <- TC.lookupVar name case dec of- LetName (_, summary) -> return summary- FParamName summary -> return $ noUniquenessReturns summary- LParamName summary -> return summary- IndexName it -> return $ MemPrim $ IntType it+ LetName (_, summary) -> pure $ letDecMem summary+ FParamName summary -> pure $ noUniquenessReturns summary+ LParamName summary -> pure summary+ IndexName it -> pure $ MemPrim $ IntType it -nameInfoToMemInfo :: Mem rep => NameInfo rep -> MemBound NoUniqueness+nameInfoToMemInfo :: Mem rep inner => NameInfo rep -> MemBound NoUniqueness nameInfoToMemInfo info = case info of FParamName summary -> noUniquenessReturns summary LParamName summary -> summary- LetName summary -> summary+ LetName summary -> letDecMem summary IndexName it -> MemPrim $ IntType it lookupMemInfo ::- (HasScope rep m, Mem rep) =>+ (HasScope rep m, Mem rep inner) => VName -> m (MemInfo SubExp NoUniqueness MemBind) lookupMemInfo = fmap nameInfoToMemInfo . lookupInfo subExpMemInfo ::- (HasScope rep m, Monad m, Mem rep) =>+ (HasScope rep m, Monad m, Mem rep inner) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind) subExpMemInfo (Var v) = lookupMemInfo v subExpMemInfo (Constant v) = return $ MemPrim $ primValueType v lookupArraySummary ::- (Mem rep, HasScope rep m, Monad m) =>+ (Mem rep inner, HasScope rep m, Monad m) => VName -> m (VName, IxFun.IxFun (TPrimExp Int64 VName)) lookupArraySummary name = do@@ -908,7 +848,9 @@ MemArray _ _ _ (ArrayIn mem ixfun) -> return (mem, ixfun) _ ->- error $ "Variable " ++ pretty name ++ " does not look like an array."+ error $+ "Expected " ++ pretty name ++ " to be array but bound to:\n"+ ++ pretty summary checkMemInfo :: TC.Checkable rep =>@@ -947,15 +889,12 @@ ++ show ident_rank ++ ")" -bodyReturnsFromPattern ::- PatternT (MemBound NoUniqueness) ->- ([(VName, BodyReturns)], [(VName, BodyReturns)])-bodyReturnsFromPattern pat =- ( map asReturns $ patternContextElements pat,- map asReturns $ patternValueElements pat- )+bodyReturnsFromPat ::+ PatT (MemBound NoUniqueness) -> [(VName, BodyReturns)]+bodyReturnsFromPat pat =+ map asReturns $ patElems pat where- ctx = patternContextElements pat+ ctx = patElems pat ext (Var v) | Just (i, _) <- find ((== v) . patElemName . snd) $ zip [0 ..] ctx =@@ -1001,7 +940,7 @@ convert (Free v) = Free <$> pe64 v arrayVarReturns ::- (HasScope rep m, Monad m, Mem rep) =>+ (HasScope rep m, Monad m, Mem rep inner) => VName -> m (PrimType, Shape, VName, IxFun) arrayVarReturns v = do@@ -1013,7 +952,7 @@ error $ "arrayVarReturns: " ++ pretty v ++ " is not an array." varReturns ::- (HasScope rep m, Monad m, Mem rep) =>+ (HasScope rep m, Monad m, Mem rep inner) => VName -> m ExpReturns varReturns v = do@@ -1030,7 +969,7 @@ MemAcc acc ispace ts u -> return $ MemAcc acc ispace ts u -subExpReturns :: (HasScope rep m, Monad m, Mem rep) => SubExp -> m ExpReturns+subExpReturns :: (HasScope rep m, Monad m, Mem rep inner) => SubExp -> m ExpReturns subExpReturns (Var v) = varReturns v subExpReturns (Constant v) =@@ -1041,13 +980,13 @@ expReturns :: ( Monad m, LocalScope rep m,- Mem rep+ Mem rep inner ) => Exp rep -> m [ExpReturns] expReturns (BasicOp (SubExp se)) = pure <$> subExpReturns se-expReturns (BasicOp (Opaque (Var v))) =+expReturns (BasicOp (Opaque _ (Var v))) = pure <$> varReturns v expReturns (BasicOp (Reshape newshape v)) = do (et, _, mem, ixfun) <- arrayVarReturns v@@ -1075,23 +1014,18 @@ Just $ ReturnsInBlock mem $ existentialiseIxFun [] ixfun' ] expReturns (BasicOp (Index v slice)) = do- info <- sliceInfo v slice- case info of- MemArray et shape u (ArrayIn mem ixfun) ->- return- [ MemArray et (fmap Free shape) u $- Just $ ReturnsInBlock mem $ existentialiseIxFun [] ixfun- ]- MemPrim pt -> return [MemPrim pt]- MemAcc acc ispace ts u -> return [MemAcc acc ispace ts u]- MemMem space -> return [MemMem space]-expReturns (BasicOp (Update v _ _)) =+ pure . varInfoToExpReturns <$> sliceInfo v slice+expReturns (BasicOp (Update _ v _ _)) = pure <$> varReturns v+expReturns (BasicOp (FlatIndex v slice)) = do+ pure . varInfoToExpReturns <$> flatSliceInfo v slice+expReturns (BasicOp (FlatUpdate v _ _)) =+ pure <$> varReturns v expReturns (BasicOp op) =- extReturns . staticShapes <$> primOpType op-expReturns e@(DoLoop ctx val _ _) = do+ extReturns . staticShapes <$> basicOpType op+expReturns e@(DoLoop merge _ _) = do t <- expExtType e- zipWithM typeWithDec t $ map fst val+ zipWithM typeWithDec t $ map fst merge where typeWithDec t p = case (t, paramDec p) of@@ -1102,10 +1036,7 @@ Mem space <- paramType mem_p -> return $ MemArray pt shape u $ Just $ ReturnsNewBlock space i ixfun' | otherwise ->- return- ( MemArray pt shape u $- Just $ ReturnsInBlock mem ixfun'- )+ return $ MemArray pt shape u $ Just $ ReturnsInBlock mem ixfun' where ixfun' = existentialiseIxFun (map paramName mergevars) ixfun (Array {}, _) ->@@ -1114,10 +1045,10 @@ return $ MemAcc acc ispace ts u (Prim pt, _) -> return $ MemPrim pt- (Mem {}, _) ->- error "expReturns: loop returns memory block explicitly."+ (Mem space, _) ->+ pure $ MemMem space isMergeVar v = find ((== v) . paramName . snd) $ zip [0 ..] mergevars- mergevars = map fst $ ctx ++ val+ mergevars = map fst merge expReturns (Apply _ _ ret _) = return $ map funReturnsToExpReturns ret expReturns (If _ _ _ (IfDec ret _)) =@@ -1136,7 +1067,7 @@ num_accs = length inputs sliceInfo ::- (Monad m, HasScope rep m, Mem rep) =>+ (Monad m, HasScope rep m, Mem rep inner) => VName -> Slice SubExp -> m (MemInfo SubExp NoUniqueness MemBind)@@ -1146,18 +1077,33 @@ [] -> return $ MemPrim et dims -> return $- MemArray et (Shape dims) NoUniqueness $- ArrayIn mem $- IxFun.slice- ixfun- (map (fmap (isInt64 . primExpFromSubExp int64)) slice)+ MemArray et (Shape dims) NoUniqueness . ArrayIn mem $+ IxFun.slice ixfun (fmap pe64 slice) -class TypedOp (Op rep) => OpReturns rep where- opReturns ::- (Monad m, HasScope rep m) =>- Op rep ->- m [ExpReturns]+flatSliceInfo ::+ (Monad m, HasScope rep m, Mem rep inner) =>+ VName ->+ FlatSlice SubExp ->+ m (MemInfo SubExp NoUniqueness MemBind)+flatSliceInfo v slice@(FlatSlice offset idxs) = do+ (et, _, mem, ixfun) <- arrayVarReturns v+ map (fmap pe64) idxs+ & FlatSlice (pe64 offset)+ & IxFun.flatSlice ixfun+ & ArrayIn mem+ & MemArray et (Shape (flatSliceDims slice)) NoUniqueness+ & pure++class TypedOp op => OpReturns op where+ opReturns :: (Mem rep inner, Monad m, HasScope rep m) => op -> m [ExpReturns] opReturns op = extReturns <$> opType op++instance OpReturns inner => OpReturns (MemOp inner) where+ opReturns (Alloc _ space) = pure [MemMem space]+ opReturns (Inner op) = opReturns op++instance OpReturns () where+ opReturns () = pure [] applyFunReturns :: Typed dec =>
src/Futhark/IR/Mem/IxFun.hs view
@@ -15,6 +15,7 @@ rotate, reshape, slice,+ flatSlice, rebase, shape, rank,@@ -33,7 +34,7 @@ import Control.Monad.Identity import Control.Monad.State import Control.Monad.Writer-import Data.Function (on)+import Data.Function (on, (&)) import Data.List (sort, sortBy, zip4, zip5, zipWith5) import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE@@ -51,9 +52,13 @@ import Futhark.IR.Syntax ( DimChange (..), DimIndex (..),+ FlatDimIndex (..),+ FlatSlice (..), ShapeChange,- Slice,+ Slice (..), dimFix,+ flatSliceDims,+ flatSliceStrides, unitSlice, ) import Futhark.IR.Syntax.Core (Ext (..))@@ -369,11 +374,11 @@ IxFun num -> Slice num -> Maybe (IxFun num)-sliceOneLMAD (IxFun (lmad@(LMAD _ ldims) :| lmads) oshp cg) is = do+sliceOneLMAD (IxFun (lmad@(LMAD _ ldims) :| lmads) oshp cg) (Slice is) = do let perm = lmadPermutation lmad is' = permuteInv perm is- cg' = cg && slicePreservesContiguous lmad is'- guard $ harmlessRotation lmad is'+ cg' = cg && slicePreservesContiguous lmad (Slice is')+ guard $ harmlessRotation lmad (Slice is') let lmad' = foldl sliceOne (LMAD (lmadOffset lmad) []) $ zip is' ldims -- need to remove the fixed dims from the permutation perm' =@@ -414,7 +419,7 @@ LMAD num -> Slice num -> Bool- harmlessRotation (LMAD _ dims) iss =+ harmlessRotation (LMAD _ dims) (Slice iss) = and $ zipWith harmlessRotation' dims iss -- XXX: TODO: what happens to r on a negative-stride slice; is there@@ -450,7 +455,7 @@ LMAD num -> Slice num -> Bool- slicePreservesContiguous (LMAD _ dims) slc =+ slicePreservesContiguous (LMAD _ dims) (Slice slc) = -- remove from the slice the LMAD dimensions that have stride 0. -- If the LMAD was contiguous in mem, then these dims will not -- influence the contiguousness of the result.@@ -497,10 +502,9 @@ IxFun num -> Slice num -> IxFun num-slice _ [] = error "slice: empty slice" slice ixfun@(IxFun (lmad@(LMAD _ _) :| lmads) oshp cg) dim_slices -- Avoid identity slicing.- | dim_slices == map (unitSlice 0) (shape ixfun) = ixfun+ | unSlice dim_slices == map (unitSlice 0) (shape ixfun) = ixfun | Just ixfun' <- sliceOneLMAD ixfun dim_slices = ixfun' | otherwise = case sliceOneLMAD (iota (lmadShape lmad)) dim_slices of@@ -508,6 +512,36 @@ IxFun (lmad' :| lmad : lmads) oshp (cg && cg') _ -> error "slice: reached impossible case" +-- | Flat-slice an index function.+flatSlice ::+ (Eq num, IntegralExp num) =>+ IxFun num ->+ FlatSlice num ->+ IxFun num+flatSlice ixfun@(IxFun (LMAD offset (dim : dims) :| lmads) oshp cg) (FlatSlice new_offset is)+ | hasContiguousPerm ixfun,+ ldRotate dim == 0 =+ let lmad =+ LMAD+ (offset + new_offset * ldStride dim)+ ( map (helper $ ldStride dim) is+ <> dims+ )+ & setLMADPermutation [0 ..]+ in IxFun (lmad :| lmads) oshp cg+ where+ helper s0 (FlatDimIndex n s) = LMADDim (s0 * s) 0 n 0 Unknown+flatSlice (IxFun (lmad :| lmads) oshp cg) s@(FlatSlice new_offset _) =+ IxFun (LMAD (new_offset * base_stride) (new_dims <> tail_dims) :| lmad : lmads) oshp cg+ where+ tail_shapes = tail $ lmadShape lmad+ base_stride = product tail_shapes+ tail_strides = tail $ scanr (*) 1 tail_shapes+ tail_dims = zipWith5 LMADDim tail_strides (repeat 0) tail_shapes [length new_shapes ..] (repeat Inc)+ new_shapes = flatSliceDims s+ new_strides = map (* base_stride) $ flatSliceStrides s+ new_dims = zipWith5 LMADDim new_strides (repeat 0) new_shapes [0 ..] (repeat Inc)+ -- | Handle the simple case where all reshape dimensions are coercions. reshapeCoercion :: (Eq num, IntegralExp num) =>@@ -853,11 +887,13 @@ | r == 0 = i * s | otherwise = ((i + r) `mod` n) * s --- | Generalised iota with user-specified offset and strides.+-- | Generalised iota with user-specified offset and rotates. makeRotIota :: IntegralExp num => Monotonicity ->+ -- | Offset num ->+ -- | Pairs of shape and rotation [(num, num)] -> LMAD num makeRotIota mon off support
src/Futhark/IR/Mem/Simplify.hs view
@@ -19,7 +19,6 @@ import Futhark.Construct import Futhark.IR.Mem import qualified Futhark.IR.Mem.IxFun as IxFun-import qualified Futhark.IR.Syntax as AST import qualified Futhark.Optimise.Simplify as Simplify import qualified Futhark.Optimise.Simplify.Engine as Engine import Futhark.Optimise.Simplify.Rep@@ -30,14 +29,14 @@ import Futhark.Util simpleGeneric ::- (SimplifyMemory rep, Op rep ~ MemOp inner) =>+ (SimplifyMemory rep inner) => (OpWithWisdom inner -> UT.UsageTable) -> Simplify.SimplifyOp rep inner -> Simplify.SimpleOps rep simpleGeneric = simplifiable simplifyProgGeneric ::- (SimplifyMemory rep, Op rep ~ MemOp inner) =>+ (SimplifyMemory rep inner) => Simplify.SimpleOps rep -> Prog rep -> PassM (Prog rep)@@ -56,13 +55,12 @@ -- corruption. At this point in the compiler we have probably -- already moved all the array creations that matter. blockAllocs _ _ (Let pat _ _) =- not $ all primType $ patternTypes pat+ not $ all primType $ patTypes pat simplifyStmsGeneric :: ( HasScope rep m, MonadFreshNames m,- SimplifyMemory rep,- Op rep ~ MemOp inner+ SimplifyMemory rep inner ) => Simplify.SimpleOps rep -> Stms rep ->@@ -77,8 +75,8 @@ stms isResultAlloc :: Op rep ~ MemOp op => Engine.BlockPred rep-isResultAlloc _ usage (Let (AST.Pattern [] [bindee]) _ (Op Alloc {})) =- UT.isInResult (patElemName bindee) usage+isResultAlloc _ usage (Let (Pat [pe]) _ (Op Alloc {})) =+ UT.isInResult (patElemName pe) usage isResultAlloc _ _ _ = False isAlloc :: Op rep ~ MemOp op => Engine.BlockPred rep@@ -96,17 +94,17 @@ } -- | Some constraints that must hold for the simplification rules to work.-type SimplifyMemory rep =+type SimplifyMemory rep inner = ( Simplify.SimplifiableRep rep,+ LetDec rep ~ LetDecMem, ExpDec rep ~ (), BodyDec rep ~ (),- AllocOp (Op (Wise rep)), CanBeWise (Op rep),- BinderOps (Wise rep),- Mem rep+ BuilderOps (Wise rep),+ Mem rep inner ) -callKernelRules :: SimplifyMemory rep => RuleBook (Wise rep)+callKernelRules :: SimplifyMemory rep inner => RuleBook (Wise rep) callKernelRules = standardRules <> ruleBook@@ -121,10 +119,10 @@ -- the array is not existential, and the index function of the array -- does not refer to any names in the pattern, then we can create a -- block of the proper size and always return there.-unExistentialiseMemory :: SimplifyMemory rep => TopDownRuleIf (Wise rep)+unExistentialiseMemory :: SimplifyMemory rep inner => TopDownRuleIf (Wise rep) unExistentialiseMemory vtable pat _ (cond, tbranch, fbranch, ifdec) | ST.simplifyMemory vtable,- fixable <- foldl hasConcretisableMemory mempty $ patternElements pat,+ fixable <- foldl hasConcretisableMemory mempty $ patElems pat, not $ null fixable = Simplify $ do -- Create non-existential memory blocks big enough to hold the -- arrays.@@ -132,28 +130,24 @@ fmap unzip $ forM fixable $ \(arr_pe, mem_size, oldmem, space) -> do size <- toSubExp "size" mem_size- mem <- letExp "mem" $ Op $ allocOp size space+ mem <- letExp "mem" $ Op $ Alloc size space return ((patElemName arr_pe, mem), (oldmem, mem)) -- Update the branches to contain Copy expressions putting the -- arrays where they are expected. let updateBody body = buildBody_ $ do res <- bodyBind body- zipWithM updateResult (patternElements pat) res- updateResult pat_elem (Var v)+ zipWithM updateResult (patElems pat) res+ updateResult pat_elem (SubExpRes cs (Var v)) | Just mem <- lookup (patElemName pat_elem) arr_to_mem, (_, MemArray pt shape u (ArrayIn _ ixfun)) <- patElemDec pat_elem = do v_copy <- newVName $ baseString v <> "_nonext_copy" let v_pat =- Pattern- []- [ PatElem v_copy $- MemArray pt shape u $ ArrayIn mem ixfun- ]+ Pat [PatElem v_copy $ MemArray pt shape u $ ArrayIn mem ixfun] addStm $ mkWiseLetStm v_pat (defAux ()) $ BasicOp (Copy v)- return $ Var v_copy+ return $ SubExpRes cs $ Var v_copy | Just mem <- lookup (patElemName pat_elem) oldmem_to_mem =- return $ Var mem+ return $ SubExpRes cs $ Var mem updateResult _ se = return se tbranch' <- updateBody tbranch@@ -161,13 +155,11 @@ letBind pat $ If cond tbranch' fbranch' ifdec where onlyUsedIn name here =- not $- any ((name `nameIn`) . freeIn) $- filter ((/= here) . patElemName) $- patternValueElements pat+ not . any ((name `nameIn`) . freeIn) . filter ((/= here) . patElemName) $+ patElems pat knownSize Constant {} = True knownSize (Var v) = not $ inContext v- inContext = (`elem` patternContextNames pat)+ inContext = (`elem` patNames pat) hasConcretisableMemory fixable pat_elem | (_, MemArray pt shape _ (ArrayIn mem ixfun)) <- patElemDec pat_elem,@@ -175,12 +167,12 @@ fmap patElemType <$> find ((mem ==) . patElemName . snd)- (zip [(0 :: Int) ..] $ patternElements pat),+ (zip [(0 :: Int) ..] $ patElems pat), Just tse <- maybeNth j $ bodyResult tbranch, Just fse <- maybeNth j $ bodyResult fbranch, mem `onlyUsedIn` patElemName pat_elem, all knownSize (shapeDims shape),- not $ freeIn ixfun `namesIntersect` namesFromList (patternNames pat),+ not $ freeIn ixfun `namesIntersect` namesFromList (patNames pat), fse /= tse = let mem_size = untyped $ product $ primByteSize pt : map sExt64 (IxFun.base ixfun)@@ -192,11 +184,11 @@ -- | If we are copying something that is itself a copy, just copy the -- original one instead. copyCopyToCopy ::- ( BinderOps rep,+ ( BuilderOps rep, LetDec rep ~ (VarWisdom, MemBound u) ) => TopDownRuleBasicOp rep-copyCopyToCopy vtable pat@(Pattern [] [pat_elem]) _ (Copy v1)+copyCopyToCopy vtable pat@(Pat [pat_elem]) _ (Copy v1) | Just (BasicOp (Copy v2), v1_cs) <- ST.lookupExp v1 vtable, Just (_, MemArray _ _ _ (ArrayIn srcmem src_ixfun)) <- ST.entryLetBoundDec =<< ST.lookup v1 vtable,@@ -218,11 +210,11 @@ -- | If the destination of a copy is the same as the source, just -- remove it. removeIdentityCopy ::- ( BinderOps rep,+ ( BuilderOps rep, LetDec rep ~ (VarWisdom, MemBound u) ) => TopDownRuleBasicOp rep-removeIdentityCopy vtable pat@(Pattern [] [pe]) _ (Copy v)+removeIdentityCopy vtable pat@(Pat [pe]) _ (Copy v) | (_, MemArray _ _ _ (ArrayIn dest_mem dest_ixfun)) <- patElemDec pe, Just (_, MemArray _ _ _ (ArrayIn src_mem src_ixfun)) <- ST.entryLetBoundDec =<< ST.lookup v vtable,@@ -234,10 +226,10 @@ -- If an allocation is statically known to be safe, then we can remove -- the certificates on it. This can help hoist things that would -- otherwise be stuck inside loops or branches.-decertifySafeAlloc :: SimplifyMemory rep => TopDownRuleOp (Wise rep)+decertifySafeAlloc :: SimplifyMemory rep inner => TopDownRuleOp (Wise rep) decertifySafeAlloc _ pat (StmAux cs attrs _) op | cs /= mempty,- [Mem _] <- patternTypes pat,+ [Mem _] <- patTypes pat, safeOp op = Simplify $ attributing attrs $ letBind pat $ Op op decertifySafeAlloc _ _ _ _ = Skip
src/Futhark/IR/Parse.hs view
@@ -24,7 +24,7 @@ import Futhark.Analysis.PrimExp.Parse import Futhark.IR import Futhark.IR.GPU (GPU)-import qualified Futhark.IR.GPU.Kernel as Kernel+import qualified Futhark.IR.GPU.Op as GPU import Futhark.IR.GPUMem (GPUMem) import Futhark.IR.MC (MC) import qualified Futhark.IR.MC.Op as MC@@ -157,14 +157,6 @@ pVNames :: Parser [VName] pVNames = braces (pVName `sepBy` pComma) -pPatternLike :: Parser a -> Parser ([a], [a])-pPatternLike p = braces $ do- xs <- p `sepBy` pComma- choice- [ pSemi *> ((xs,) <$> (p `sepBy` pComma)),- pure (mempty, xs)- ]- pConvOp :: T.Text -> (t1 -> t2 -> ConvOp) -> Parser t1 -> Parser t2 -> Parser BasicOp pConvOp s op t1 t2 =@@ -202,20 +194,27 @@ ] pSlice :: Parser (Slice SubExp)-pSlice = brackets $ pDimIndex `sepBy` pComma+pSlice = Slice <$> brackets (pDimIndex `sepBy` pComma) pIndex :: Parser BasicOp pIndex = try $ Index <$> pVName <*> pSlice +pFlatDimIndex :: Parser (FlatDimIndex SubExp)+pFlatDimIndex =+ FlatDimIndex <$> pSubExp <* lexeme ":" <*> pSubExp++pFlatSlice :: Parser (FlatSlice SubExp)+pFlatSlice =+ brackets $ FlatSlice <$> pSubExp <* pSemi <*> (pFlatDimIndex `sepBy` pComma)++pFlatIndex :: Parser BasicOp+pFlatIndex = try $ FlatIndex <$> pVName <*> pFlatSlice+ pErrorMsgPart :: Parser (ErrorMsgPart SubExp) pErrorMsgPart = choice [ ErrorString <$> pStringLiteral,- flip ($) <$> (pSubExp <* pColon)- <*> choice- [ keyword "i32" $> ErrorInt32,- keyword "i64" $> ErrorInt64- ]+ flip ErrorVal <$> (pSubExp <* pColon) <*> pPrimType ] pErrorMsg :: Parser (ErrorMsg SubExp)@@ -253,7 +252,9 @@ pBasicOp :: Parser BasicOp pBasicOp = choice- [ keyword "opaque" $> Opaque <*> parens pSubExp,+ [ keyword "opaque" $> Opaque OpaqueNil <*> parens pSubExp,+ keyword "trace" $> uncurry (Opaque . OpaqueTrace)+ <*> parens ((,) <$> lexeme pStringLiteral <* pComma <*> pSubExp), keyword "copy" $> Copy <*> parens pVName, keyword "assert" *> parens@@ -283,10 +284,16 @@ Concat d <$> pVName <*> many (pComma *> pVName) <*> pure w, pIota, try $- Update+ flip Update <$> pVName <* keyword "with"+ <*> choice [lexeme "?" $> Safe, pure Unsafe] <*> pSlice <* lexeme "=" <*> pSubExp,+ try $+ FlatUpdate+ <$> pVName <* keyword "with"+ <*> pFlatSlice <* lexeme "="+ <*> pVName, ArrayLit <$> brackets (pSubExp `sepBy` pComma) <*> (lexeme ":" *> "[]" *> pType),@@ -305,6 +312,7 @@ pConvOp "btoi" (const BToI) (keyword "bool") pIntType, -- pIndex,+ pFlatIndex, pBinOp, pCmpOp, pUnOp,@@ -371,9 +379,12 @@ pPatElem pr = (PatElem <$> pVName <*> (pColon *> pLetDec pr)) <?> "pattern element" -pPattern :: PR rep -> Parser (Pattern rep)-pPattern pr = uncurry Pattern <$> pPatternLike (pPatElem pr)+pPat :: PR rep -> Parser (Pat rep)+pPat pr = Pat <$> braces (pPatElem pr `sepBy` pComma) +pResult :: Parser Result+pResult = braces $ pSubExpRes `sepBy` pComma+ pIf :: PR rep -> Parser (Exp rep) pIf pr = keyword "if" $> f <*> pSort <*> pSubExp@@ -391,7 +402,7 @@ If cond tbranch fbranch $ IfDec t sort pBranchBody = choice- [ try $ braces $ Body (pBodyDec pr) mempty <$> pSubExp `sepBy` pComma,+ [ try $ Body (pBodyDec pr) mempty <$> pResult, braces (pBody pr) ] @@ -414,17 +425,16 @@ pLoop :: PR rep -> Parser (Exp rep) pLoop pr =- keyword "loop" $> uncurry DoLoop+ keyword "loop" $> DoLoop <*> pLoopParams <*> pLoopForm <* keyword "do" <*> braces (pBody pr) where pLoopParams = do- (ctx, val) <- pPatternLike (pFParam pr)+ params <- braces $ pFParam pr `sepBy` pComma void $ lexeme "="- (ctx_init, val_init) <-- splitAt (length ctx) <$> braces (pSubExp `sepBy` pComma)- pure (zip ctx ctx_init, zip val val_init)+ args <- braces (pSubExp `sepBy` pComma)+ pure (zip params args) pLoopForm = choice@@ -487,17 +497,22 @@ BasicOp <$> pBasicOp ] +pCerts :: Parser Certs+pCerts =+ choice+ [ lexeme "#" *> braces (Certs <$> pVName `sepBy` pComma)+ <?> "certificates",+ pure mempty+ ]++pSubExpRes :: Parser SubExpRes+pSubExpRes = SubExpRes <$> pCerts <*> pSubExp+ pStm :: PR rep -> Parser (Stm rep) pStm pr =- keyword "let" $> Let <*> pPattern pr <* pEqual <*> pStmAux <*> pExp pr+ keyword "let" $> Let <*> pPat pr <* pEqual <*> pStmAux <*> pExp pr where pStmAux = flip StmAux <$> pAttrs <*> pCerts <*> pure (pExpDec pr)- pCerts =- choice- [ lexeme "#" *> braces (Certificates <$> pVName `sepBy` pComma)- <?> "certificates",- pure mempty- ] pStms :: PR rep -> Parser (Stms rep) pStms pr = stmsFromList <$> many (pStm pr)@@ -508,8 +523,6 @@ [ Body (pBodyDec pr) <$> pStms pr <* keyword "in" <*> pResult, Body (pBodyDec pr) mempty <$> pResult ]- where- pResult = braces $ pSubExp `sepBy` pComma pEntry :: Parser EntryPoint pEntry =@@ -633,23 +646,23 @@ <*> braces (pSubExp `sepBy` pComma) <* pComma <*> pLambda pr -pSizeClass :: Parser Kernel.SizeClass+pSizeClass :: Parser GPU.SizeClass pSizeClass = choice- [ keyword "group_size" $> Kernel.SizeGroup,- keyword "num_groups" $> Kernel.SizeNumGroups,- keyword "num_groups" $> Kernel.SizeNumGroups,- keyword "tile_size" $> Kernel.SizeTile,- keyword "reg_tile_size" $> Kernel.SizeRegTile,- keyword "local_memory" $> Kernel.SizeLocalMemory,+ [ keyword "group_size" $> GPU.SizeGroup,+ keyword "num_groups" $> GPU.SizeNumGroups,+ keyword "num_groups" $> GPU.SizeNumGroups,+ keyword "tile_size" $> GPU.SizeTile,+ keyword "reg_tile_size" $> GPU.SizeRegTile,+ keyword "local_memory" $> GPU.SizeLocalMemory, keyword "threshold" *> parens- ( flip Kernel.SizeThreshold+ ( flip GPU.SizeThreshold <$> choice [Just <$> pInt64, "def" $> Nothing] <* pComma <*> pKernelPath ), keyword "bespoke"- *> parens (Kernel.SizeBespoke <$> pName <* pComma <*> pInt64)+ *> parens (GPU.SizeBespoke <$> pName <* pComma <*> pInt64) ] where pKernelPath = many pStep@@ -659,33 +672,33 @@ (,) <$> pName <*> pure True ] -pSizeOp :: Parser Kernel.SizeOp+pSizeOp :: Parser GPU.SizeOp pSizeOp = choice [ keyword "get_size"- *> parens (Kernel.GetSize <$> pName <* pComma <*> pSizeClass),+ *> parens (GPU.GetSize <$> pName <* pComma <*> pSizeClass), keyword "get_size_max"- *> parens (Kernel.GetSizeMax <$> pSizeClass),+ *> parens (GPU.GetSizeMax <$> pSizeClass), keyword "cmp_size"- *> ( parens (Kernel.CmpSizeLe <$> pName <* pComma <*> pSizeClass)+ *> ( parens (GPU.CmpSizeLe <$> pName <* pComma <*> pSizeClass) <*> (lexeme "<=" *> pSubExp) ), keyword "calc_num_groups" *> parens- ( Kernel.CalcNumGroups+ ( GPU.CalcNumGroups <$> pSubExp <* pComma <*> pName <* pComma <*> pSubExp ), keyword "split_space" *> parens- ( Kernel.SplitSpace Kernel.SplitContiguous+ ( GPU.SplitSpace GPU.SplitContiguous <$> pSubExp <* pComma <*> pSubExp <* pComma <*> pSubExp ), keyword "split_space_strided" *> parens- ( Kernel.SplitSpace- <$> (Kernel.SplitStrided <$> pSubExp) <* pComma+ ( GPU.SplitSpace+ <$> (GPU.SplitStrided <$> pSubExp) <* pComma <*> pSubExp <* pComma <*> pSubExp <* pComma <*> pSubExp@@ -701,7 +714,8 @@ pDim = (,) <$> pVName <* lexeme "<" <*> pSubExp pKernelResult :: Parser SegOp.KernelResult-pKernelResult =+pKernelResult = do+ cs <- pCerts choice [ keyword "returns" $> SegOp.Returns <*> choice@@ -709,26 +723,27 @@ keyword "(private)" $> SegOp.ResultPrivate, pure SegOp.ResultMaySimplify ]+ <*> pure cs <*> pSubExp, try $- flip SegOp.WriteReturns+ flip (SegOp.WriteReturns cs) <$> pVName <* pColon <*> pShape <* keyword "with" <*> parens (pWrite `sepBy` pComma), try "tile"- *> parens (SegOp.TileReturns <$> (pTile `sepBy` pComma)) <*> pVName,+ *> parens (SegOp.TileReturns cs <$> (pTile `sepBy` pComma)) <*> pVName, try "blkreg_tile"- *> parens (SegOp.RegTileReturns <$> (pRegTile `sepBy` pComma)) <*> pVName,+ *> parens (SegOp.RegTileReturns cs <$> (pRegTile `sepBy` pComma)) <*> pVName, keyword "concat" *> parens- ( SegOp.ConcatReturns SegOp.SplitContiguous+ ( SegOp.ConcatReturns cs SegOp.SplitContiguous <$> pSubExp <* pComma <*> pSubExp ) <*> pVName, keyword "concat_strided" *> parens- ( SegOp.ConcatReturns+ ( SegOp.ConcatReturns cs <$> (SegOp.SplitStrided <$> pSubExp) <* pComma <*> pSubExp <* pComma <*> pSubExp@@ -790,15 +805,15 @@ pSegScan = pSegOp' SegOp.SegScan pSegBinOp pSegHist = pSegOp' SegOp.SegHist pHistOp -pSegLevel :: Parser Kernel.SegLevel+pSegLevel :: Parser GPU.SegLevel pSegLevel = parens $ choice- [ keyword "thread" $> Kernel.SegThread,- keyword "group" $> Kernel.SegGroup+ [ keyword "thread" $> GPU.SegThread,+ keyword "group" $> GPU.SegGroup ]- <*> (pSemi *> lexeme "#groups=" $> Kernel.Count <*> pSubExp)- <*> (pSemi *> lexeme "groupsize=" $> Kernel.Count <*> pSubExp)+ <*> (pSemi *> lexeme "#groups=" $> GPU.Count <*> pSubExp)+ <*> (pSemi *> lexeme "groupsize=" $> GPU.Count <*> pSubExp) <*> choice [ pSemi *> choice@@ -808,12 +823,12 @@ pure SegOp.SegNoVirt ] -pHostOp :: PR rep -> Parser op -> Parser (Kernel.HostOp rep op)+pHostOp :: PR rep -> Parser op -> Parser (GPU.HostOp rep op) pHostOp pr pOther = choice- [ Kernel.SegOp <$> pSegOp pr pSegLevel,- Kernel.SizeOp <$> pSizeOp,- Kernel.OtherOp <$> pOther+ [ GPU.SegOp <$> pSegOp pr pSegLevel,+ GPU.SizeOp <$> pSizeOp,+ GPU.OtherOp <$> pOther ] pMCOp :: PR rep -> Parser op -> Parser (MC.MCOp rep op)
src/Futhark/IR/Pretty.hs view
@@ -92,13 +92,16 @@ ppr (Var v) = ppr v ppr (Constant v) = ppr v -instance Pretty Certificates where- ppr (Certificates []) = empty- ppr (Certificates cs) = text "#" <> braces (commasep (map ppr cs))+instance Pretty Certs where+ ppr (Certs []) = empty+ ppr (Certs cs) = text "#" <> braces (commasep (map ppr cs)) instance PrettyRep rep => Pretty (Stms rep) where ppr = stack . map ppr . stmsToList +instance Pretty SubExpRes where+ ppr (SubExpRes cs se) = spread $ certAnnots cs ++ [ppr se]+ instance PrettyRep rep => Pretty (Body rep) where ppr (Body _ stms res) | null stms = braces (commasep $ map ppr res)@@ -118,7 +121,7 @@ stmAttrAnnots :: Stm rep -> [Doc] stmAttrAnnots = attrAnnots . stmAuxAttrs . stmAux -certAnnots :: Certificates -> [Doc]+certAnnots :: Certs -> [Doc] certAnnots cs | cs == mempty = [] | otherwise = [ppr cs]@@ -126,9 +129,12 @@ stmCertAnnots :: Stm rep -> [Doc] stmCertAnnots = certAnnots . stmAuxCerts . stmAux -instance Pretty (PatElemT dec) => Pretty (PatternT dec) where- ppr pat = ppPattern (patternContextElements pat) (patternValueElements pat)+instance Pretty Attrs where+ ppr = spread . attrAnnots +instance Pretty (PatElemT dec) => Pretty (PatT dec) where+ ppr (Pat xs) = braces $ commastack $ map ppr xs+ instance Pretty t => Pretty (PatElemT t) where ppr (PatElem name t) = ppr name <+> colon <+> align (ppr t) @@ -159,9 +165,19 @@ stmCertAnnots bnd ] +instance Pretty a => Pretty (Slice a) where+ ppr (Slice xs) = brackets (commasep (map ppr xs))++instance Pretty d => Pretty (FlatDimIndex d) where+ ppr (FlatDimIndex n s) = ppr n <+> text ":" <+> ppr s++instance Pretty a => Pretty (FlatSlice a) where+ ppr (FlatSlice offset xs) = brackets (ppr offset <> text ";" <+> commasep (map ppr xs))+ instance Pretty BasicOp where ppr (SubExp se) = ppr se- ppr (Opaque e) = text "opaque" <> apply [ppr e]+ ppr (Opaque OpaqueNil e) = text "opaque" <> apply [ppr e]+ ppr (Opaque (OpaqueTrace s) e) = text "trace" <> apply [ppr (show s), ppr e] ppr (ArrayLit es rt) = case rt of Array {} -> brackets $ commastack $ map ppr es@@ -175,12 +191,16 @@ where (fromtype, totype) = convOpType conv ppr (UnOp op e) = ppr op <+> pprPrec 9 e- ppr (Index v idxs) =- ppr v <> brackets (commasep (map ppr idxs))- ppr (Update src idxs se) =- ppr src <+> text "with" <+> brackets (commasep (map ppr idxs))- <+> text "="- <+> ppr se+ ppr (Index v slice) = ppr v <> ppr slice+ ppr (Update safety src slice se) =+ ppr src <+> with <+> ppr slice <+> text "=" <+> ppr se+ where+ with = case safety of+ Unsafe -> text "with"+ Safe -> text "with?"+ ppr (FlatIndex v slice) = ppr v <> ppr slice+ ppr (FlatUpdate src slice se) =+ ppr src <+> text "with" <+> ppr slice <+> text "=" <+> ppr se ppr (Iota e x s et) = text "iota" <> et' <> apply [ppr e, ppr x, ppr s] where et' = text $ show $ primBitSize $ IntType et@@ -207,8 +227,7 @@ ppr (ErrorMsg parts) = braces $ align $ commasep $ map p parts where p (ErrorString s) = text $ show s- p (ErrorInt32 x) = ppr x <+> colon <+> text "i32"- p (ErrorInt64 x) = ppr x <+> colon <+> text "i64"+ p (ErrorVal t x) = ppr x <+> colon <+> ppr t instance PrettyRep rep => Pretty (Exp rep) where ppr (If c t f (IfDec ret ifsort)) =@@ -217,8 +236,8 @@ <+> maybeNest t <+> text "else" <+> maybeNest f- <+> colon- <+> braces (commasep $ map ppr ret)+ </> colon+ <+> ppTuple' ret where info' = case ifsort of IfNormal -> mempty@@ -241,10 +260,10 @@ Unsafe -> text "apply <unsafe>" Safe -> text "apply" ppr (Op op) = ppr op- ppr (DoLoop ctx val form loopbody) =- text "loop" <+> ppPattern ctxparams valparams+ ppr (DoLoop merge form loopbody) =+ text "loop" <+> braces (commastack $ map ppr params) <+> equals- <+> ppTuple' (ctxinit ++ valinit)+ <+> ppTuple' args </> ( case form of ForLoop i it bound [] -> text "for"@@ -267,8 +286,7 @@ <+> text "do" <+> nestedBlock "{" "}" (ppr loopbody) where- (ctxparams, ctxinit) = unzip ctx- (valparams, valinit) = unzip val+ (params, args) = unzip merge pprLoopVar (p, a) = ppr p <+> text "in" <+> ppr a ppr (WithAcc inputs lam) = text "with_acc"@@ -327,10 +345,6 @@ ppr (DimFix i) = ppr i ppr (DimSlice i n s) = ppr i <+> text ":+" <+> ppr n <+> text "*" <+> ppr s -ppPattern :: (Pretty a, Pretty b) => [a] -> [b] -> Doc-ppPattern [] bs = braces $ commastack $ map ppr bs-ppPattern as bs = braces $ commastack (map ppr as) <> semi </> commasep (map ppr bs)- -- | Like 'prettyTuple', but produces a 'Doc'. ppTuple' :: Pretty a => [a] -> Doc-ppTuple' ets = braces $ commasep $ map ppr ets+ppTuple' ets = braces $ commasep $ map (align . ppr) ets
src/Futhark/IR/Primitive.hs view
@@ -17,6 +17,7 @@ PrimType (..), allPrimTypes, module Data.Int,+ Half, -- * Values IntValue (..),@@ -116,9 +117,11 @@ import Data.Int (Int16, Int32, Int64, Int8) import qualified Data.Map as M import Data.Word+import Foreign.C.Types (CUShort (..)) import Futhark.Util ( ceilDouble, ceilFloat,+ convFloat, floorDouble, floorFloat, hypot,@@ -131,6 +134,7 @@ tgammaf, ) import Futhark.Util.Pretty+import Numeric.Half import Prelude hiding (id, (.)) -- | An integer type, ordered by size. Note that signedness is not a@@ -155,11 +159,13 @@ -- | A floating point type. data FloatType- = Float32+ = Float16+ | Float32 | Float64 deriving (Eq, Ord, Show, Enum, Bounded) instance Pretty FloatType where+ ppr Float16 = text "f16" ppr Float32 = text "f32" ppr Float64 = text "f64" @@ -181,19 +187,21 @@ toEnum 1 = IntType Int16 toEnum 2 = IntType Int32 toEnum 3 = IntType Int64- toEnum 4 = FloatType Float32- toEnum 5 = FloatType Float64- toEnum 6 = Bool+ toEnum 4 = FloatType Float16+ toEnum 5 = FloatType Float32+ toEnum 6 = FloatType Float64+ toEnum 7 = Bool toEnum _ = Unit fromEnum (IntType Int8) = 0 fromEnum (IntType Int16) = 1 fromEnum (IntType Int32) = 2 fromEnum (IntType Int64) = 3- fromEnum (FloatType Float32) = 4- fromEnum (FloatType Float64) = 5- fromEnum Bool = 6- fromEnum Unit = 7+ fromEnum (FloatType Float16) = 4+ fromEnum (FloatType Float32) = 5+ fromEnum (FloatType Float64) = 6+ fromEnum Bool = 7+ fromEnum Unit = 8 instance Bounded PrimType where minBound = IntType Int8@@ -249,32 +257,48 @@ -- | A floating-point value. data FloatValue- = Float32Value !Float+ = Float16Value !Half+ | Float32Value !Float | Float64Value !Double deriving (Show) instance Eq FloatValue where+ Float16Value x == Float16Value y = isNaN x && isNaN y || x == y Float32Value x == Float32Value y = isNaN x && isNaN y || x == y Float64Value x == Float64Value y = isNaN x && isNaN y || x == y- Float32Value _ == Float64Value _ = False- Float64Value _ == Float32Value _ = False+ _ == _ = False -- The derived Ord instance does not handle NaNs correctly. instance Ord FloatValue where+ Float16Value x <= Float16Value y = x <= y Float32Value x <= Float32Value y = x <= y Float64Value x <= Float64Value y = x <= y+ Float16Value _ <= Float32Value _ = True+ Float16Value _ <= Float64Value _ = True+ Float32Value _ <= Float16Value _ = False Float32Value _ <= Float64Value _ = True+ Float64Value _ <= Float16Value _ = False Float64Value _ <= Float32Value _ = False + Float16Value x < Float16Value y = x < y Float32Value x < Float32Value y = x < y Float64Value x < Float64Value y = x < y+ Float16Value _ < Float32Value _ = True+ Float16Value _ < Float64Value _ = True+ Float32Value _ < Float16Value _ = False Float32Value _ < Float64Value _ = True+ Float64Value _ < Float16Value _ = False Float64Value _ < Float32Value _ = False (>) = flip (<) (>=) = flip (<=) instance Pretty FloatValue where+ ppr (Float16Value v)+ | isInfinite v, v >= 0 = text "f16.inf"+ | isInfinite v, v < 0 = text "-f16.inf"+ | isNaN v = text "f16.nan"+ | otherwise = text $ show v ++ "f16" ppr (Float32Value v) | isInfinite v, v >= 0 = text "f32.inf" | isInfinite v, v < 0 = text "-f32.inf"@@ -288,11 +312,13 @@ -- | Create a t'FloatValue' from a type and a 'Rational'. floatValue :: Real num => FloatType -> num -> FloatValue+floatValue Float16 = Float16Value . fromRational . toRational floatValue Float32 = Float32Value . fromRational . toRational floatValue Float64 = Float64Value . fromRational . toRational -- | The type of a floating-point value. floatValueType :: FloatValue -> FloatType+floatValueType Float16Value {} = Float16 floatValueType Float32Value {} = Float32 floatValueType Float64Value {} = Float64 @@ -327,6 +353,7 @@ blankPrimValue (IntType Int16) = IntValue $ Int16Value 0 blankPrimValue (IntType Int32) = IntValue $ Int32Value 0 blankPrimValue (IntType Int64) = IntValue $ Int64Value 0+blankPrimValue (FloatType Float16) = FloatValue $ Float16Value 0.0 blankPrimValue (FloatType Float32) = FloatValue $ Float32Value 0.0 blankPrimValue (FloatType Float64) = FloatValue $ Float64Value 0.0 blankPrimValue Bool = BoolValue False@@ -628,6 +655,7 @@ -- | @abs(-2.0) = 2.0@. doFAbs :: FloatValue -> FloatValue+doFAbs (Float16Value x) = Float16Value $ abs x doFAbs (Float32Value x) = Float32Value $ abs x doFAbs (Float64Value x) = Float64Value $ abs x @@ -641,6 +669,7 @@ -- | @fsignum(-2.0)@ = -1.0. doFSignum :: FloatValue -> FloatValue+doFSignum (Float16Value v) = Float16Value $ signum v doFSignum (Float32Value v) = Float32Value $ signum v doFSignum (Float64Value v) = Float64Value $ signum v @@ -649,27 +678,27 @@ -- zero). doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue doBinOp Add {} = doIntBinOp doAdd-doBinOp FAdd {} = doFloatBinOp (+) (+)+doBinOp FAdd {} = doFloatBinOp (+) (+) (+) doBinOp Sub {} = doIntBinOp doSub-doBinOp FSub {} = doFloatBinOp (-) (-)+doBinOp FSub {} = doFloatBinOp (-) (-) (-) doBinOp Mul {} = doIntBinOp doMul-doBinOp FMul {} = doFloatBinOp (*) (*)+doBinOp FMul {} = doFloatBinOp (*) (*) (*) doBinOp UDiv {} = doRiskyIntBinOp doUDiv doBinOp UDivUp {} = doRiskyIntBinOp doUDivUp doBinOp SDiv {} = doRiskyIntBinOp doSDiv doBinOp SDivUp {} = doRiskyIntBinOp doSDivUp-doBinOp FDiv {} = doFloatBinOp (/) (/)-doBinOp FMod {} = doFloatBinOp mod' mod'+doBinOp FDiv {} = doFloatBinOp (/) (/) (/)+doBinOp FMod {} = doFloatBinOp mod' mod' mod' doBinOp UMod {} = doRiskyIntBinOp doUMod doBinOp SMod {} = doRiskyIntBinOp doSMod doBinOp SQuot {} = doRiskyIntBinOp doSQuot doBinOp SRem {} = doRiskyIntBinOp doSRem doBinOp SMin {} = doIntBinOp doSMin doBinOp UMin {} = doIntBinOp doUMin-doBinOp FMin {} = doFloatBinOp min min+doBinOp FMin {} = doFloatBinOp min min min doBinOp SMax {} = doIntBinOp doSMax doBinOp UMax {} = doIntBinOp doUMax-doBinOp FMax {} = doFloatBinOp max max+doBinOp FMax {} = doFloatBinOp max max max doBinOp Shl {} = doIntBinOp doShl doBinOp LShr {} = doIntBinOp doLShr doBinOp AShr {} = doIntBinOp doAShr@@ -677,7 +706,7 @@ doBinOp Or {} = doIntBinOp doOr doBinOp Xor {} = doIntBinOp doXor doBinOp Pow {} = doRiskyIntBinOp doPow-doBinOp FPow {} = doFloatBinOp (**) (**)+doBinOp FPow {} = doFloatBinOp (**) (**) (**) doBinOp LogAnd {} = doBoolBinOp (&&) doBinOp LogOr {} = doBoolBinOp (||) @@ -700,16 +729,19 @@ doRiskyIntBinOp _ _ _ = Nothing doFloatBinOp ::+ (Half -> Half -> Half) -> (Float -> Float -> Float) -> (Double -> Double -> Double) -> PrimValue -> PrimValue -> Maybe PrimValue-doFloatBinOp f32 _ (FloatValue (Float32Value v1)) (FloatValue (Float32Value v2)) =+doFloatBinOp f16 _ _ (FloatValue (Float16Value v1)) (FloatValue (Float16Value v2)) =+ Just $ FloatValue $ Float16Value $ f16 v1 v2+doFloatBinOp _ f32 _ (FloatValue (Float32Value v1)) (FloatValue (Float32Value v2)) = Just $ FloatValue $ Float32Value $ f32 v1 v2-doFloatBinOp _ f64 (FloatValue (Float64Value v1)) (FloatValue (Float64Value v2)) =+doFloatBinOp _ _ f64 (FloatValue (Float64Value v1)) (FloatValue (Float64Value v2)) = Just $ FloatValue $ Float64Value $ f64 v1 v2-doFloatBinOp _ _ _ _ = Nothing+doFloatBinOp _ _ _ _ _ = Nothing doBoolBinOp :: (Bool -> Bool -> Bool) ->@@ -890,6 +922,7 @@ -- | Convert the former floating-point type to the latter. doFPConv :: FloatValue -> FloatType -> FloatValue+doFPConv v Float16 = Float16Value $ floatToHalf v doFPConv v Float32 = Float32Value $ floatToFloat v doFPConv v Float64 = Float64Value $ floatToDouble v @@ -974,6 +1007,11 @@ intToInt = fromIntegral . intToInt64 floatToDouble :: FloatValue -> Double+floatToDouble (Float16Value v)+ | isInfinite v, v > 0 = 1 / 0+ | isInfinite v, v < 0 = -1 / 0+ | isNaN v = 0 / 0+ | otherwise = fromRational $ toRational v floatToDouble (Float32Value v) | isInfinite v, v > 0 = 1 / 0 | isInfinite v, v < 0 = -1 / 0@@ -982,13 +1020,31 @@ floatToDouble (Float64Value v) = v floatToFloat :: FloatValue -> Float-floatToFloat (Float64Value v)+floatToFloat (Float16Value v) | isInfinite v, v > 0 = 1 / 0 | isInfinite v, v < 0 = -1 / 0 | isNaN v = 0 / 0 | otherwise = fromRational $ toRational v floatToFloat (Float32Value v) = v+floatToFloat (Float64Value v)+ | isInfinite v, v > 0 = 1 / 0+ | isInfinite v, v < 0 = -1 / 0+ | isNaN v = 0 / 0+ | otherwise = fromRational $ toRational v +floatToHalf :: FloatValue -> Half+floatToHalf (Float16Value v) = v+floatToHalf (Float32Value v)+ | isInfinite v, v > 0 = 1 / 0+ | isInfinite v, v < 0 = -1 / 0+ | isNaN v = 0 / 0+ | otherwise = fromRational $ toRational v+floatToHalf (Float64Value v)+ | isInfinite v, v > 0 = 1 / 0+ | isInfinite v, v < 0 = -1 / 0+ | isNaN v = 0 / 0+ | otherwise = fromRational $ toRational v+ -- | The result type of a binary operator. binOpType :: BinOp -> PrimType binOpType (Add t _) = IntType t@@ -1058,6 +1114,12 @@ convOpType (IToB from) = (IntType from, Bool) convOpType (BToI to) = (Bool, IntType to) +halfToWord :: Half -> Word16+halfToWord (Half (CUShort x)) = x++wordToHalf :: Word16 -> Half+wordToHalf = Half . CUShort+ floatToWord :: Float -> Word32 floatToWord = G.runGet G.getWord32le . P.runPut . P.putFloatle @@ -1081,50 +1143,94 @@ ) primFuns = M.fromList- [ f32 "sqrt32" sqrt,+ [ f16 "sqrt16" sqrt,+ f32 "sqrt32" sqrt, f64 "sqrt64" sqrt,+ --+ f16 "log16" log, f32 "log32" log, f64 "log64" log,+ --+ f16 "log10_16" (logBase 10), f32 "log10_32" (logBase 10), f64 "log10_64" (logBase 10),+ --+ f16 "log2_16" (logBase 2), f32 "log2_32" (logBase 2), f64 "log2_64" (logBase 2),+ --+ f16 "exp16" exp, f32 "exp32" exp, f64 "exp64" exp,+ --+ f16 "sin16" sin, f32 "sin32" sin, f64 "sin64" sin,+ --+ f16 "sinh16" sinh, f32 "sinh32" sinh, f64 "sinh64" sinh,+ --+ f16 "cos16" cos, f32 "cos32" cos, f64 "cos64" cos,+ --+ f16 "cosh16" cosh, f32 "cosh32" cosh, f64 "cosh64" cosh,+ --+ f16 "tan16" tan, f32 "tan32" tan, f64 "tan64" tan,+ --+ f16 "tanh16" tanh, f32 "tanh32" tanh, f64 "tanh64" tanh,+ --+ f16 "asin16" asin, f32 "asin32" asin, f64 "asin64" asin,+ --+ f16 "asinh16" asinh, f32 "asinh32" asinh, f64 "asinh64" asinh,+ --+ f16 "acos16" acos, f32 "acos32" acos, f64 "acos64" acos,+ --+ f16 "acosh16" acosh, f32 "acosh32" acosh, f64 "acosh64" acosh,+ --+ f16 "atan16" atan, f32 "atan32" atan, f64 "atan64" atan,+ --+ f16 "atanh16" atanh, f32 "atanh32" atanh, f64 "atanh64" atanh,+ --+ f16 "round16" $ convFloat . roundFloat . convFloat, f32 "round32" roundFloat, f64 "round64" roundDouble,+ --+ f16 "ceil16" $ convFloat . ceilFloat . convFloat, f32 "ceil32" ceilFloat, f64 "ceil64" ceilDouble,+ --+ f16 "floor16" $ convFloat . floorFloat . convFloat, f32 "floor32" floorFloat, f64 "floor64" floorDouble,+ --+ f16 "gamma16" $ convFloat . tgammaf . convFloat, f32 "gamma32" tgammaf, f64 "gamma64" tgamma,+ --+ f16 "lgamma16" $ convFloat . lgammaf . convFloat, f32 "lgamma32" lgammaf, f64 "lgamma64" lgamma,+ -- i8 "clz8" $ IntValue . Int32Value . fromIntegral . countLeadingZeros, i16 "clz16" $ IntValue . Int32Value . fromIntegral . countLeadingZeros, i32 "clz32" $ IntValue . Int32Value . fromIntegral . countLeadingZeros,@@ -1209,6 +1315,16 @@ _ -> Nothing ) ),+ --+ ( "atan2_16",+ ( [FloatType Float16, FloatType Float16],+ FloatType Float16,+ \case+ [FloatValue (Float16Value x), FloatValue (Float16Value y)] ->+ Just $ FloatValue $ Float16Value $ atan2 x y+ _ -> Nothing+ )+ ), ( "atan2_32", ( [FloatType Float32, FloatType Float32], FloatType Float32,@@ -1227,6 +1343,16 @@ _ -> Nothing ) ),+ --+ ( "hypot16",+ ( [FloatType Float16, FloatType Float16],+ FloatType Float16,+ \case+ [FloatValue (Float16Value x), FloatValue (Float16Value y)] ->+ Just $ FloatValue $ Float16Value $ convFloat $ hypotf (convFloat x) (convFloat y)+ _ -> Nothing+ )+ ), ( "hypot32", ( [FloatType Float32, FloatType Float32], FloatType Float32,@@ -1245,6 +1371,14 @@ _ -> Nothing ) ),+ ( "isinf16",+ ( [FloatType Float16],+ Bool,+ \case+ [FloatValue (Float16Value x)] -> Just $ BoolValue $ isInfinite x+ _ -> Nothing+ )+ ), ( "isinf32", ( [FloatType Float32], Bool,@@ -1261,6 +1395,14 @@ _ -> Nothing ) ),+ ( "isnan16",+ ( [FloatType Float16],+ Bool,+ \case+ [FloatValue (Float16Value x)] -> Just $ BoolValue $ isNaN x+ _ -> Nothing+ )+ ), ( "isnan32", ( [FloatType Float32], Bool,@@ -1277,6 +1419,15 @@ _ -> Nothing ) ),+ ( "to_bits16",+ ( [FloatType Float16],+ IntType Int16,+ \case+ [FloatValue (Float16Value x)] ->+ Just $ IntValue $ Int16Value $ fromIntegral $ halfToWord x+ _ -> Nothing+ )+ ), ( "to_bits32", ( [FloatType Float32], IntType Int32,@@ -1295,6 +1446,15 @@ _ -> Nothing ) ),+ ( "from_bits16",+ ( [IntType Int16],+ FloatType Float16,+ \case+ [IntValue (Int16Value x)] ->+ Just $ FloatValue $ Float16Value $ wordToHalf $ fromIntegral x+ _ -> Nothing+ )+ ), ( "from_bits32", ( [IntType Int32], FloatType Float32,@@ -1313,10 +1473,13 @@ _ -> Nothing ) ),+ f16_3 "lerp16" (\v0 v1 t -> v0 + (v1 - v0) * max 0 (min 1 t)), f32_3 "lerp32" (\v0 v1 t -> v0 + (v1 - v0) * max 0 (min 1 t)), f64_3 "lerp64" (\v0 v1 t -> v0 + (v1 - v0) * max 0 (min 1 t)),+ f16_3 "mad16" (\a b c -> a * b + c), f32_3 "mad32" (\a b c -> a * b + c), f64_3 "mad64" (\a b c -> a * b + c),+ f16_3 "fma16" (\a b c -> a * b + c), f32_3 "fma32" (\a b c -> a * b + c), f64_3 "fma64" (\a b c -> a * b + c) ]@@ -1325,8 +1488,16 @@ i16 s f = (s, ([IntType Int16], IntType Int32, i16PrimFun f)) i32 s f = (s, ([IntType Int32], IntType Int32, i32PrimFun f)) i64 s f = (s, ([IntType Int64], IntType Int32, i64PrimFun f))+ f16 s f = (s, ([FloatType Float16], FloatType Float16, f16PrimFun f)) f32 s f = (s, ([FloatType Float32], FloatType Float32, f32PrimFun f)) f64 s f = (s, ([FloatType Float64], FloatType Float64, f64PrimFun f))+ f16_3 s f =+ ( s,+ ( [FloatType Float16, FloatType Float16, FloatType Float16],+ FloatType Float16,+ f16PrimFun3 f+ )+ ) f32_3 s f = ( s, ( [FloatType Float32, FloatType Float32, FloatType Float32],@@ -1358,6 +1529,10 @@ Just $ f x i64PrimFun _ _ = Nothing + f16PrimFun f [FloatValue (Float16Value x)] =+ Just $ FloatValue $ Float16Value $ f x+ f16PrimFun _ _ = Nothing+ f32PrimFun f [FloatValue (Float32Value x)] = Just $ FloatValue $ Float32Value $ f x f32PrimFun _ _ = Nothing@@ -1366,6 +1541,15 @@ Just $ FloatValue $ Float64Value $ f x f64PrimFun _ _ = Nothing + f16PrimFun3+ f+ [ FloatValue (Float16Value a),+ FloatValue (Float16Value b),+ FloatValue (Float16Value c)+ ] =+ Just $ FloatValue $ Float16Value $ f a b c+ f16PrimFun3 _ _ = Nothing+ f32PrimFun3 f [ FloatValue (Float32Value a),@@ -1387,6 +1571,7 @@ -- | Is the given value kind of zero? zeroIsh :: PrimValue -> Bool zeroIsh (IntValue k) = zeroIshInt k+zeroIsh (FloatValue (Float16Value k)) = k == 0 zeroIsh (FloatValue (Float32Value k)) = k == 0 zeroIsh (FloatValue (Float64Value k)) = k == 0 zeroIsh (BoolValue False) = True@@ -1395,6 +1580,7 @@ -- | Is the given value kind of one? oneIsh :: PrimValue -> Bool oneIsh (IntValue k) = oneIshInt k+oneIsh (FloatValue (Float16Value k)) = k == 1 oneIsh (FloatValue (Float32Value k)) = k == 1 oneIsh (FloatValue (Float64Value k)) = k == 1 oneIsh (BoolValue True) = True@@ -1403,6 +1589,7 @@ -- | Is the given value kind of negative? negativeIsh :: PrimValue -> Bool negativeIsh (IntValue k) = negativeIshInt k+negativeIsh (FloatValue (Float16Value k)) = k < 0 negativeIsh (FloatValue (Float32Value k)) = k < 0 negativeIsh (FloatValue (Float64Value k)) = k < 0 negativeIsh (BoolValue _) = False@@ -1449,6 +1636,7 @@ -- | The size of a value of a given floating-point type in eight-bit bytes. floatByteSize :: Num a => FloatType -> a+floatByteSize Float16 = 2 floatByteSize Float32 = 4 floatByteSize Float64 = 8 @@ -1563,6 +1751,7 @@ taggedI s Int64 = text $ s ++ "64" taggedF :: String -> FloatType -> Doc+taggedF s Float16 = text $ s ++ "16" taggedF s Float32 = text $ s ++ "32" taggedF s Float64 = text $ s ++ "64"
src/Futhark/IR/Primitive/Parse.hs view
@@ -48,6 +48,9 @@ pFloatValue = choice [ pNum,+ keyword "f16.nan" $> Float16Value (0 / 0),+ keyword "f16.inf" $> Float16Value (1 / 0),+ keyword "-f16.inf" $> Float16Value (-1 / 0), keyword "f32.nan" $> Float32Value (0 / 0), keyword "f32.inf" $> Float32Value (1 / 0), keyword "-f32.inf" $> Float32Value (-1 / 0),
src/Futhark/IR/Prop.hs view
@@ -33,7 +33,7 @@ defAux, stmCerts, certify,- expExtTypesFromPattern,+ expExtTypesFromPat, attrsForAssert, lamIsBinOp, ASTConstraints,@@ -125,7 +125,7 @@ safeBasicOp Replicate {} = True safeBasicOp Copy {} = True safeBasicOp _ = False-safeExp (DoLoop _ _ _ body) = safeBody body+safeExp (DoLoop _ _ body) = safeBody body safeExp (Apply fname _ _ _) = isBuiltInFunction fname safeExp (If _ tbranch fbranch _) =@@ -158,12 +158,14 @@ (xps, yps) = splitAt n2 (lambdaParams lam) okComponent c = isJust $ find (okBinOp c) $ bodyStms body- okBinOp (xp, yp, Var r) (Let (Pattern [] [pe]) _ (BasicOp (BinOp op (Var x) (Var y)))) =- patElemName pe == r- && commutativeBinOp op- && ( (x == paramName xp && y == paramName yp)- || (y == paramName xp && x == paramName yp)- )+ okBinOp+ (xp, yp, SubExpRes _ (Var r))+ (Let (Pat [pe]) _ (BasicOp (BinOp op (Var x) (Var y)))) =+ patElemName pe == r+ && commutativeBinOp op+ && ( (x == paramName xp && y == paramName yp)+ || (y == paramName xp && x == paramName yp)+ ) okBinOp _ _ = False in n2 * 2 == length (lambdaParams lam) && n2 == length (bodyResult body)@@ -178,16 +180,16 @@ entryPointSize (TypeUnsigned _) = 1 entryPointSize (TypeDirect _) = 1 --- | A 'StmAux' with empty 'Certificates'.+-- | A 'StmAux' with empty 'Certs'. defAux :: dec -> StmAux dec defAux = StmAux mempty mempty -- | The certificates associated with a statement.-stmCerts :: Stm rep -> Certificates+stmCerts :: Stm rep -> Certs stmCerts = stmAuxCerts . stmAux -- | Add certificates to a statement.-certify :: Certificates -> Stm rep -> Stm rep+certify :: Certs -> Stm rep -> Stm rep certify cs1 (Let pat (StmAux cs2 attrs dec) e) = Let pat (StmAux (cs2 <> cs1) attrs dec) e @@ -228,17 +230,17 @@ where -- | Given a pattern, construct the type of a body that would match -- it. An implementation for many representations would be- -- 'expExtTypesFromPattern'.- expTypesFromPattern ::+ -- 'expExtTypesFromPat'.+ expTypesFromPat :: (HasScope rep m, Monad m) =>- Pattern rep ->+ Pat rep -> m [BranchType rep] -- | Construct the type of an expression that would match the pattern.-expExtTypesFromPattern :: Typed dec => PatternT dec -> [ExtType]-expExtTypesFromPattern pat =- existentialiseExtTypes (patternContextNames pat) $- staticShapes $ map patElemType $ patternValueElements pat+expExtTypesFromPat :: Typed dec => PatT dec -> [ExtType]+expExtTypesFromPat pat =+ existentialiseExtTypes (patNames pat) $+ staticShapes $ map patElemType $ patElems pat -- | Keep only those attributes that are relevant for 'Assert' -- expressions.@@ -253,11 +255,12 @@ lamIsBinOp lam = mapM splitStm $ bodyResult $ lambdaBody lam where n = length $ lambdaReturnType lam- splitStm (Var res) = do- Let (Pattern [] [pe]) _ (BasicOp (BinOp op (Var x) (Var y))) <-- find (([res] ==) . patternNames . stmPattern) $+ splitStm (SubExpRes cs (Var res)) = do+ guard $ cs == mempty+ Let (Pat [pe]) _ (BasicOp (BinOp op (Var x) (Var y))) <-+ find (([res] ==) . patNames . stmPat) $ stmsToList $ bodyStms $ lambdaBody lam- i <- Var res `elemIndex` bodyResult (lambdaBody lam)+ i <- Var res `elemIndex` map resSubExp (bodyResult (lambdaBody lam)) xp <- maybeNth i $ lambdaParams lam yp <- maybeNth (n + i) $ lambdaParams lam guard $ paramName xp == x
src/Futhark/IR/Prop/Aliases.hs view
@@ -14,7 +14,7 @@ module Futhark.IR.Prop.Aliases ( subExpAliases, expAliases,- patternAliases,+ patAliases, lookupAliases, Aliased (..), AliasesOf (..),@@ -58,7 +58,7 @@ basicOpAliases :: BasicOp -> [Names] basicOpAliases (SubExp se) = [subExpAliases se]-basicOpAliases (Opaque se) = [subExpAliases se]+basicOpAliases (Opaque _ se) = [subExpAliases se] basicOpAliases (ArrayLit _ _) = [mempty] basicOpAliases BinOp {} = [mempty] basicOpAliases ConvOp {} = [mempty]@@ -66,6 +66,8 @@ basicOpAliases UnOp {} = [mempty] basicOpAliases (Index ident _) = [vnameAliases ident] basicOpAliases Update {} = [mempty]+basicOpAliases (FlatIndex ident _) = [vnameAliases ident]+basicOpAliases FlatUpdate {} = [mempty] basicOpAliases Iota {} = [mempty] basicOpAliases Replicate {} = [mempty] basicOpAliases Scratch {} = [mempty]@@ -99,12 +101,11 @@ (bodyAliases tb, consumedInBody tb) (bodyAliases fb, consumedInBody fb) expAliases (BasicOp op) = basicOpAliases op-expAliases (DoLoop ctxmerge valmerge _ loopbody) =- map (`namesSubtract` merge_names) val_aliases+expAliases (DoLoop merge _ loopbody) =+ map (`namesSubtract` merge_names) aliases where- (_ctx_aliases, val_aliases) =- splitAt (length ctxmerge) $ bodyAliases loopbody- merge_names = namesFromList $ map (paramName . fst) $ ctxmerge ++ valmerge+ aliases = bodyAliases loopbody+ merge_names = namesFromList $ map (paramName . fst) merge expAliases (Apply _ args t _) = funcallAliases args $ map declExtTypeOf t expAliases (WithAcc inputs lam) =@@ -126,7 +127,7 @@ returnType' Acc {} = error "returnAliases Acc" returnType' Mem {} =- error "returnAliases Mem"+ mconcat $ map (uncurry maskAliases) args maskAliases :: Names -> Diet -> Names maskAliases _ Consume = mempty@@ -146,7 +147,7 @@ consumeArg _ = mempty consumedInExp (If _ tb fb _) = consumedInBody tb <> consumedInBody fb-consumedInExp (DoLoop _ merge form body) =+consumedInExp (DoLoop merge form body) = mconcat ( map (subExpAliases . snd) $ filter (unique . paramDeclType . fst) merge@@ -166,7 +167,8 @@ ) where inputConsumed (_, arrs, _) = namesFromList arrs-consumedInExp (BasicOp (Update src _ _)) = oneName src+consumedInExp (BasicOp (Update _ src _ _)) = oneName src+consumedInExp (BasicOp (FlatUpdate src _ _)) = oneName src consumedInExp (BasicOp (UpdateAcc acc _ _)) = oneName acc consumedInExp (BasicOp _) = mempty consumedInExp (Op op) = consumedInOp op@@ -176,8 +178,8 @@ consumedByLambda = consumedInBody . lambdaBody -- | The aliases of each pattern element (including the context).-patternAliases :: AliasesOf dec => PatternT dec -> [Names]-patternAliases = map (aliasesOf . patElemDec) . patternElements+patAliases :: AliasesOf dec => PatT dec -> [Names]+patAliases = map (aliasesOf . patElemDec) . patElems -- | Something that contains alias information. class AliasesOf a where
src/Futhark/IR/Prop/Names.hs view
@@ -265,18 +265,12 @@ ) => FreeIn (Exp rep) where- freeIn' (DoLoop ctxmerge valmerge form loopbody) =- let (ctxparams, ctxinits) = unzip ctxmerge- (valparams, valinits) = unzip valmerge+ freeIn' (DoLoop merge form loopbody) =+ let (params, args) = unzip merge bound_here =- namesFromList $- M.keys $- scopeOf form- <> scopeOfFParams (ctxparams ++ valparams)+ namesFromList $ M.keys $ scopeOf form <> scopeOfFParams params in fvBind bound_here $- freeIn' (ctxinits ++ valinits) <> freeIn' form- <> freeIn' (ctxparams ++ valparams)- <> freeIn' loopbody+ freeIn' args <> freeIn' form <> freeIn' params <> freeIn' loopbody freeIn' (WithAcc inputs lam) = freeIn' inputs <> freeIn' lam freeIn' e = execState (walkExpM freeWalker e) mempty@@ -356,14 +350,26 @@ instance FreeIn d => FreeIn (DimIndex d) where freeIn' = Data.Foldable.foldMap freeIn' -instance FreeIn dec => FreeIn (PatternT dec) where- freeIn' (Pattern context values) =- fvBind bound_here $ freeIn' $ context ++ values+instance FreeIn d => FreeIn (Slice d) where+ freeIn' = Data.Foldable.foldMap freeIn'++instance FreeIn d => FreeIn (FlatDimIndex d) where+ freeIn' = Data.Foldable.foldMap freeIn'++instance FreeIn d => FreeIn (FlatSlice d) where+ freeIn' = Data.Foldable.foldMap freeIn'++instance FreeIn SubExpRes where+ freeIn' (SubExpRes cs se) = freeIn' cs <> freeIn' se++instance FreeIn dec => FreeIn (PatT dec) where+ freeIn' (Pat xs) =+ fvBind bound_here $ freeIn' xs where- bound_here = namesFromList $ map patElemName $ context ++ values+ bound_here = namesFromList $ map patElemName xs -instance FreeIn Certificates where- freeIn' (Certificates cs) = freeIn' cs+instance FreeIn Certs where+ freeIn' (Certs cs) = freeIn' cs instance FreeIn Attrs where freeIn' (Attrs _) = mempty@@ -403,7 +409,7 @@ -- | The names bound by a binding. boundByStm :: Stm rep -> Names-boundByStm = namesFromList . patternNames . stmPattern+boundByStm = namesFromList . patNames . stmPat -- | The names bound by the bindings. boundByStms :: Stms rep -> Names
src/Futhark/IR/Prop/Patterns.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} --- | Inspecing and modifying t'Pattern's, function parameters and+-- | Inspecing and modifying t'Pat's, function parameters and -- pattern elements. module Futhark.IR.Prop.Patterns ( -- * Function parameters@@ -9,23 +9,17 @@ paramType, paramDeclType, - -- * Pattern elements+ -- * Pat elements patElemIdent, patElemType, setPatElemDec,- patternElements,- patternIdents,- patternContextIdents,- patternValueIdents,- patternNames,- patternValueNames,- patternContextNames,- patternTypes,- patternValueTypes,- patternSize,+ patIdents,+ patNames,+ patTypes,+ patSize, - -- * Pattern construction- basicPattern,+ -- * Pat construction+ basicPat, ) where @@ -56,49 +50,25 @@ setPatElemDec :: PatElemT oldattr -> newattr -> PatElemT newattr setPatElemDec pe x = fmap (const x) pe --- | All pattern elements in the pattern - context first, then values.-patternElements :: PatternT dec -> [PatElemT dec]-patternElements pat = patternContextElements pat ++ patternValueElements pat---- | Return a list of the 'Ident's bound by the t'Pattern'.-patternIdents :: Typed dec => PatternT dec -> [Ident]-patternIdents pat = patternContextIdents pat ++ patternValueIdents pat---- | Return a list of the context 'Ident's bound by the t'Pattern'.-patternContextIdents :: Typed dec => PatternT dec -> [Ident]-patternContextIdents = map patElemIdent . patternContextElements---- | Return a list of the value 'Ident's bound by the t'Pattern'.-patternValueIdents :: Typed dec => PatternT dec -> [Ident]-patternValueIdents = map patElemIdent . patternValueElements---- | Return a list of the 'Name's bound by the t'Pattern'.-patternNames :: PatternT dec -> [VName]-patternNames = map patElemName . patternElements---- | Return a list of the 'Name's bound by the context part of the t'Pattern'.-patternContextNames :: PatternT dec -> [VName]-patternContextNames = map patElemName . patternContextElements+-- | Return a list of the 'Ident's bound by the t'Pat'.+patIdents :: Typed dec => PatT dec -> [Ident]+patIdents = map patElemIdent . patElems --- | Return a list of the 'Name's bound by the value part of the t'Pattern'.-patternValueNames :: PatternT dec -> [VName]-patternValueNames = map patElemName . patternValueElements+-- | Return a list of the 'Name's bound by the t'Pat'.+patNames :: PatT dec -> [VName]+patNames = map patElemName . patElems -- | Return a list of the typess bound by the pattern.-patternTypes :: Typed dec => PatternT dec -> [Type]-patternTypes = map identType . patternIdents---- | Return a list of the typess bound by the value part of the pattern.-patternValueTypes :: Typed dec => PatternT dec -> [Type]-patternValueTypes = map identType . patternValueIdents+patTypes :: Typed dec => PatT dec -> [Type]+patTypes = map identType . patIdents -- | Return the number of names bound by the pattern.-patternSize :: PatternT dec -> Int-patternSize (Pattern context values) = length context + length values+patSize :: PatT dec -> Int+patSize (Pat xs) = length xs -- | Create a pattern using 'Type' as the attribute.-basicPattern :: [Ident] -> [Ident] -> PatternT Type-basicPattern context values =- Pattern (map patElem context) (map patElem values)+basicPat :: [Ident] -> PatT Type+basicPat values =+ Pat $ map patElem values where patElem (Ident name t) = PatElem name t
src/Futhark/IR/Prop/Scope.hs view
@@ -25,7 +25,7 @@ inScopeOf, scopeOfLParams, scopeOfFParams,- scopeOfPattern,+ scopeOfPat, scopeOfPatElem, SameScope, castScope,@@ -42,7 +42,6 @@ import Control.Monad.Reader import qualified Data.Map.Strict as M import Futhark.IR.Pretty ()-import Futhark.IR.Prop.Patterns import Futhark.IR.Prop.Types import Futhark.IR.Rep import Futhark.IR.Syntax@@ -165,7 +164,7 @@ scopeOf = foldMap scopeOf instance Scoped rep (Stm rep) where- scopeOf = scopeOfPattern . stmPattern+ scopeOf = scopeOfPat . stmPat instance Scoped rep (FunDef rep) where scopeOf = scopeOfFParams . funDefParams@@ -179,9 +178,9 @@ M.insert i (IndexName it) $ scopeOfLParams (map fst xs) -- | The scope of a pattern.-scopeOfPattern :: LetDec rep ~ dec => PatternT dec -> Scope rep-scopeOfPattern =- mconcat . map scopeOfPatElem . patternElements+scopeOfPat :: LetDec rep ~ dec => PatT dec -> Scope rep+scopeOfPat =+ mconcat . map scopeOfPatElem . patElems -- | The scope of a pattern element. scopeOfPatElem :: LetDec rep ~ dec => PatElemT dec -> Scope rep
src/Futhark/IR/Prop/TypeOf.hs view
@@ -20,7 +20,8 @@ ( expExtType, expExtTypeSize, subExpType,- primOpType,+ subExpResType,+ basicOpType, mapType, -- * Return type@@ -34,9 +35,7 @@ ) where -import Data.Maybe import Futhark.IR.Prop.Constants-import Futhark.IR.Prop.Patterns import Futhark.IR.Prop.Reshape import Futhark.IR.Prop.Scope import Futhark.IR.Prop.Types@@ -48,6 +47,11 @@ subExpType (Constant val) = pure $ Prim $ primValueType val subExpType (Var name) = lookupType name +-- | Type type of a 'SubExpRes' - not that this might refer to names+-- bound in the body containing the result.+subExpResType :: HasScope t m => SubExpRes -> m Type+subExpResType = subExpType . resSubExp+ -- | @mapType f arrts@ wraps each element in the return type of @f@ in -- an array with size equal to the outermost dimension of the first -- element of @arrts@.@@ -58,65 +62,70 @@ ] -- | The type of a primitive operation.-primOpType :: HasScope rep m => BasicOp -> m [Type]-primOpType (SubExp se) =+basicOpType :: HasScope rep m => BasicOp -> m [Type]+basicOpType (SubExp se) = pure <$> subExpType se-primOpType (Opaque se) =+basicOpType (Opaque _ se) = pure <$> subExpType se-primOpType (ArrayLit es rt) =+basicOpType (ArrayLit es rt) = pure [arrayOf rt (Shape [n]) NoUniqueness] where n = intConst Int64 $ toInteger $ length es-primOpType (BinOp bop _ _) =+basicOpType (BinOp bop _ _) = pure [Prim $ binOpType bop]-primOpType (UnOp _ x) =+basicOpType (UnOp _ x) = pure <$> subExpType x-primOpType CmpOp {} =+basicOpType CmpOp {} = pure [Prim Bool]-primOpType (ConvOp conv _) =+basicOpType (ConvOp conv _) = pure [Prim $ snd $ convOpType conv]-primOpType (Index ident slice) =+basicOpType (Index ident slice) = result <$> lookupType ident where result t = [Prim (elemType t) `arrayOfShape` shape]- shape = Shape $ mapMaybe dimSize slice- dimSize (DimSlice _ d _) = Just d- dimSize DimFix {} = Nothing-primOpType (Update src _ _) =+ shape = Shape $ sliceDims slice+basicOpType (Update _ src _ _) = pure <$> lookupType src-primOpType (Iota n _ _ et) =+basicOpType (FlatIndex ident slice) =+ result <$> lookupType ident+ where+ result t = [Prim (elemType t) `arrayOfShape` shape]+ shape = Shape $ flatSliceDims slice+basicOpType (FlatUpdate src _ _) =+ pure <$> lookupType src+basicOpType (Iota n _ _ et) = pure [arrayOf (Prim (IntType et)) (Shape [n]) NoUniqueness]-primOpType (Replicate (Shape []) e) =+basicOpType (Replicate (Shape []) e) = pure <$> subExpType e-primOpType (Replicate shape e) =+basicOpType (Replicate shape e) = pure . flip arrayOfShape shape <$> subExpType e-primOpType (Scratch t shape) =+basicOpType (Scratch t shape) = pure [arrayOf (Prim t) (Shape shape) NoUniqueness]-primOpType (Reshape [] e) =+basicOpType (Reshape [] e) = result <$> lookupType e where result t = [Prim $ elemType t]-primOpType (Reshape shape e) =+basicOpType (Reshape shape e) = result <$> lookupType e where result t = [t `setArrayShape` newShape shape]-primOpType (Rearrange perm e) =+basicOpType (Rearrange perm e) = result <$> lookupType e where result t = [rearrangeType perm t]-primOpType (Rotate _ e) =+basicOpType (Rotate _ e) = pure <$> lookupType e-primOpType (Concat i x _ ressize) =+basicOpType (Concat i x _ ressize) = result <$> lookupType x where result xt = [setDimSize i xt ressize]-primOpType (Copy v) =+basicOpType (Copy v) = pure <$> lookupType v-primOpType (Manifest _ v) =+basicOpType (Manifest _ v) = pure <$> lookupType v-primOpType Assert {} =+basicOpType Assert {} = pure [Prim Unit]-primOpType (UpdateAcc v _ _) =+basicOpType (UpdateAcc v _ _) = pure <$> lookupType v -- | The type of an expression.@@ -126,9 +135,9 @@ m [ExtType] expExtType (Apply _ _ rt _) = pure $ map (fromDecl . declExtTypeOf) rt expExtType (If _ _ _ rt) = pure $ map extTypeOf $ ifReturns rt-expExtType (DoLoop ctxmerge valmerge _ _) =- pure $ loopExtType (map (paramIdent . fst) ctxmerge) (map (paramIdent . fst) valmerge)-expExtType (BasicOp op) = staticShapes <$> primOpType op+expExtType (DoLoop merge _ _) =+ pure $ loopExtType $ map fst merge+expExtType (BasicOp op) = staticShapes <$> basicOpType op expExtType (WithAcc inputs lam) = fmap staticShapes $ (<>)@@ -160,13 +169,12 @@ lookupType = const $ pure $ Prim $ IntType Int64 askScope = pure mempty --- | Given the context and value merge parameters of a Futhark @loop@,--- produce the return type.-loopExtType :: [Ident] -> [Ident] -> [ExtType]-loopExtType ctx val =- existentialiseExtTypes inaccessible $ staticShapes $ map identType val+-- | Given the parameters of a loop, produce the return type.+loopExtType :: Typed dec => [Param dec] -> [ExtType]+loopExtType params =+ existentialiseExtTypes inaccessible $ staticShapes $ map typeOf params where- inaccessible = map identName ctx+ inaccessible = map paramName params -- | Any operation must define an instance of this class, which -- describes the type of the operation (at the value level).
src/Futhark/IR/Prop/Types.hs view
@@ -434,12 +434,9 @@ return $ Just v extract' (Free _) _ = return Nothing --- | The set of identifiers used for the shape context in the given--- 'ExtType's.+-- | The 'Ext' integers used for existential sizes in the given types. shapeContext :: [TypeBase ExtShape u] -> S.Set Int-shapeContext =- S.fromList- . concatMap (mapMaybe ext . shapeDims . arrayShape)+shapeContext = S.fromList . concatMap (mapMaybe ext . shapeDims . arrayShape) where ext (Ext x) = Just x ext (Free _) = Nothing@@ -475,11 +472,7 @@ put (n + 1, m) return $ Ext n unifyExtDims (Ext x) (Ext y)- | x == y =- Ext- <$> ( maybe (new x) return- =<< gets (M.lookup x . snd)- )+ | x == y = Ext <$> (maybe (new x) return =<< gets (M.lookup x . snd)) unifyExtDims (Ext x) _ = Ext <$> new x unifyExtDims _ (Ext x) = Ext <$> new x new x = do
src/Futhark/IR/RetType.hs view
@@ -43,8 +43,8 @@ [(SubExp, Type)] -> Maybe [rt] --- | Given shape parameter names and value parameter types, produce the--- types of arguments accepted.+-- | Given shape parameter names and types, produce the types of+-- arguments accepted. expectedTypes :: Typed t => [VName] -> [t] -> [SubExp] -> [Type] expectedTypes shapes value_ts args = map (correctDims . typeOf) value_ts where
src/Futhark/IR/SOACS.hs view
@@ -8,7 +8,7 @@ -- * Syntax types Body, Stm,- Pattern,+ Pat, Exp, Lambda, FParam,@@ -24,12 +24,12 @@ module Futhark.IR.SOACS.SOAC, AST.LambdaT (Lambda), AST.BodyT (Body),- AST.PatternT (Pattern),+ AST.PatT (Pat), AST.PatElemT (PatElem), ) where -import Futhark.Binder+import Futhark.Builder import Futhark.Construct import Futhark.IR.Pretty import Futhark.IR.Prop@@ -40,8 +40,8 @@ FParam, LParam, Lambda,+ Pat, PatElem,- Pattern, RetType, Stm, )@@ -60,7 +60,7 @@ type Op SOACS = SOAC SOACS instance ASTRep SOACS where- expTypesFromPattern = return . expExtTypesFromPattern+ expTypesFromPat = return . expExtTypesFromPat type Exp = AST.Exp SOACS @@ -68,7 +68,7 @@ type Stm = AST.Stm SOACS -type Pattern = AST.Pattern SOACS+type Pat = AST.Pat SOACS type Lambda = AST.Lambda SOACS @@ -85,12 +85,12 @@ instance TypeCheck.Checkable SOACS -instance Bindable SOACS where+instance Buildable SOACS where mkBody = AST.Body ()- mkExpPat ctx val _ = basicPattern ctx val+ mkExpPat merge _ = basicPat merge mkExpDec _ _ = () mkLetNames = simpleMkLetNames -instance BinderOps SOACS+instance BuilderOps SOACS instance PrettyRep SOACS
src/Futhark/IR/SOACS/SOAC.hs view
@@ -161,7 +161,7 @@ (Lambda rep) deriving (Eq, Ord, Show) -singleBinOp :: Bindable rep => [Lambda rep] -> Lambda rep+singleBinOp :: Buildable rep => [Lambda rep] -> Lambda rep singleBinOp lams = Lambda { lambdaParams = concatMap xParams lams ++ concatMap yParams lams,@@ -187,7 +187,7 @@ scanResults = sum . map (length . scanNeutral) -- | Combine multiple scan operators to a single operator.-singleScan :: Bindable rep => [Scan rep] -> Scan rep+singleScan :: Buildable rep => [Scan rep] -> Scan rep singleScan scans = let scan_nes = concatMap scanNeutral scans scan_lam = singleBinOp $ map scanLambda scans@@ -206,7 +206,7 @@ redResults = sum . map (length . redNeutral) -- | Combine multiple reduction operators to a single operator.-singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep+singleReduce :: Buildable rep => [Reduce rep] -> Reduce rep singleReduce reds = let red_nes = concatMap redNeutral reds red_lam = singleBinOp $ map redLambda reds@@ -227,7 +227,7 @@ -- | Construct a lambda that takes parameters of the given types and -- simply returns them unchanged. mkIdentityLambda ::- (Bindable rep, MonadFreshNames m) =>+ (Buildable rep, MonadFreshNames m) => [Type] -> m (Lambda rep) mkIdentityLambda ts = do@@ -235,18 +235,18 @@ return Lambda { lambdaParams = params,- lambdaBody = mkBody mempty $ map (Var . paramName) params,+ lambdaBody = mkBody mempty $ varsRes $ map paramName params, lambdaReturnType = ts } -- | Is the given lambda an identity lambda? isIdentityLambda :: Lambda rep -> Bool isIdentityLambda lam =- bodyResult (lambdaBody lam)+ map resSubExp (bodyResult (lambdaBody lam)) == map (Var . paramName) (lambdaParams lam) -- | A lambda with no parameters that returns no values.-nilFn :: Bindable rep => Lambda rep+nilFn :: Buildable rep => Lambda rep nilFn = Lambda mempty (mkBody mempty mempty) mempty -- | Construct a Screma with possibly multiple scans, and@@ -262,7 +262,7 @@ -- | Construct a Screma with possibly multiple scans, and identity map -- function. scanSOAC ::- (Bindable rep, MonadFreshNames m) =>+ (Buildable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep) scanSOAC scans = scanomapSOAC scans <$> mkIdentityLambda ts@@ -272,7 +272,7 @@ -- | Construct a Screma with possibly multiple reductions, and -- identity map function. reduceSOAC ::- (Bindable rep, MonadFreshNames m) =>+ (Buildable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep) reduceSOAC reds = redomapSOAC reds <$> mkIdentityLambda ts@@ -327,7 +327,7 @@ -- This function is used for extracting and grouping the results of a -- scatter. In the SOAC representation, the lambda inside a 'Scatter' returns -- all indices and values as one big list. This function groups each value with--- its corresponding indices (as determined by the 'Shape' of the output array).+-- its corresponding indices (as determined by the t'Shape' of the output array). -- -- The elements of the resulting list correspond to the shape and name of the -- output parameters, in addition to a list of values written to that output@@ -601,7 +601,7 @@ let arr_indexes = M.fromList $ catMaybes $ zipWith arrIndex arr_params arrs arr_indexes' = foldl expandPrimExpTable arr_indexes $ bodyStms $ lambdaBody lam case se of- Var v -> uncurry (flip ST.Indexed) <$> M.lookup v arr_indexes'+ SubExpRes _ (Var v) -> uncurry (flip ST.Indexed) <$> M.lookup v arr_indexes' _ -> Nothing where lambdaAndSubExp (Screma _ arrs (ScremaForm scans reds map_lam)) =@@ -618,10 +618,10 @@ return (paramName p, (pe, cs)) expandPrimExpTable table stm- | [v] <- patternNames $ stmPattern stm,+ | [v] <- patNames $ stmPat stm, Just (pe, cs) <- runWriterT $ primExpFromExp (asPrimExp table) $ stmExp stm,- all (`ST.elem` vtable) (unCertificates $ stmCerts stm) =+ all (`ST.elem` vtable) (unCerts $ stmCerts stm) = M.insert v (pe, stmCerts stm <> cs) table | otherwise = table
src/Futhark/IR/SOACS/Simplify.hs view
@@ -152,15 +152,15 @@ ) <*> pure (mconcat scans_hoisted <> mconcat reds_hoisted <> map_lam_hoisted) -instance BinderOps (Wise SOACS)+instance BuilderOps (Wise SOACS) fixLambdaParams ::- (MonadBinder m, Bindable (Rep m), BinderOps (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m), BuilderOps (Rep m)) => AST.Lambda (Rep m) -> [Maybe SubExp] -> m (AST.Lambda (Rep m)) fixLambdaParams lam fixes = do- body <- runBodyBinder $+ body <- runBodyBuilder $ localScope (scopeOfLParams $ lambdaParams lam) $ do zipWithM_ maybeFix (lambdaParams lam) fixes' return $ lambdaBody lam@@ -205,7 +205,7 @@ topDownRules :: [TopDownRule (Wise SOACS)] topDownRules =- [ RuleOp hoistCertificates,+ [ RuleOp hoistCerts, RuleOp removeReplicateMapping, RuleOp removeReplicateWrite, RuleOp removeUnusedSOACInput,@@ -230,8 +230,8 @@ -- Any certificates attached to a trivial Stm in the body might as -- well be applied to the SOAC itself.-hoistCertificates :: TopDownRuleOp (Wise SOACS)-hoistCertificates vtable pat aux soac+hoistCerts :: TopDownRuleOp (Wise SOACS)+hoistCerts vtable pat aux soac | (soac', hoisted) <- runState (mapSOACM mapper soac) mempty, hoisted /= mempty = Simplify $ auxing aux $ certifying hoisted $ letBind pat $ Op soac'@@ -247,17 +247,17 @@ onStm (Let se_pat se_aux (BasicOp (SubExp se))) = do let (invariant, variant) = partition (`ST.elem` vtable) $- unCertificates $ stmAuxCerts se_aux- se_aux' = se_aux {stmAuxCerts = Certificates variant}- modify (Certificates invariant <>)+ unCerts $ stmAuxCerts se_aux+ se_aux' = se_aux {stmAuxCerts = Certs variant}+ modify (Certs invariant <>) return $ Let se_pat se_aux' $ BasicOp $ SubExp se onStm stm = return stm-hoistCertificates _ _ _ _ =+hoistCerts _ _ _ _ = Skip liftIdentityMapping :: forall rep.- (Bindable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) =>+ (Buildable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep) liftIdentityMapping _ pat aux op | Just (Screma w arrs form :: SOAC (Wise rep)) <- asSOAC op,@@ -270,15 +270,19 @@ freeOrConst (Var v) = v `nameIn` free freeOrConst Constant {} = True - checkInvariance (outId, Var v, _) (invariant, mapresult, rettype')+ checkInvariance (outId, SubExpRes _ (Var v), _) (invariant, mapresult, rettype') | Just inp <- M.lookup v inputMap =- ( (Pattern [] [outId], BasicOp (Copy inp)) : invariant,+ ( (Pat [outId], e inp) : invariant, mapresult, rettype' )- checkInvariance (outId, e, t) (invariant, mapresult, rettype')+ where+ e inp = case patElemType outId of+ Acc {} -> BasicOp $ SubExp $ Var inp+ _ -> BasicOp (Copy inp)+ checkInvariance (outId, SubExpRes _ e, t) (invariant, mapresult, rettype') | freeOrConst e =- ( (Pattern [] [outId], BasicOp $ Replicate (Shape [w]) e) : invariant,+ ( (Pat [outId], BasicOp $ Replicate (Shape [w]) e) : invariant, mapresult, rettype' )@@ -289,13 +293,13 @@ ) case foldr checkInvariance ([], [], []) $- zip3 (patternElements pat) ses rettype of+ zip3 (patElems pat) ses rettype of ([], _, _) -> Skip (invariant, mapresult, rettype') -> Simplify $ do let (pat', ses') = unzip mapresult fun' = fun- { lambdaBody = (lambdaBody fun) {bodyResult = ses'},+ { lambdaBody = (lambdaBody fun) {bodyResult = subExpsRes ses'}, lambdaReturnType = rettype' } mapM_ (uncurry letBind) invariant@@ -304,12 +308,12 @@ liftIdentityMapping _ _ _ _ = Skip liftIdentityStreaming :: BottomUpRuleOp (Wise SOACS)-liftIdentityStreaming _ (Pattern [] pes) aux (Stream w arrs form nes lam)+liftIdentityStreaming _ (Pat pes) aux (Stream w arrs form nes lam) | (variant_map, invariant_map) <- partitionEithers $ map isInvariantRes $ zip3 map_ts map_pes map_res, not $ null invariant_map = Simplify $ do forM_ invariant_map $ \(pe, arr) ->- letBind (Pattern [] [pe]) $ BasicOp $ Copy arr+ letBind (Pat [pe]) $ BasicOp $ Copy arr let (variant_map_ts, variant_map_pes, variant_map_res) = unzip3 variant_map lam' =@@ -319,7 +323,7 @@ } auxing aux $- letBind (Pattern [] $ fold_pes ++ variant_map_pes) $+ letBind (Pat $ fold_pes ++ variant_map_pes) $ Op $ Stream w arrs form nes lam' where num_folds = length nes@@ -329,7 +333,7 @@ (fold_res, map_res) = splitAt num_folds lam_res params_to_arrs = zip (map paramName $ drop (1 + num_folds) $ lambdaParams lam) arrs - isInvariantRes (_, pe, Var v)+ isInvariantRes (_, pe, SubExpRes _ (Var v)) | Just arr <- lookup v params_to_arrs = Right (pe, arr) isInvariantRes x =@@ -339,7 +343,7 @@ -- | Remove all arguments to the map that are simply replicates. -- These can be turned into free variables instead. removeReplicateMapping ::- (Bindable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) =>+ (Buildable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep) removeReplicateMapping vtable pat aux op | Just (Screma w arrs form) <- asSOAC op,@@ -363,7 +367,7 @@ AST.Lambda rep -> [VName] -> Maybe- ( [([VName], Certificates, AST.Exp rep)],+ ( [([VName], Certs, AST.Exp rep)], AST.Lambda rep, [VName] )@@ -416,26 +420,24 @@ (pat', ses', ts') = unzip3 $ filter isUsed $- zip3 (patternElements pat) ses $ lambdaReturnType fun+ zip3 (patElems pat) ses $ lambdaReturnType fun fun' = fun { lambdaBody = (lambdaBody fun) {bodyResult = ses'}, lambdaReturnType = ts' }- in if pat /= Pattern [] pat'+ in if pat /= Pat pat' then- Simplify $- auxing aux $- letBind (Pattern [] pat') $ Op $ Screma w arrs $ mapSOAC fun'+ Simplify . auxing aux $+ letBind (Pat pat') $ Op $ Screma w arrs $ mapSOAC fun' else Skip removeDeadMapping _ _ _ _ = Skip removeDuplicateMapOutput :: TopDownRuleOp (Wise SOACS)-removeDuplicateMapOutput _ pat aux (Screma w arrs form)+removeDuplicateMapOutput _ (Pat pes) aux (Screma w arrs form) | Just fun <- isMapSOAC form = let ses = bodyResult $ lambdaBody fun ts = lambdaReturnType fun- pes = patternValueElements pat ses_ts_pes = zip3 ses ts pes (ses_ts_pes', copies) = foldl checkForDuplicates (mempty, mempty) ses_ts_pes@@ -443,19 +445,18 @@ then Skip else Simplify $ do let (ses', ts', pes') = unzip3 ses_ts_pes'- pat' = Pattern [] pes' fun' = fun { lambdaBody = (lambdaBody fun) {bodyResult = ses'}, lambdaReturnType = ts' }- auxing aux $ letBind pat' $ Op $ Screma w arrs $ mapSOAC fun'+ auxing aux $ letBind (Pat pes') $ Op $ Screma w arrs $ mapSOAC fun' forM_ copies $ \(from, to) ->- letBind (Pattern [] [to]) $ BasicOp $ Copy $ patElemName from+ letBind (Pat [to]) $ BasicOp $ Copy $ patElemName from where checkForDuplicates (ses_ts_pes', copies) (se, t, pe)- | Just (_, _, pe') <- find (\(x, _, _) -> x == se) ses_ts_pes' =- -- This subexp has been returned before, producing the+ | Just (_, _, pe') <- find (\(x, _, _) -> resSubExp x == resSubExp se) ses_ts_pes' =+ -- This result has been returned before, producing the -- array pe'. (ses_ts_pes', (pe', pe) : copies) | otherwise = (ses_ts_pes' ++ [(se, t, pe)], copies)@@ -514,23 +515,23 @@ mapOpToOp _ _ _ _ = Skip isMapWithOp ::- PatternT dec ->+ PatT dec -> SOAC (Wise SOACS) -> Maybe ( PatElemT dec,- Certificates,+ Certs, SubExp, AST.Exp (Wise SOACS), [Param Type], [VName] ) isMapWithOp pat e- | Pattern [] [map_pe] <- pat,+ | Pat [map_pe] <- pat, Screma w arrs form <- e, Just map_lam <- isMapSOAC form,- [Let (Pattern [] [pe]) aux2 e'] <-+ [Let (Pat [pe]) aux2 e'] <- stmsToList $ bodyStms $ lambdaBody map_lam,- [Var r] <- bodyResult $ lambdaBody map_lam,+ [SubExpRes _ (Var r)] <- bodyResult $ lambdaBody map_lam, r == patElemName pe = Just (map_pe, stmAuxCerts aux2, w, e', lambdaParams map_lam, arrs) | otherwise = Nothing@@ -542,8 +543,8 @@ removeDeadReduction :: BottomUpRuleOp (Wise SOACS) removeDeadReduction (_, used) pat aux (Screma w arrs form) | Just ([Reduce comm redlam nes], maplam) <- isRedomapSOAC form,- not $ all (`UT.used` used) $ patternNames pat, -- Quick/cheap check- let (red_pes, map_pes) = splitAt (length nes) $ patternElements pat,+ not $ all (`UT.used` used) $ patNames pat, -- Quick/cheap check+ let (red_pes, map_pes) = splitAt (length nes) $ patElems pat, let redlam_deps = dataDependencies $ lambdaBody redlam, let redlam_res = bodyResult $ lambdaBody redlam, let redlam_params = lambdaParams redlam,@@ -554,7 +555,7 @@ let necessary = findNecessaryForReturned (`elem` used_after)- (zip redlam_params $ redlam_res <> redlam_res)+ (zip redlam_params $ map resSubExp $ redlam_res <> redlam_res) redlam_deps, let alive_mask = map ((`nameIn` necessary) . paramName) redlam_params, not $ all (== True) alive_mask = Simplify $ do@@ -569,7 +570,7 @@ redlam' <- removeLambdaResults (take (length nes) alive_mask) <$> fixLambdaParams redlam (dead_fix ++ dead_fix) auxing aux $- letBind (Pattern [] $ used_red_pes ++ map_pes) $+ letBind (Pat $ used_red_pes ++ map_pes) $ Op $ Screma w arrs $ redomapSOAC [Reduce comm redlam' used_nes] maplam' removeDeadReduction _ _ _ _ = Skip @@ -582,17 +583,17 @@ (pat', i_ses', v_ses', i_ts', v_ts', dests') = unzip6 $ filter isUsed $- zip6 (patternElements pat) i_ses v_ses i_ts v_ts dests+ zip6 (patElems pat) i_ses v_ses i_ts v_ts dests fun' = fun { lambdaBody = (lambdaBody fun) {bodyResult = concat i_ses' ++ v_ses'}, lambdaReturnType = concat i_ts' ++ v_ts' }- in if pat /= Pattern [] pat'+ in if pat /= Pat pat' then Simplify $ auxing aux $- letBind (Pattern [] pat') $ Op $ Scatter w fun' arrs dests'+ letBind (Pat pat') $ Op $ Scatter w fun' arrs dests' else Skip removeDeadWrite _ _ _ _ = Skip @@ -650,7 +651,7 @@ | Just nes <- concatMap redNeutral . fst <$> isRedomapSOAC form, zeroIsh w = Simplify $- forM_ (zip (patternNames pat) nes) $ \(v, ne) ->+ forM_ (zip (patNames pat) nes) $ \(v, ne) -> letBindNames [v] $ BasicOp $ SubExp ne simplifyClosedFormReduce vtable pat _ (Screma _ arrs form) | Just [Reduce _ red_fun nes] <- isReduceSOAC form =@@ -659,7 +660,7 @@ -- For now we just remove singleton SOACs. simplifyKnownIterationSOAC ::- (Bindable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) =>+ (Buildable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep) simplifyKnownIterationSOAC _ pat _ op | Just (Screma (Constant k) arrs (ScremaForm scans reds map_lam)) <- asSOAC op,@@ -668,23 +669,23 @@ (Scan scan_lam scan_nes) = singleScan scans (scan_pes, red_pes, map_pes) = splitAt3 (length scan_nes) (length red_nes) $- patternElements pat+ patElems pat bindMapParam p a = do a_t <- lookupType a letBindNames [paramName p] $ BasicOp $ Index a $ fullSlice a_t [DimFix $ constant (0 :: Int64)]- bindArrayResult pe se =- letBindNames [patElemName pe] $+ bindArrayResult pe (SubExpRes cs se) =+ certifying cs . letBindNames [patElemName pe] $ BasicOp $ ArrayLit [se] $ rowType $ patElemType pe- bindResult pe se =- letBindNames [patElemName pe] $ BasicOp $ SubExp se+ bindResult pe (SubExpRes cs se) =+ certifying cs $ letBindNames [patElemName pe] $ BasicOp $ SubExp se zipWithM_ bindMapParam (lambdaParams map_lam) arrs (to_scan, to_red, map_res) <- splitAt3 (length scan_nes) (length red_nes) <$> bodyBind (lambdaBody map_lam)- scan_res <- eLambda scan_lam $ map eSubExp $ scan_nes ++ to_scan- red_res <- eLambda red_lam $ map eSubExp $ red_nes ++ to_red+ scan_res <- eLambda scan_lam $ map eSubExp $ scan_nes ++ map resSubExp to_scan+ red_res <- eLambda red_lam $ map eSubExp $ red_nes ++ map resSubExp to_red zipWithM_ bindArrayResult scan_pes scan_res zipWithM_ bindResult red_pes red_res@@ -706,17 +707,17 @@ res <- bodyBind $ lambdaBody fold_lam - forM_ (zip (patternNames pat) res) $ \(v, se) ->- letBindNames [v] $ BasicOp $ SubExp se+ forM_ (zip (patNames pat) res) $ \(v, SubExpRes cs se) ->+ certifying cs $ letBindNames [v] $ BasicOp $ SubExp se simplifyKnownIterationSOAC _ _ _ _ = Skip data ArrayOp- = ArrayIndexing Certificates VName (Slice SubExp)- | ArrayRearrange Certificates VName [Int]- | ArrayRotate Certificates VName [SubExp]- | ArrayCopy Certificates VName+ = ArrayIndexing Certs VName (Slice SubExp)+ | ArrayRearrange Certs VName [Int]+ | ArrayRotate Certs VName [SubExp]+ | ArrayCopy Certs VName | -- | Never constructed.- ArrayVar Certificates VName+ ArrayVar Certs VName deriving (Eq, Ord, Show) arrayOpArr :: ArrayOp -> VName@@ -726,14 +727,14 @@ arrayOpArr (ArrayCopy _ arr) = arr arrayOpArr (ArrayVar _ arr) = arr -arrayOpCerts :: ArrayOp -> Certificates+arrayOpCerts :: ArrayOp -> Certs arrayOpCerts (ArrayIndexing cs _ _) = cs arrayOpCerts (ArrayRearrange cs _ _) = cs arrayOpCerts (ArrayRotate cs _ _) = cs arrayOpCerts (ArrayCopy cs _) = cs arrayOpCerts (ArrayVar cs _) = cs -isArrayOp :: Certificates -> AST.Exp (Wise SOACS) -> Maybe ArrayOp+isArrayOp :: Certs -> AST.Exp (Wise SOACS) -> Maybe ArrayOp isArrayOp cs (BasicOp (Index arr slice)) = Just $ ArrayIndexing cs arr slice isArrayOp cs (BasicOp (Rearrange perm arr)) =@@ -745,14 +746,14 @@ isArrayOp _ _ = Nothing -fromArrayOp :: ArrayOp -> (Certificates, AST.Exp (Wise SOACS))+fromArrayOp :: ArrayOp -> (Certs, AST.Exp (Wise SOACS)) fromArrayOp (ArrayIndexing cs arr slice) = (cs, BasicOp $ Index arr slice) fromArrayOp (ArrayRearrange cs arr perm) = (cs, BasicOp $ Rearrange perm arr) fromArrayOp (ArrayRotate cs arr rots) = (cs, BasicOp $ Rotate rots arr) fromArrayOp (ArrayCopy cs arr) = (cs, BasicOp $ Copy arr) fromArrayOp (ArrayVar cs arr) = (cs, BasicOp $ SubExp $ Var arr) -arrayOps :: AST.Body (Wise SOACS) -> S.Set (AST.Pattern (Wise SOACS), ArrayOp)+arrayOps :: AST.Body (Wise SOACS) -> S.Set (AST.Pat (Wise SOACS), ArrayOp) arrayOps = mconcat . map onStm . stmsToList . bodyStms where onStm (Let pat aux e) =@@ -778,8 +779,7 @@ where onStm (Let pat aux e) = let (cs', e') = onExp (stmAuxCerts aux) e- in certify cs' $- mkLet' (patternContextIdents pat) (patternValueIdents pat) aux e'+ in certify cs' $ mkLet' (patIdents pat) aux e' onExp cs e | Just op <- isArrayOp cs e, Just op' <- M.lookup op substs =@@ -838,9 +838,9 @@ zeroIsh o && oneIsh s _ -> False - indexesWith v (ArrayIndexing cs arr (DimFix (Var i) : _))+ indexesWith v (ArrayIndexing cs arr (Slice (DimFix (Var i) : _))) | arr `ST.elem` vtable,- all (`ST.elem` vtable) $ unCertificates cs =+ all (`ST.elem` vtable) $ unCerts cs = i == v indexesWith _ _ = False @@ -851,16 +851,13 @@ if arraySize 0 arr_t == w then return arr else- certifying cs $- letExp (baseString arr ++ "_prefix") $- BasicOp $- Index arr $- fullSlice arr_t [DimSlice (intConst Int64 0) w (intConst Int64 1)]+ certifying cs . letExp (baseString arr ++ "_prefix") . BasicOp . Index arr $+ fullSlice arr_t [DimSlice (intConst Int64 0) w (intConst Int64 1)] return $ Just ( arr', Param arr_elem (rowType arr_t),- ArrayIndexing cs arr_elem (drop 1 slice)+ ArrayIndexing cs arr_elem (Slice (drop 1 (unSlice slice))) ) mapOverArr _ = return Nothing simplifyMapIota _ _ _ _ = Skip@@ -891,7 +888,7 @@ letBind pat $ Op $ Screma w (arrs <> more_arrs) (ScremaForm scan reduce map_lam') where map_param_names = map paramName (lambdaParams map_lam)- topLevelPattern = (`elem` fmap stmPattern (bodyStms (lambdaBody map_lam)))+ topLevelPat = (`elem` fmap stmPat (bodyStms (lambdaBody map_lam))) onlyUsedOnce arr = case filter ((arr `nameIn`) . freeIn) $ stmsToList $ bodyStms $ lambdaBody map_lam of _ : _ : _ -> False@@ -903,7 +900,7 @@ arr `elem` map_param_names && all (`ST.elem` vtable) (namesToList $ freeIn cs <> freeIn slice) && not (null slice)- && (not (null $ sliceDims slice) || (topLevelPattern pat' && onlyUsedOnce arr))+ && (not (null $ sliceDims slice) || (topLevelPat pat' && onlyUsedOnce arr)) arrayIsMapParam (_, ArrayRearrange cs arr perm) = arr `elem` map_param_names && all (`ST.elem` vtable) (namesToList $ freeIn cs)@@ -924,8 +921,8 @@ arr_transformed <- certifying (arrayOpCerts op) $ letExp (baseString arr ++ "_transformed") $ case op of- ArrayIndexing _ _ slice ->- BasicOp $ Index arr $ whole_dim : slice+ ArrayIndexing _ _ (Slice slice) ->+ BasicOp $ Index arr $ Slice $ whole_dim : slice ArrayRearrange _ _ perm -> BasicOp $ Rearrange (0 : map (+ 1) perm) arr ArrayRotate _ _ rots ->
src/Futhark/IR/SegOp.hs view
@@ -32,6 +32,7 @@ consumedInKernelBody, ResultManifest (..), KernelResult (..),+ kernelResultCerts, kernelResultSubExp, SplitOrdering (..), @@ -56,6 +57,7 @@ import Control.Monad.Writer hiding (mapM_) import Data.Bifunctor (first) import Data.Bitraversable+import Data.Foldable (traverse_) import Data.List ( elemIndex, foldl',@@ -206,23 +208,27 @@ = -- | Each "worker" in the kernel returns this. -- Whether this is a result-per-thread or a -- result-per-group depends on where the 'SegOp' occurs.- Returns ResultManifest SubExp+ Returns ResultManifest Certs SubExp | WriteReturns+ Certs Shape -- Size of array. Must match number of dims. VName -- Which array [(Slice SubExp, SubExp)] | -- Arbitrary number of index/value pairs. ConcatReturns+ Certs SplitOrdering -- Permuted? SubExp -- The final size. SubExp -- Per-thread/group (max) chunk size. VName -- Chunk by this worker. | TileReturns+ Certs [(SubExp, SubExp)] -- Total/tile for each dimension VName -- Tile written by this worker. -- The TileReturns must not expect more than one -- result to be written per physical thread. | RegTileReturns+ Certs -- For each dim of result: [ ( SubExp, -- size of this dim. SubExp, -- block tile size for this dim.@@ -232,23 +238,31 @@ VName -- Tile returned by this worker/group. deriving (Eq, Show, Ord) +-- | Get the certs for this 'KernelResult'.+kernelResultCerts :: KernelResult -> Certs+kernelResultCerts (Returns _ cs _) = cs+kernelResultCerts (WriteReturns cs _ _ _) = cs+kernelResultCerts (ConcatReturns cs _ _ _ _) = cs+kernelResultCerts (TileReturns cs _ _) = cs+kernelResultCerts (RegTileReturns cs _ _) = cs+ -- | Get the root t'SubExp' corresponding values for a 'KernelResult'. kernelResultSubExp :: KernelResult -> SubExp-kernelResultSubExp (Returns _ se) = se-kernelResultSubExp (WriteReturns _ arr _) = Var arr-kernelResultSubExp (ConcatReturns _ _ _ v) = Var v-kernelResultSubExp (TileReturns _ v) = Var v-kernelResultSubExp (RegTileReturns _ v) = Var v+kernelResultSubExp (Returns _ _ se) = se+kernelResultSubExp (WriteReturns _ _ arr _) = Var arr+kernelResultSubExp (ConcatReturns _ _ _ _ v) = Var v+kernelResultSubExp (TileReturns _ _ v) = Var v+kernelResultSubExp (RegTileReturns _ _ v) = Var v instance FreeIn KernelResult where- freeIn' (Returns _ what) = freeIn' what- freeIn' (WriteReturns rws arr res) = freeIn' rws <> freeIn' arr <> freeIn' res- freeIn' (ConcatReturns o w per_thread_elems v) =- freeIn' o <> freeIn' w <> freeIn' per_thread_elems <> freeIn' v- freeIn' (TileReturns dims v) =- freeIn' dims <> freeIn' v- freeIn' (RegTileReturns dims_n_tiles v) =- freeIn' dims_n_tiles <> freeIn' v+ freeIn' (Returns _ cs what) = freeIn' cs <> freeIn' what+ freeIn' (WriteReturns cs rws arr res) = freeIn' cs <> freeIn' rws <> freeIn' arr <> freeIn' res+ freeIn' (ConcatReturns cs o w per_thread_elems v) =+ freeIn' cs <> freeIn' o <> freeIn' w <> freeIn' per_thread_elems <> freeIn' v+ freeIn' (TileReturns cs dims v) =+ freeIn' cs <> freeIn' dims <> freeIn' v+ freeIn' (RegTileReturns cs dims_n_tiles v) =+ freeIn' cs <> freeIn' dims_n_tiles <> freeIn' v instance ASTRep rep => FreeIn (KernelBody rep) where freeIn' (KernelBody dec stms res) =@@ -264,23 +278,29 @@ (substituteNames subst res) instance Substitute KernelResult where- substituteNames subst (Returns manifest se) =- Returns manifest (substituteNames subst se)- substituteNames subst (WriteReturns rws arr res) =+ substituteNames subst (Returns manifest cs se) =+ Returns manifest (substituteNames subst cs) (substituteNames subst se)+ substituteNames subst (WriteReturns cs rws arr res) = WriteReturns+ (substituteNames subst cs) (substituteNames subst rws) (substituteNames subst arr) (substituteNames subst res)- substituteNames subst (ConcatReturns o w per_thread_elems v) =+ substituteNames subst (ConcatReturns cs o w per_thread_elems v) = ConcatReturns+ (substituteNames subst cs) (substituteNames subst o) (substituteNames subst w) (substituteNames subst per_thread_elems) (substituteNames subst v)- substituteNames subst (TileReturns dims v) =- TileReturns (substituteNames subst dims) (substituteNames subst v)- substituteNames subst (RegTileReturns dims_n_tiles v) =+ substituteNames subst (TileReturns cs dims v) =+ TileReturns+ (substituteNames subst cs)+ (substituteNames subst dims)+ (substituteNames subst v)+ substituteNames subst (RegTileReturns cs dims_n_tiles v) = RegTileReturns+ (substituteNames subst cs) (substituteNames subst dims_n_tiles) (substituteNames subst v) @@ -328,7 +348,7 @@ consumedInKernelBody (KernelBody dec stms res) = consumedInBody (Body dec stms []) <> mconcat (map consumedByReturn res) where- consumedByReturn (WriteReturns _ a _) = oneName a+ consumedByReturn (WriteReturns _ _ a _) = oneName a consumedByReturn _ = mempty checkKernelBody ::@@ -352,18 +372,20 @@ ++ " values." zipWithM_ checkKernelResult kres ts where- consumeKernelResult (WriteReturns _ arr _) =+ consumeKernelResult (WriteReturns _ _ arr _) = TC.consume =<< TC.lookupAliases arr consumeKernelResult _ = pure () - checkKernelResult (Returns _ what) t =+ checkKernelResult (Returns _ cs what) t = do+ TC.checkCerts cs TC.require [t] what- checkKernelResult (WriteReturns shape arr res) t = do+ checkKernelResult (WriteReturns cs shape arr res) t = do+ TC.checkCerts cs mapM_ (TC.require [Prim int64]) $ shapeDims shape arr_t <- lookupType arr forM_ res $ \(slice, e) -> do- mapM_ (traverse $ TC.require [Prim int64]) slice+ traverse_ (TC.require [Prim int64]) slice TC.require [t] e unless (arr_t == t `arrayOfShape` shape) $ TC.bad $@@ -376,7 +398,8 @@ ++ pretty shape ++ ", but destination array has type " ++ pretty arr_t- checkKernelResult (ConcatReturns o w per_thread_elems v) t = do+ checkKernelResult (ConcatReturns cs o w per_thread_elems v) t = do+ TC.checkCerts cs case o of SplitContiguous -> return () SplitStrided stride -> TC.require [Prim int64] stride@@ -385,14 +408,16 @@ vt <- lookupType v unless (vt == t `arrayOfRow` arraySize 0 vt) $ TC.bad $ TC.TypeError $ "Invalid type for ConcatReturns " ++ pretty v- checkKernelResult (TileReturns dims v) t = do+ checkKernelResult (TileReturns cs dims v) t = do+ TC.checkCerts cs forM_ dims $ \(dim, tile) -> do TC.require [Prim int64] dim TC.require [Prim int64] tile vt <- lookupType v unless (vt == t `arrayOfShape` Shape (map snd dims)) $ TC.bad $ TC.TypeError $ "Invalid type for TileReturns " ++ pretty v- checkKernelResult (RegTileReturns dims_n_tiles arr) t = do+ checkKernelResult (RegTileReturns cs dims_n_tiles arr) t = do+ TC.checkCerts cs mapM_ (TC.require [Prim int64]) dims mapM_ (TC.require [Prim int64]) blk_tiles mapM_ (TC.require [Prim int64]) reg_tiles@@ -417,31 +442,44 @@ PP.stack (map ppr (stmsToList stms)) </> text "return" <+> PP.braces (PP.commasep $ map ppr res) +certAnnots :: Certs -> [PP.Doc]+certAnnots cs+ | cs == mempty = []+ | otherwise = [ppr cs]+ instance Pretty KernelResult where- ppr (Returns ResultNoSimplify what) =- text "returns (manifest)" <+> ppr what- ppr (Returns ResultPrivate what) =- text "returns (private)" <+> ppr what- ppr (Returns ResultMaySimplify what) =- text "returns" <+> ppr what- ppr (WriteReturns shape arr res) =- ppr arr <+> PP.colon <+> ppr shape- </> text "with" <+> PP.apply (map ppRes res)+ ppr (Returns ResultNoSimplify cs what) =+ PP.spread $ certAnnots cs ++ ["returns (manifest)" <+> ppr what]+ ppr (Returns ResultPrivate cs what) =+ PP.spread $ certAnnots cs ++ ["returns (private)" <+> ppr what]+ ppr (Returns ResultMaySimplify cs what) =+ PP.spread $ certAnnots cs ++ ["returns" <+> ppr what]+ ppr (WriteReturns cs shape arr res) =+ PP.spread $+ certAnnots cs+ ++ [ ppr arr <+> PP.colon <+> ppr shape+ </> "with" <+> PP.apply (map ppRes res)+ ] where- ppRes (slice, e) =- PP.brackets (commasep (map ppr slice)) <+> text "=" <+> ppr e- ppr (ConcatReturns SplitContiguous w per_thread_elems v) =- text "concat"- <> parens (commasep [ppr w, ppr per_thread_elems]) <+> ppr v- ppr (ConcatReturns (SplitStrided stride) w per_thread_elems v) =- text "concat_strided"- <> parens (commasep [ppr stride, ppr w, ppr per_thread_elems]) <+> ppr v- ppr (TileReturns dims v) =- "tile" <> parens (commasep $ map onDim dims) <+> ppr v+ ppRes (slice, e) = ppr slice <+> text "=" <+> ppr e+ ppr (ConcatReturns cs SplitContiguous w per_thread_elems v) =+ PP.spread $+ certAnnots cs+ ++ [ "concat"+ <> parens (commasep [ppr w, ppr per_thread_elems]) <+> ppr v+ ]+ ppr (ConcatReturns cs (SplitStrided stride) w per_thread_elems v) =+ PP.spread $+ certAnnots cs+ ++ [ "concat_strided"+ <> parens (commasep [ppr stride, ppr w, ppr per_thread_elems]) <+> ppr v+ ]+ ppr (TileReturns cs dims v) =+ PP.spread $ certAnnots cs ++ ["tile" <> parens (commasep $ map onDim dims) <+> ppr v] where onDim (dim, tile) = ppr dim <+> "/" <+> ppr tile- ppr (RegTileReturns dims_n_tiles v) =- "blkreg_tile" <> parens (commasep $ map onDim dims_n_tiles) <+> ppr v+ ppr (RegTileReturns cs dims_n_tiles v) =+ PP.spread $ certAnnots cs ++ ["blkreg_tile" <> parens (commasep $ map onDim dims_n_tiles) <+> ppr v] where onDim (dim, blk_tile, reg_tile) = ppr dim <+> "/" <+> parens (ppr blk_tile <+> "*" <+> ppr reg_tile)@@ -529,15 +567,15 @@ SegHist _ _ _ _ body -> body segResultShape :: SegSpace -> Type -> KernelResult -> Type-segResultShape _ t (WriteReturns shape _ _) =+segResultShape _ t (WriteReturns _ shape _ _) = t `arrayOfShape` shape-segResultShape space t (Returns _ _) =+segResultShape space t Returns {} = foldr (flip arrayOfRow) t $ segSpaceDims space-segResultShape _ t (ConcatReturns _ w _ _) =+segResultShape _ t (ConcatReturns _ _ w _ _) = t `arrayOfRow` w-segResultShape _ t (TileReturns dims _) =+segResultShape _ t (TileReturns _ dims _) = t `arrayOfShape` Shape (map fst dims)-segResultShape _ t (RegTileReturns dims_n_tiles _) =+segResultShape _ t (RegTileReturns _ dims_n_tiles _) = t `arrayOfShape` Shape (map (\(dim, _, _) -> dim) dims_n_tiles) -- | The return type of a 'SegOp'.@@ -962,7 +1000,7 @@ instance ASTRep rep => ST.IndexOp (SegOp lvl rep) where indexOp vtable k (SegMap _ space _ kbody) is = do- Returns ResultMaySimplify se <- maybeNth k $ kernelBodyResult kbody+ Returns ResultMaySimplify _ se <- maybeNth k $ kernelBodyResult kbody guard $ length gtids <= length is let idx_table = M.fromList $ zip gtids $ map (ST.Indexed mempty . untyped) is idx_table' = foldl' expandIndexedTable idx_table $ kernelBodyStms kbody@@ -976,11 +1014,11 @@ excess_is = drop (length gtids) is expandIndexedTable table stm- | [v] <- patternNames $ stmPattern stm,+ | [v] <- patNames $ stmPat stm, Just (pe, cs) <- runWriterT $ primExpFromExp (asPrimExp table) $ stmExp stm = M.insert v (ST.Indexed (stmCerts stm <> cs) pe) table- | [v] <- patternNames $ stmPattern stm,+ | [v] <- patNames $ stmPat stm, BasicOp (Index arr slice) <- stmExp stm, length (sliceDims slice) == length excess_is, arr `ST.elem` vtable,@@ -989,13 +1027,13 @@ ST.IndexedArray (stmCerts stm <> cs) arr- (fixSlice (map (fmap isInt64) slice') excess_is)+ (fixSlice (fmap isInt64 slice') excess_is) in M.insert v idx table | otherwise = table asPrimExpSlice table =- runWriterT . mapM (traverse (primExpFromSubExpM (asPrimExp table)))+ runWriterT . traverse (primExpFromSubExpM (asPrimExp table)) asPrimExp table v | Just (ST.Indexed cs e) <- M.lookup v table = tell cs >> return e@@ -1024,21 +1062,26 @@ SegSpace phys <$> mapM (traverse Engine.simplify) dims instance Engine.Simplifiable KernelResult where- simplify (Returns manifest what) =- Returns manifest <$> Engine.simplify what- simplify (WriteReturns ws a res) =- WriteReturns <$> Engine.simplify ws <*> Engine.simplify a <*> Engine.simplify res- simplify (ConcatReturns o w pte what) =+ simplify (Returns manifest cs what) =+ Returns manifest <$> Engine.simplify cs <*> Engine.simplify what+ simplify (WriteReturns cs ws a res) =+ WriteReturns <$> Engine.simplify cs+ <*> Engine.simplify ws+ <*> Engine.simplify a+ <*> Engine.simplify res+ simplify (ConcatReturns cs o w pte what) = ConcatReturns- <$> Engine.simplify o+ <$> Engine.simplify cs+ <*> Engine.simplify o <*> Engine.simplify w <*> Engine.simplify pte <*> Engine.simplify what- simplify (TileReturns dims what) =- TileReturns <$> Engine.simplify dims <*> Engine.simplify what- simplify (RegTileReturns dims_n_tiles what) =+ simplify (TileReturns cs dims what) =+ TileReturns <$> Engine.simplify cs <*> Engine.simplify dims <*> Engine.simplify what+ simplify (RegTileReturns cs dims_n_tiles what) = RegTileReturns- <$> Engine.simplify dims_n_tiles+ <$> Engine.simplify cs+ <*> Engine.simplify dims_n_tiles <*> Engine.simplify what mkWiseKernelBody ::@@ -1048,18 +1091,18 @@ [KernelResult] -> KernelBody (Wise rep) mkWiseKernelBody dec bnds res =- let Body dec' _ _ = mkWiseBody dec bnds res_vs+ let Body dec' _ _ = mkWiseBody dec bnds $ subExpsRes res_vs in KernelBody dec' bnds res where res_vs = map kernelResultSubExp res mkKernelBodyM ::- MonadBinder m =>+ MonadBuilder m => Stms (Rep m) -> [KernelResult] -> m (KernelBody (Rep m)) mkKernelBodyM stms kres = do- Body dec' _ _ <- mkBodyM stms res_ses+ Body dec' _ _ <- mkBodyM stms $ subExpsRes res_ses return $ KernelBody dec' stms kres where res_ses = map kernelResultSubExp kres@@ -1095,7 +1138,7 @@ scope_vtable = segSpaceSymbolTable space bound_here = namesFromList $ M.keys $ scopeOfSegSpace space - consumedInResult (WriteReturns _ arr _) =+ consumedInResult (WriteReturns _ _ arr _) = [arr] consumedInResult _ = []@@ -1200,13 +1243,13 @@ -- | Simplification rules for simplifying 'SegOp's. segOpRules ::- (HasSegOp rep, BinderOps rep, Bindable rep) =>+ (HasSegOp rep, BuilderOps rep, Buildable rep) => RuleBook rep segOpRules = ruleBook [RuleOp segOpRuleTopDown] [RuleOp segOpRuleBottomUp] segOpRuleTopDown ::- (HasSegOp rep, BinderOps rep, Bindable rep) =>+ (HasSegOp rep, BuilderOps rep, Buildable rep) => TopDownRuleOp rep segOpRuleTopDown vtable pat dec op | Just op' <- asSegOp op =@@ -1215,7 +1258,7 @@ Skip segOpRuleBottomUp ::- (HasSegOp rep, BinderOps rep) =>+ (HasSegOp rep, BuilderOps rep) => BottomUpRuleOp rep segOpRuleBottomUp vtable pat dec op | Just op' <- asSegOp op =@@ -1224,35 +1267,31 @@ Skip topDownSegOp ::- (HasSegOp rep, BinderOps rep, Bindable rep) =>+ (HasSegOp rep, BuilderOps rep, Buildable rep) => ST.SymbolTable rep ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> SegOp (SegOpLevel rep) rep -> Rule rep -- If a SegOp produces something invariant to the SegOp, turn it -- into a replicate.-topDownSegOp vtable (Pattern [] kpes) dec (SegMap lvl space ts (KernelBody _ kstms kres)) = Simplify $ do+topDownSegOp vtable (Pat kpes) dec (SegMap lvl space ts (KernelBody _ kstms kres)) = Simplify $ do (ts', kpes', kres') <- unzip3 <$> filterM checkForInvarianceResult (zip3 ts kpes kres) -- Check if we did anything at all.- when- (kres == kres')- cannotSimplify+ when (kres == kres') cannotSimplify kbody <- mkKernelBodyM kstms kres' addStm $- Let (Pattern [] kpes') dec $- Op $- segOp $- SegMap lvl space ts' kbody+ Let (Pat kpes') dec $ Op $ segOp $ SegMap lvl space ts' kbody where isInvariant Constant {} = True isInvariant (Var v) = isJust $ ST.lookup v vtable - checkForInvarianceResult (_, pe, Returns rm se)- | rm == ResultMaySimplify,+ checkForInvarianceResult (_, pe, Returns rm cs se)+ | cs == mempty,+ rm == ResultMaySimplify, isInvariant se = do letBindNames [patElemName pe] $ BasicOp $ Replicate (Shape $ segSpaceDims space) se@@ -1263,7 +1302,7 @@ -- If a SegRed contains two reduction operations that have the same -- vector shape, merge them together. This saves on communication -- overhead, but can in principle lead to more local memory usage.-topDownSegOp _ (Pattern [] pes) _ (SegRed lvl space ops ts kbody)+topDownSegOp _ (Pat pes) _ (SegRed lvl space ops ts kbody) | length ops > 1, op_groupings <- groupBy sameShape $@@ -1276,7 +1315,7 @@ pes' = red_pes' ++ map_pes ts' = red_ts' ++ map_ts kbody' = kbody {kernelBodyResult = red_res' ++ map_res}- letBind (Pattern [] pes') $ Op $ segOp $ SegRed lvl space ops' ts' kbody'+ letBind (Pat pes') $ Op $ segOp $ SegRed lvl space ops' ts' kbody' where (red_pes, map_pes) = splitAt (segBinOpResults ops) pes (red_ts, map_ts) = splitAt (segBinOpResults ops) ts@@ -1334,15 +1373,15 @@ (kts, body, sum $ map (length . histDest) ops, SegHist lvl space ops) bottomUpSegOp ::- (HasSegOp rep, BinderOps rep) =>+ (HasSegOp rep, BuilderOps rep) => (ST.SymbolTable rep, UT.UsageTable) ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> SegOp (SegOpLevel rep) rep -> Rule rep -- Some SegOp results can be moved outside the SegOp, which can -- simplify further analysis.-bottomUpSegOp (vtable, used) (Pattern [] kpes) dec segop = Simplify $ do+bottomUpSegOp (vtable, used) (Pat kpes) dec segop = Simplify $ do -- Iterate through the bindings. For each, we check whether it is -- in kres and can be moved outside. If so, we remove it from kres -- and kpes and make it a binding outside. We have to be careful@@ -1361,7 +1400,7 @@ localScope (scopeOfSegSpace space) $ mkKernelBodyM kstms' kres' - addStm $ Let (Pattern [] kpes') dec $ Op $ segOp $ mk_segop kts' kbody+ addStm $ Let (Pat kpes') dec $ Op $ segOp $ mk_segop kts' kbody where (kts, KernelBody _ kstms kres, num_nonmap_results, mk_segop) = segOpGuts segop@@ -1371,8 +1410,8 @@ sliceWithGtidsFixed stm | Let _ _ (BasicOp (Index arr slice)) <- stm, space_slice <- map (DimFix . Var . fst) $ unSegSpace space,- space_slice `isPrefixOf` slice,- remaining_slice <- drop (length space_slice) slice,+ space_slice `isPrefixOf` unSlice slice,+ remaining_slice <- Slice $ drop (length space_slice) (unSlice slice), all (isJust . flip ST.lookup vtable) $ namesToList $ freeIn arr <> freeIn remaining_slice =@@ -1381,8 +1420,8 @@ Nothing distribute (kpes', kts', kres', kstms') stm- | Let (Pattern [] [pe]) _ _ <- stm,- Just (remaining_slice, arr) <- sliceWithGtidsFixed stm,+ | Let (Pat [pe]) _ _ <- stm,+ Just (Slice remaining_slice, arr) <- sliceWithGtidsFixed stm, Just (kpe, kpes'', kts'', kres'') <- isResult kpes' kts' kres' pe = do let outer_slice = map@@ -1395,7 +1434,7 @@ $ segSpaceDims space index kpe' = letBindNames [patElemName kpe'] . BasicOp . Index arr $- outer_slice <> remaining_slice+ Slice $ outer_slice <> remaining_slice if patElemName kpe `UT.isConsumed` used then do precopy <- newVName $ baseString (patElemName kpe) <> "_precopy"@@ -1422,26 +1461,25 @@ Just (kpe, kpes'', kts'', kres'') _ -> Nothing where- matches (_, _, Returns _ (Var v)) = v == patElemName pe+ matches (_, _, Returns _ _ (Var v)) = v == patElemName pe matches _ = False-bottomUpSegOp _ _ _ _ = Skip --- Memory kernelBodyReturns ::- (Mem rep, HasScope rep m, Monad m) =>- KernelBody rep ->+ (Mem rep inner, HasScope rep m, Monad m) =>+ KernelBody somerep -> [ExpReturns] -> m [ExpReturns] kernelBodyReturns = zipWithM correct . kernelBodyResult where- correct (WriteReturns _ arr _) _ = varReturns arr+ correct (WriteReturns _ _ arr _) _ = varReturns arr correct _ ret = return ret -- | Like 'segOpType', but for memory representations. segOpReturns ::- (Mem rep, Monad m, HasScope rep m) =>- SegOp lvl rep ->+ (Mem rep inner, Monad m, HasScope rep m) =>+ SegOp lvl somerep -> m [ExpReturns] segOpReturns k@(SegMap _ _ _ kbody) = kernelBodyReturns kbody . extReturns =<< opType k
src/Futhark/IR/Seq.hs view
@@ -16,7 +16,7 @@ ) where -import Futhark.Binder+import Futhark.Builder import Futhark.Construct import Futhark.IR.Pretty import Futhark.IR.Prop@@ -35,24 +35,24 @@ type Op Seq = () instance ASTRep Seq where- expTypesFromPattern = return . expExtTypesFromPattern+ expTypesFromPat = return . expExtTypesFromPat instance TypeCheck.CheckableOp Seq where checkOp = pure instance TypeCheck.Checkable Seq -instance Bindable Seq where+instance Buildable Seq where mkBody = Body ()- mkExpPat ctx val _ = basicPattern ctx val+ mkExpPat idents _ = basicPat idents mkExpDec _ _ = () mkLetNames = simpleMkLetNames -instance BinderOps Seq+instance BuilderOps Seq instance PrettyRep Seq -instance BinderOps (Engine.Wise Seq)+instance BuilderOps (Engine.Wise Seq) simpleSeq :: Simplify.SimpleOps Seq simpleSeq = Simplify.bindableSimpleOps (const $ pure ((), mempty))
src/Futhark/IR/SeqMem.hs view
@@ -21,7 +21,7 @@ import Futhark.IR.Mem.Simplify import qualified Futhark.Optimise.Simplify.Engine as Engine import Futhark.Pass-import Futhark.Pass.ExplicitAllocations (BinderOps (..), mkLetNamesB', mkLetNamesB'')+import Futhark.Pass.ExplicitAllocations (BuilderOps (..), mkLetNamesB', mkLetNamesB'') import qualified Futhark.TypeCheck as TC data SeqMem@@ -35,11 +35,7 @@ type Op SeqMem = MemOp () instance ASTRep SeqMem where- expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern--instance OpReturns SeqMem where- opReturns (Alloc _ space) = return [MemMem space]- opReturns (Inner ()) = pure []+ expTypesFromPat = return . map snd . bodyReturnsFromPat instance PrettyRep SeqMem @@ -55,17 +51,17 @@ checkLetBoundDec = checkMemInfo checkRetType = mapM_ (TC.checkExtType . declExtTypeOf) primFParam name t = return $ Param name (MemPrim t)- matchPattern = matchPatternToExp+ matchPat = matchPatToExp matchReturnType = matchFunctionReturnType matchBranchType = matchBranchReturnType matchLoopResult = matchLoopResultMem -instance BinderOps SeqMem where+instance BuilderOps SeqMem where mkExpDecB _ _ = return () mkBodyB stms res = return $ Body () stms res mkLetNamesB = mkLetNamesB' () -instance BinderOps (Engine.Wise SeqMem) where+instance BuilderOps (Engine.Wise SeqMem) where mkExpDecB pat e = return $ Engine.mkWiseExpDec pat () e mkBodyB stms res = return $ Engine.mkWiseBody () stms res mkLetNamesB = mkLetNamesB''
src/Futhark/IR/Syntax.hs view
@@ -56,10 +56,8 @@ -- t'Body' consists of executing all of the statements, then returning -- the values of the variables indicated by the result. ----- A statement ('Stm') consists of a t'Pattern' alongside an--- expression 'ExpT'. A pattern contains a "context" part and a--- "value" part. The context is used for things like the size of--- arrays in the value part whose size is existential.+-- A statement ('Stm') consists of a t'Pat' alongside an+-- expression 'ExpT'. A pattern is a sequence of name/type pairs. -- -- For example, the source language expression @let z = x + y - 1 in -- z@ would in the core language be represented (in prettyprinted@@ -125,11 +123,12 @@ SubExp (..), PatElem, PatElemT (..),- PatternT (..),- Pattern,+ PatT (..),+ Pat, StmAux (..), Stm (..), Stms,+ SubExpRes (..), Result, BodyT (..), Body,@@ -138,6 +137,7 @@ BinOp (..), CmpOp (..), ConvOp (..),+ OpaqueOp (..), DimChange (..), ShapeChange, ExpT (..),@@ -163,6 +163,10 @@ stmsFromList, stmsToList, stmsHead,+ subExpRes,+ subExpsRes,+ varRes,+ varsRes, ) where @@ -208,36 +212,31 @@ type PatElem rep = PatElemT (LetDec rep) -- | A pattern is conceptually just a list of names and their types.-data PatternT dec = Pattern- { -- | existential context (sizes and memory blocks)- patternContextElements :: [PatElemT dec],- -- | "real" values- patternValueElements :: [PatElemT dec]- }+newtype PatT dec = Pat {patElems :: [PatElemT dec]} deriving (Ord, Show, Eq) -instance Semigroup (PatternT dec) where- Pattern cs1 vs1 <> Pattern cs2 vs2 = Pattern (cs1 ++ cs2) (vs1 ++ vs2)+instance Semigroup (PatT dec) where+ Pat xs <> Pat ys = Pat (xs <> ys) -instance Monoid (PatternT dec) where- mempty = Pattern [] []+instance Monoid (PatT dec) where+ mempty = Pat mempty -instance Functor PatternT where+instance Functor PatT where fmap = fmapDefault -instance Foldable PatternT where+instance Foldable PatT where foldMap = foldMapDefault -instance Traversable PatternT where- traverse f (Pattern ctx vals) =- Pattern <$> traverse (traverse f) ctx <*> traverse (traverse f) vals+instance Traversable PatT where+ traverse f (Pat xs) =+ Pat <$> traverse (traverse f) xs -- | A type alias for namespace control.-type Pattern rep = PatternT (LetDec rep)+type Pat rep = PatT (LetDec rep) -- | Auxilliary Information associated with a statement. data StmAux dec = StmAux- { stmAuxCerts :: !Certificates,+ { stmAuxCerts :: !Certs, stmAuxAttrs :: Attrs, stmAuxDec :: dec }@@ -249,8 +248,8 @@ -- | A local variable binding. data Stm rep = Let- { -- | Pattern.- stmPattern :: Pattern rep,+ { -- | Pat.+ stmPat :: Pat rep, -- | Auxiliary information statement. stmAux :: StmAux (ExpDec rep), -- | Expression.@@ -284,8 +283,31 @@ stm Seq.:< stms' -> Just (stm, stms') Seq.EmptyL -> Nothing +-- | A pairing of a subexpression and some certificates.+data SubExpRes = SubExpRes+ { resCerts :: Certs,+ resSubExp :: SubExp+ }+ deriving (Eq, Ord, Show)++-- | Construct a 'SubExpRes' with no certificates.+subExpRes :: SubExp -> SubExpRes+subExpRes = SubExpRes mempty++-- | Construct a 'SubExpRes' from a variable name.+varRes :: VName -> SubExpRes+varRes = subExpRes . Var++-- | Construct a 'Result' from subexpressions.+subExpsRes :: [SubExp] -> Result+subExpsRes = map subExpRes++-- | Construct a 'Result' from variable names.+varsRes :: [VName] -> Result+varsRes = map varRes+ -- | The result of a body is a sequence of subexpressions.-type Result = [SubExp]+type Result = [SubExpRes] -- | A body consists of a number of bindings, terminating in a result -- (essentially a tuple literal).@@ -338,16 +360,26 @@ -- | A list of 'DimChange's, indicating the new dimensions of an array. type ShapeChange d = [DimChange d] +-- | Apart from being Opaque, what else is going on here?+data OpaqueOp+ = -- | No special operation.+ OpaqueNil+ | -- | Print the argument, prefixed by this string.+ OpaqueTrace String+ deriving (Eq, Ord, Show)+ -- | A primitive operation that returns something of known size and -- does not itself contain any bindings. data BasicOp = -- | A variable or constant. SubExp SubExp | -- | Semantically and operationally just identity, but is- -- invisible/impenetrable to optimisations (hopefully). This is- -- just a hack to avoid optimisation (so, to work around compiler- -- limitations).- Opaque SubExp+ -- invisible/impenetrable to optimisations (hopefully). This+ -- partially a hack to avoid optimisation (so, to work around+ -- compiler limitations), but is also used to implement tracing+ -- and other operations that are semantically invisible, but have+ -- some sort of effect (brrr).+ Opaque OpaqueOp SubExp | -- | Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@. -- Second arg is the element type of the rows of the array. ArrayLit [SubExp] Type@@ -367,8 +399,11 @@ -- | The certificates for bounds-checking are part of the 'Stm'. Index VName (Slice SubExp) | -- | An in-place update of the given array at the given position.- -- Consumes the array.- Update VName (Slice SubExp) SubExp+ -- Consumes the array. If 'Safe', perform a run-time bounds check+ -- and ignore the write if out of bounds (like @Scatter@).+ Update Safety VName (Slice SubExp) SubExp+ | FlatIndex VName (FlatSlice SubExp)+ | FlatUpdate VName (FlatSlice SubExp) VName | -- | @concat@0([1],[2, 3, 4]) = [1, 2, 3, 4]@. Concat Int VName [VName] SubExp | -- | Copy the given array. The result will not alias anything.@@ -413,15 +448,14 @@ BasicOp BasicOp | Apply Name [(SubExp, Diet)] [RetType rep] (Safety, SrcLoc, [SrcLoc]) | If SubExp (BodyT rep) (BodyT rep) (IfDec (BranchType rep))- | -- | @loop {a} = {v} (for i < n|while b) do b@. The merge- -- parameters are divided into context and value part.- DoLoop [(FParam rep, SubExp)] [(FParam rep, SubExp)] (LoopForm rep) (BodyT rep)+ | -- | @loop {a} = {v} (for i < n|while b) do b@.+ DoLoop [(FParam rep, SubExp)] (LoopForm rep) (BodyT rep) | -- | Create accumulators backed by the given arrays (which are -- consumed) and pass them to the lambda, which must return the -- updated accumulators and possibly some extra values. The- -- accumulators are turned back into arrays. The 'Shape' is the+ -- accumulators are turned back into arrays. The t'Shape' is the -- write index space. The corresponding arrays must all have this- -- shape outermost. This construct is not part of 'BasicOp'+ -- shape outermost. This construct is not part of t'BasicOp' -- because we need the @rep@ parameter. WithAcc [(Shape, [VName], Maybe (Lambda rep, [SubExp]))] (Lambda rep) | Op (Op rep)
src/Futhark/IR/Syntax/Core.hs view
@@ -40,11 +40,11 @@ -- * Abstract syntax tree Ident (..),- Certificates (..),+ Certs (..), SubExp (..), Param (..), DimIndex (..),- Slice,+ Slice (..), dimFix, sliceIndices, sliceDims,@@ -52,6 +52,12 @@ fixSlice, sliceSlice, PatElemT (..),++ -- * Flat (LMAD) slices+ FlatSlice (..),+ FlatDimIndex (..),+ flatSliceDims,+ flatSliceStrides, ) where @@ -281,14 +287,14 @@ x `compare` y = identName x `compare` identName y -- | A list of names used for certificates in some expressions.-newtype Certificates = Certificates {unCertificates :: [VName]}+newtype Certs = Certs {unCerts :: [VName]} deriving (Eq, Ord, Show) -instance Semigroup Certificates where- Certificates x <> Certificates y = Certificates (x <> y)+instance Semigroup Certs where+ Certs x <> Certs y = Certs (x <> y) -instance Monoid Certificates where- mempty = Certificates mempty+instance Monoid Certs where+ mempty = Certs mempty -- | A subexpression is either a scalar constant or a variable. One -- important property is that evaluation of a subexpression is@@ -336,12 +342,22 @@ traverse f (DimFix d) = DimFix <$> f d traverse f (DimSlice i j s) = DimSlice <$> f i <*> f j <*> f s --- | A list of 'DimFix's, indicating how an array should be sliced.+-- | A list of 'DimIndex's, indicating how an array should be sliced. -- Whenever a function accepts a 'Slice', that slice should be total, -- i.e, cover all dimensions of the array. Deviators should be -- indicated by taking a list of 'DimIndex'es instead.-type Slice d = [DimIndex d]+newtype Slice d = Slice {unSlice :: [DimIndex d]}+ deriving (Eq, Ord, Show) +instance Traversable Slice where+ traverse f = fmap Slice . traverse (traverse f) . unSlice++instance Functor Slice where+ fmap = fmapDefault++instance Foldable Slice where+ foldMap = foldMapDefault+ -- | If the argument is a 'DimFix', return its component. dimFix :: DimIndex d -> Maybe d dimFix (DimFix d) = Just d@@ -349,11 +365,11 @@ -- | If the slice is all 'DimFix's, return the components. sliceIndices :: Slice d -> Maybe [d]-sliceIndices = mapM dimFix+sliceIndices = mapM dimFix . unSlice -- | The dimensions of the array produced by this slice. sliceDims :: Slice d -> [d]-sliceDims = mapMaybe dimSlice+sliceDims = mapMaybe dimSlice . unSlice where dimSlice (DimSlice _ d _) = Just d dimSlice DimFix {} = Nothing@@ -365,30 +381,74 @@ -- | Fix the 'DimSlice's of a slice. The number of indexes must equal -- the length of 'sliceDims' for the slice. fixSlice :: Num d => Slice d -> [d] -> [d]-fixSlice (DimFix j : mis') is' =- j : fixSlice mis' is'-fixSlice (DimSlice orig_k _ orig_s : mis') (i : is') =- (orig_k + i * orig_s) : fixSlice mis' is'-fixSlice _ _ = []+fixSlice = fixSlice' . unSlice+ where+ fixSlice' (DimFix j : mis') is' =+ j : fixSlice' mis' is'+ fixSlice' (DimSlice orig_k _ orig_s : mis') (i : is') =+ (orig_k + i * orig_s) : fixSlice' mis' is'+ fixSlice' _ _ = [] -- | Further slice the 'DimSlice's of a slice. The number of slices -- must equal the length of 'sliceDims' for the slice. sliceSlice :: Num d => Slice d -> Slice d -> Slice d-sliceSlice (DimFix j : js') is' =- DimFix j : sliceSlice js' is'-sliceSlice (DimSlice j _ s : js') (DimFix i : is') =- DimFix (j + (i * s)) : sliceSlice js' is'-sliceSlice (DimSlice j _ s0 : js') (DimSlice i n s1 : is') =- DimSlice (j + (s0 * i)) n (s0 * s1) : sliceSlice js' is'-sliceSlice _ _ = []+sliceSlice (Slice jslice) (Slice islice) = Slice $ sliceSlice' jslice islice+ where+ sliceSlice' (DimFix j : js') is' =+ DimFix j : sliceSlice' js' is'+ sliceSlice' (DimSlice j _ s : js') (DimFix i : is') =+ DimFix (j + (i * s)) : sliceSlice' js' is'+ sliceSlice' (DimSlice j _ s0 : js') (DimSlice i n s1 : is') =+ DimSlice (j + (s0 * i)) n (s0 * s1) : sliceSlice' js' is'+ sliceSlice' _ _ = [] +data FlatDimIndex d+ = FlatDimIndex+ d+ -- ^ Number of elements in dimension+ d+ -- ^ Stride of dimension+ deriving (Eq, Ord, Show)++instance Traversable FlatDimIndex where+ traverse f (FlatDimIndex n s) = FlatDimIndex <$> f n <*> f s++instance Functor FlatDimIndex where+ fmap = fmapDefault++instance Foldable FlatDimIndex where+ foldMap = foldMapDefault++data FlatSlice d = FlatSlice d [FlatDimIndex d]+ deriving (Eq, Ord, Show)++instance Traversable FlatSlice where+ traverse f (FlatSlice offset is) =+ FlatSlice <$> f offset <*> traverse (traverse f) is++instance Functor FlatSlice where+ fmap = fmapDefault++instance Foldable FlatSlice where+ foldMap = foldMapDefault++flatSliceDims :: FlatSlice d -> [d]+flatSliceDims (FlatSlice _ ds) = map dimSlice ds+ where+ dimSlice (FlatDimIndex n _) = n++flatSliceStrides :: FlatSlice d -> [d]+flatSliceStrides (FlatSlice _ ds) = map dimStride ds+ where+ dimStride (FlatDimIndex _ s) = s+ -- | An element of a pattern - consisting of a name and an addditional -- parametric decoration. This decoration is what is expected to -- contain the type of the resulting variable. data PatElemT dec = PatElem { -- | The name being bound. patElemName :: VName,- -- | Pattern element decoration.+ -- | Pat element decoration. patElemDec :: dec } deriving (Ord, Show, Eq)@@ -415,10 +475,8 @@ data ErrorMsgPart a = -- | A literal string. ErrorString String- | -- | A run-time integer value.- ErrorInt32 a- | -- | A bigger run-time integer value.- ErrorInt64 a+ | -- | A run-time value.+ ErrorVal PrimType a deriving (Eq, Ord, Show) instance IsString (ErrorMsgPart a) where@@ -434,19 +492,14 @@ traverse f (ErrorMsg parts) = ErrorMsg <$> traverse (traverse f) parts instance Functor ErrorMsgPart where- fmap _ (ErrorString s) = ErrorString s- fmap f (ErrorInt32 a) = ErrorInt32 $ f a- fmap f (ErrorInt64 a) = ErrorInt64 $ f a+ fmap = fmapDefault instance Foldable ErrorMsgPart where- foldMap _ ErrorString {} = mempty- foldMap f (ErrorInt32 a) = f a- foldMap f (ErrorInt64 a) = f a+ foldMap = foldMapDefault instance Traversable ErrorMsgPart where traverse _ (ErrorString s) = pure $ ErrorString s- traverse f (ErrorInt32 a) = ErrorInt32 <$> f a- traverse f (ErrorInt64 a) = ErrorInt64 <$> f a+ traverse f (ErrorVal t a) = ErrorVal t <$> f a -- | How many non-constant parts does the error message have, and what -- is their type?@@ -454,5 +507,4 @@ errorMsgArgTypes (ErrorMsg parts) = mapMaybe onPart parts where onPart ErrorString {} = Nothing- onPart ErrorInt32 {} = Just $ IntType Int32- onPart ErrorInt64 {} = Just $ IntType Int64+ onPart (ErrorVal t _) = Just t
src/Futhark/IR/Traversals.hs view
@@ -106,14 +106,25 @@ mapExpM tv (BasicOp (Index arr slice)) = BasicOp <$> ( Index <$> mapOnVName tv arr- <*> mapM (traverse (mapOnSubExp tv)) slice+ <*> traverse (mapOnSubExp tv) slice )-mapExpM tv (BasicOp (Update arr slice se)) =+mapExpM tv (BasicOp (Update safety arr slice se)) = BasicOp- <$> ( Update <$> mapOnVName tv arr- <*> mapM (traverse (mapOnSubExp tv)) slice+ <$> ( Update safety <$> mapOnVName tv arr+ <*> traverse (mapOnSubExp tv) slice <*> mapOnSubExp tv se )+mapExpM tv (BasicOp (FlatIndex arr slice)) =+ BasicOp+ <$> ( FlatIndex <$> mapOnVName tv arr+ <*> traverse (mapOnSubExp tv) slice+ )+mapExpM tv (BasicOp (FlatUpdate arr slice se)) =+ BasicOp+ <$> ( FlatUpdate <$> mapOnVName tv arr+ <*> traverse (mapOnSubExp tv) slice+ <*> mapOnVName tv se+ ) mapExpM tv (BasicOp (Iota n x s et)) = BasicOp <$> (Iota <$> mapOnSubExp tv n <*> mapOnSubExp tv x <*> mapOnSubExp tv s <*> pure et) mapExpM tv (BasicOp (Replicate shape vexp)) =@@ -143,8 +154,8 @@ BasicOp <$> (Manifest perm <$> mapOnVName tv e) mapExpM tv (BasicOp (Assert e msg loc)) = BasicOp <$> (Assert <$> mapOnSubExp tv e <*> traverse (mapOnSubExp tv) msg <*> pure loc)-mapExpM tv (BasicOp (Opaque e)) =- BasicOp <$> (Opaque <$> mapOnSubExp tv e)+mapExpM tv (BasicOp (Opaque op e)) =+ BasicOp <$> (Opaque op <$> mapOnSubExp tv e) mapExpM tv (BasicOp (UpdateAcc v is ses)) = BasicOp <$> ( UpdateAcc@@ -158,19 +169,16 @@ onInput (shape, vs, op) = (,,) <$> mapOnShape tv shape <*> mapM (mapOnVName tv) vs <*> traverse (bitraverse (mapOnLambda tv) (mapM (mapOnSubExp tv))) op-mapExpM tv (DoLoop ctxmerge valmerge form loopbody) = do- ctxparams' <- mapM (mapOnFParam tv) ctxparams- valparams' <- mapM (mapOnFParam tv) valparams+mapExpM tv (DoLoop merge form loopbody) = do+ params' <- mapM (mapOnFParam tv) params form' <- mapOnLoopForm tv form- let scope = scopeOf form' <> scopeOfFParams (ctxparams' ++ valparams')+ let scope = scopeOf form' <> scopeOfFParams params' DoLoop- <$> (zip ctxparams' <$> mapM (mapOnSubExp tv) ctxinits)- <*> (zip valparams' <$> mapM (mapOnSubExp tv) valinits)+ <$> (zip params' <$> mapM (mapOnSubExp tv) args) <*> pure form' <*> mapOnBody tv scope loopbody where- (ctxparams, ctxinits) = unzip ctxmerge- (valparams, valinits) = unzip valmerge+ (params, args) = unzip merge mapExpM tv (Op op) = Op <$> mapOnOp tv op @@ -283,11 +291,17 @@ walkExpM tv (Apply _ args ret _) = mapM_ (walkOnSubExp tv . fst) args >> mapM_ (walkOnRetType tv) ret walkExpM tv (BasicOp (Index arr slice)) =- walkOnVName tv arr >> mapM_ (traverse_ (walkOnSubExp tv)) slice-walkExpM tv (BasicOp (Update arr slice se)) =+ walkOnVName tv arr >> traverse_ (walkOnSubExp tv) slice+walkExpM tv (BasicOp (Update _ arr slice se)) = walkOnVName tv arr- >> mapM_ (traverse_ (walkOnSubExp tv)) slice+ >> traverse_ (walkOnSubExp tv) slice >> walkOnSubExp tv se+walkExpM tv (BasicOp (FlatIndex arr slice)) =+ walkOnVName tv arr >> traverse_ (walkOnSubExp tv) slice+walkExpM tv (BasicOp (FlatUpdate arr slice se)) =+ walkOnVName tv arr+ >> traverse_ (walkOnSubExp tv) slice+ >> walkOnVName tv se walkExpM tv (BasicOp (Iota n x s _)) = walkOnSubExp tv n >> walkOnSubExp tv x >> walkOnSubExp tv s walkExpM tv (BasicOp (Replicate shape vexp)) =@@ -308,7 +322,7 @@ walkOnVName tv e walkExpM tv (BasicOp (Assert e msg _)) = walkOnSubExp tv e >> traverse_ (walkOnSubExp tv) msg-walkExpM tv (BasicOp (Opaque e)) =+walkExpM tv (BasicOp (Opaque _ e)) = walkOnSubExp tv e walkExpM tv (BasicOp (UpdateAcc v is ses)) = do walkOnVName tv v@@ -320,16 +334,13 @@ mapM_ (walkOnVName tv) vs traverse_ (bitraverse (walkOnLambda tv) (mapM (walkOnSubExp tv))) op walkOnLambda tv lam-walkExpM tv (DoLoop ctxmerge valmerge form loopbody) = do- mapM_ (walkOnFParam tv) ctxparams- mapM_ (walkOnFParam tv) valparams+walkExpM tv (DoLoop merge form loopbody) = do+ mapM_ (walkOnFParam tv) params walkOnLoopForm tv form- mapM_ (walkOnSubExp tv) ctxinits- mapM_ (walkOnSubExp tv) valinits- let scope = scopeOfFParams (ctxparams ++ valparams) <> scopeOf form+ mapM_ (walkOnSubExp tv) args+ let scope = scopeOfFParams params <> scopeOf form walkOnBody tv scope loopbody where- (ctxparams, ctxinits) = unzip ctxmerge- (valparams, valinits) = unzip valmerge+ (params, args) = unzip merge walkExpM tv (Op op) = walkOnOp tv op
src/Futhark/Internalise.hs view
@@ -9,7 +9,7 @@ import qualified Data.Text as T import Futhark.Compiler.Config-import Futhark.IR.SOACS as I hiding (stmPattern)+import Futhark.IR.SOACS as I hiding (stmPat) import Futhark.Internalise.Defunctionalise as Defunctionalise import Futhark.Internalise.Defunctorise as Defunctorise import qualified Futhark.Internalise.Exps as Exps
src/Futhark/Internalise/AccurateSizes.hs view
@@ -75,9 +75,9 @@ InternaliseM Result ensureResultExtShape msg loc rettype res = do res' <- ensureResultExtShapeNoCtx msg loc rettype res- ts <- mapM subExpType res'+ ts <- mapM subExpResType res' let ctx = extractShapeContext rettype $ map arrayDims ts- pure $ ctx ++ res'+ pure $ subExpsRes ctx ++ res' ensureResultExtShapeNoCtx :: ErrorMsg SubExp ->@@ -86,12 +86,12 @@ Result -> InternaliseM Result ensureResultExtShapeNoCtx msg loc rettype es = do- es_ts <- mapM subExpType es+ es_ts <- mapM subExpResType es let ext_mapping = shapeExtMapping rettype es_ts rettype' = foldr (uncurry fixExt) rettype $ M.toList ext_mapping- assertProperShape t se =+ assertProperShape t (SubExpRes cs se) = let name = "result_proper_shape"- in ensureExtShape msg loc t name se+ in SubExpRes cs <$> ensureExtShape msg loc t name se zipWithM assertProperShape rettype' es ensureExtShape ::
src/Futhark/Internalise/Bindings.hs view
@@ -6,7 +6,7 @@ ( bindingFParams, bindingLoopParams, bindingLambdaParams,- stmPattern,+ stmPat, ) where @@ -21,11 +21,11 @@ bindingFParams :: [E.TypeParam] ->- [E.Pattern] ->+ [E.Pat] -> ([I.FParam] -> [[I.FParam]] -> InternaliseM a) -> InternaliseM a bindingFParams tparams params m = do- flattened_params <- mapM flattenPattern params+ flattened_params <- mapM flattenPat params let params_idents = concat flattened_params params_ts <- internaliseParamTypes $@@ -35,7 +35,7 @@ let shape_params = [I.Param v $ I.Prim I.int64 | E.TypeParamDim v _ <- tparams] shape_subst = M.fromList [(I.paramName p, [I.Var $ I.paramName p]) | p <- shape_params]- bindingFlatPattern params_idents (concat params_ts) $ \valueparams -> do+ bindingFlatPat params_idents (concat params_ts) $ \valueparams -> do let (certparams, valueparams') = unzip $ map fixAccParam (concat valueparams) I.localScope (I.scopeOfFParams $ catMaybes certparams ++ shape_params ++ valueparams') $ substitutingVars shape_subst $@@ -49,45 +49,45 @@ bindingLoopParams :: [E.TypeParam] ->- E.Pattern ->+ E.Pat -> [I.Type] -> ([I.FParam] -> [I.FParam] -> InternaliseM a) -> InternaliseM a bindingLoopParams tparams pat ts m = do- pat_idents <- flattenPattern pat+ pat_idents <- flattenPat pat pat_ts <- internaliseLoopParamType (E.patternStructType pat) ts let shape_params = [I.Param v $ I.Prim I.int64 | E.TypeParamDim v _ <- tparams] shape_subst = M.fromList [(I.paramName p, [I.Var $ I.paramName p]) | p <- shape_params] - bindingFlatPattern pat_idents pat_ts $ \valueparams ->+ bindingFlatPat pat_idents pat_ts $ \valueparams -> I.localScope (I.scopeOfFParams $ shape_params ++ concat valueparams) $ substitutingVars shape_subst $ m shape_params $ concat valueparams bindingLambdaParams ::- [E.Pattern] ->+ [E.Pat] -> [I.Type] -> ([I.LParam] -> InternaliseM a) -> InternaliseM a bindingLambdaParams params ts m = do- params_idents <- concat <$> mapM flattenPattern params+ params_idents <- concat <$> mapM flattenPat params - bindingFlatPattern params_idents ts $ \params' ->+ bindingFlatPat params_idents ts $ \params' -> I.localScope (I.scopeOfLParams $ concat params') $ m $ concat params' -processFlatPattern ::+processFlatPat :: Show t => [E.Ident] -> [t] ->- InternaliseM ([[I.Param t]], VarSubstitutions)-processFlatPattern x y = processFlatPattern' [] x y+ InternaliseM ([[I.Param t]], VarSubsts)+processFlatPat x y = processFlatPat' [] x y where- processFlatPattern' pat [] _ = do+ processFlatPat' pat [] _ = do let (vs, substs) = unzip pat return (reverse vs, M.fromList substs)- processFlatPattern' pat (p : rest) ts = do+ processFlatPat' pat (p : rest) ts = do (ps, rest_ts) <- handleMapping ts <$> internaliseBindee p- processFlatPattern' ((ps, (E.identName p, map (I.Var . I.paramName) ps)) : pat) rest rest_ts+ processFlatPat' ((ps, (E.identName p, map (I.Var . I.paramName) ps)) : pat) rest rest_ts handleMapping ts [] = ([], ts)@@ -105,49 +105,49 @@ 1 -> return [name] _ -> replicateM n $ newVName $ baseString name -bindingFlatPattern ::+bindingFlatPat :: Show t => [E.Ident] -> [t] -> ([[I.Param t]] -> InternaliseM a) -> InternaliseM a-bindingFlatPattern idents ts m = do- (ps, substs) <- processFlatPattern idents ts+bindingFlatPat idents ts m = do+ (ps, substs) <- processFlatPat idents ts local (\env -> env {envSubsts = substs `M.union` envSubsts env}) $ m ps -- | Flatten a pattern. Returns a list of identifiers.-flattenPattern :: MonadFreshNames m => E.Pattern -> m [E.Ident]-flattenPattern = flattenPattern'+flattenPat :: MonadFreshNames m => E.Pat -> m [E.Ident]+flattenPat = flattenPat' where- flattenPattern' (E.PatternParens p _) =- flattenPattern' p- flattenPattern' (E.Wildcard t loc) = do+ flattenPat' (E.PatParens p _) =+ flattenPat' p+ flattenPat' (E.Wildcard t loc) = do name <- newVName "nameless"- flattenPattern' $ E.Id name t loc- flattenPattern' (E.Id v (Info t) loc) =+ flattenPat' $ E.Id name t loc+ flattenPat' (E.Id v (Info t) loc) = return [E.Ident v (Info t) loc] -- XXX: treat empty tuples and records as unit.- flattenPattern' (E.TuplePattern [] loc) =- flattenPattern' (E.Wildcard (Info $ E.Scalar $ E.Record mempty) loc)- flattenPattern' (E.RecordPattern [] loc) =- flattenPattern' (E.Wildcard (Info $ E.Scalar $ E.Record mempty) loc)- flattenPattern' (E.TuplePattern pats _) =- concat <$> mapM flattenPattern' pats- flattenPattern' (E.RecordPattern fs loc) =- flattenPattern' $ E.TuplePattern (map snd $ sortFields $ M.fromList fs) loc- flattenPattern' (E.PatternAscription p _ _) =- flattenPattern' p- flattenPattern' (E.PatternLit _ t loc) =- flattenPattern' $ E.Wildcard t loc- flattenPattern' (E.PatternConstr _ _ ps _) =- concat <$> mapM flattenPattern' ps+ flattenPat' (E.TuplePat [] loc) =+ flattenPat' (E.Wildcard (Info $ E.Scalar $ E.Record mempty) loc)+ flattenPat' (E.RecordPat [] loc) =+ flattenPat' (E.Wildcard (Info $ E.Scalar $ E.Record mempty) loc)+ flattenPat' (E.TuplePat pats _) =+ concat <$> mapM flattenPat' pats+ flattenPat' (E.RecordPat fs loc) =+ flattenPat' $ E.TuplePat (map snd $ sortFields $ M.fromList fs) loc+ flattenPat' (E.PatAscription p _ _) =+ flattenPat' p+ flattenPat' (E.PatLit _ t loc) =+ flattenPat' $ E.Wildcard t loc+ flattenPat' (E.PatConstr _ _ ps _) =+ concat <$> mapM flattenPat' ps -stmPattern ::- E.Pattern ->+stmPat ::+ E.Pat -> [I.Type] -> ([VName] -> InternaliseM a) -> InternaliseM a-stmPattern pat ts m = do- pat' <- flattenPattern pat- bindingFlatPattern pat' ts $ m . map I.paramName . concat+stmPat pat ts m = do+ pat' <- flattenPat pat+ bindingFlatPat pat' ts $ m . map I.paramName . concat
src/Futhark/Internalise/Defunctionalise.hs view
@@ -27,19 +27,19 @@ -- | An expression or an extended 'Lambda' (with size parameters, -- which AST lambdas do not support). data ExtExp- = ExtLambda [Pattern] Exp StructType SrcLoc+ = ExtLambda [Pat] Exp StructType SrcLoc | ExtExp Exp deriving (Show) -- | A static value stores additional information about the result of -- defunctionalization of an expression, aside from the residual expression. data StaticVal- = Dynamic PatternType- | LambdaSV Pattern StructType ExtExp Env+ = Dynamic PatType+ | LambdaSV Pat StructType ExtExp Env | RecordSV [(Name, StaticVal)] | -- | The constructor that is actually present, plus -- the others that are not.- SumSV Name [StaticVal] [(Name, [PatternType])]+ SumSV Name [StaticVal] [(Name, [PatType])] | -- | The pair is the StaticVal and residual expression of this -- function as a whole, while the second StaticVal is its -- body. (Don't trust this too much, my understanding may have@@ -120,7 +120,7 @@ where tv substs = identityMapper- { mapOnPatternType = pure . replaceTypeSizes substs,+ { mapOnPatType = pure . replaceTypeSizes substs, mapOnStructType = pure . replaceTypeSizes substs, mapOnExp = pure . onExp substs, mapOnName = pure . onName substs@@ -290,7 +290,7 @@ dimName (NamedDim qn) = S.singleton $ qualLeaf qn dimName _ = mempty -patternArraySizes :: Pattern -> S.Set VName+patternArraySizes :: Pat -> S.Set VName patternArraySizes = arraySizes . patternStructType data SizeSubst@@ -336,7 +336,7 @@ foldMap sizesToRename svs sizesToRename (LambdaSV param _ _ _) = patternDimNames param- <> S.map identName (S.filter couldBeSize $ patternIdents param)+ <> S.map identName (S.filter couldBeSize $ patIdents param) where couldBeSize ident = unInfo (identType ident) == Scalar (Prim (Signed Int64))@@ -375,7 +375,7 @@ defuncFun :: [VName] ->- [Pattern] ->+ [Pat] -> Exp -> StructType -> SrcLoc ->@@ -513,8 +513,8 @@ | otherwise = defuncExp e0 defuncExp (AppExp (LetPat sizes pat e1 e2 loc) (Info (AppRes t retext))) = do (e1', sv1) <- defuncExp e1- let env = matchPatternSV pat sv1- pat' = updatePattern pat sv1+ let env = matchPatSV pat sv1+ pat' = updatePat pat sv1 (e2', sv2) <- localEnv env $ defuncExp e2 -- To maintain any sizes going out of scope, we need to compute the -- old size substitution induced by retext and also apply it to the@@ -543,6 +543,9 @@ defuncExp (Negate e0 loc) = do (e0', sv) <- defuncExp e0 return (Negate e0' loc, sv)+defuncExp (Not e0 loc) = do+ (e0', sv) <- defuncExp e0+ return (Not e0' loc, sv) defuncExp (Lambda pats e0 _ (Info (_, ret)) loc) = defuncFun [] pats e0 ret loc -- Operator sections are expected to be converted to lambda-expressions@@ -554,14 +557,14 @@ defuncExp IndexSection {} = error "defuncExp: unexpected projection section." defuncExp (AppExp (DoLoop sparams pat e1 form e3 loc) res) = do (e1', sv1) <- defuncExp e1- let env1 = matchPatternSV pat sv1+ let env1 = matchPatSV pat sv1 (form', env2) <- case form of For v e2 -> do e2' <- defuncExp' e2 return (For v e2', envFromIdent v) ForIn pat2 e2 -> do e2' <- defuncExp' e2- return (ForIn pat2 e2', envFromPattern pat2)+ return (ForIn pat2 e2', envFromPat pat2) While e2 -> do e2' <- localEnv env1 $ defuncExp' e2 return (While e2', mempty)@@ -677,8 +680,8 @@ defuncCase :: StaticVal -> Case -> DefM (Case, StaticVal) defuncCase sv (CasePat p e loc) = do- let p' = updatePattern p sv- env = matchPatternSV p sv+ let p' = updatePat p sv+ env = matchPatSV p sv (e', sv') <- localEnv env $ defuncExp e return (CasePat p' e' loc, sv') @@ -692,18 +695,18 @@ defuncSoacExp (Parens e loc) = Parens <$> defuncSoacExp e <*> pure loc defuncSoacExp (Lambda params e0 decl tp loc) = do- let env = foldMap envFromPattern params+ let env = foldMap envFromPat params e0' <- localEnv env $ defuncSoacExp e0 return $ Lambda params e0' decl tp loc defuncSoacExp e | Scalar Arrow {} <- typeOf e = do (pats, body, tp) <- etaExpand (typeOf e) e- let env = foldMap envFromPattern pats+ let env = foldMap envFromPat pats body' <- localEnv env $ defuncExp' body return $ Lambda pats body' Nothing (Info (mempty, tp)) mempty | otherwise = defuncExp' e -etaExpand :: PatternType -> Exp -> DefM ([Pattern], Exp, StructType)+etaExpand :: PatType -> Exp -> DefM ([Pat], Exp, StructType) etaExpand e_t e = do let (ps, ret) = getType e_t (pats, vars) <- fmap unzip . forM ps $ \(p, t) -> do@@ -741,16 +744,16 @@ -- that have order 0 types (i.e., non-functional). defuncLet :: [VName] ->- [Pattern] ->+ [Pat] -> Exp -> StructType ->- DefM ([VName], [Pattern], Exp, StaticVal)+ DefM ([VName], [Pat], Exp, StaticVal) defuncLet dims ps@(pat : pats) body rettype | patternOrderZero pat = do let bound_by_pat = (`S.member` patternDimNames pat) -- Take care to not include more size parameters than necessary. (pat_dims, rest_dims) = partition bound_by_pat dims- env = envFromPattern pat <> envFromDimNames pat_dims+ env = envFromPat pat <> envFromDimNames pat_dims (rest_dims', pats', body', sv) <- localEnv env $ defuncLet rest_dims pats body rettype closure <- defuncFun dims ps body rettype mempty return@@ -772,13 +775,13 @@ RecordSV $ M.toList $ M.intersectionWith imposeType (M.fromList fs1) fs2 imposeType sv _ = sv -sizesForAll :: MonadFreshNames m => S.Set VName -> [Pattern] -> m ([VName], [Pattern])+sizesForAll :: MonadFreshNames m => S.Set VName -> [Pat] -> m ([VName], [Pat]) sizesForAll bound_sizes params = do (params', sizes) <- runStateT (mapM (astMap tv) params) mempty return (S.toList sizes, params') where- bound = bound_sizes <> foldMap patternNames params- tv = identityMapper {mapOnPatternType = bitraverse onDim pure}+ bound = bound_sizes <> foldMap patNames params+ tv = identityMapper {mapOnPatType = bitraverse onDim pure} onDim (AnyDim (Just v)) = do modify $ S.insert v pure $ NamedDim $ qualName v@@ -804,14 +807,14 @@ let e' = AppExp (Apply e1' e2' d loc) t case sv1 of LambdaSV pat e0_t e0 closure_env -> do- let env' = matchPatternSV pat sv2+ let env' = matchPatSV pat sv2 dims = mempty (e0', sv) <- localNewEnv (env' <> closure_env) $ defuncExtExp e0 - let closure_pat = buildEnvPattern dims closure_env- pat' = updatePattern pat sv2+ let closure_pat = buildEnvPat dims closure_env+ pat' = updatePat pat sv2 globals <- asks fst @@ -827,7 +830,7 @@ already_bound = globals <> S.fromList dims- <> S.map identName (foldMap patternIdents params)+ <> S.map identName (foldMap patIdents params) more_dims = S.toList $@@ -979,7 +982,7 @@ -- dimensions, a list of parameters, a function body, and the -- appropriate static value for applying the function at the given -- depth of partial application.-liftDynFun :: String -> StaticVal -> Int -> ([Pattern], Exp, StaticVal)+liftDynFun :: String -> StaticVal -> Int -> ([Pat], Exp, StaticVal) liftDynFun _ (DynamicFun (e, sv) _) 0 = ([], e, sv) liftDynFun s (DynamicFun clsr@(_, LambdaSV pat _ _ _) sv) d | d > 0 =@@ -995,16 +998,16 @@ -- | Converts a pattern to an environment that binds the individual names of the -- pattern to their corresponding types wrapped in a 'Dynamic' static value.-envFromPattern :: Pattern -> Env-envFromPattern pat = case pat of- TuplePattern ps _ -> foldMap envFromPattern ps- RecordPattern fs _ -> foldMap (envFromPattern . snd) fs- PatternParens p _ -> envFromPattern p+envFromPat :: Pat -> Env+envFromPat pat = case pat of+ TuplePat ps _ -> foldMap envFromPat ps+ RecordPat fs _ -> foldMap (envFromPat . snd) fs+ PatParens p _ -> envFromPat p Id vn (Info t) _ -> M.singleton vn $ Binding Nothing $ Dynamic t Wildcard _ _ -> mempty- PatternAscription p _ _ -> envFromPattern p- PatternLit {} -> mempty- PatternConstr _ _ ps _ -> foldMap envFromPattern ps+ PatAscription p _ _ -> envFromPat p+ PatLit {} -> mempty+ PatConstr _ _ ps _ -> foldMap envFromPat ps envFromDimNames :: [VName] -> Env envFromDimNames = M.fromList . flip zip (repeat d)@@ -1013,7 +1016,7 @@ -- | Create a new top-level value declaration with the given function name, -- return type, list of parameters, and body expression.-liftValDec :: VName -> PatternType -> [VName] -> [Pattern] -> Exp -> DefM ()+liftValDec :: VName -> PatType -> [VName] -> [Pat] -> Exp -> DefM () liftValDec fname rettype dims pats body = addValBind dec where dims' = map (`TypeParamDim` mempty) dims@@ -1021,7 +1024,7 @@ -- forget those return sizes that we forgot to propagate along -- the way. Hopefully the internaliser is conservative and -- will insert reshapes...- bound_here = S.fromList dims <> S.map identName (foldMap patternIdents pats)+ bound_here = S.fromList dims <> S.map identName (foldMap patIdents pats) anyDimIfNotBound (NamedDim v) | qualLeaf v `S.member` bound_here = NamedDim v | otherwise = AnyDim $ Just $ qualLeaf v@@ -1045,8 +1048,8 @@ -- | Given a closure environment, construct a record pattern that -- binds the closed over variables. Insert wildcard for any patterns -- that would otherwise clash with size parameters.-buildEnvPattern :: [VName] -> Env -> Pattern-buildEnvPattern sizes env = RecordPattern (map buildField $ M.toList env) mempty+buildEnvPat :: [VName] -> Env -> Pat+buildEnvPat sizes env = RecordPat (map buildField $ M.toList env) mempty where buildField (vn, Binding _ sv) = ( nameFromString (pretty vn),@@ -1062,14 +1065,14 @@ -- lifted function can create unique arrays as long as they do not -- alias any of its parameters. XXX: it is not clear that this is a -- sufficient property, unfortunately.-buildRetType :: Env -> [Pattern] -> StructType -> PatternType -> PatternType+buildRetType :: Env -> [Pat] -> StructType -> PatType -> PatType buildRetType env pats = comb where bound =- S.fromList (M.keys env) <> S.map identName (foldMap patternIdents pats)+ S.fromList (M.keys env) <> S.map identName (foldMap patIdents pats) boundAsUnique v = maybe False (unique . unInfo . identType) $- find ((== v) . identName) $ S.toList $ foldMap patternIdents pats+ find ((== v) . identName) $ S.toList $ foldMap patIdents pats problematic v = (v `S.member` bound) && not (boundAsUnique v) comb (Scalar (Record fs_annot)) (Scalar (Record fs_got)) = Scalar $ Record $ M.intersectionWith comb fs_annot fs_got@@ -1087,7 +1090,7 @@ -- | Compute the corresponding type for the *representation* of a -- given static value (not the original possibly higher-order value).-typeFromSV :: StaticVal -> PatternType+typeFromSV :: StaticVal -> PatType typeFromSV (Dynamic tp) = tp typeFromSV (LambdaSV _ _ _ env) =@@ -1107,7 +1110,7 @@ -- | Construct the type for a fully-applied dynamic function from its -- static value and the original types of its arguments.-dynamicFunType :: StaticVal -> [PatternType] -> ([PatternType], PatternType)+dynamicFunType :: StaticVal -> [PatType] -> ([PatType], PatType) dynamicFunType (DynamicFun _ sv) (p : ps) = let (ps', ret) = dynamicFunType sv ps in (p : ps', ret) dynamicFunType sv _ = ([], typeFromSV sv)@@ -1115,16 +1118,16 @@ -- | Match a pattern with its static value. Returns an environment with -- the identifier components of the pattern mapped to the corresponding -- subcomponents of the static value.-matchPatternSV :: PatternBase Info VName -> StaticVal -> Env-matchPatternSV (TuplePattern ps _) (RecordSV ls) =- mconcat $ zipWith (\p (_, sv) -> matchPatternSV p sv) ps ls-matchPatternSV (RecordPattern ps _) (RecordSV ls)+matchPatSV :: PatBase Info VName -> StaticVal -> Env+matchPatSV (TuplePat ps _) (RecordSV ls) =+ mconcat $ zipWith (\p (_, sv) -> matchPatSV p sv) ps ls+matchPatSV (RecordPat ps _) (RecordSV ls) | ps' <- sortOn fst ps, ls' <- sortOn fst ls, map fst ps' == map fst ls' =- mconcat $ zipWith (\(_, p) (_, sv) -> matchPatternSV p sv) ps' ls'-matchPatternSV (PatternParens pat _) sv = matchPatternSV pat sv-matchPatternSV (Id vn (Info t) _) sv =+ mconcat $ zipWith (\(_, p) (_, sv) -> matchPatSV p sv) ps' ls'+matchPatSV (PatParens pat _) sv = matchPatSV pat sv+matchPatSV (Id vn (Info t) _) sv = -- When matching a pattern with a zero-order STaticVal, the type of -- the pattern wins out. This is important when matching a -- nonunique pattern with a unique value.@@ -1135,23 +1138,23 @@ dim_env = M.fromList $ map (,i64) $ S.toList $ typeDimNames t i64 = Binding Nothing $ Dynamic $ Scalar $ Prim $ Signed Int64-matchPatternSV (Wildcard _ _) _ = mempty-matchPatternSV (PatternAscription pat _ _) sv = matchPatternSV pat sv-matchPatternSV PatternLit {} _ = mempty-matchPatternSV (PatternConstr c1 _ ps _) (SumSV c2 ls fs)+matchPatSV (Wildcard _ _) _ = mempty+matchPatSV (PatAscription pat _ _) sv = matchPatSV pat sv+matchPatSV PatLit {} _ = mempty+matchPatSV (PatConstr c1 _ ps _) (SumSV c2 ls fs) | c1 == c2 =- mconcat $ zipWith matchPatternSV ps ls+ mconcat $ zipWith matchPatSV ps ls | Just ts <- lookup c1 fs =- mconcat $ zipWith matchPatternSV ps $ map svFromType ts+ mconcat $ zipWith matchPatSV ps $ map svFromType ts | otherwise =- error $ "matchPatternSV: missing constructor in type: " ++ pretty c1-matchPatternSV (PatternConstr c1 _ ps _) (Dynamic (Scalar (Sum fs)))+ error $ "matchPatSV: missing constructor in type: " ++ pretty c1+matchPatSV (PatConstr c1 _ ps _) (Dynamic (Scalar (Sum fs))) | Just ts <- M.lookup c1 fs =- mconcat $ zipWith matchPatternSV ps $ map svFromType ts+ mconcat $ zipWith matchPatSV ps $ map svFromType ts | otherwise =- error $ "matchPatternSV: missing constructor in type: " ++ pretty c1-matchPatternSV pat (Dynamic t) = matchPatternSV pat $ svFromType t-matchPatternSV pat sv =+ error $ "matchPatSV: missing constructor in type: " ++ pretty c1+matchPatSV pat (Dynamic t) = matchPatSV pat $ svFromType t+matchPatSV pat sv = error $ "Tried to match pattern " ++ pretty pat ++ " with static value "@@ -1165,18 +1168,18 @@ -- | Given a pattern and the static value for the defunctionalized argument, -- update the pattern to reflect the changes in the types.-updatePattern :: Pattern -> StaticVal -> Pattern-updatePattern (TuplePattern ps loc) (RecordSV svs) =- TuplePattern (zipWith updatePattern ps $ map snd svs) loc-updatePattern (RecordPattern ps loc) (RecordSV svs)+updatePat :: Pat -> StaticVal -> Pat+updatePat (TuplePat ps loc) (RecordSV svs) =+ TuplePat (zipWith updatePat ps $ map snd svs) loc+updatePat (RecordPat ps loc) (RecordSV svs) | ps' <- sortOn fst ps, svs' <- sortOn fst svs =- RecordPattern- (zipWith (\(n, p) (_, sv) -> (n, updatePattern p sv)) ps' svs')+ RecordPat+ (zipWith (\(n, p) (_, sv) -> (n, updatePat p sv)) ps' svs') loc-updatePattern (PatternParens pat loc) sv =- PatternParens (updatePattern pat sv) loc-updatePattern (Id vn (Info tp) loc) sv =+updatePat (PatParens pat loc) sv =+ PatParens (updatePat pat sv) loc+updatePat (Id vn (Info tp) loc) sv = Id vn (Info $ comb tp (typeFromSV sv `setUniqueness` Nonunique)) loc where -- Preserve any original zeroth-order types.@@ -1186,24 +1189,24 @@ comb (Scalar (Sum m1)) (Scalar (Sum m2)) = Scalar $ Sum $ M.intersectionWith (zipWith comb) m1 m2 comb t1 _ = t1 -- t1 must be array or prim.-updatePattern pat@(Wildcard (Info tp) loc) sv+updatePat pat@(Wildcard (Info tp) loc) sv | orderZero tp = pat | otherwise = Wildcard (Info $ typeFromSV sv) loc-updatePattern (PatternAscription pat tydecl loc) sv+updatePat (PatAscription pat tydecl loc) sv | orderZero . unInfo $ expandedType tydecl =- PatternAscription (updatePattern pat sv) tydecl loc- | otherwise = updatePattern pat sv-updatePattern p@PatternLit {} _ = p-updatePattern pat@(PatternConstr c1 (Info t) ps loc) sv@(SumSV _ svs _)+ PatAscription (updatePat pat sv) tydecl loc+ | otherwise = updatePat pat sv+updatePat p@PatLit {} _ = p+updatePat pat@(PatConstr c1 (Info t) ps loc) sv@(SumSV _ svs _) | orderZero t = pat- | otherwise = PatternConstr c1 (Info t') ps' loc+ | otherwise = PatConstr c1 (Info t') ps' loc where t' = typeFromSV sv `setUniqueness` Nonunique- ps' = zipWith updatePattern ps svs-updatePattern (PatternConstr c1 _ ps loc) (Dynamic t) =- PatternConstr c1 (Info t) ps loc-updatePattern pat (Dynamic t) = updatePattern pat (svFromType t)-updatePattern pat sv =+ ps' = zipWith updatePat ps svs+updatePat (PatConstr c1 _ ps loc) (Dynamic t) =+ PatConstr c1 (Info t) ps loc+updatePat pat (Dynamic t) = updatePat pat (svFromType t)+updatePat pat sv = error $ "Tried to update pattern " ++ pretty pat ++ "to reflect the static value "@@ -1211,7 +1214,7 @@ -- | Convert a record (or tuple) type to a record static value. This is used for -- "unwrapping" tuples and records that are nested in 'Dynamic' static values.-svFromType :: PatternType -> StaticVal+svFromType :: PatType -> StaticVal svFromType (Scalar (Record fs)) = RecordSV . M.toList $ M.map svFromType fs svFromType t = Dynamic t @@ -1244,7 +1247,7 @@ (tparams', params', body', sv) <- defuncLet (map typeParamName tparams) params body rettype globals <- asks fst- let bound_sizes = foldMap patternNames params' <> S.fromList tparams' <> globals+ let bound_sizes = foldMap patNames params' <> S.fromList tparams' <> globals rettype' = -- FIXME: dubious that we cannot assume that all sizes in the -- body are in scope. This is because when we insert
src/Futhark/Internalise/Defunctorise.hs view
@@ -169,10 +169,8 @@ -- we need to make them visible, because substitutions involving -- abstract types must be lifted out in transformModBind. let subst_abs =- S.fromList $- map snd $- filter ((`S.member` abs) . fst) $- M.toList ascript_substs+ S.fromList . map snd . filter ((`S.member` abs) . fst) $+ M.toList ascript_substs bindingAbs subst_abs m evalModExp :: ModExp -> TransformM Mod@@ -254,7 +252,7 @@ mapOnQualName = \v -> return $ fst $ lookupSubstInScope v scope, mapOnStructType = astMap (substituter scope),- mapOnPatternType = astMap (substituter scope)+ mapOnPatType = astMap (substituter scope) } onExp scope e = -- One expression is tricky, because it interacts with scoping rules.
src/Futhark/Internalise/Exps.hs view
@@ -4,6 +4,8 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} +-- | Conversion of a monomorphic, first-order, defunctorised source+-- program to a core Futhark program. module Futhark.Internalise.Exps (transformProg) where import Control.Monad.Reader@@ -11,7 +13,7 @@ import qualified Data.List.NonEmpty as NE import qualified Data.Map.Strict as M import qualified Data.Set as S-import Futhark.IR.SOACS as I hiding (stmPattern)+import Futhark.IR.SOACS as I hiding (stmPat) import Futhark.Internalise.AccurateSizes import Futhark.Internalise.Bindings import Futhark.Internalise.Lambdas@@ -58,12 +60,14 @@ (body', rettype') <- buildBody $ do body_res <- internaliseExp (baseString fname <> "_res") body- rettype_bad <-- internaliseReturnType rettype =<< mapM subExpType body_res- let rettype' = zeroExts rettype_bad+ rettype' <-+ fmap zeroExts . internaliseReturnType rettype =<< mapM subExpType body_res body_res' <-- ensureResultExtShape msg loc (map I.fromDecl rettype') body_res- pure (body_res', rettype')+ ensureResultExtShape msg loc (map I.fromDecl rettype') $ subExpsRes body_res+ pure+ ( body_res',+ replicate (length (shapeContext rettype')) (I.Prim int64) ++ rettype'+ ) let all_params = shapeparams ++ concat params' @@ -102,7 +106,7 @@ let entry' = entryPoint (baseName ofname) (zip e_paramts params') (e_rettype, entry_rettype) args = map (I.Var . I.paramName) $ concat params' - entry_body <- buildBody_ $ do+ (entry_body, ctx_ts) <- buildBody $ do -- Special case the (rare) situation where the entry point is -- not a function. maybe_const <- lookupConst ofname@@ -114,14 +118,14 @@ ctx <- extractShapeContext (concat entry_rettype) <$> mapM (fmap I.arrayDims . subExpType) vals- pure $ ctx ++ vals+ pure (subExpsRes $ ctx ++ vals, map (const (I.Prim int64)) ctx) addFunDef $ I.FunDef (Just entry') (internaliseAttrs attrs) ("entry_" <> baseName ofname)- (concat entry_rettype)+ (ctx_ts ++ concat entry_rettype) (shapeparams ++ concat params') entry_body @@ -182,7 +186,7 @@ internaliseBody :: String -> E.Exp -> InternaliseM Body internaliseBody desc e =- buildBody_ $ internaliseExp (desc <> "_res") e+ buildBody_ $ subExpsRes <$> internaliseExp (desc <> "_res") e bodyFromStms :: InternaliseM (Result, a) ->@@ -221,17 +225,17 @@ let errmsg = errorMsg $ ["Range "]- ++ [ErrorInt64 start'_i64]+ ++ [ErrorVal int64 start'_i64] ++ ( case maybe_second'_i64 of Nothing -> []- Just second_i64 -> ["..", ErrorInt64 second_i64]+ Just second_i64 -> ["..", ErrorVal int64 second_i64] ) ++ ( case end of DownToExclusive {} -> ["..>"] ToInclusive {} -> ["..."] UpToExclusive {} -> ["..<"] )- ++ [ErrorInt64 end'_i64, " is invalid."]+ ++ [ErrorVal int64 end'_i64, " is invalid."] (it, le_op, lt_op) <- case E.typeOf start of@@ -348,7 +352,7 @@ dims <- arrayDims <$> subExpType e' let parts = ["Value of (core language) shape ("]- ++ intersperse ", " (map ErrorInt64 dims)+ ++ intersperse ", " (map (ErrorVal int64) dims) ++ [") cannot match shape of type `"] ++ dt' ++ ["`."]@@ -375,12 +379,7 @@ let tag ses = [(se, I.Observe) | se <- ses] args' <- reverse <$> mapM (internaliseArg arg_desc) (reverse args) let args'' = concatMap tag args'- letTupExp' desc $- I.Apply- fname- args''- [I.Prim rettype]- (Safe, loc, [])+ letTupExp' desc $ I.Apply fname args'' [I.Prim rettype] (Safe, loc, []) | otherwise -> do args' <- concat . reverse <$> mapM (internaliseArg arg_desc) (reverse args) fst <$> funcall desc qfname args' loc@@ -414,18 +413,20 @@ merge_ts = map (I.paramType . fst) merge loopbody'' <- localScope (scopeOfFParams $ map fst merge) . inScopeOf form' . buildBody_ $- ensureArgShapes- "shape of loop result does not match shapes in loop parameter"- loc- (map (I.paramName . fst) ctxmerge)- merge_ts+ fmap subExpsRes+ . ensureArgShapes+ "shape of loop result does not match shapes in loop parameter"+ loc+ (map (I.paramName . fst) ctxmerge)+ merge_ts+ . map resSubExp =<< bodyBind loopbody' attrs <- asks envAttrs map I.Var . dropCond <$> attributing attrs- (letTupExp desc (I.DoLoop ctxmerge valmerge form' loopbody''))+ (letTupExp desc (I.DoLoop (ctxmerge <> valmerge) form' loopbody'')) where sparams' = map (`TypeParamDim` mempty) sparams @@ -436,7 +437,7 @@ sets <- mapM subExpType ses shapeargs <- argShapes (map I.paramName shapepat) mergepat' sets return- ( shapeargs ++ ses,+ ( subExpsRes $ shapeargs ++ ses, ( form', shapepat, mergepat',@@ -518,11 +519,11 @@ | not $ primType $ paramType p -> Reshape (map DimCoercion $ arrayDims $ paramType p) v _ -> SubExp se- internaliseExp "loop_cond" cond+ subExpsRes <$> internaliseExp "loop_cond" cond loop_end_cond <- bodyBind loop_end_cond_body return- ( shapeargs ++ loop_end_cond ++ ses,+ ( subExpsRes shapeargs ++ loop_end_cond ++ subExpsRes ses, ( I.WhileLoop $ I.paramName loop_while, shapepat, loop_while : mergepat',@@ -670,6 +671,16 @@ I.Prim (I.FloatType t) -> letTupExp' desc $ I.BasicOp $ I.BinOp (I.FSub t) (I.floatConst t 0) e' _ -> error "Futhark.Internalise.internaliseExp: non-numeric type in Negate"+internaliseExp desc (E.Not e _) = do+ e' <- internaliseExp1 "not_arg" e+ et <- subExpType e'+ case et of+ I.Prim (I.IntType t) ->+ letTupExp' desc $ I.BasicOp $ I.UnOp (I.Complement t) e'+ I.Prim I.Bool ->+ letTupExp' desc $ I.BasicOp $ I.UnOp I.Not e'+ _ ->+ error "Futhark.Internalise.internaliseExp: non-int/bool type in Not" internaliseExp desc (E.Update src slice ve loc) = do ves <- internaliseExp "lw_val" ve srcs <- internaliseExpToVars "src" src@@ -707,16 +718,27 @@ src'' <- replace t fs ve' to_update return $ bef ++ src'' ++ aft replace _ _ ve' _ = return ve'-internaliseExp desc (E.Attr attr e _) =- local f $ internaliseExp desc e+internaliseExp desc (E.Attr attr e loc) = do+ e' <- local f $ internaliseExp desc e+ case attr' of+ "trace" ->+ traceRes (locStr loc) e'+ I.AttrComp "trace" [I.AttrAtom tag] ->+ traceRes (nameToString tag) e'+ "opaque" ->+ mapM (letSubExp desc . BasicOp . Opaque OpaqueNil) e'+ _ ->+ pure e' where- attrs = oneAttr $ internaliseAttr attr+ traceRes tag' e' =+ mapM (letSubExp desc . BasicOp . Opaque (OpaqueTrace tag')) e'+ attr' = internaliseAttr attr f env- | "unsafe" `inAttrs` attrs,+ | attr' == "unsafe", not $ envSafe env = env {envDoBoundsChecks = False} | otherwise =- env {envAttrs = envAttrs env <> attrs}+ env {envAttrs = envAttrs env <> oneAttr attr'} internaliseExp desc (E.Assert e1 e2 (Info check) loc) = do e1' <- internaliseExp1 "assert_cond" e1 c <- assert "assert_c" e1' (errorMsg [ErrorString $ "Assertion is false: " <> check]) loc@@ -794,23 +816,28 @@ internaliseArg :: String -> (E.Exp, Maybe VName) -> InternaliseM [SubExp] internaliseArg desc (arg, argdim) = do- arg' <- internaliseExp desc arg- case (arg', argdim) of- ([se], Just d) -> letBindNames [d] $ BasicOp $ SubExp se- _ -> return ()- return arg'+ exists <- askScope+ case argdim of+ Just d | d `M.member` exists -> pure [I.Var d]+ _ -> do+ arg' <- internaliseExp desc arg+ case (arg', argdim) of+ ([se], Just d) -> do+ letBindNames [d] $ BasicOp $ SubExp se+ _ -> return ()+ pure arg' subExpPrimType :: I.SubExp -> InternaliseM I.PrimType subExpPrimType = fmap I.elemType . subExpType -generateCond :: E.Pattern -> [I.SubExp] -> InternaliseM (I.SubExp, [I.SubExp])+generateCond :: E.Pat -> [I.SubExp] -> InternaliseM (I.SubExp, [I.SubExp]) generateCond orig_p orig_ses = do (cmps, pertinent, _) <- compares orig_p orig_ses cmp <- letSubExp "matches" =<< eAll cmps return (cmp, pertinent) where -- Literals are always primitive values.- compares (E.PatternLit l t _) (se : ses) = do+ compares (E.PatLit l t _) (se : ses) = do e' <- case l of PatLitPrim v -> pure $ constant $ internalisePrimValue v PatLitInt x -> internaliseExp1 "constant" $ E.IntLit x t mempty@@ -818,7 +845,7 @@ t' <- subExpPrimType se cmp <- letSubExp "match_lit" $ I.BasicOp $ I.CmpOp (I.CmpEq t') e' se return ([cmp], [se], ses)- compares (E.PatternConstr c (Info (E.Scalar (E.Sum fs))) pats _) (se : ses) = do+ compares (E.PatConstr c (Info (E.Scalar (E.Sum fs))) pats _) (se : ses) = do (payload_ts, m) <- internaliseSumType $ M.map (map toStruct) fs case M.lookup c m of Just (i, payload_is) -> do@@ -829,26 +856,26 @@ return (cmp : cmps, pertinent, ses') Nothing -> error "generateCond: missing constructor"- compares (E.PatternConstr _ (Info t) _ _) _ =- error $ "generateCond: PatternConstr has nonsensical type: " ++ pretty t+ compares (E.PatConstr _ (Info t) _ _) _ =+ error $ "generateCond: PatConstr has nonsensical type: " ++ pretty t compares (E.Id _ t loc) ses = compares (E.Wildcard t loc) ses compares (E.Wildcard (Info t) _) ses = do n <- internalisedTypeSize $ E.toStruct t let (id_ses, rest_ses) = splitAt n ses return ([], id_ses, rest_ses)- compares (E.PatternParens pat _) ses =+ compares (E.PatParens pat _) ses = compares pat ses -- XXX: treat empty tuples and records as bool.- compares (E.TuplePattern [] loc) ses =+ compares (E.TuplePat [] loc) ses = compares (E.Wildcard (Info $ E.Scalar $ E.Prim E.Bool) loc) ses- compares (E.RecordPattern [] loc) ses =+ compares (E.RecordPat [] loc) ses = compares (E.Wildcard (Info $ E.Scalar $ E.Prim E.Bool) loc) ses- compares (E.TuplePattern pats _) ses =+ compares (E.TuplePat pats _) ses = comparesMany pats ses- compares (E.RecordPattern fs _) ses =+ compares (E.RecordPat fs _) ses = comparesMany (map snd $ E.sortFields $ M.fromList fs) ses- compares (E.PatternAscription pat _ _) ses =+ compares (E.PatAscription pat _ _) ses = compares pat ses compares pat [] = error $ "generateCond: No values left for pattern " ++ pretty pat@@ -872,7 +899,7 @@ internalisePat :: String -> [E.SizeBinder VName] ->- E.Pattern ->+ E.Pat -> E.Exp -> E.Exp -> (E.Exp -> InternaliseM a) ->@@ -881,20 +908,20 @@ ses <- internaliseExp desc' e internalisePat' sizes p ses body m where- desc' = case S.toList $ E.patternIdents p of+ desc' = case S.toList $ E.patIdents p of [v] -> baseString $ E.identName v _ -> desc internalisePat' :: [E.SizeBinder VName] ->- E.Pattern ->+ E.Pat -> [I.SubExp] -> E.Exp -> (E.Exp -> InternaliseM a) -> InternaliseM a internalisePat' sizes p ses body m = do ses_ts <- mapM subExpType ses- stmPattern p ses_ts $ \pat_names -> do+ stmPat p ses_ts $ \pat_names -> do bindExtSizes (AppRes (E.patternType p) (map E.sizeName sizes)) ses forM_ (zip pat_names ses) $ \(v, se) -> letBindNames [v] $ I.BasicOp $ I.SubExp se@@ -904,7 +931,7 @@ SrcLoc -> [SubExp] -> [E.DimIndex] ->- InternaliseM ([I.DimIndex SubExp], Certificates)+ InternaliseM ([I.DimIndex SubExp], Certs) internaliseSlice loc dims idxs = do (idxs', oks, parts) <- unzip3 <$> zipWithM internaliseDimIndex dims idxs ok <- letSubExp "index_ok" =<< eAll oks@@ -912,7 +939,7 @@ errorMsg $ ["Index ["] ++ intercalate [", "] parts ++ ["] out of bounds for array of shape ["]- ++ intersperse "][" (map ErrorInt64 $ take (length idxs) dims)+ ++ intersperse "][" (map (ErrorVal int64) $ take (length idxs) dims) ++ ["]."] c <- assert "index_certs" ok msg loc return (idxs', c)@@ -930,7 +957,7 @@ I.BasicOp $ I.CmpOp (I.CmpSlt I.Int64) i' w ok <- letSubExp "bounds_check" =<< eBinOp I.LogAnd (pure lowerBound) (pure upperBound)- return (I.DimFix i', ok, [ErrorInt64 i'])+ return (I.DimFix i', ok, [ErrorVal int64 i']) -- Special-case an important common case that otherwise leads to horrible code. internaliseDimIndex@@ -986,7 +1013,7 @@ n <- letSubExp "n" =<< divRounding (toExp j_m_i) (toExp s') zero_stride <- letSubExp "zero_stride" $ I.BasicOp $ I.CmpOp (CmpEq int64) s_sign zero- nonzero_stride <- letSubExp "nonzero_stride" $ I.BasicOp $ I.UnOp Not zero_stride+ nonzero_stride <- letSubExp "nonzero_stride" $ I.BasicOp $ I.UnOp I.Not zero_stride -- Bounds checks depend on whether we are slicing forwards or -- backwards. If forwards, we must check '0 <= i && i <= j'. If@@ -1038,20 +1065,20 @@ let parts = case (i, j, s) of (_, _, Just {}) ->- [ maybe "" (const $ ErrorInt64 i') i,+ [ maybe "" (const $ ErrorVal int64 i') i, ":",- maybe "" (const $ ErrorInt64 j') j,+ maybe "" (const $ ErrorVal int64 j') j, ":",- ErrorInt64 s'+ ErrorVal int64 s' ] (_, Just {}, _) ->- [ maybe "" (const $ ErrorInt64 i') i,+ [ maybe "" (const $ ErrorVal int64 i') i, ":",- ErrorInt64 j'+ ErrorVal int64 j' ]- ++ maybe mempty (const [":", ErrorInt64 s']) s+ ++ maybe mempty (const [":", ErrorVal int64 s']) s (_, Nothing, Nothing) ->- [ErrorInt64 i', ":"]+ [ErrorVal int64 i', ":"] return (I.DimSlice i' n s', acceptable, parts) where zero = constant (0 :: Int64)@@ -1119,7 +1146,7 @@ img_params <- mapM (newParam "img_p" . rowType) =<< mapM lookupType img' let params = bucket_param : img_params rettype = I.Prim int64 : ne_ts- body = mkBody mempty $ map (I.Var . paramName) params+ body = mkBody mempty $ varsRes $ map paramName params lam' <- mkLambda params $ ensureResultShape@@ -1191,7 +1218,7 @@ I.arrayDims $ I.paramType p nes <- bodyBind =<< renameBody lam_body - nes_ts <- mapM I.subExpType nes+ nes_ts <- mapM I.subExpResType nes outsz <- arraysSize 0 <$> mapM lookupType arrs let acc_arr_tps = [I.arrayOf t (I.Shape [outsz]) NoUniqueness | t <- nes_ts] lam0' <- internaliseFoldLambda internaliseLambda lam0 nes_ts acc_arr_tps@@ -1212,7 +1239,7 @@ (srclocOf lam) [] (map I.typeOf $ I.lambdaParams lam0')- lam_res+ (map resSubExp lam_res) ensureResultShape "shape of result does not match shape of initial value" (srclocOf lam0)@@ -1223,7 +1250,7 @@ let form = I.Parallel o comm lam0' w <- arraysSize 0 <$> mapM lookupType arrs- letTupExp' desc $ I.Op $ I.Stream w arrs form nes lam'+ letTupExp' desc $ I.Op $ I.Stream w arrs form (map resSubExp nes) lam' internaliseStreamAcc :: String ->@@ -1246,7 +1273,8 @@ internaliseMapLambda internaliseLambda lam $ map I.Var $ paramName acc_p : bs' w <- arraysSize 0 <$> mapM lookupType bs'- letTupExp' "acc_res" $ I.Op $ I.Screma w (paramName acc_p : bs') (I.mapSOAC lam')+ fmap subExpsRes . letTupExp' "acc_res" $+ I.Op $ I.Screma w (paramName acc_p : bs') (I.mapSOAC lam') op' <- case op of@@ -1308,7 +1336,7 @@ letSubExp "zero" $ I.BasicOp $ CmpOp (CmpEq (IntType t)) x (intConst t 0)- nonzero <- letSubExp "nonzero" $ I.BasicOp $ UnOp Not zero+ nonzero <- letSubExp "nonzero" $ I.BasicOp $ UnOp I.Not zero c <- assert "nonzero_cert" nonzero "division by zero" loc certifying c m @@ -1493,7 +1521,7 @@ bodyExtType :: Body -> InternaliseM [ExtType] bodyExtType (Body _ stms res) = existentialiseExtTypes (M.keys stmsscope) . staticShapes- <$> extendedScope (traverse subExpType res) stmsscope+ <$> extendedScope (traverse subExpResType res) stmsscope where stmsscope = scopeOf stms @@ -1592,7 +1620,7 @@ dims_match <- forM (zip x_dims y_dims) $ \(x_dim, y_dim) -> letSubExp "dim_eq" $ I.BasicOp $ I.CmpOp (I.CmpEq int64) x_dim y_dim shapes_match <- letSubExp "shapes_match" =<< eAll dims_match- compare_elems_body <- runBodyBinder $ do+ compare_elems_body <- runBodyBuilder $ do -- Flatten both x and y. x_num_elems <- letSubExp "x_num_elems"@@ -1686,9 +1714,6 @@ fmap pure $ letSubExp desc $ BasicOp $ UpdateAcc acc' [i'] vs handleAccs _ _ = Nothing - handleRest [x] "!" = Just $ complementF x- handleRest [x] "opaque" = Just $ \desc ->- mapM (letSubExp desc . BasicOp . Opaque) =<< internaliseExp "opaque_arg" x handleRest [E.TupLit [a, si, v] _] "scatter" = Just $ scatterF 1 a si v handleRest [E.TupLit [a, si, v] _] "scatter_2d" = Just $ scatterF 2 a si v handleRest [E.TupLit [a, si, v] _] "scatter_3d" = Just $ scatterF 3 a si v@@ -1760,8 +1785,18 @@ <*> internaliseExpToVars (desc ++ "_zip_y") y ) handleRest [x] "unzip" = Just $ flip internaliseExp x- handleRest [x] "trace" = Just $ flip internaliseExp x- handleRest [x] "break" = Just $ flip internaliseExp x+ handleRest [TupLit [arr, offset, n1, s1, n2, s2] _] "flat_index_2d" = Just $ \desc -> do+ flatIndexHelper desc loc arr offset [(n1, s1), (n2, s2)]+ handleRest [TupLit [arr1, offset, s1, s2, arr2] _] "flat_update_2d" = Just $ \desc -> do+ flatUpdateHelper desc loc arr1 offset [s1, s2] arr2+ handleRest [TupLit [arr, offset, n1, s1, n2, s2, n3, s3] _] "flat_index_3d" = Just $ \desc -> do+ flatIndexHelper desc loc arr offset [(n1, s1), (n2, s2), (n3, s3)]+ handleRest [TupLit [arr1, offset, s1, s2, s3, arr2] _] "flat_update_3d" = Just $ \desc -> do+ flatUpdateHelper desc loc arr1 offset [s1, s2, s3] arr2+ handleRest [TupLit [arr, offset, n1, s1, n2, s2, n3, s3, n4, s4] _] "flat_index_4d" = Just $ \desc -> do+ flatIndexHelper desc loc arr offset [(n1, s1), (n2, s2), (n3, s3), (n4, s4)]+ handleRest [TupLit [arr1, offset, s1, s2, s3, s4, arr2] _] "flat_update_4d" = Just $ \desc -> do+ flatUpdateHelper desc loc arr1 offset [s1, s2, s3, s4] arr2 handleRest _ _ = Nothing toSigned int_to e desc = do@@ -1800,17 +1835,6 @@ letTupExp' desc $ I.BasicOp $ I.ConvOp (I.FPToUI float_from int_to) e' _ -> error "Futhark.Internalise.internaliseExp: non-numeric type in ToUnsigned" - complementF e desc = do- e' <- internaliseExp1 "complement_arg" e- et <- subExpType e'- case et of- I.Prim (I.IntType t) ->- letTupExp' desc $ I.BasicOp $ I.UnOp (I.Complement t) e'- I.Prim I.Bool ->- letTupExp' desc $ I.BasicOp $ I.UnOp I.Not e'- _ ->- error "Futhark.Internalise.internaliseExp: non-int/bool type in Complement"- scatterF dim a si v desc = do si' <- internaliseExpToVars "write_arg_i" si svs <- internaliseExpToVars "write_arg_v" v@@ -1859,7 +1883,7 @@ "scatter value has wrong size" loc bodyTypes- results+ (subExpsRes results) let lam = I.Lambda@@ -1872,6 +1896,100 @@ let sa_ws = map (Shape . take dim . arrayDims) sa_ts letTupExp' desc $ I.Op $ I.Scatter si_w lam sivs $ zip3 sa_ws (repeat 1) sas +flatIndexHelper :: String -> SrcLoc -> E.Exp -> E.Exp -> [(E.Exp, E.Exp)] -> InternaliseM [SubExp]+flatIndexHelper desc loc arr offset slices = do+ arrs <- internaliseExpToVars "arr" arr+ offset' <- internaliseExp1 "offset" offset+ old_dim <- I.arraysSize 0 <$> mapM lookupType arrs+ offset_inbounds_down <- letSubExp "offset_inbounds_down" $ I.BasicOp $ I.CmpOp (I.CmpUle Int64) (intConst Int64 0) offset'+ offset_inbounds_up <- letSubExp "offset_inbounds_up" $ I.BasicOp $ I.CmpOp (I.CmpUlt Int64) offset' old_dim+ slices' <-+ mapM+ ( \(n, s) -> do+ n' <- internaliseExp1 "n" n+ s' <- internaliseExp1 "s" s+ return (n', s')+ )+ slices+ (min_bound, max_bound) <-+ foldM+ ( \(lower, upper) (n, s) -> do+ n_m1 <- letSubExp "span" $ I.BasicOp $ I.BinOp (I.Sub Int64 I.OverflowUndef) n (intConst Int64 1)+ spn <- letSubExp "span" $ I.BasicOp $ I.BinOp (I.Mul Int64 I.OverflowUndef) n_m1 s++ span_and_lower <- letSubExp "span_and_lower" $ I.BasicOp $ I.BinOp (I.Add Int64 I.OverflowUndef) spn lower+ span_and_upper <- letSubExp "span_and_upper" $ I.BasicOp $ I.BinOp (I.Add Int64 I.OverflowUndef) spn upper++ lower' <- letSubExp "minimum" $ I.BasicOp $ I.BinOp (I.UMin Int64) span_and_lower lower+ upper' <- letSubExp "maximum" $ I.BasicOp $ I.BinOp (I.UMax Int64) span_and_upper upper++ return (lower', upper')+ )+ (offset', offset')+ slices'+ min_in_bounds <- letSubExp "min_in_bounds" $ I.BasicOp $ I.CmpOp (I.CmpUle Int64) (intConst Int64 0) min_bound+ max_in_bounds <- letSubExp "max_in_bounds" $ I.BasicOp $ I.CmpOp (I.CmpUlt Int64) max_bound old_dim++ all_bounds <-+ foldM+ (\x y -> letSubExp "inBounds" $ I.BasicOp $ I.BinOp I.LogAnd x y)+ offset_inbounds_down+ [offset_inbounds_up, min_in_bounds, max_in_bounds]++ c <- assert "bounds_cert" all_bounds (ErrorMsg [ErrorString $ "Flat slice out of bounds: " ++ pretty old_dim ++ " and " ++ pretty slices']) loc+ let slice = I.FlatSlice offset' $ map (uncurry FlatDimIndex) slices'+ certifying c $+ forM arrs $ \arr' ->+ letSubExp desc $ I.BasicOp $ I.FlatIndex arr' slice++flatUpdateHelper :: String -> SrcLoc -> E.Exp -> E.Exp -> [E.Exp] -> E.Exp -> InternaliseM [SubExp]+flatUpdateHelper desc loc arr1 offset slices arr2 = do+ arrs1 <- internaliseExpToVars "arr" arr1+ offset' <- internaliseExp1 "offset" offset+ old_dim <- I.arraysSize 0 <$> mapM lookupType arrs1+ offset_inbounds_down <- letSubExp "offset_inbounds_down" $ I.BasicOp $ I.CmpOp (I.CmpUle Int64) (intConst Int64 0) offset'+ offset_inbounds_up <- letSubExp "offset_inbounds_up" $ I.BasicOp $ I.CmpOp (I.CmpUlt Int64) offset' old_dim+ arrs2 <- internaliseExpToVars "arr" arr2+ ts <- mapM lookupType arrs2+ slices' <-+ mapM+ ( \(s, i) -> do+ s' <- internaliseExp1 "s" s+ let n = arraysSize i ts+ return (n, s')+ )+ $ zip slices [0 ..]+ (min_bound, max_bound) <-+ foldM+ ( \(lower, upper) (n, s) -> do+ n_m1 <- letSubExp "span" $ I.BasicOp $ I.BinOp (I.Sub Int64 I.OverflowUndef) n (intConst Int64 1)+ spn <- letSubExp "span" $ I.BasicOp $ I.BinOp (I.Mul Int64 I.OverflowUndef) n_m1 s++ span_and_lower <- letSubExp "span_and_lower" $ I.BasicOp $ I.BinOp (I.Add Int64 I.OverflowUndef) spn lower+ span_and_upper <- letSubExp "span_and_upper" $ I.BasicOp $ I.BinOp (I.Add Int64 I.OverflowUndef) spn upper++ lower' <- letSubExp "minimum" $ I.BasicOp $ I.BinOp (I.UMin Int64) span_and_lower lower+ upper' <- letSubExp "maximum" $ I.BasicOp $ I.BinOp (I.UMax Int64) span_and_upper upper++ return (lower', upper')+ )+ (offset', offset')+ slices'+ min_in_bounds <- letSubExp "min_in_bounds" $ I.BasicOp $ I.CmpOp (I.CmpUle Int64) (intConst Int64 0) min_bound+ max_in_bounds <- letSubExp "max_in_bounds" $ I.BasicOp $ I.CmpOp (I.CmpUlt Int64) max_bound old_dim++ all_bounds <-+ foldM+ (\x y -> letSubExp "inBounds" $ I.BasicOp $ I.BinOp I.LogAnd x y)+ offset_inbounds_down+ [offset_inbounds_up, min_in_bounds, max_in_bounds]++ c <- assert "bounds_cert" all_bounds (ErrorMsg [ErrorString $ "Flat slice out of bounds: " ++ pretty old_dim ++ " and " ++ pretty slices']) loc+ let slice = I.FlatSlice offset' $ map (uncurry FlatDimIndex) slices'+ certifying c $+ forM (zip arrs1 arrs2) $ \(arr1', arr2') ->+ letSubExp desc $ I.BasicOp $ I.FlatUpdate arr1' slice arr2'+ funcall :: String -> QualName VName ->@@ -1959,7 +2077,7 @@ replicateM k $ I.Param <$> newVName "x" <*> pure (I.Prim int64) add_lam_y_params <- replicateM k $ I.Param <$> newVName "y" <*> pure (I.Prim int64)- add_lam_body <- runBodyBinder $+ add_lam_body <- runBodyBuilder $ localScope (scopeOfLParams $ add_lam_x_params ++ add_lam_y_params) $ fmap resultBody $ forM (zip add_lam_x_params add_lam_y_params) $ \(x, y) ->@@ -1984,10 +2102,10 @@ -- the total sizes, which are the last elements in the offests. We -- just have to be careful in case the array is empty. last_index <- letSubExp "last_index" $ I.BasicOp $ I.BinOp (I.Sub Int64 OverflowUndef) w $ constant (1 :: Int64)- nonempty_body <- runBodyBinder $+ nonempty_body <- runBodyBuilder $ fmap resultBody $ forM all_offsets $ \offset_array ->- letSubExp "last_offset" $ I.BasicOp $ I.Index offset_array [I.DimFix last_index]+ letSubExp "last_offset" $ I.BasicOp $ I.Index offset_array $ Slice [I.DimFix last_index] let empty_body = resultBody $ replicate k $ constant (0 :: Int64) is_empty <- letSubExp "is_empty" $ I.BasicOp $ I.CmpOp (CmpEq int64) w $ constant (0 :: Int64) sizes <-@@ -2024,8 +2142,8 @@ ++ map I.rowType arr_ts, I.lambdaBody = mkBody offset_stms $- replicate (length arr_ts) offset- ++ map (I.Var . I.paramName) value_params+ replicate (length arr_ts) (subExpRes offset)+ ++ I.varsRes (map I.paramName value_params) } results <- letTupExp "partition_res" $@@ -2111,7 +2229,7 @@ d' <- case substs of Just [v] -> return v _ -> return $ I.Var $ E.qualLeaf d- return $ ErrorInt64 d'+ return $ ErrorVal int64 d' dimExpForError (DimExpConst d _) = return $ ErrorString $ pretty d dimExpForError DimExpAny = return ""
src/Futhark/Internalise/FreeVars.hs view
@@ -3,12 +3,11 @@ module Futhark.Internalise.FreeVars ( freeVars, without,- member, ident, size, sizes, NameSet (..),- patternVars,+ patVars, ) where @@ -36,10 +35,6 @@ withoutM :: NameSet -> NameSet -> NameSet withoutM (NameSet x) (NameSet y) = NameSet $ x `M.difference` y --- | Is this name in the 'NameSet'?-member :: VName -> NameSet -> Bool-member v (NameSet m) = v `M.member` m- -- | A 'NameSet' with a single 'Nonunique' name. ident :: Ident -> NameSet ident v = NameSet $ M.singleton (identName v) (toStruct $ unInfo $ identType v)@@ -74,11 +69,11 @@ AppExp (LetPat let_sizes pat e1 e2 _) _ -> freeVars e1 <> ( (sizes (patternDimNames pat) <> freeVars e2)- `withoutM` (patternVars pat <> foldMap (size . sizeName) let_sizes)+ `withoutM` (patVars pat <> foldMap (size . sizeName) let_sizes) ) AppExp (LetFun vn (tparams, pats, _, _, e1) e2 _) _ -> ( (freeVars e1 <> sizes (foldMap patternDimNames pats))- `without` ( S.map identName (foldMap patternIdents pats)+ `without` ( S.map identName (foldMap patIdents pats) <> S.fromList (map typeParamName tparams) ) )@@ -86,9 +81,10 @@ AppExp (If e1 e2 e3 _) _ -> freeVars e1 <> freeVars e2 <> freeVars e3 AppExp (Apply e1 e2 _ _) _ -> freeVars e1 <> freeVars e2 Negate e _ -> freeVars e+ Not e _ -> freeVars e Lambda pats e0 _ (Info (_, t)) _ -> (sizes (foldMap patternDimNames pats) <> freeVars e0 <> sizes (typeDimNames t))- `withoutM` foldMap patternVars pats+ `withoutM` foldMap patVars pats OpSection {} -> mempty OpSectionLeft _ _ e _ _ _ -> freeVars e OpSectionRight _ _ e _ _ _ -> freeVars e@@ -98,11 +94,11 @@ let (e2fv, e2ident) = formVars form in freeVars e1 <> ( (e2fv <> freeVars e3)- `withoutM` (sizes (S.fromList sparams) <> patternVars pat <> e2ident)+ `withoutM` (sizes (S.fromList sparams) <> patVars pat <> e2ident) ) where formVars (For v e2) = (freeVars e2, ident v)- formVars (ForIn p e2) = (freeVars e2, patternVars p)+ formVars (ForIn p e2) = (freeVars e2, patVars p) formVars (While e2) = (freeVars e2, mempty) AppExp (BinOp (qn, _) (Info qn_t) (e1, _) (e2, _) _) _ -> NameSet (M.singleton (qualLeaf qn) $ toStruct qn_t)@@ -122,7 +118,7 @@ where caseFV (CasePat p eCase _) = (sizes (patternDimNames p) <> freeVars eCase)- `withoutM` patternVars p+ `withoutM` patVars p freeDimIndex :: DimIndexBase Info VName -> NameSet freeDimIndex (DimFix e) = freeVars e@@ -130,5 +126,5 @@ foldMap (foldMap freeVars) [me1, me2, me3] -- | Extract all the variable names bound in a pattern.-patternVars :: Pattern -> NameSet-patternVars = mconcat . map ident . S.toList . patternIdents+patVars :: Pat -> NameSet+patVars = mconcat . map ident . S.toList . patIdents
src/Futhark/Internalise/Lambdas.hs view
@@ -49,7 +49,7 @@ (lam_params, orig_body, rettype) <- internaliseLambda lam $ I.Prim int64 : map outer argtypes let orig_chunk_param : params = lam_params- body <- runBodyBinder $ do+ body <- runBodyBuilder $ do letBindNames [paramName orig_chunk_param] $ I.BasicOp $ I.SubExp $ I.Var chunk_size return orig_body mkLambda (chunk_param : params) $ do@@ -95,7 +95,7 @@ (lam_params, orig_body, _) <- internaliseLambda lam $ I.Prim int64 : chunktypes let orig_chunk_param : params = lam_params- body <- runBodyBinder $ do+ body <- runBodyBuilder $ do letBindNames [paramName orig_chunk_param] $ I.BasicOp $ I.SubExp $ I.Var chunk_size return orig_body return (chunk_param : params, body)@@ -139,6 +139,6 @@ (resultBody <$> mkResult eq_class (i + 1)) lambdaWithIncrement :: I.Body -> InternaliseM I.Body- lambdaWithIncrement lam_body = runBodyBinder $ do- eq_class <- head <$> bodyBind lam_body+ lambdaWithIncrement lam_body = runBodyBuilder $ do+ eq_class <- resSubExp . head <$> bodyBind lam_body resultBody <$> mkResult eq_class 0
src/Futhark/Internalise/LiftLambdas.hs view
@@ -73,18 +73,17 @@ m = identityMapper {mapOnExp = \e' -> modify (<> existentials e') >> pure e'} in execState (astMap m e) here -liftFunction :: VName -> [TypeParam] -> [Pattern] -> StructType -> Exp -> LiftM Exp+liftFunction :: VName -> [TypeParam] -> [Pat] -> StructType -> Exp -> LiftM Exp liftFunction fname tparams params ret funbody = do -- Find free variables global <- gets stateGlobal let bound = global- <> foldMap patternNames params+ <> foldMap patNames params <> S.fromList (map typeParamName tparams)- <> existentials funbody free =- let immediate_free = FV.freeVars funbody `FV.without` bound+ let immediate_free = FV.freeVars funbody `FV.without` (bound <> existentials funbody) sizes_in_free = foldMap typeDimNames $ M.elems $ FV.unNameSet immediate_free
src/Futhark/Internalise/Monad.hs view
@@ -9,7 +9,7 @@ ( InternaliseM, runInternaliseM, throwError,- VarSubstitutions,+ VarSubsts, InternaliseEnv (..), FunInfo, substitutingVars,@@ -48,10 +48,10 @@ -- | A mapping from external variable names to the corresponding -- internalised subexpressions.-type VarSubstitutions = M.Map VName [SubExp]+type VarSubsts = M.Map VName [SubExp] data InternaliseEnv = InternaliseEnv- { envSubsts :: VarSubstitutions,+ { envSubsts :: VarSubsts, envDoBoundsChecks :: Bool, envSafe :: Bool, envAttrs :: Attrs@@ -60,14 +60,14 @@ data InternaliseState = InternaliseState { stateNameSource :: VNameSource, stateFunTable :: FunTable,- stateConstSubsts :: VarSubstitutions,+ stateConstSubsts :: VarSubsts, stateConstScope :: Scope SOACS, stateFuns :: [FunDef SOACS] } newtype InternaliseM a = InternaliseM- (BinderT SOACS (ReaderT InternaliseEnv (State InternaliseState)) a)+ (BuilderT SOACS (ReaderT InternaliseEnv (State InternaliseState)) a) deriving ( Functor, Applicative,@@ -83,7 +83,7 @@ getNameSource = gets stateNameSource putNameSource src = modify $ \s -> s {stateNameSource = src} -instance MonadBinder InternaliseM where+instance MonadBuilder InternaliseM where type Rep InternaliseM = SOACS mkExpDecM pat e = InternaliseM $ mkExpDecM pat e mkBodyM bnds res = InternaliseM $ mkBodyM bnds res@@ -100,7 +100,7 @@ runInternaliseM safe (InternaliseM m) = modifyNameSource $ \src -> let ((_, consts), s) =- runState (runReaderT (runBinderT m mempty) newEnv) (newState src)+ runState (runReaderT (runBuilderT m mempty) newEnv) (newState src) in ((consts, reverse $ stateFuns s), stateNameSource s) where newEnv =@@ -119,7 +119,7 @@ stateFuns = mempty } -substitutingVars :: VarSubstitutions -> InternaliseM a -> InternaliseM a+substitutingVars :: VarSubsts -> InternaliseM a -> InternaliseM a substitutingVars substs = local $ \env -> env {envSubsts = substs <> envSubsts env} lookupSubst :: VName -> InternaliseM (Maybe [SubExp])@@ -153,7 +153,7 @@ let stms = bodyStms $ funDefBody fd substs = takeLast (length (funDefRetType fd)) $- bodyResult $ funDefBody fd+ map resSubExp $ bodyResult $ funDefBody fd addStms stms modify $ \s -> s@@ -174,7 +174,7 @@ SubExp -> ErrorMsg SubExp -> SrcLoc ->- InternaliseM Certificates+ InternaliseM Certs assert desc se msg loc = assertingOne $ do attrs <- asks $ attrsForAssert . envAttrs attributing attrs $@@ -184,8 +184,8 @@ -- | Execute the given action if 'envDoBoundsChecks' is true, otherwise -- just return an empty list. asserting ::- InternaliseM Certificates ->- InternaliseM Certificates+ InternaliseM Certs ->+ InternaliseM Certs asserting m = do doBoundsChecks <- asks envDoBoundsChecks if doBoundsChecks@@ -196,5 +196,5 @@ -- just return an empty list. assertingOne :: InternaliseM VName ->- InternaliseM Certificates-assertingOne m = asserting $ Certificates . pure <$> m+ InternaliseM Certs+assertingOne m = asserting $ Certs . pure <$> m
src/Futhark/Internalise/Monomorphise.hs view
@@ -63,7 +63,7 @@ RecordReplacements ( VName, [TypeParam],- [Pattern],+ [Pat], StructType, [VName], Exp,@@ -76,7 +76,7 @@ -- record patterns. type RecordReplacements = M.Map VName RecordReplacement -type RecordReplacement = M.Map Name (VName, PatternType)+type RecordReplacement = M.Map Name (VName, PatType) -- Monomorphization environment mapping names of polymorphic functions -- to a representation of their corresponding function bindings.@@ -264,12 +264,12 @@ then second (mconcat . map replace . S.toList) t else t -sizesForPat :: MonadFreshNames m => Pattern -> m ([VName], Pattern)+sizesForPat :: MonadFreshNames m => Pat -> m ([VName], Pat) sizesForPat pat = do (params', sizes) <- runStateT (astMap tv pat) [] return (sizes, params') where- tv = identityMapper {mapOnPatternType = bitraverse onDim pure}+ tv = identityMapper {mapOnPatType = bitraverse onDim pure} onDim (AnyDim _) = do v <- lift $ newVName "size" modify (v :)@@ -289,7 +289,7 @@ transformAppExp (Coerce e tp loc) res = AppExp <$> (Coerce <$> transformExp e <*> pure tp <*> pure loc) <*> pure (Info res) transformAppExp (LetPat sizes pat e1 e2 loc) res = do- (pat', rr) <- transformPattern pat+ (pat', rr) <- transformPat pat AppExp <$> ( LetPat sizes pat' <$> transformExp e1 <*> withRecordReplacements rr (transformExp e2)@@ -442,6 +442,8 @@ Ascript <$> transformExp e <*> pure tp <*> pure loc transformExp (Negate e loc) = Negate <$> transformExp e <*> pure loc+transformExp (Not e loc) =+ Not <$> transformExp e <*> pure loc transformExp (Lambda params e0 decl tp loc) = do e0' <- transformExp e0 return $ Lambda params e0' decl tp loc@@ -508,7 +510,7 @@ transformCase :: Case -> MonoM Case transformCase (CasePat p e loc) = do- (p', rr) <- transformPattern p+ (p', rr) <- transformPat p CasePat p' <$> withRecordReplacements rr (transformExp e) <*> pure loc transformDimIndex :: DimIndexBase Info VName -> MonoM (DimIndexBase Info VName)@@ -523,10 +525,10 @@ Exp -> Maybe Exp -> Maybe Exp ->- PatternType ->+ PatType -> (PName, StructType, Maybe VName) -> (PName, StructType, Maybe VName) ->- (PatternType, [VName]) ->+ (PatType, [VName]) -> SrcLoc -> MonoM Exp desugarBinOpSection op e_left e_right t (xp, xtype, xext) (yp, ytype, yext) (rettype, retext) loc = do@@ -576,7 +578,7 @@ (v, pat, var_e) <- patAndVar argtype return (v, id, var_e, [pat]) -desugarProjectSection :: [Name] -> PatternType -> SrcLoc -> MonoM Exp+desugarProjectSection :: [Name] -> PatType -> SrcLoc -> MonoM Exp desugarProjectSection fields (Scalar (Arrow _ _ t1 t2)) loc = do p <- newVName "project_p" let body = foldl project (Var (qualName p) (Info t1) mempty) fields@@ -594,7 +596,7 @@ ++ pretty field desugarProjectSection _ t _ = error $ "desugarOpSection: not a function type: " ++ pretty t -desugarIndexSection :: [DimIndex] -> PatternType -> SrcLoc -> MonoM Exp+desugarIndexSection :: [DimIndex] -> PatType -> SrcLoc -> MonoM Exp desugarIndexSection idxs (Scalar (Arrow _ _ t1 t2)) loc = do p <- newVName "index_i" let body = AppExp (Index (Var (qualName p) (Info t1) loc) idxs loc) (Info (AppRes t2 []))@@ -617,43 +619,43 @@ e' = unfoldLetFuns rest e e_t = typeOf e' -transformPattern :: Pattern -> MonoM (Pattern, RecordReplacements)-transformPattern (Id v (Info (Scalar (Record fs))) loc) = do+transformPat :: Pat -> MonoM (Pat, RecordReplacements)+transformPat (Id v (Info (Scalar (Record fs))) loc) = do let fs' = M.toList fs (fs_ks, fs_ts) <- fmap unzip $ forM fs' $ \(f, ft) -> (,) <$> newVName (nameToString f) <*> transformType ft return- ( RecordPattern+ ( RecordPat (zip (map fst fs') (zipWith3 Id fs_ks (map Info fs_ts) $ repeat loc)) loc, M.singleton v $ M.fromList $ zip (map fst fs') $ zip fs_ks fs_ts )-transformPattern (Id v t loc) = return (Id v t loc, mempty)-transformPattern (TuplePattern pats loc) = do- (pats', rrs) <- unzip <$> mapM transformPattern pats- return (TuplePattern pats' loc, mconcat rrs)-transformPattern (RecordPattern fields loc) = do+transformPat (Id v t loc) = return (Id v t loc, mempty)+transformPat (TuplePat pats loc) = do+ (pats', rrs) <- unzip <$> mapM transformPat pats+ return (TuplePat pats' loc, mconcat rrs)+transformPat (RecordPat fields loc) = do let (field_names, field_pats) = unzip fields- (field_pats', rrs) <- unzip <$> mapM transformPattern field_pats- return (RecordPattern (zip field_names field_pats') loc, mconcat rrs)-transformPattern (PatternParens pat loc) = do- (pat', rr) <- transformPattern pat- return (PatternParens pat' loc, rr)-transformPattern (Wildcard (Info t) loc) = do+ (field_pats', rrs) <- unzip <$> mapM transformPat field_pats+ return (RecordPat (zip field_names field_pats') loc, mconcat rrs)+transformPat (PatParens pat loc) = do+ (pat', rr) <- transformPat pat+ return (PatParens pat' loc, rr)+transformPat (Wildcard (Info t) loc) = do t' <- transformType t return (wildcard t' loc, mempty)-transformPattern (PatternAscription pat td loc) = do- (pat', rr) <- transformPattern pat- return (PatternAscription pat' td loc, rr)-transformPattern (PatternLit e t loc) = return (PatternLit e t loc, mempty)-transformPattern (PatternConstr name t all_ps loc) = do- (all_ps', rrs) <- unzip <$> mapM transformPattern all_ps- return (PatternConstr name t all_ps' loc, mconcat rrs)+transformPat (PatAscription pat td loc) = do+ (pat', rr) <- transformPat pat+ return (PatAscription pat' td loc, rr)+transformPat (PatLit e t loc) = return (PatLit e t loc, mempty)+transformPat (PatConstr name t all_ps loc) = do+ (all_ps', rrs) <- unzip <$> mapM transformPat all_ps+ return (PatConstr name t all_ps' loc, mconcat rrs) -wildcard :: PatternType -> SrcLoc -> Pattern+wildcard :: PatType -> SrcLoc -> Pat wildcard (Scalar (Record fs)) loc =- RecordPattern (zip (M.keys fs) $ map ((`Wildcard` loc) . Info) $ M.elems fs) loc+ RecordPat (zip (M.keys fs) $ map ((`Wildcard` loc) . Info) $ M.elems fs) loc wildcard t loc = Wildcard (Info t) loc @@ -718,15 +720,15 @@ (substs, t_shape_params) <- typeSubstsM loc (noSizes bind_t) $ noNamedParams t let substs' = M.map (Subst []) substs rettype' = substTypesAny (`M.lookup` substs') rettype- substPatternType =+ substPatType = substTypesAny (fmap (fmap fromStruct) . (`M.lookup` substs'))- params' = map (substPattern entry substPatternType) params+ params' = map (substPat entry substPatType) params bind_t' = substTypesAny (`M.lookup` substs') bind_t (shape_params_explicit, shape_params_implicit) = partition ((`S.member` mustBeExplicit bind_t') . typeParamName) $ shape_params ++ t_shape_params - (params'', rrs) <- unzip <$> mapM transformPattern params'+ (params'', rrs) <- unzip <$> mapM transformPat params' mapM_ noticeDims $ rettype : map patternStructType params'' @@ -763,7 +765,7 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = pure . applySubst substs,- mapOnPatternType = pure . applySubst substs+ mapOnPatType = pure . applySubst substs } shapeParam tp = Id (typeParamName tp) (Info i64) $ srclocOf tp@@ -836,20 +838,20 @@ onDim (MonoAnon v) = pure $ AnyDim v -- Perform a given substitution on the types in a pattern.-substPattern :: Bool -> (PatternType -> PatternType) -> Pattern -> Pattern-substPattern entry f pat = case pat of- TuplePattern pats loc -> TuplePattern (map (substPattern entry f) pats) loc- RecordPattern fs loc -> RecordPattern (map substField fs) loc+substPat :: Bool -> (PatType -> PatType) -> Pat -> Pat+substPat entry f pat = case pat of+ TuplePat pats loc -> TuplePat (map (substPat entry f) pats) loc+ RecordPat fs loc -> RecordPat (map substField fs) loc where- substField (n, p) = (n, substPattern entry f p)- PatternParens p loc -> PatternParens (substPattern entry f p) loc+ substField (n, p) = (n, substPat entry f p)+ PatParens p loc -> PatParens (substPat entry f p) loc Id vn (Info tp) loc -> Id vn (Info $ f tp) loc Wildcard (Info tp) loc -> Wildcard (Info $ f tp) loc- PatternAscription p td loc- | entry -> PatternAscription (substPattern False f p) td loc- | otherwise -> substPattern False f p- PatternLit e (Info tp) loc -> PatternLit e (Info $ f tp) loc- PatternConstr n (Info tp) ps loc -> PatternConstr n (Info $ f tp) ps loc+ PatAscription p td loc+ | entry -> PatAscription (substPat False f p) td loc+ | otherwise -> substPat False f p+ PatLit e (Info tp) loc -> PatLit e (Info $ f tp) loc+ PatConstr n (Info tp) ps loc -> PatConstr n (Info $ f tp) ps loc toPolyBinding :: ValBind -> PolyBinding toPolyBinding (ValBind _ name _ (Info (rettype, retext)) tparams params body _ attrs loc) =@@ -865,7 +867,7 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = pure . applySubst (`M.lookup` subs),- mapOnPatternType = pure . applySubst (`M.lookup` subs)+ mapOnPatType = pure . applySubst (`M.lookup` subs) } body' <- astMap mapper body@@ -873,7 +875,7 @@ return valbind { valBindRetType = Info (applySubst (`M.lookup` subs) rettype, retext),- valBindParams = map (substPattern entry $ applySubst (`M.lookup` subs)) pats,+ valBindParams = map (substPat entry $ applySubst (`M.lookup` subs)) pats, valBindBody = body' }
src/Futhark/Optimise/BlkRegTiling.hs view
@@ -32,7 +32,8 @@ mmBlkRegTiling :: Stm GPU -> TileM (Maybe (Stms GPU, Stm GPU)) mmBlkRegTiling (Let pat aux (Op (SegOp (SegMap SegThread {} seg_space ts old_kbody))))- | KernelBody () kstms [Returns ResultMaySimplify (Var res_nm)] <- old_kbody,+ | KernelBody () kstms [Returns ResultMaySimplify cs (Var res_nm)] <- old_kbody,+ cs == mempty, -- check kernel has one result of primitive type [res_tp] <- ts, primType res_tp,@@ -59,7 +60,7 @@ -- exactly one of the two innermost dimensions of the kernel Just var_dims <- isInvarTo1of2InnerDims mempty seg_space variance arrs, -- get the variables on which the first result of redomap depends on- [redomap_orig_res] <- patternValueElements pat_redomap,+ [redomap_orig_res] <- patElems pat_redomap, Just res_red_var <- M.lookup (patElemName redomap_orig_res) variance, -- variance of the reduce result -- we furthermore check that code1 is only formed by@@ -90,7 +91,7 @@ red_t <- subExpType red_ne ---- in this binder: host code and outer seggroup (ie. the new kernel) ----- (new_kernel, host_stms) <- runBinder $ do+ (new_kernel, host_stms) <- runBuilder $ do -- host code tk_name <- nameFromString . pretty <$> newVName "Tk"@@ -132,7 +133,7 @@ gid_flat <- newVName "gid_flat" ---- in this binder: outer seggroup ----- (ret_seggroup, stms_seggroup) <- runBinder $ do+ (ret_seggroup, stms_seggroup) <- runBuilder $ do iii <- letExp "iii" =<< toExp (le64 gid_y * pe64 ty_ry) jjj <- letExp "jjj" =<< toExp (le64 gid_x * pe64 tx_rx) @@ -144,7 +145,7 @@ css'' <- update' "css" css_merge' [i, j] red_ne resultBodyM [Var css''] resultBodyM [Var css']- return [Var css]+ return [varRes css] let [cssss] = cssss_list a_loc_init <- scratch "A_loc" map_t1 [a_loc_sz]@@ -278,7 +279,7 @@ index "B_loc_elem" b_loc [b_loc_ind] >>= update "bsss" bsss_merge [j] resultBodyM [Var bsss]- return $ map Var [asss, bsss]+ return $ varsRes [asss, bsss] let [asss, bsss] = reg_mem @@ -323,7 +324,7 @@ ) (resultBodyM [Var css_merge']) resultBodyM [Var css]- return [Var css]+ return [varRes css] resultBodyM $ map Var redomap_res )@@ -388,7 +389,7 @@ rss'' <- update' "rss" rss_merge' [i, j] res_el resultBodyM [Var rss''] resultBodyM [Var rss']- return [Var rss]+ return [varRes rss] let rssss : _ = rssss_list return rssss @@ -407,7 +408,7 @@ new_shape = concat [ones, block_dims, ones, rest_dims] letExp "res_reshaped" $ BasicOp $ Reshape (map DimNew new_shape) epilogue_res - return [RegTileReturns regtile_ret_dims epilogue_res']+ return [RegTileReturns mempty regtile_ret_dims epilogue_res'] let level' = SegGroup (Count grid_size) (Count group_size) SegNoVirt space' = SegSpace gid_flat (rem_outer_dims ++ [(gid_y, gridDim_y), (gid_x, gridDim_x)])@@ -416,39 +417,39 @@ return $ Just (host_stms, new_kernel) mmBlkRegTiling _ = return Nothing -ceilDiv :: MonadBinder m => SubExp -> SubExp -> m (Exp (Rep m))+ceilDiv :: MonadBuilder m => SubExp -> SubExp -> m (Exp (Rep m)) ceilDiv x y = pure $ BasicOp $ BinOp (SDivUp Int64 Unsafe) x y -scratch :: MonadBinder m => String -> PrimType -> [SubExp] -> m VName+scratch :: MonadBuilder m => String -> PrimType -> [SubExp] -> m VName scratch se_name t shape = letExp se_name $ BasicOp $ Scratch t shape -- index an array with indices given in outer_indices; any inner -- dims of arr not indexed by outer_indices are sliced entirely-index :: MonadBinder m => String -> VName -> [VName] -> m VName+index :: MonadBuilder m => String -> VName -> [VName] -> m VName index se_desc arr outer_indices = do arr_t <- lookupType arr let shape = arrayShape arr_t inner_dims = shapeDims $ stripDims (length outer_indices) shape untouched d = DimSlice (intConst Int64 0) d (intConst Int64 1) inner_slices = map untouched inner_dims- indices = map (DimFix . Var) outer_indices ++ inner_slices- letExp se_desc $ BasicOp $ Index arr indices+ slice = Slice $ map (DimFix . Var) outer_indices ++ inner_slices+ letExp se_desc $ BasicOp $ Index arr slice -update :: MonadBinder m => String -> VName -> [VName] -> VName -> m VName+update :: MonadBuilder m => String -> VName -> [VName] -> VName -> m VName update se_desc arr indices new_elem = update' se_desc arr indices (Var new_elem) -update' :: MonadBinder m => String -> VName -> [VName] -> SubExp -> m VName+update' :: MonadBuilder m => String -> VName -> [VName] -> SubExp -> m VName update' se_desc arr indices new_elem =- letExp se_desc $ BasicOp $ Update arr (map (DimFix . Var) indices) new_elem+ letExp se_desc $ BasicOp $ Update Unsafe arr (Slice $ map (DimFix . Var) indices) new_elem forLoop' :: SubExp -> -- loop var [VName] -> -- loop inits ( VName -> [VName] -> -- (loop var -> loop inits -> loop body)- Binder GPU (Body GPU)+ Builder GPU (Body GPU) ) ->- Binder GPU [VName]+ Builder GPU [VName] forLoop' i_bound merge body = do i <- newVName "i" -- could give this as arg to the function let loop_form = ForLoop i Int64 i_bound []@@ -457,17 +458,17 @@ loop_inits <- mapM (\merge_t -> newParam "merge" $ toDecl merge_t Unique) merge_ts loop_body <-- runBodyBinder . inScopeOf loop_form . localScope (scopeOfFParams loop_inits) $+ runBodyBuilder . inScopeOf loop_form . localScope (scopeOfFParams loop_inits) $ body i $ map paramName loop_inits letTupExp "loop" $- DoLoop [] (zip loop_inits $ map Var merge) loop_form loop_body+ DoLoop (zip loop_inits $ map Var merge) loop_form loop_body forLoop :: SubExp -> [VName] ->- (VName -> [VName] -> Binder GPU (Body GPU)) ->- Binder GPU VName+ (VName -> [VName] -> Builder GPU (Body GPU)) ->+ Builder GPU VName forLoop i_bound merge body = do res_list <- forLoop' i_bound merge body return $ head res_list@@ -486,9 +487,7 @@ rebindLambda lam new_params res_names = stmsFromList ( zipWith- ( \ident new_param ->- mkLet [] [ident] $ BasicOp $ SubExp $ Var new_param- )+ (\ident new_param -> mkLet [ident] $ BasicOp $ SubExp $ Var new_param) idents new_params )@@ -503,8 +502,8 @@ lam_params res_cpy_stms = zipWith- ( \res_name lam_res ->- mkLet [] [Ident res_name lam_ret_type] $ BasicOp $ SubExp lam_res+ ( \res_name (SubExpRes cs lam_res) ->+ certify cs $ mkLet [Ident res_name lam_ret_type] $ BasicOp $ SubExp lam_res ) res_names lam_ress@@ -573,13 +572,13 @@ Maybe (Stms GPU, M.Map VName (Stm GPU)) processIndirections arrs _ acc stm@(Let patt _ (BasicOp (Index _ _))) | Just (ss, tab) <- acc,- [p] <- patternValueElements patt,+ [p] <- patElems patt, p_nm <- patElemName p, nameIn p_nm arrs = Just (ss, M.insert p_nm stm tab) processIndirections _ res_red_var acc stm'@(Let patt _ _) | Just (ss, tab) <- acc,- ps <- patternValueElements patt,+ ps <- patElems patt, all (\p -> not (nameIn (patElemName p) res_red_var)) ps = Just (ss Seq.|> stm', tab) | otherwise = Nothing@@ -599,7 +598,7 @@ se8 :: SubExp se8 = intConst Int64 8 -getParTiles :: (String, String) -> (Name, Name) -> SubExp -> Binder GPU (SubExp, SubExp)+getParTiles :: (String, String) -> (Name, Name) -> SubExp -> Builder GPU (SubExp, SubExp) getParTiles (t_str, r_str) (t_name, r_name) len_dim = case len_dim of Constant (IntValue (Int64Value 8)) ->@@ -613,7 +612,7 @@ r <- letSubExp r_str $ Op $ SizeOp $ GetSize r_name SizeRegTile return (t, r) -getSeqTile :: String -> Name -> SubExp -> SubExp -> SubExp -> Binder GPU SubExp+getSeqTile :: String -> Name -> SubExp -> SubExp -> SubExp -> Builder GPU SubExp getSeqTile tk_str tk_name len_dim ty tx = case (tx, ty) of (Constant (IntValue (Int64Value v_x)), Constant (IntValue (Int64Value v_y))) ->@@ -728,7 +727,7 @@ -- exactly one of the two innermost dimensions of the kernel Just _ <- isInvarTo2of3InnerDims mempty space variance inp_soac_arrs, -- get the free variables on which the result of redomap depends on- redomap_orig_res <- patternValueElements pat_redomap,+ redomap_orig_res <- patElems pat_redomap, res_red_var <- -- variance of the reduce result mconcat $ mapMaybe ((`M.lookup` variance) . patElemName) redomap_orig_res, mempty /= res_red_var,@@ -751,11 +750,10 @@ -- (for sanity sake, they should be) ker_res_nms <- mapMaybe getResNm kres, length ker_res_nms == length kres,- Pattern [] _ <- pat, all primType kertp, all (variantToDim variance gtid_z) ker_res_nms = do -- HERE STARTS THE IMPLEMENTATION:- (new_kernel, host_stms) <- runBinder $ do+ (new_kernel, host_stms) <- runBuilder $ do -- host code -- process the z-variant arrays that need transposition; -- these "manifest" statements should come before the kernel@@ -791,7 +789,7 @@ gid_flat <- newVName "gid_flat" ---- in this binder: outer seggroup ----- (ret_seggroup, stms_seggroup) <- runBinder $ do+ (ret_seggroup, stms_seggroup) <- runBuilder $ do ii <- letExp "ii" =<< toExp (le64 gid_z * pe64 rz) jj1 <- letExp "jj1" =<< toExp (le64 gid_y * pe64 ty) jj2 <- letExp "jj2" =<< toExp (le64 gid_x * pe64 tx)@@ -803,7 +801,7 @@ css <- forLoop rz [css_init] $ \i [css_merge] -> do css' <- update' "css" css_merge [i] red_ne resultBodyM [Var css']- return $ Var css+ return $ varRes css -- scratch the shared-memory arrays corresponding to the arrays that are -- input to the redomap and are invariant to the outermost parallel dimension.@@ -824,7 +822,7 @@ ltid_flat <- newVName "ltid_flat" ltid <- newVName "ltid" let segspace = SegSpace ltid_flat [(ltid, group_size)]- ((res_v, res_i), stms) <- runBinder $ do+ ((res_v, res_i), stms) <- runBuilder $ do offs <- letExp "offs" =<< toExp (pe64 group_size * le64 tt) loc_ind <- letExp "loc_ind" =<< toExp (le64 ltid + le64 offs) letBindNames [gtid_z] =<< toExp (le64 ii + le64 loc_ind)@@ -848,7 +846,7 @@ --y_tp <- subExpType y_elm return (y_elm, y_ind) - let ret = WriteReturns (Shape [rz]) loc_Y_nm [([DimFix res_i], res_v)]+ let ret = WriteReturns mempty (Shape [rz]) loc_Y_nm [(Slice [DimFix res_i], res_v)] let body = KernelBody () stms [ret] res_nms <-@@ -865,7 +863,7 @@ letBindNames [gtid_x] =<< toExp (le64 jj2 + le64 ltid_x) reg_arr_merge_nms_slc <- forM reg_arr_merge_nms $ \reg_arr_nm -> index "res_reg_slc" reg_arr_nm [ltid_y, ltid_x]- letTupExp' "redomap_guarded"+ fmap subExpsRes . letTupExp' "redomap_guarded" =<< eIf (toExp $ le64 gtid_y .<. pe64 d_Ky .&&. le64 gtid_x .<. pe64 d_Kx) ( do@@ -925,11 +923,11 @@ segMap3D "rssss" segthd_lvl ResultPrivate (se1, ty, tx) $ \(_ltid_z, ltid_y, ltid_x) -> forM (zip kertp redomap_res) $ \(res_tp, res) -> do rss_init <- scratch "rss_init" (elemType res_tp) [rz, se1, se1]- fmap Var $+ fmap varRes $ forLoop rz [rss_init] $ \i [rss] -> do- let slice = [DimFix $ Var i, DimFix se0, DimFix se0]+ let slice = Slice [DimFix $ Var i, DimFix se0, DimFix se0] thread_res <- index "thread_res" res [ltid_y, ltid_x, i]- rss' <- letSubExp "rss" $ BasicOp $ Update rss slice $ Var thread_res+ rss' <- letSubExp "rss" $ BasicOp $ Update Unsafe rss slice $ Var thread_res resultBodyM [rss'] else segMap3D "rssss" segthd_lvl ResultPrivate (se1, ty, tx) $ \(_ltid_z, ltid_y, ltid_x) -> do letBindNames [gtid_y] =<< toExp (le64 jj1 + le64 ltid_y)@@ -956,10 +954,10 @@ ) (eBody $ map eBlank kertp) rss' <- forM (zip res_els rss_merge) $ \(res_el, rs_merge) -> do- let slice = [DimFix $ Var i, DimFix se0, DimFix se0]- letSubExp "rss" $ BasicOp $ Update rs_merge slice res_el+ let slice = Slice [DimFix $ Var i, DimFix se0, DimFix se0]+ letSubExp "rss" $ BasicOp $ Update Unsafe rs_merge slice res_el resultBodyM rss'- return $ map Var rss+ return $ varsRes rss ---------------------------------------------------------------- -- Finally, reshape the result arrays for the RegTileReturn ---@@ -979,32 +977,32 @@ new_shape = concat [ones, block_dims, ones, rest_dims] letExp "res_reshaped" $ BasicOp $ Reshape (map DimNew new_shape) res - return $ map (RegTileReturns regtile_ret_dims) epilogue_res'- -- END (ret_seggroup, stms_seggroup) <- runBinder $ do+ return $ map (RegTileReturns mempty regtile_ret_dims) epilogue_res'+ -- END (ret_seggroup, stms_seggroup) <- runBuilder $ do let level' = SegGroup (Count grid_size) (Count group_size) SegNoVirt space' = SegSpace gid_flat (rem_outer_dims ++ [(gid_z, gridDim_z), (gid_y, gridDim_y), (gid_x, gridDim_x)]) kbody' = KernelBody () stms_seggroup ret_seggroup return $ Let pat aux $ Op $ SegOp $ SegMap level' space' kertp kbody'- -- END (new_kernel, host_stms) <- runBinder $ do+ -- END (new_kernel, host_stms) <- runBuilder $ do return $ Just (host_stms, new_kernel) where- getResNm (Returns ResultMaySimplify (Var res_nm)) = Just res_nm+ getResNm (Returns ResultMaySimplify _ (Var res_nm)) = Just res_nm getResNm _ = Nothing - limitTile :: String -> SubExp -> SubExp -> Binder GPU SubExp+ limitTile :: String -> SubExp -> SubExp -> Builder GPU SubExp limitTile t_str t d_K = letSubExp t_str $ BasicOp $ BinOp (SMin Int64) t d_K insertTranspose :: VarianceTable -> (VName, SubExp) -> (M.Map VName (Stm GPU), M.Map VName (PrimType, Stm GPU)) -> (VName, Stm GPU) ->- Binder GPU (M.Map VName (Stm GPU), M.Map VName (PrimType, Stm GPU))+ Builder GPU (M.Map VName (Stm GPU), M.Map VName (PrimType, Stm GPU)) insertTranspose variance (gidz, _) (tab_inn, tab_out) (p_nm, stm@(Let patt yy (BasicOp (Index arr_nm slc))))- | [p] <- patternValueElements patt,+ | [p] <- patElems patt, ptp <- elemType $ patElemType p, p_nm == patElemName p =- case L.findIndices (variantSliceDim variance gidz) slc of+ case L.findIndices (variantSliceDim variance gidz) (unSlice slc) of [] -> return (M.insert p_nm stm tab_inn, tab_out) i : _ -> do arr_tp <- lookupType arr_nm
src/Futhark/Optimise/CSE.hs view
@@ -37,6 +37,7 @@ import Control.Monad.Reader import qualified Data.Map.Strict as M+import Data.Maybe (isJust) import Futhark.Analysis.Alias import Futhark.IR import Futhark.IR.Aliases@@ -46,7 +47,7 @@ removeProgAliases, removeStmAliases, )-import qualified Futhark.IR.GPU.Kernel as Kernel+import qualified Futhark.IR.GPU as GPU import qualified Futhark.IR.MC as MC import qualified Futhark.IR.Mem as Memory import Futhark.IR.Prop.Aliases@@ -139,13 +140,15 @@ runReader (cseInBody ds $ funDefBody fundec) $ newCSEState cse_arrays } where- -- XXX: we treat every result as a consumption here, because we+ -- XXX: we treat every non-entry result as a consumption here, because we -- our core language is not strong enough to fully capture the -- aliases we want, so we are turning some parts off (see #803, -- #1241, and the related comment in TypeCheck.hs). This is not a -- practical problem while we still perform such aggressive -- inlining.- ds = map retDiet $ funDefRetType fundec+ ds+ | isJust $ funDefEntryPoint fundec = map (diet . declExtTypeOf) $ funDefRetType fundec+ | otherwise = map retDiet $ funDefRetType fundec retDiet t | primType $ declExtTypeOf t = Observe | otherwise = Consume@@ -186,16 +189,19 @@ cseInStms _ [] m = do a <- m return (mempty, a)-cseInStms consumed (bnd : bnds) m =- cseInStm consumed bnd $ \bnd' -> do- (bnds', a) <- cseInStms consumed bnds m- bnd'' <- mapM nestedCSE bnd'- return (stmsFromList bnd'' <> bnds', a)+cseInStms consumed (stm : stms) m =+ cseInStm consumed stm $ \stm' -> do+ (stms', a) <- cseInStms consumed stms m+ stm'' <- mapM nestedCSE stm'+ return (stmsFromList stm'' <> stms', a) where- nestedCSE bnd' = do- let ds = map patElemDiet $ patternValueElements $ stmPattern bnd'- e <- mapExpM (cse ds) $ stmExp bnd'- return bnd' {stmExp = e}+ nestedCSE stm' = do+ let ds =+ case stmExp stm' of+ DoLoop merge _ _ -> map (diet . declTypeOf . fst) merge+ _ -> map patElemDiet $ patElems $ stmPat stm'+ e <- mapExpM (cse ds) $ stmExp stm'+ return stm' {stmExp = e} cse ds = identityMapper@@ -217,15 +223,15 @@ CSEState (esubsts, nsubsts) cse_arrays <- ask let e' = substituteNames nsubsts e pat' = substituteNames nsubsts pat- if any (bad cse_arrays) $ patternValueElements pat+ if any (bad cse_arrays) $ patElems pat then m [Let pat' (StmAux cs attrs edec) e'] else case M.lookup (edec, e') esubsts of Just subpat -> local (addNameSubst pat' subpat) $ do let lets =- [ Let (Pattern [] [patElem']) (StmAux cs attrs edec) $+ [ Let (Pat [patElem']) (StmAux cs attrs edec) $ BasicOp $ SubExp $ Var $ patElemName patElem- | (name, patElem) <- zip (patternNames pat') $ patternElements subpat,+ | (name, patElem) <- zip (patNames pat') $ patElems subpat, let patElem' = patElem {patElemName = name} ] m lets@@ -242,7 +248,7 @@ type ExpressionSubstitutions rep = M.Map (ExpDec rep, Exp rep)- (Pattern rep)+ (Pat rep) type NameSubstitutions = M.Map VName VName @@ -254,16 +260,16 @@ newCSEState :: Bool -> CSEState rep newCSEState = CSEState (M.empty, M.empty) -mkSubsts :: PatternT dec -> PatternT dec -> M.Map VName VName-mkSubsts pat vs = M.fromList $ zip (patternNames pat) (patternNames vs)+mkSubsts :: PatT dec -> PatT dec -> M.Map VName VName+mkSubsts pat vs = M.fromList $ zip (patNames pat) (patNames vs) -addNameSubst :: PatternT dec -> PatternT dec -> CSEState rep -> CSEState rep+addNameSubst :: PatT dec -> PatT dec -> CSEState rep -> CSEState rep addNameSubst pat subpat (CSEState (esubsts, nsubsts) cse_arrays) = CSEState (esubsts, mkSubsts pat subpat `M.union` nsubsts) cse_arrays addExpSubst :: ASTRep rep =>- Pattern rep ->+ Pat rep -> ExpDec rep -> Exp rep -> CSEState rep ->@@ -290,10 +296,10 @@ CSEInOp (Op rep), CSEInOp op ) =>- CSEInOp (Kernel.HostOp rep op)+ CSEInOp (GPU.HostOp rep op) where- cseInOp (Kernel.SegOp op) = Kernel.SegOp <$> cseInOp op- cseInOp (Kernel.OtherOp op) = Kernel.OtherOp <$> cseInOp op+ cseInOp (GPU.SegOp op) = GPU.SegOp <$> cseInOp op+ cseInOp (GPU.OtherOp op) = GPU.OtherOp <$> cseInOp op cseInOp x = return x instance@@ -311,20 +317,20 @@ instance (ASTRep rep, Aliased rep, CSEInOp (Op rep)) =>- CSEInOp (Kernel.SegOp lvl rep)+ CSEInOp (GPU.SegOp lvl rep) where cseInOp = subCSE- . Kernel.mapSegOpM- (Kernel.SegOpMapper return cseInLambda cseInKernelBody return return)+ . GPU.mapSegOpM+ (GPU.SegOpMapper return cseInLambda cseInKernelBody return return) cseInKernelBody :: (ASTRep rep, Aliased rep, CSEInOp (Op rep)) =>- Kernel.KernelBody rep ->- CSEM rep (Kernel.KernelBody rep)-cseInKernelBody (Kernel.KernelBody bodydec bnds res) = do+ GPU.KernelBody rep ->+ CSEM rep (GPU.KernelBody rep)+cseInKernelBody (GPU.KernelBody bodydec bnds res) = do Body _ bnds' _ <- cseInBody (map (const Observe) res) $ Body bodydec bnds []- return $ Kernel.KernelBody bodydec bnds' res+ return $ GPU.KernelBody bodydec bnds' res instance CSEInOp op => CSEInOp (Memory.MemOp op) where cseInOp o@Memory.Alloc {} = return o
src/Futhark/Optimise/DoubleBuffer.hs view
@@ -11,22 +11,76 @@ -- dead at the end of the loop. If it is not, we may cause data -- hazards. ----- This module rewrites loops with memory block merge parameters such--- that each memory block is copied at the end of the iteration, thus--- ensuring that any allocation inside the loop is dead at the end of--- the loop. This is only possible for allocations whose size is--- loop-invariant, although the initial size may differ from the size--- produced by the loop result.+-- This pass tries to rewrite loops with memory parameters.+-- Specifically, it takes loops of this form: ----- Additionally, inside parallel kernels we also copy the initial--- value. This has the effect of making the memory block returned by--- the array non-existential, which is important for later memory--- expansion to work.+-- @+-- loop {..., A_mem, ..., A, ...} ... do {+-- ...+-- let A_out_mem = alloc(...) -- stores A_out+-- in {..., A_out_mem, ..., A_out, ...}+-- }+-- @+--+-- and turns them into+--+-- @+-- let A_in_mem = alloc(...)+-- let A_out_mem = alloc(...)+-- let A_in = copy A -- in A_in_mem+-- loop {..., A_in_mem, A_out_mem, ..., A=A_in, ...} ... do {+-- ...+-- in {..., A_out_mem, A_mem, ..., A_out, ...}+-- }+-- @+--+-- The result is essentially "pointer swapping" between the two memory+-- initial blocks @A_mem@ and @A_out_mem@. The invariant is that the+-- array is always stored in the "first" memory block at the beginning+-- of the loop (and also in the final result). We do need to add an+-- extra element to the pattern, however. The initial copy of @A@+-- could be elided if @A@ is unique (thus @A_in_mem=A_mem@). This is+-- because only then is it safe to use @A_mem@ to store loop results.+-- We don't currently do this.+--+-- Unfortunately, not all loops fit the pattern above. In particular,+-- a nested loop that has been transformed as such does not!+-- Therefore we also have another double buffering strategy, that+-- turns+--+-- @+-- loop {..., A_mem, ..., A, ...} ... do {+-- ...+-- let A_out_mem = alloc(...)+-- -- A in A_out_mem+-- in {..., A_out_mem, ..., A, ...}+-- }+-- @+--+-- into+--+-- @+-- let A_res_mem = alloc(...)+-- loop {..., A_mem, ..., A, ...} ... do {+-- ...+-- let A_out_mem = alloc(...)+-- -- A in A_out_mem+-- let A' = copy A+-- -- A' in A_res_mem+-- in {..., A_res_mem, ..., A, ...}+-- }+-- @+--+-- The allocation of A_out_mem can then be hoisted out because it is+-- dead at the end of the loop. This always works as long as+-- A_out_mem has a loop-invariant allocation size, but requires a copy+-- per iteration (and an initial one, elided above). module Futhark.Optimise.DoubleBuffer (doubleBufferGPU, doubleBufferMC) where import Control.Monad.Reader import Control.Monad.State import Control.Monad.Writer+import Data.Bifunctor import Data.List (find) import qualified Data.Map.Strict as M import Data.Maybe@@ -37,7 +91,8 @@ import Futhark.Pass import Futhark.Pass.ExplicitAllocations (arraySizeInBytesExp) import Futhark.Pass.ExplicitAllocations.GPU ()-import Futhark.Util (maybeHead)+import Futhark.Transform.Substitute+import Futhark.Util (mapAccumLM, maybeHead) -- | The pass for GPU kernels. doubleBufferGPU :: Pass GPUMem GPUMem@@ -48,7 +103,7 @@ doubleBufferMC = doubleBuffer optimiseMCOp -- | The double buffering pass definition.-doubleBuffer :: Mem rep => OptimiseOp rep -> Pass rep rep+doubleBuffer :: Mem rep inner => OptimiseOp rep -> Pass rep rep doubleBuffer onOp = Pass { passName = "Double buffer",@@ -58,22 +113,20 @@ where optimise scope stms = modifyNameSource $ \src -> let m =- runDoubleBufferM $- localScope scope $- fmap stmsFromList $ optimiseStms $ stmsToList stms+ runDoubleBufferM $ localScope scope $ optimiseStms $ stmsToList stms in runState (runReaderT m env) src env = Env mempty doNotTouchLoop onOp- doNotTouchLoop ctx val body = return (mempty, ctx, val, body)+ doNotTouchLoop pat merge body = pure (mempty, pat, merge, body) type OptimiseLoop rep =- [(FParam rep, SubExp)] ->+ Pat rep -> [(FParam rep, SubExp)] -> Body rep -> DoubleBufferM rep- ( [Stm rep],- [(FParam rep, SubExp)],+ ( Stms rep,+ Pat rep, [(FParam rep, SubExp)], Body rep )@@ -100,27 +153,27 @@ optimiseBody :: ASTRep rep => Body rep -> DoubleBufferM rep (Body rep) optimiseBody body = do- bnds' <- optimiseStms $ stmsToList $ bodyStms body- return $ body {bodyStms = stmsFromList bnds'}+ stms' <- optimiseStms $ stmsToList $ bodyStms body+ pure $ body {bodyStms = stms'} -optimiseStms :: ASTRep rep => [Stm rep] -> DoubleBufferM rep [Stm rep]-optimiseStms [] = return []+optimiseStms :: ASTRep rep => [Stm rep] -> DoubleBufferM rep (Stms rep)+optimiseStms [] = pure mempty optimiseStms (e : es) = do e_es <- optimiseStm e es' <- localScope (castScope $ scopeOf e_es) $ optimiseStms es- return $ e_es ++ es'+ pure $ e_es <> es' -optimiseStm :: forall rep. ASTRep rep => Stm rep -> DoubleBufferM rep [Stm rep]-optimiseStm (Let pat aux (DoLoop ctx val form body)) = do+optimiseStm :: forall rep. ASTRep rep => Stm rep -> DoubleBufferM rep (Stms rep)+optimiseStm (Let pat aux (DoLoop merge form body)) = do body' <-- localScope (scopeOf form <> scopeOfFParams (map fst $ ctx ++ val)) $+ localScope (scopeOf form <> scopeOfFParams (map fst merge)) $ optimiseBody body opt_loop <- asks envOptimiseLoop- (bnds, ctx', val', body'') <- opt_loop ctx val body'- return $ bnds ++ [Let pat aux $ DoLoop ctx' val' form body'']+ (stms, pat', merge', body'') <- opt_loop pat merge body'+ pure $ stms <> oneStm (Let pat' aux $ DoLoop merge' form body'') optimiseStm (Let pat aux e) = do onOp <- asks envOptimiseOp- pure . Let pat aux <$> mapExpM (optimise onOp) e+ oneStm . Let pat aux <$> mapExpM (optimise onOp) e where optimise onOp = identityMapper@@ -139,7 +192,7 @@ mapOnSegOpBody = optimiseKernelBody } inSegOp env = env {envOptimiseLoop = optimiseLoop}-optimiseGPUOp op = return op+optimiseGPUOp op = pure op optimiseMCOp :: OptimiseOp MCMem optimiseMCOp (Inner (ParOp par_op op)) =@@ -153,7 +206,7 @@ mapOnSegOpBody = optimiseKernelBody } inSegOp env = env {envOptimiseLoop = optimiseLoop}-optimiseMCOp op = return op+optimiseMCOp op = pure op optimiseKernelBody :: ASTRep rep =>@@ -161,7 +214,7 @@ DoubleBufferM rep (KernelBody rep) optimiseKernelBody kbody = do stms' <- optimiseStms $ stmsToList $ kernelBodyStms kbody- return $ kbody {kernelBodyStms = stmsFromList stms'}+ pure $ kbody {kernelBodyStms = stms'} optimiseLambda :: ASTRep rep =>@@ -169,39 +222,119 @@ DoubleBufferM rep (Lambda rep) optimiseLambda lam = do body <- localScope (castScope $ scopeOf lam) $ optimiseBody $ lambdaBody lam- return lam {lambdaBody = body}+ pure lam {lambdaBody = body} -type Constraints rep =- ( ASTRep rep,- FParamInfo rep ~ FParamMem,- LParamInfo rep ~ LParamMem,- RetType rep ~ RetTypeMem,- LetDec rep ~ LetDecMem,- BranchType rep ~ BranchTypeMem,+type Constraints rep inner =+ ( Mem rep inner,+ BuilderOps rep, ExpDec rep ~ (), BodyDec rep ~ (),- OpReturns rep+ LetDec rep ~ LetDecMem ) -optimiseLoop :: (Constraints rep, Op rep ~ MemOp inner, BinderOps rep) => OptimiseLoop rep-optimiseLoop ctx val body = do+extractAllocOf :: Constraints rep inner => Names -> VName -> Stms rep -> Maybe (Stm rep, Stms rep)+extractAllocOf bound needle stms = do+ (stm, stms') <- stmsHead stms+ case stm of+ Let (Pat [pe]) _ (Op (Alloc size _))+ | patElemName pe == needle,+ invariant size ->+ Just (stm, stms')+ _ ->+ let bound' = namesFromList (patNames (stmPat stm)) <> bound+ in second (oneStm stm <>) <$> extractAllocOf bound' needle stms'+ where+ invariant Constant {} = True+ invariant (Var v) = not $ v `nameIn` bound++optimiseLoop :: Constraints rep inner => OptimiseLoop rep+optimiseLoop pat merge body = do+ (outer_stms_1, pat', merge', body') <-+ optimiseLoopBySwitching pat merge body+ (outer_stms_2, pat'', merge'', body'') <-+ inScopeOf outer_stms_1 $ optimiseLoopByCopying pat' merge' body'+ pure (outer_stms_1 <> outer_stms_2, pat'', merge'', body'')++isArrayIn :: VName -> Param FParamMem -> Bool+isArrayIn x (Param _ (MemArray _ _ _ (ArrayIn y _))) = x == y+isArrayIn _ _ = False++optimiseLoopBySwitching :: Constraints rep inner => OptimiseLoop rep+optimiseLoopBySwitching (Pat pes) merge (Body _ body_stms body_res) = do+ ((pat', merge', body'), outer_stms) <- runBuilder $ do+ ((buffered, body_stms'), (pes', merge', body_res')) <-+ second unzip3 <$> mapAccumLM check (mempty, body_stms) (zip3 pes merge body_res)+ merge'' <- mapM (maybeCopyInitial buffered) $ mconcat merge'+ pure (Pat $ mconcat pes', merge'', Body () body_stms' $ mconcat body_res')+ pure (outer_stms, pat', merge', body')+ where+ merge_bound = namesFromList $ map (paramName . fst) merge++ check (buffered, body_stms') (pe, (param, arg), res)+ | Mem space <- paramType param,+ Var arg_v <- arg,+ -- XXX: what happens if there are multiple arrays in the same+ -- memory block?+ [arr_param] <- filter (isArrayIn (paramName param)) $ map fst merge,+ MemArray pt _ _ (ArrayIn _ ixfun) <- paramDec arr_param,+ Var res_v <- resSubExp res,+ Just (res_v_alloc, body_stms'') <- extractAllocOf merge_bound res_v body_stms' = do+ num_bytes <-+ letSubExp "num_bytes" =<< toExp (product $ primByteSize pt : IxFun.base ixfun)+ arr_mem_in <-+ letExp (baseString arg_v <> "_in") $ Op $ Alloc num_bytes space+ pe_unused <-+ PatElem+ <$> newVName (baseString (patElemName pe) <> "_unused")+ <*> pure (MemMem space)+ param_out <-+ Param+ <$> newVName (baseString (paramName param) <> "_out")+ <*> pure (MemMem space)+ addStm res_v_alloc+ pure+ ( ( M.insert (paramName param) arr_mem_in buffered,+ substituteNames (M.singleton res_v (paramName param_out)) body_stms''+ ),+ ( [pe, pe_unused],+ [(param, Var arr_mem_in), (param_out, resSubExp res)],+ [ res {resSubExp = Var $ paramName param_out},+ subExpRes $ Var $ paramName param+ ]+ )+ )+ | otherwise =+ pure+ ( (buffered, body_stms'),+ ([pe], [(param, arg)], [res])+ )++ maybeCopyInitial buffered (param@(Param _ (MemArray _ _ _ (ArrayIn mem _))), Var arg)+ | Just mem' <- mem `M.lookup` buffered = do+ arg_info <- lookupMemInfo arg+ case arg_info of+ MemArray pt shape u (ArrayIn _ arg_ixfun) -> do+ arg_copy <- newVName (baseString arg <> "_dbcopy")+ letBind (Pat [PatElem arg_copy $ MemArray pt shape u $ ArrayIn mem' arg_ixfun]) $+ BasicOp $ Copy arg+ pure (param, Var arg_copy)+ _ -> pure (param, Var arg)+ maybeCopyInitial _ (param, arg) = pure (param, arg)++optimiseLoopByCopying :: Constraints rep inner => OptimiseLoop rep+optimiseLoopByCopying pat merge body = do -- We start out by figuring out which of the merge variables should -- be double-buffered. buffered <- doubleBufferMergeParams- (zip (map fst ctx) (bodyResult body))- (map fst merge)+ (zip (map fst merge) (bodyResult body)) (boundInBody body) -- Then create the allocations of the buffers and copies of the -- initial values. (merge', allocs) <- allocStms merge buffered -- Modify the loop body to copy buffered result arrays. let body' = doubleBufferResult (map fst merge) buffered body- (ctx', val') = splitAt (length ctx) merge'- -- Modify the initial merge p- return (allocs, ctx', val', body')- where- merge = ctx ++ val+ pure (stmsFromList allocs, pat, merge', body') -- | The booleans indicate whether we should also play with the -- initial merge values.@@ -215,13 +348,13 @@ doubleBufferMergeParams :: MonadFreshNames m =>- [(Param FParamMem, SubExp)] ->- [Param FParamMem] ->+ [(Param FParamMem, SubExpRes)] -> Names -> m [DoubleBuffer]-doubleBufferMergeParams ctx_and_res val_params bound_in_loop =- evalStateT (mapM buffer val_params) M.empty+doubleBufferMergeParams ctx_and_res bound_in_loop =+ evalStateT (mapM buffer ctx_and_res) M.empty where+ params = map fst ctx_and_res loopVariant v = v `nameIn` bound_in_loop || v `elem` map (paramName . fst) ctx_and_res@@ -230,9 +363,9 @@ Just (Constant v, True) loopInvariantSize (Var v) = case find ((== v) . paramName . fst) ctx_and_res of- Just (_, Constant val) ->+ Just (_, SubExpRes _ (Constant val)) -> Just (Constant val, False)- Just (_, Var v')+ Just (_, SubExpRes _ (Var v')) | not $ loopVariant v' -> Just (Var v', False) Just _ ->@@ -240,7 +373,7 @@ Nothing -> Just (Var v, True) - sizeForMem mem = maybeHead $ mapMaybe (arrayInMem . paramDec) val_params+ sizeForMem mem = maybeHead $ mapMaybe (arrayInMem . paramDec) params where arrayInMem (MemArray pt shape _ (ArrayIn arraymem ixfun)) | IxFun.isDirect ixfun,@@ -254,26 +387,28 @@ ) arrayInMem _ = Nothing - buffer fparam = case paramType fparam of+ buffer (fparam, res) = case paramType fparam of Mem space- | Just (size, b) <- sizeForMem $ paramName fparam -> do+ | Just (size, b) <- sizeForMem $ paramName fparam,+ Var res_v <- resSubExp res,+ res_v `nameIn` bound_in_loop -> do -- Let us double buffer this! bufname <- lift $ newVName "double_buffer_mem" modify $ M.insert (paramName fparam) (bufname, b)- return $ BufferAlloc bufname size space b+ pure $ BufferAlloc bufname size space b Array {} | MemArray _ _ _ (ArrayIn mem ixfun) <- paramDec fparam -> do buffered <- gets $ M.lookup mem case buffered of Just (bufname, b) -> do copyname <- lift $ newVName "double_buffer_array"- return $ BufferCopy bufname ixfun copyname b+ pure $ BufferCopy bufname ixfun copyname b Nothing ->- return NoBuffer- _ -> return NoBuffer+ pure NoBuffer+ _ -> pure NoBuffer allocStms ::- (Constraints rep, Op rep ~ MemOp inner, BinderOps rep) =>+ Constraints rep inner => [(FParam rep, SubExp)] -> [DoubleBuffer] -> DoubleBufferM rep ([(FParam rep, SubExp)], [Stm rep])@@ -281,13 +416,13 @@ where allocation m@(Param pname _, _) (BufferAlloc name size space b) = do stms <- lift $- runBinder_ $ do+ runBuilder_ $ do size' <- toSubExp "double_buffer_size" size letBindNames [name] $ Op $ Alloc size' space tell $ stmsToList stms if b- then return (Param pname $ MemMem space, Var name)- else return m+ then pure (Param pname $ MemMem space, Var name)+ else pure m allocation (f, Var v) (BufferCopy mem _ _ b) | b = do v_copy <- lift $ newVName $ baseString v ++ "_double_buffer_copy" (_v_mem, v_ixfun) <- lift $ lookupArraySummary v@@ -295,7 +430,7 @@ shape = arrayShape $ paramType f bound = MemArray bt shape NoUniqueness $ ArrayIn mem v_ixfun tell- [ Let (Pattern [] [PatElem v_copy bound]) (defAux ()) $+ [ Let (Pat [PatElem v_copy bound]) (defAux ()) $ BasicOp $ Copy v ] -- It is important that we treat this as a consumption, to@@ -305,37 +440,37 @@ let uniqueMemInfo (MemArray pt pshape _ ret) = MemArray pt pshape Unique ret uniqueMemInfo info = info- return (uniqueMemInfo <$> f, Var v_copy)+ pure (uniqueMemInfo <$> f, Var v_copy) allocation (f, se) _ =- return (f, se)+ pure (f, se) doubleBufferResult ::- (Constraints rep) =>+ Constraints rep inner => [FParam rep] -> [DoubleBuffer] -> Body rep -> Body rep-doubleBufferResult valparams buffered (Body _ bnds res) =+doubleBufferResult valparams buffered (Body _ stms res) = let (ctx_res, val_res) = splitAt (length res - length valparams) res- (copybnds, val_res') =+ (copystms, val_res') = unzip $ zipWith3 buffer valparams buffered val_res- in Body () (bnds <> stmsFromList (catMaybes copybnds)) $ ctx_res ++ val_res'+ in Body () (stms <> stmsFromList (catMaybes copystms)) $ ctx_res ++ val_res' where- buffer _ (BufferAlloc bufname _ _ _) _ =- (Nothing, Var bufname)- buffer fparam (BufferCopy bufname ixfun copyname _) (Var v) =+ buffer _ (BufferAlloc bufname _ _ _) se =+ (Nothing, se {resSubExp = Var bufname})+ buffer fparam (BufferCopy bufname ixfun copyname _) (SubExpRes cs (Var v)) = -- To construct the copy we will need to figure out its type -- based on the type of the function parameter. let t = resultType $ paramType fparam summary = MemArray (elemType t) (arrayShape t) NoUniqueness $ ArrayIn bufname ixfun copybnd =- Let (Pattern [] [PatElem copyname summary]) (defAux ()) $+ Let (Pat [PatElem copyname summary]) (defAux ()) $ BasicOp $ Copy v- in (Just copybnd, Var copyname)+ in (Just copybnd, SubExpRes cs (Var copyname)) buffer _ _ se = (Nothing, se) - parammap = M.fromList $ zip (map paramName valparams) res+ parammap = M.fromList $ zip (map paramName valparams) $ map resSubExp res resultType t = t `setArrayDims` map substitute (arrayDims t)
src/Futhark/Optimise/Fusion.hs view
@@ -102,16 +102,14 @@ binding :: [(Ident, Names)] -> FusionGM a -> FusionGM a binding vs = local (`bindVars` vs) -gatherStmPattern :: Pattern -> Exp -> FusionGM FusedRes -> FusionGM FusedRes-gatherStmPattern pat e = binding $ zip idents aliases+gatherStmPat :: Pat -> Exp -> FusionGM FusedRes -> FusionGM FusedRes+gatherStmPat pat e = binding $ zip idents aliases where- idents = patternIdents pat- aliases =- replicate (length (patternContextNames pat)) mempty- ++ expAliases (Alias.analyseExp mempty e)+ idents = patIdents pat+ aliases = expAliases (Alias.analyseExp mempty e) -bindingPat :: Pattern -> FusionGM a -> FusionGM a-bindingPat = binding . (`zip` repeat mempty) . patternIdents+bindingPat :: Pat -> FusionGM a -> FusionGM a+bindingPat = binding . (`zip` repeat mempty) . patIdents bindingParams :: Typed t => [Param t] -> FusionGM a -> FusionGM a bindingParams = binding . (`zip` repeat mempty) . map paramIdent@@ -148,9 +146,12 @@ return res' {kernels = M.map inspectKer $ kernels res'} checkForUpdates :: FusedRes -> Exp -> FusionGM FusedRes-checkForUpdates res (BasicOp (Update src is _)) = do- let ifvs = namesToList $ mconcat $ map freeIn is+checkForUpdates res (BasicOp (Update _ src slice _)) = do+ let ifvs = namesToList $ freeIn slice updateKerInPlaces res ([src], ifvs)+checkForUpdates res (BasicOp (FlatUpdate src slice _)) = do+ let ifvs = namesToList $ freeIn slice+ updateKerInPlaces res ([src], ifvs) checkForUpdates res (Op (Futhark.Scatter _ _ _ written_info)) = do let updt_arrs = map (\(_, _, x) -> x) written_info updateKerInPlaces res (updt_arrs, [])@@ -161,11 +162,11 @@ -- variables in scope (map) by inserting each (pattern-array) name. -- Finally, if the binding is an in-place update, then the @inplace@ field -- of each (result) kernel is updated with the new in-place updates.-bindingFamily :: Pattern -> FusionGM FusedRes -> FusionGM FusedRes+bindingFamily :: Pat -> FusionGM FusedRes -> FusionGM FusedRes bindingFamily pat = local bind where- idents = patternIdents pat- family = patternNames pat+ idents = patIdents pat+ family = patNames pat bind env = foldl (bindingFamilyVar family) env idents bindingTransform :: PatElem -> VName -> SOAC.ArrayTransform -> FusionGM a -> FusionGM a@@ -223,7 +224,7 @@ fuseConsts :: Names -> Stms SOACS -> PassM (Stms SOACS) fuseConsts used_consts consts =- fuseStms mempty consts $ map Var $ namesToList used_consts+ fuseStms mempty consts $ varsRes $ namesToList used_consts fuseFun :: Stms SOACS -> FunDef SOACS -> PassM (FunDef SOACS) fuseFun consts fun = do@@ -397,13 +398,13 @@ [Stm] -> Names -> FusedRes ->- (Pattern, StmAux (), SOAC, Names) ->+ (Pat, StmAux (), SOAC, Names) -> FusionGM FusedRes greedyFuse rem_bnds lam_used_nms res (out_idds, aux, orig_soac, consumed) = do soac <- inlineSOACInputs orig_soac (inp_nms, other_nms) <- soacInputs soac -- Assumption: the free vars in lambda are already in @infusible res@.- let out_nms = patternNames out_idds+ let out_nms = patNames out_idds isInfusible = (`nameIn` infusible res) is_screma = case orig_soac of SOAC.Screma _ form _ ->@@ -452,7 +453,7 @@ let comb = M.unionWith S.union if not fusible_ker- then addNewKerWithInfusible res (patternIdents out_idds, aux, soac, consumed) ufs+ then addNewKerWithInfusible res (patIdents out_idds, aux, soac, consumed) ufs else do -- Need to suitably update `inpArr': -- (i) first remove the inpArr bindings of the old kernel@@ -496,10 +497,10 @@ prodconsGreedyFuse :: FusedRes ->- (Pattern, StmAux (), SOAC, Names) ->+ (Pat, StmAux (), SOAC, Names) -> FusionGM (Bool, [FusedKer], [KernName], [FusedKer], [KernName]) prodconsGreedyFuse res (out_idds, aux, soac, consumed) = do- let out_nms = patternNames out_idds -- Extract VNames from output patterns+ let out_nms = patNames out_idds -- Extract VNames from output patterns to_fuse_knmSet = getKersWithInpArrs res out_nms -- Find kernels which consume outputs to_fuse_knms = S.toList to_fuse_knmSet lookup_kern k = case M.lookup k (kernels res) of@@ -515,7 +516,7 @@ (ok_kers_compat, fused_kers) <- do kers <- forM to_fuse_kers $- attemptFusion mempty (patternNames out_idds) soac consumed+ attemptFusion mempty (patNames out_idds) soac consumed case sequence kers of Nothing -> return (False, []) Just kers' -> return (True, map certifyKer kers')@@ -526,11 +527,11 @@ horizontGreedyFuse :: [Stm] -> FusedRes ->- (Pattern, StmAux (), SOAC, Names) ->+ (Pat, StmAux (), SOAC, Names) -> FusionGM (Bool, [FusedKer], [KernName], [FusedKer], [KernName]) horizontGreedyFuse rem_bnds res (out_idds, aux, soac, consumed) = do (inp_nms, _) <- soacInputs soac- let out_nms = patternNames out_idds+ let out_nms = patNames out_idds infusible_nms = namesFromList $ filter (`nameIn` infusible res) out_nms out_arr_nms = case soac of -- the accumulator result cannot be fused!@@ -554,7 +555,7 @@ -- located and sort based on the index so that partial fusion may -- succeed. We use the last position where one of the kernel -- outputs occur.- let bnd_nms = map (patternNames . stmPattern) rem_bnds+ let bnd_nms = map (patNames . stmPat) rem_bnds kernminds <- forM to_fuse_knms $ \ker_nm -> do ker <- lookupKernel ker_nm case mapMaybe (\out_nm -> L.findIndex (elem out_nm) bnd_nms) (outNames ker) of@@ -567,7 +568,6 @@ -- now try to fuse kernels one by one (in a fold); @ok_ind@ is the index of the -- kernel until which fusion succeded, and @fused_ker@ is the resulting kernel.- use_scope <- (<> scopeOf rem_bnds) <$> askScope (_, ok_ind, _, fused_ker, _) <- foldM ( \(cur_ok, n, prev_ind, cur_ker, ufus_nms) (ker, _ker_nm, bnd_ind) -> do@@ -589,25 +589,20 @@ -- output transforms. cons_no_out_transf = SOAC.nullTransforms $ outputTransform ker - consumer_ok <- do- let consumer_bnd = rem_bnds !! bnd_ind- maybesoac <- runReaderT (SOAC.fromExp $ stmExp consumer_bnd) use_scope- case maybesoac of- -- check that consumer's lambda body does not use- -- directly the produced arrays (e.g., see noFusion3.fut).- Right conssoac ->- return $- not $- curker_outset- `namesIntersect` freeIn (lambdaBody $ SOAC.lambda conssoac)- Left _ -> return True+ -- check that consumer's lambda body does not use+ -- directly the produced arrays (e.g., see noFusion3.fut).+ let consumer_ok =+ not $+ curker_outset+ `namesIntersect` freeIn (lambdaBody $ SOAC.lambda $ fsoac ker) let interm_bnds_ok = cur_ok && consumer_ok && out_transf_ok && cons_no_out_transf && foldl ( \ok bnd -> ok- && not (curker_outset `namesIntersect` freeIn (stmExp bnd)) -- hardwired to False after first fail+ && not (curker_outset `namesIntersect` freeIn (stmExp bnd))+ -- hardwired to False after first fail -- (i) check that the in-between bindings do -- not use the result of current kernel OR ||@@ -619,7 +614,7 @@ not ( null $ curker_outnms- `L.intersect` patternNames (stmPattern bnd)+ `L.intersect` patNames (stmPat bnd) ) ) True@@ -646,7 +641,7 @@ -- Find the kernels we have fused into and the name of the last such -- kernel (if any). let (to_fuse_kers', to_fuse_knms', _) = unzip3 $ take ok_ind kernminds'- new_kernms = drop (ok_ind -1) to_fuse_knms'+ new_kernms = drop (ok_ind - 1) to_fuse_knms' return (ok_ind > 0, [fused_ker], new_kernms, to_fuse_kers', to_fuse_knms') where@@ -686,12 +681,7 @@ -- be considered a stream, to avoid infinite recursion. fusionGatherStms fres- ( Let- (Pattern [] pes)- bndtp- (DoLoop [] merge (ForLoop i it w loop_vars) body)- : bnds- )+ (Let (Pat pes) bndtp (DoLoop merge (ForLoop i it w loop_vars) body) : bnds) res | not $ null loop_vars = do let (merge_params, merge_init) = unzip merge@@ -711,11 +701,11 @@ let lam_params = chunk_param : acc_params ++ [offset_param] ++ chunked_params - lam_body <- runBodyBinder $+ lam_body <- runBodyBuilder $ localScope (scopeOfLParams lam_params) $ do let merge' = zip merge_params $ map (Futhark.Var . paramName) acc_params j <- newVName "j"- loop_body <- runBodyBinder $ do+ loop_body <- runBodyBuilder $ do forM_ (zip loop_params chunked_params) $ \(p, a_p) -> letBindNames [paramName p] $ BasicOp $@@ -725,7 +715,7 @@ return body eBody [ pure $- DoLoop [] merge' (ForLoop j it (Futhark.Var chunk_size) []) loop_body,+ DoLoop merge' (ForLoop j it (Futhark.Var chunk_size) []) loop_body, pure $ BasicOp $ BinOp (Add Int64 OverflowUndef) (Futhark.Var offset) (Futhark.Var chunk_size) ]@@ -745,7 +735,7 @@ fusionGatherStms fres- (Let (Pattern [] (pes <> [discard_pe])) bndtp (Op stream) : bnds)+ (Let (Pat (pes <> [discard_pe])) bndtp (Op stream) : bnds) res fusionGatherStms fres (bnd@(Let pat _ e) : bnds) res = do maybesoac <- SOAC.fromExp e@@ -754,14 +744,14 @@ -- We put the variables produced by Scatter into the infusible -- set to force horizontal fusion. It is not possible to -- producer/consumer-fuse Scatter anyway.- fres' <- addNamesToInfusible fres $ namesFromList $ patternNames pat+ fres' <- addNamesToInfusible fres $ namesFromList $ patNames pat fres'' <- mapLike fres' soac lam checkForUpdates fres'' e Right soac@(SOAC.Hist _ _ lam _) -> do -- We put the variables produced by Hist into the infusible -- set to force horizontal fusion. It is not possible to -- producer/consumer-fuse Hist anyway.- fres' <- addNamesToInfusible fres $ namesFromList $ patternNames pat+ fres' <- addNamesToInfusible fres $ namesFromList $ patNames pat mapLike fres' soac lam Right soac@(SOAC.Screma _ (ScremaForm scans reds map_lam) _) -> reduceLike soac (map scanLambda scans <> map redLambda reds <> [map_lam]) $@@ -777,12 +767,12 @@ Sequential -> [lam] reduceLike soac lambdas nes _- | [pe] <- patternValueElements pat,+ | Pat [pe] <- pat, Just (src, trns) <- SOAC.transformFromExp (stmCerts bnd) e -> bindingTransform pe src trns $ fusionGatherStms fres bnds res | otherwise -> do- let pat_vars = map (BasicOp . SubExp . Var) $ patternNames pat- bres <- gatherStmPattern pat e $ fusionGatherStms fres bnds res+ let pat_vars = map (BasicOp . SubExp . Var) $ patNames pat+ bres <- gatherStmPat pat e $ fusionGatherStms fres bnds res bres' <- checkForUpdates bres e foldM fusionGatherExp bres' (e : pat_vars) where@@ -803,11 +793,11 @@ consumed' <- varsAliases consumed greedyFuse rem_bnds used_lam blres (pat, aux, soac, consumed') fusionGatherStms fres [] res =- foldM fusionGatherExp fres $ map (BasicOp . SubExp) res+ foldM fusionGatherExp fres $ map (BasicOp . SubExp . resSubExp) res fusionGatherExp :: FusedRes -> Exp -> FusionGM FusedRes-fusionGatherExp fres (DoLoop ctx val form loop_body) = do- fres' <- addNamesToInfusible fres $ freeIn form <> freeIn ctx <> freeIn val+fusionGatherExp fres (DoLoop merge form loop_body) = do+ fres' <- addNamesToInfusible fres $ freeIn form <> freeIn merge let form_idents = case form of ForLoop i it _ loopvars ->@@ -815,11 +805,8 @@ WhileLoop {} -> [] new_res <-- binding- ( zip (form_idents ++ map (paramIdent . fst) (ctx <> val)) $- repeat mempty- )- $ fusionGatherBody mempty loop_body+ binding (zip (form_idents ++ map (paramIdent . fst) merge) $ repeat mempty) $+ fusionGatherBody mempty loop_body -- make the inpArr infusible, so that they -- cannot be fused from outside the loop: let (inp_arrs, _) = unzip $ M.toList $ inpArr new_res@@ -902,10 +889,10 @@ fuseInExp :: Exp -> FusionGM Exp -- Handle loop specially because we need to bind the types of the -- merge variables.-fuseInExp (DoLoop ctx val form loopbody) =+fuseInExp (DoLoop merge form loopbody) = binding (zip form_idents $ repeat mempty) $- bindingParams (map fst $ ctx ++ val) $- DoLoop ctx val form <$> fuseInBody loopbody+ bindingParams (map fst merge) $+ DoLoop merge form <$> fuseInBody loopbody where form_idents = case form of WhileLoop {} -> []@@ -926,12 +913,12 @@ body' <- bindingParams params $ fuseInBody body return $ Lambda params body' rtp -replaceSOAC :: Pattern -> StmAux () -> Exp -> FusionGM (Stms SOACS)-replaceSOAC (Pattern _ []) _ _ = return mempty-replaceSOAC pat@(Pattern _ (patElem : _)) aux e = do+replaceSOAC :: Pat -> StmAux () -> Exp -> FusionGM (Stms SOACS)+replaceSOAC (Pat []) _ _ = return mempty+replaceSOAC pat@(Pat (patElem : _)) aux e = do fres <- asks fusedRes let pat_nm = patElemName patElem- names = patternIdents pat+ names = patIdents pat case M.lookup pat_nm (outArr fres) of Nothing -> oneStm . Let pat aux <$> fuseInExp e@@ -957,13 +944,13 @@ insertKerSOAC :: StmAux () -> [VName] -> FusedKer -> FusionGM (Stms SOACS) insertKerSOAC aux names ker = do new_soac' <- finaliseSOAC $ fsoac ker- runBinder_ $ do+ runBuilder_ $ do f_soac <- SOAC.toSOAC new_soac' -- The fused kernel may consume more than the original SOACs (see -- issue #224). We insert copy expressions to fix it. f_soac' <- copyNewlyConsumed (fusedConsumed ker) $ addOpAliases mempty f_soac validents <- zipWithM newIdent (map baseString names) $ SOAC.typeOf new_soac'- auxing (kerAux ker <> aux) $ letBind (basicPattern [] validents) $ Op f_soac'+ auxing (kerAux ker <> aux) $ letBind (basicPat validents) $ Op f_soac' transformOutput (outputTransform ker) names validents -- | Perform simplification and fusion inside the lambda(s) of a SOAC.@@ -1002,7 +989,7 @@ copyNewlyConsumed :: Names -> Futhark.SOAC (Aliases.Aliases SOACS) ->- Binder SOACS (Futhark.SOAC SOACS)+ Builder SOACS (Futhark.SOAC SOACS) copyNewlyConsumed was_consumed soac = case soac of Futhark.Screma w arrs (Futhark.ScremaForm scans reds map_lam) -> do
src/Futhark/Optimise/Fusion/Composing.hs view
@@ -21,7 +21,7 @@ import qualified Data.Map.Strict as M import Data.Maybe import qualified Futhark.Analysis.HORep.SOAC as SOAC-import Futhark.Binder (Bindable (..), insertStm, insertStms, mkLet)+import Futhark.Builder (Buildable (..), insertStm, insertStms, mkLet) import Futhark.Construct (mapResult) import Futhark.IR import Futhark.Util (dropLast, splitAt3, takeLast)@@ -44,7 +44,7 @@ -- The result is the fused function, and a list of the array inputs -- expected by the SOAC containing the fused function. fuseMaps ::- Bindable rep =>+ Buildable rep => -- | The producer var names that still need to be returned Names -> -- | Function of SOAC to be fused.@@ -76,19 +76,15 @@ } new_body2 = let bnds res =- [ mkLet [] [p] $ BasicOp $ SubExp e- | (p, e) <- zip pat res+ [ certify cs $ mkLet [p] $ BasicOp $ SubExp e+ | (p, SubExpRes cs e) <- zip pat res ] bindLambda res = stmsFromList (bnds res) `insertStms` makeCopiesInner (lambdaBody lam2) in makeCopies $ mapResult bindLambda (lambdaBody lam1) new_body2_rses = bodyResult new_body2 new_body2' =- new_body2- { bodyResult =- new_body2_rses- ++ map (Var . identName) unfus_pat- }+ new_body2 {bodyResult = new_body2_rses ++ map (varRes . identName) unfus_pat} -- infusible variables are added at the end of the result/pattern/type (lam2redparams, unfus_pat, pat, inputmap, makeCopies, makeCopiesInner) = fuseInputs unfus_nms lam1 inp1 out1 lam2 inp2@@ -96,7 +92,7 @@ --(unfus_accpat, unfus_arrpat) = splitAt (length unfus_accs) unfus_pat fuseInputs ::- Bindable rep =>+ Buildable rep => Names -> Lambda rep -> [SOAC.Input] ->@@ -172,7 +168,7 @@ _ -> (m, ra) removeDuplicateInputs ::- Bindable rep =>+ Buildable rep => M.Map Ident SOAC.Input -> (M.Map Ident SOAC.Input, Body rep -> Body rep) removeDuplicateInputs = fst . M.foldlWithKey' comb ((M.empty, id), M.empty)@@ -188,11 +184,10 @@ arrmap ) forward to from b =- mkLet [] [to] (BasicOp $ SubExp $ Var from)- `insertStm` b+ mkLet [to] (BasicOp $ SubExp $ Var from) `insertStm` b fuseRedomap ::- Bindable rep =>+ Buildable rep => Names -> [VName] -> Lambda rep ->
src/Futhark/Optimise/Fusion/LoopKernel.hs view
@@ -76,7 +76,7 @@ SOAC.ArrayTransforms -> [VName] -> [Ident] ->- Binder SOACS ()+ Builder SOACS () transformOutput ts names = descend ts where descend ts' validents =@@ -86,15 +86,15 @@ letBindNames [k] $ BasicOp $ SubExp $ Var $ identName valident t SOAC.:< ts'' -> do let (es, css) = unzip $ map (applyTransform t) validents- mkPat (Ident nm tp) = Pattern [] [PatElem nm tp]- opts <- concat <$> mapM primOpType es+ mkPat (Ident nm tp) = Pat [PatElem nm tp]+ opts <- concat <$> mapM basicOpType es newIds <- forM (zip names opts) $ \(k, opt) -> newIdent (baseString k) opt forM_ (zip3 css newIds es) $ \(cs, ids, e) -> certifying cs $ letBind (mkPat ids) (BasicOp e) descend ts'' newIds -applyTransform :: SOAC.ArrayTransform -> Ident -> (BasicOp, Certificates)+applyTransform :: SOAC.ArrayTransform -> Ident -> (BasicOp, Certs) applyTransform (SOAC.Rearrange cs perm) v = (Rearrange perm' $ identName v, cs) where@@ -684,10 +684,10 @@ let map_body = mkBody ( oneStm $- Let (setPatternOuterDimTo w map_pat) (defAux ()) $+ Let (setPatOuterDimTo w map_pat) (defAux ()) $ Op $ Futhark.Screma w arrs' scan_form )- $ map Var $ patternNames map_pat+ $ varsRes $ patNames map_pat map_fun' = Lambda map_params map_body map_rettype perm = case lambdaReturnType map_fun of [] -> []@@ -710,8 +710,8 @@ let t = paramType param `setOuterSize` w in param {paramDec = t} -setPatternOuterDimTo :: SubExp -> Pattern -> Pattern-setPatternOuterDimTo w = fmap (`setOuterSize` w)+setPatOuterDimTo :: SubExp -> Pat -> Pat+setPatOuterDimTo w = fmap (`setOuterSize` w) -- Now for fiddling with transpositions... @@ -857,7 +857,7 @@ stripArray (length shape - length outershape) inpt inner_body <-- runBodyBinder $+ runBodyBuilder $ eBody [SOAC.toExp $ inner $ map (SOAC.identInput . paramIdent) ps] let inner_fun = Lambda
src/Futhark/Optimise/InPlaceLowering.hs view
@@ -71,7 +71,7 @@ import Control.Monad.RWS import qualified Data.Map.Strict as M import Futhark.Analysis.Alias-import Futhark.Binder+import Futhark.Builder import Futhark.IR.Aliases import Futhark.IR.GPU import Futhark.IR.MC@@ -119,17 +119,14 @@ descend [] m = m descend (stm : stms) m = bindingStm stm $ descend stms m -type Constraints rep = (Bindable rep, CanBeAliased (Op rep))+type Constraints rep = (Buildable rep, CanBeAliased (Op rep)) optimiseBody :: Constraints rep => Body (Aliases rep) -> ForwardingM rep (Body (Aliases rep)) optimiseBody (Body als bnds res) = do- bnds' <-- deepen $- optimiseStms (stmsToList bnds) $- mapM_ seen res+ bnds' <- deepen $ optimiseStms (stmsToList bnds) $ mapM_ (seen . resSubExp) res return $ Body als (stmsFromList bnds') res where seen Constant {} = return ()@@ -156,7 +153,7 @@ let updated_names = map updateName updates notUpdated =- not . any (`elem` updated_names) . patternNames . stmPattern+ not . any (`elem` updated_names) . patNames . stmPat -- Condition (5) and (7) are assumed to be checked by -- lowerUpdate.@@ -171,11 +168,11 @@ checkIfForwardableUpdate bnd' return $ bnd' : bnds' where- boundHere = patternNames $ stmPattern bnd+ boundHere = patNames $ stmPat bnd checkIfForwardableUpdate (Let pat (StmAux cs _ _) e)- | Pattern [] [PatElem v dec] <- pat,- BasicOp (Update src slice (Var ve)) <- e =+ | Pat [PatElem v dec] <- pat,+ BasicOp (Update Unsafe src slice (Var ve)) <- e = maybeForward ve v dec cs src slice checkIfForwardableUpdate _ = return () @@ -184,10 +181,9 @@ Let pat dec <$> optimiseExp e optimiseExp :: Constraints rep => Exp (Aliases rep) -> ForwardingM rep (Exp (Aliases rep))-optimiseExp (DoLoop ctx val form body) =- bindingScope (scopeOf form) $- bindingFParams (map fst $ ctx ++ val) $- DoLoop ctx val form <$> optimiseBody body+optimiseExp (DoLoop merge form body) =+ bindingScope (scopeOf form) . bindingFParams (map fst merge) $+ DoLoop merge form <$> optimiseBody body optimiseExp (Op op) = do f <- asks topOnOp Op <$> f op@@ -199,7 +195,7 @@ } onSegOp ::- (Bindable rep, CanBeAliased (Op rep)) =>+ (Buildable rep, CanBeAliased (Op rep)) => SegOp lvl (Aliases rep) -> ForwardingM rep (SegOp lvl (Aliases rep)) onSegOp op =@@ -324,7 +320,7 @@ ForwardingM rep a -> ForwardingM rep a bindingStm (Let pat _ _) = local $ \(TopDown n vtable d x y) ->- let entries = M.fromList $ map entry $ patternElements pat+ let entries = M.fromList $ map entry $ patElems pat entry patElem = let (aliases, _) = patElemDec patElem in ( patElemName patElem,@@ -394,7 +390,7 @@ VName -> VName -> LetDec (Aliases rep) ->- Certificates ->+ Certs -> VName -> Slice SubExp -> ForwardingM rep ()
src/Futhark/Optimise/InPlaceLowering/LowerIntoStm.hs view
@@ -25,7 +25,7 @@ updateName :: VName, -- | Type of result. updateType :: dec,- updateCertificates :: Certificates,+ updateCerts :: Certs, updateSource :: VName, updateIndices :: Slice SubExp, updateValue :: VName@@ -46,33 +46,32 @@ lowerUpdate :: ( MonadFreshNames m,- Bindable rep,+ Buildable rep, LetDec rep ~ Type, CanBeAliased (Op rep) ) => LowerUpdate rep m-lowerUpdate scope (Let pat aux (DoLoop ctx val form body)) updates = do- canDo <- lowerUpdateIntoLoop scope updates pat ctx val form body+lowerUpdate scope (Let pat aux (DoLoop merge form body)) updates = do+ canDo <- lowerUpdateIntoLoop scope updates pat merge form body Just $ do- (prebnds, postbnds, ctxpat, valpat, ctx', val', body') <- canDo+ (prebnds, postbnds, pat', merge', body') <- canDo return $ prebnds ++ [ certify (stmAuxCerts aux) $- mkLet ctxpat valpat $ DoLoop ctx' val' form body'+ mkLet pat' $ DoLoop merge' form body' ] ++ postbnds lowerUpdate _ (Let pat aux (BasicOp (SubExp (Var v))))- [DesiredUpdate bindee_nm bindee_dec cs src is val]- | patternNames pat == [src] =+ [DesiredUpdate bindee_nm bindee_dec cs src (Slice is) val]+ | patNames pat == [src] = let is' = fullSlice (typeOf bindee_dec) is- in Just $- return- [ certify (stmAuxCerts aux <> cs) $- mkLet [] [Ident bindee_nm $ typeOf bindee_dec] $- BasicOp $ Update v is' $ Var val- ]+ in Just . pure $+ [ certify (stmAuxCerts aux <> cs) $+ mkLet [Ident bindee_nm $ typeOf bindee_dec] $+ BasicOp $ Update Unsafe v is' $ Var val+ ] lowerUpdate _ _ _ = Nothing @@ -81,12 +80,12 @@ scope (Let pat aux (Op (SegOp (SegMap lvl space ts kbody)))) updates- | all ((`elem` patternNames pat) . updateValue) updates,+ | all ((`elem` patNames pat) . updateValue) updates, not source_used_in_kbody = do mk <- lowerUpdatesIntoSegMap scope pat updates space kbody Just $ do (pat', kbody', poststms) <- mk- let cs = stmAuxCerts aux <> foldMap updateCertificates updates+ let cs = stmAuxCerts aux <> foldMap updateCerts updates return $ certify cs (Let pat' aux $ Op $ SegOp $ SegMap lvl space ts kbody') : stmsToList poststms@@ -104,13 +103,13 @@ lowerUpdatesIntoSegMap :: MonadFreshNames m => Scope (Aliases GPU) ->- Pattern (Aliases GPU) ->+ Pat (Aliases GPU) -> [DesiredUpdate (LetDec (Aliases GPU))] -> SegSpace -> KernelBody (Aliases GPU) -> Maybe ( m- ( Pattern (Aliases GPU),+ ( Pat (Aliases GPU), KernelBody (Aliases GPU), Stms (Aliases GPU) )@@ -118,11 +117,11 @@ lowerUpdatesIntoSegMap scope pat updates kspace kbody = do -- The updates are all-or-nothing. Being more liberal would require -- changes to the in-place-lowering pass itself.- mk <- zipWithM onRet (patternElements pat) (kernelBodyResult kbody)+ mk <- zipWithM onRet (patElems pat) (kernelBodyResult kbody) return $ do (pes, bodystms, krets, poststms) <- unzip4 <$> sequence mk return- ( Pattern [] pes,+ ( Pat pes, kbody { kernelBodyStms = kernelBodyStms kbody <> mconcat bodystms, kernelBodyResult = krets@@ -135,48 +134,46 @@ onRet (PatElem v v_dec) ret | Just (DesiredUpdate bindee_nm bindee_dec _cs src slice _val) <- find ((== v) . updateValue) updates = do- Returns _ se <- Just ret+ Returns _ cs se <- Just ret -- The slice we're writing per thread must fully cover the -- underlying dimensions. guard $ let (dims', slice') = unzip . drop (length gtids) . filter (isNothing . dimFix . snd) $- zip (arrayDims (typeOf bindee_dec)) slice- in isFullSlice (Shape dims') slice'+ zip (arrayDims (typeOf bindee_dec)) (unSlice slice)+ in isFullSlice (Shape dims') (Slice slice') Just $ do (slice', bodystms) <-- flip runBinderT scope $+ flip runBuilderT scope $ traverse (toSubExp "index") $- fixSlice (map (fmap pe64) slice) $- map (pe64 . Var) gtids+ fixSlice (fmap pe64 slice) $ map (pe64 . Var) gtids let res_dims = arrayDims $ snd bindee_dec- ret' = WriteReturns (Shape res_dims) src [(map DimFix slice', se)]+ ret' = WriteReturns cs (Shape res_dims) src [(Slice $ map DimFix slice', se)] return ( PatElem bindee_nm bindee_dec, bodystms, ret', oneStm $- mkLet [] [Ident v $ typeOf v_dec] $+ mkLet [Ident v $ typeOf v_dec] $ BasicOp $ Index bindee_nm slice ) onRet pe ret = Just $ return (pe, mempty, ret, mempty) lowerUpdateIntoLoop ::- ( Bindable rep,- BinderOps rep,+ ( Buildable rep,+ BuilderOps rep, Aliased rep, LetDec rep ~ (als, Type), MonadFreshNames m ) => Scope rep -> [DesiredUpdate (LetDec rep)] ->- Pattern rep ->- [(FParam rep, SubExp)] ->+ Pat rep -> [(FParam rep, SubExp)] -> LoopForm rep -> Body rep ->@@ -185,13 +182,11 @@ ( [Stm rep], [Stm rep], [Ident],- [Ident], [(FParam rep, SubExp)],- [(FParam rep, SubExp)], Body rep ) )-lowerUpdateIntoLoop scope updates pat ctx val form body = do+lowerUpdateIntoLoop scope updates pat val form body = do -- Algorithm: -- -- 0) Map each result of the loop body to a corresponding in-place@@ -227,19 +222,19 @@ Just $ do in_place_map <- mk_in_place_map (val', prebnds, postbnds) <- mkMerges in_place_map- let (ctxpat, valpat) = mkResAndPat in_place_map+ let valpat = mkResAndPat in_place_map idxsubsts = indexSubstitutions in_place_map (idxsubsts', newbnds) <- substituteIndices idxsubsts $ bodyStms body (body_res, res_bnds) <- manipulateResult in_place_map idxsubsts' let body' = mkBody (newbnds <> res_bnds) body_res- return (prebnds, postbnds, ctxpat, valpat, ctx, val', body')+ return (prebnds, postbnds, valpat, val', body') where usedInBody = mconcat $ map (`lookupAliases` scope) $ namesToList $ freeIn body <> freeIn form- resmap = zip (bodyResult body) $ patternValueIdents pat+ resmap = zip (bodyResult body) $ patIdents pat mkMerges ::- (MonadFreshNames m, Bindable rep) =>+ (MonadFreshNames m, Buildable rep) => [LoopResultSummary (als, Type)] -> m ([(Param DeclType, SubExp)], [Stm rep], [Stm rep]) mkMerges summaries = do@@ -256,18 +251,17 @@ (updateValue update) (source_t `setArrayDims` sliceDims (updateIndices update)) tell- ( [ mkLet [] [Ident source source_t] $- BasicOp $- Update- (updateSource update)- (fullSlice source_t $ updateIndices update)- $ snd $ mergeParam summary+ ( [ mkLet [Ident source source_t] . BasicOp $+ Update+ Unsafe+ (updateSource update)+ (fullSlice source_t $ unSlice $ updateIndices update)+ $ snd $ mergeParam summary ],- [ mkLet [] [elmident] $- BasicOp $- Index- (updateName update)- (fullSlice source_t $ updateIndices update)+ [ mkLet [elmident] . BasicOp $+ Index+ (updateName update)+ (fullSlice source_t $ unSlice $ updateIndices update) ] ) return $@@ -281,15 +275,13 @@ mkResAndPat summaries = let (origpat, extrapat) = partitionEithers $ map mkResAndPat' summaries- in ( patternContextIdents pat,- origpat ++ extrapat- )+ in origpat ++ extrapat mkResAndPat' summary | Just (update, _, _) <- relatedUpdate summary = Right (Ident (updateName update) (snd $ updateType update)) | otherwise =- Left (inPatternAs summary)+ Left (inPatAs summary) summariseLoop :: ( Aliased rep,@@ -298,7 +290,7 @@ Scope rep -> [DesiredUpdate (als, Type)] -> Names ->- [(SubExp, Ident)] ->+ [(SubExpRes, Ident)] -> [(Param DeclType, SubExp)] -> Maybe (m [LoopResultSummary (als, Type)]) summariseLoop scope updates usedInBody resmap merge =@@ -316,7 +308,7 @@ return LoopResultSummary { resultSubExp = se,- inPatternAs = v,+ inPatAs = v, mergeParam = (fparam, mergeinit), relatedUpdate = Just@@ -336,8 +328,8 @@ loopInvariant Constant {} = True data LoopResultSummary dec = LoopResultSummary- { resultSubExp :: SubExp,- inPatternAs :: Ident,+ { resultSubExp :: SubExpRes,+ inPatAs :: Ident, mergeParam :: (Param DeclType, SubExp), relatedUpdate :: Maybe (DesiredUpdate dec, VName, dec) }@@ -354,28 +346,26 @@ return (name, (cs, nm, dec, is)) manipulateResult ::- (Bindable rep, MonadFreshNames m) =>+ (Buildable rep, MonadFreshNames m) => [LoopResultSummary (LetDec rep)] -> IndexSubstitutions (LetDec rep) -> m (Result, Stms rep) manipulateResult summaries substs = do let (orig_ses, updated_ses) = partitionEithers $ map unchangedRes summaries (subst_ses, res_bnds) <- runWriterT $ zipWithM substRes updated_ses substs- return (orig_ses ++ subst_ses, stmsFromList res_bnds)+ pure (orig_ses ++ subst_ses, stmsFromList res_bnds) where unchangedRes summary = case relatedUpdate summary of Nothing -> Left $ resultSubExp summary Just _ -> Right $ resultSubExp summary- substRes (Var res_v) (subst_v, (_, nm, _, _))+ substRes (SubExpRes res_cs (Var res_v)) (subst_v, (_, nm, _, _)) | res_v == subst_v =- return $ Var nm- substRes res_se (_, (cs, nm, dec, is)) = do+ pure $ SubExpRes res_cs $ Var nm+ substRes (SubExpRes res_cs res_se) (_, (cs, nm, dec, Slice is)) = do v' <- newIdent' (++ "_updated") $ Ident nm $ typeOf dec tell- [ certify cs $- mkLet [] [v'] $- BasicOp $- Update nm (fullSlice (typeOf dec) is) res_se+ [ certify (res_cs <> cs) . mkLet [v'] . BasicOp $+ Update Unsafe nm (fullSlice (typeOf dec) is) res_se ]- return $ Var $ identName v'+ pure $ varRes $ identName v'
src/Futhark/Optimise/InPlaceLowering/SubstituteIndices.hs view
@@ -20,7 +20,7 @@ import Futhark.Transform.Substitute import Futhark.Util -type IndexSubstitution dec = (Certificates, VName, dec, Slice SubExp)+type IndexSubstitution dec = (Certs, VName, dec, Slice SubExp) type IndexSubstitutions dec = [(VName, IndexSubstitution dec)] @@ -36,8 +36,8 @@ -- | Perform the substitution. substituteIndices :: ( MonadFreshNames m,- BinderOps rep,- Bindable rep,+ BuilderOps rep,+ Buildable rep, Aliased rep, LetDec rep ~ dec ) =>@@ -45,43 +45,42 @@ Stms rep -> m (IndexSubstitutions dec, Stms rep) substituteIndices substs bnds =- runBinderT (substituteIndicesInStms substs bnds) types+ runBuilderT (substituteIndicesInStms substs bnds) types where types = typeEnvFromSubstitutions substs substituteIndicesInStms ::- (MonadBinder m, Bindable (Rep m), Aliased (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m), Aliased (Rep m)) => IndexSubstitutions (LetDec (Rep m)) -> Stms (Rep m) -> m (IndexSubstitutions (LetDec (Rep m))) substituteIndicesInStms = foldM substituteIndicesInStm substituteIndicesInStm ::- (MonadBinder m, Bindable (Rep m), Aliased (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m), Aliased (Rep m)) => IndexSubstitutions (LetDec (Rep m)) -> Stm (Rep m) -> m (IndexSubstitutions (LetDec (Rep m))) substituteIndicesInStm substs (Let pat rep e) = do e' <- substituteIndicesInExp substs e- (substs', pat') <- substituteIndicesInPattern substs pat+ (substs', pat') <- substituteIndicesInPat substs pat addStm $ Let pat' rep e' return substs' -substituteIndicesInPattern ::- (MonadBinder m, LetDec (Rep m) ~ dec) =>+substituteIndicesInPat ::+ (MonadBuilder m, LetDec (Rep m) ~ dec) => IndexSubstitutions (LetDec (Rep m)) ->- PatternT dec ->- m (IndexSubstitutions (LetDec (Rep m)), PatternT dec)-substituteIndicesInPattern substs pat = do- (substs', context) <- mapAccumLM sub substs $ patternContextElements pat- (substs'', values) <- mapAccumLM sub substs' $ patternValueElements pat- return (substs'', Pattern context values)+ PatT dec ->+ m (IndexSubstitutions (LetDec (Rep m)), PatT dec)+substituteIndicesInPat substs pat = do+ (substs', pes) <- mapAccumLM sub substs $ patElems pat+ return (substs', Pat pes) where sub substs' patElem = return (substs', patElem) substituteIndicesInExp ::- ( MonadBinder m,- Bindable (Rep m),+ ( MonadBuilder m,+ Buildable (Rep m), Aliased (Rep m), LetDec (Rep m) ~ dec ) =>@@ -91,7 +90,7 @@ substituteIndicesInExp substs (Op op) = do let used_in_op = filter ((`nameIn` freeIn op) . fst) substs var_substs <- fmap mconcat $- forM used_in_op $ \(v, (cs, src, src_dec, is)) -> do+ forM used_in_op $ \(v, (cs, src, src_dec, Slice is)) -> do v' <- certifying cs $ letExp "idx" $ BasicOp $ Index src $ fullSlice (typeOf src_dec) is@@ -114,10 +113,9 @@ row <- certifying cs2 $ letExp (baseString v ++ "_row") $- BasicOp $ Index src2 $ fullSlice (typeOf src2dec) is2+ BasicOp $ Index src2 $ fullSlice (typeOf src2dec) (unSlice is2) row_copy <-- letExp (baseString v ++ "_row_copy") $- BasicOp $ Copy row+ letExp (baseString v ++ "_row_copy") $ BasicOp $ Copy row return $ update v@@ -128,7 +126,7 @@ `setType` ( typeOf src2dec `setArrayDims` sliceDims is2 ),- []+ Slice [] ) substs' consumingSubst substs' _ =@@ -136,7 +134,7 @@ in foldM consumingSubst substs . namesToList . consumedInExp substituteIndicesInSubExp ::- MonadBinder m =>+ MonadBuilder m => IndexSubstitutions (LetDec (Rep m)) -> SubExp -> m SubExp@@ -146,22 +144,22 @@ return se substituteIndicesInVar ::- MonadBinder m =>+ MonadBuilder m => IndexSubstitutions (LetDec (Rep m)) -> VName -> m VName substituteIndicesInVar substs v- | Just (cs2, src2, _, []) <- lookup v substs =+ | Just (cs2, src2, _, Slice []) <- lookup v substs = certifying cs2 $ letExp (baseString src2) $ BasicOp $ SubExp $ Var src2- | Just (cs2, src2, src2_dec, is2) <- lookup v substs =+ | Just (cs2, src2, src2_dec, Slice is2) <- lookup v substs = certifying cs2 $ letExp "idx" $ BasicOp $ Index src2 $ fullSlice (typeOf src2_dec) is2 | otherwise = return v substituteIndicesInBody ::- (MonadBinder m, Bindable (Rep m), Aliased (Rep m)) =>+ (MonadBuilder m, Buildable (Rep m), Aliased (Rep m)) => IndexSubstitutions (LetDec (Rep m)) -> Body (Rep m) -> m (Body (Rep m))@@ -171,8 +169,11 @@ collectStms $ substituteIndicesInStms substs stms (res', res_stms) <- inScopeOf stms' $- collectStms $ mapM (substituteIndicesInSubExp substs') res+ collectStms $ mapM (onSubExpRes substs') res mkBodyM (stms' <> res_stms) res'+ where+ onSubExpRes substs' (SubExpRes cs se) =+ SubExpRes cs <$> substituteIndicesInSubExp substs' se update :: VName ->
src/Futhark/Optimise/InliningDeadFun.hs view
@@ -4,7 +4,8 @@ -- | This module implements a compiler pass for inlining functions, -- then removing those that have become dead. module Futhark.Optimise.InliningDeadFun- ( inlineFunctions,+ ( inlineAggressively,+ inlineConservatively, removeDeadFunctions, ) where@@ -14,11 +15,10 @@ import Control.Parallel.Strategies import Data.List (partition) import qualified Data.Map.Strict as M-import Data.Maybe import qualified Data.Set as S import Futhark.Analysis.CallGraph import qualified Futhark.Analysis.SymbolTable as ST-import Futhark.Binder+import Futhark.Builder import Futhark.IR.SOACS import Futhark.IR.SOACS.Simplify ( simpleSOACS,@@ -45,75 +45,90 @@ (bs, srcs) = unzip $ parMap rpar f' as in (bs, mconcat srcs) -aggInlineFunctions :: MonadFreshNames m => Prog SOACS -> m (Prog SOACS)-aggInlineFunctions prog =+-- It is more efficient to shrink the program as soon as possible,+-- rather than wait until it has balooned after full inlining. This+-- is the inverse rate at which we perform full simplification after+-- inlining. For the other steps we just do copy propagation. The+-- simplification rates used have been determined heuristically and+-- are probably not optimal for any given program.+inlineFunctions ::+ MonadFreshNames m =>+ Int ->+ CallGraph ->+ S.Set Name ->+ Prog SOACS ->+ m (Prog SOACS)+inlineFunctions simplify_rate cg what_should_be_inlined prog = do let Prog consts funs = prog- in uncurry Prog . fmap (filter keep)- <$> recurse 0 (ST.fromScope (addScopeWisdom (scopeOf consts)), consts, funs)- where- fdmap fds =- M.fromList $ zip (map funDefName fds) fds+ vtable = ST.fromScope (addScopeWisdom (scopeOf consts)) - cg = buildCallGraph prog- noninlined = findNoninlined prog+ uncurry Prog <$> recurse (1, vtable) (consts, funs) what_should_be_inlined+ where+ fdmap fds = M.fromList $ zip (map funDefName fds) fds - noCallsTo which fundec =- not $ any (`S.member` which) $ allCalledBy (funDefName fundec) cg+ noCallsTo which from = S.null $ allCalledBy from cg `S.intersection` which - -- The inverse rate at which we perform full simplification- -- after inlining. For the other steps we just do copy- -- propagation. The rate here has been determined- -- heuristically and is probably not optimal for any given- -- program.- simplifyRate :: Int- simplifyRate = 4+ recurse (i, vtable) (consts, funs) to_inline = do+ let (to_inline_now, to_inline_later) =+ S.partition (noCallsTo to_inline) to_inline+ (dont_inline_in, to_inline_in) =+ partition (noCallsTo to_inline_now . funDefName) funs - -- We apply simplification after every round of inlining,- -- because it is more efficient to shrink the program as soon- -- as possible, rather than wait until it has balooned after- -- full inlining.- recurse i (vtable, consts, funs) = do- let remaining = S.fromList $ map funDefName funs- (to_be_inlined, maybe_inline_in) =- partition (noCallsTo remaining) funs- (not_to_inline_in, to_inline_in) =- partition- ( noCallsTo- (S.fromList $ map funDefName to_be_inlined)- )- maybe_inline_in- keep_although_inlined = filter keep to_be_inlined- if null to_be_inlined- then return (consts, funs)+ if null to_inline_now+ then pure (consts, funs) else do+ let inlinemap =+ fdmap $ filter ((`S.member` to_inline_now) . funDefName) dont_inline_in (vtable', consts') <-- if any ((`calledByConsts` cg) . funDefName) to_be_inlined+ if any (`calledByConsts` cg) to_inline_now then simplifyConsts . performCSEOnStms True- =<< inlineInStms (fdmap to_be_inlined) consts+ =<< inlineInStms inlinemap consts else pure (vtable, consts) let simplifyFun' fd- | i `rem` simplifyRate == 0 =+ | i `rem` simplify_rate == 0 = copyPropagateInFun simpleSOACS vtable' . performCSEOnFunDef True =<< simplifyFun vtable' fd | otherwise = copyPropagateInFun simpleSOACS vtable' fd - let onFun =- simplifyFun'- <=< inlineInFunDef (fdmap to_be_inlined)+ onFun = simplifyFun' <=< inlineInFunDef inlinemap+ to_inline_in' <- parMapM onFun to_inline_in- fmap (keep_although_inlined <>)- <$> recurse- (i + 1)- (vtable', consts', not_to_inline_in <> to_inline_in') - keep fd =- isJust (funDefEntryPoint fd)- || funDefName fd `S.member` noninlined+ recurse+ (i + 1, vtable')+ (consts', dont_inline_in <> to_inline_in')+ to_inline_later +calledOnce :: CallGraph -> S.Set Name+calledOnce = S.fromList . map fst . filter ((== 1) . snd) . M.toList . numOccurences++inlineBecauseTiny :: Prog SOACS -> S.Set Name+inlineBecauseTiny = foldMap onFunDef . progFuns+ where+ onFunDef fd+ | length (bodyStms (funDefBody fd)) < 2+ || "inline" `inAttrs` funDefAttrs fd =+ S.singleton (funDefName fd)+ | otherwise = mempty++-- Conservative inlining of functions that are called just once, or+-- have #[inline] on them.+consInlineFunctions :: MonadFreshNames m => Prog SOACS -> m (Prog SOACS)+consInlineFunctions prog =+ inlineFunctions 4 cg (calledOnce cg <> inlineBecauseTiny prog) prog+ where+ cg = buildCallGraph prog++aggInlineFunctions :: MonadFreshNames m => Prog SOACS -> m (Prog SOACS)+aggInlineFunctions prog =+ inlineFunctions 3 cg (S.fromList $ map funDefName $ progFuns prog) prog+ where+ cg = buildCallGraph prog+ -- | @inlineInFunDef constf fdmap caller@ inlines in @calleer@ the -- functions in @fdmap@ that are called as @constf@. At this point the -- preconditions are that if @fdmap@ is not empty, and, more@@ -129,40 +144,35 @@ inlineFunction :: MonadFreshNames m =>- Pattern ->+ Pat -> StmAux dec -> [(SubExp, Diet)] -> (Safety, SrcLoc, [SrcLoc]) -> FunDef SOACS ->- m [Stm]+ m (Stms SOACS) inlineFunction pat aux args (safety, loc, locs) fun = do Body _ stms res <-- renameBody $- mkBody- (stmsFromList param_stms <> stmsFromList body_stms)- (bodyResult (funDefBody fun))- let res_stms =- certify (stmAuxCerts aux)- <$> zipWith bindSubExp (patternIdents pat) res- pure $ stmsToList stms <> res_stms+ renameBody $ mkBody (param_stms <> body_stms) (bodyResult (funDefBody fun))+ pure $ stms <> stmsFromList (zipWith bindSubExpRes (patIdents pat) res) where param_stms =- zipWith- bindSubExp- (map paramIdent $ funDefParams fun)- (map fst args)+ stmsFromList $+ certify (stmAuxCerts aux)+ <$> zipWith bindSubExp (map paramIdent $ funDefParams fun) (map fst args) body_stms =- stmsToList $- addLocations (stmAuxAttrs aux) safety (filter notmempty (loc : locs)) $- bodyStms $ funDefBody fun+ addLocations (stmAuxAttrs aux) safety (filter notmempty (loc : locs)) $+ bodyStms $ funDefBody fun -- Note that the sizes of arrays may not be correct at this -- point - it is crucial that we run copy propagation before -- the type checker sees this! bindSubExp ident se =- mkLet [] [ident] $ BasicOp $ SubExp se+ mkLet [ident] $ BasicOp $ SubExp se + bindSubExpRes ident (SubExpRes cs se) =+ certify cs $ bindSubExp ident se+ notmempty = (/= mempty) . locOf inlineInStms ::@@ -185,16 +195,16 @@ not $ "noinline" `inAttrs` funDefAttrs fd, not $ "noinline" `inAttrs` stmAuxAttrs aux = (<>) <$> inlineFunction pat aux args what fd <*> inline rest+ inline (stm@(Let _ _ BasicOp {}) : rest) =+ (oneStm stm <>) <$> inline rest inline (stm : rest) =- (:) <$> onStm stm <*> inline rest+ (<>) <$> (oneStm <$> onStm stm) <*> inline rest inline [] = pure mempty onBody (Body dec stms res) =- Body dec . stmsFromList <$> inline (stmsToList stms) <*> pure res-- onStm (Let pat aux e) =- Let pat aux <$> mapExpM inliner e+ Body dec <$> inline (stmsToList stms) <*> pure res+ onStm (Let pat aux e) = Let pat aux <$> mapExpM inliner e inliner = identityMapper@@ -203,10 +213,7 @@ } onSOAC =- mapSOACM- identitySOACMapper- { mapOnSOACLambda = onLambda- }+ mapSOACM identitySOACMapper {mapOnSOACLambda = onLambda} onLambda (Lambda params body ret) = Lambda params <$> onBody body <*> pure ret@@ -260,15 +267,34 @@ bodyStms body } +-- | Remove functions not ultimately called from an entry point or a+-- constant.+removeDeadFunctionsF :: Prog SOACS -> Prog SOACS+removeDeadFunctionsF prog =+ let cg = buildCallGraph prog+ live_funs = filter ((`isFunInCallGraph` cg) . funDefName) $ progFuns prog+ in prog {progFuns = live_funs}+ -- | Inline all functions and remove the resulting dead functions.-inlineFunctions :: Pass SOACS SOACS-inlineFunctions =+inlineAggressively :: Pass SOACS SOACS+inlineAggressively = Pass- { passName = "Inline functions",- passDescription = "Inline and remove resulting dead functions.",- passFunction = copyPropagateInProg simpleSOACS <=< aggInlineFunctions+ { passName = "Inline aggressively",+ passDescription = "Aggressively inline and remove resulting dead functions.",+ passFunction =+ copyPropagateInProg simpleSOACS . removeDeadFunctionsF <=< aggInlineFunctions } +-- | Inline some functions and remove the resulting dead functions.+inlineConservatively :: Pass SOACS SOACS+inlineConservatively =+ Pass+ { passName = "Inline conservatively",+ passDescription = "Conservatively inline and remove resulting dead functions.",+ passFunction =+ copyPropagateInProg simpleSOACS . removeDeadFunctionsF <=< consInlineFunctions+ }+ -- | @removeDeadFunctions prog@ removes the functions that are unreachable from -- the main function from the program. removeDeadFunctions :: Pass SOACS SOACS@@ -276,12 +302,5 @@ Pass { passName = "Remove dead functions", passDescription = "Remove the functions that are unreachable from entry points",- passFunction = return . pass+ passFunction = pure . removeDeadFunctionsF }- where- pass prog =- let cg = buildCallGraph prog- live_funs =- filter ((`isFunInCallGraph` cg) . funDefName) $- progFuns prog- in prog {progFuns = live_funs}
src/Futhark/Optimise/ReuseAllocations.hs view
@@ -18,7 +18,7 @@ import qualified Data.Set as S import qualified Futhark.Analysis.Interference as Interference import qualified Futhark.Analysis.LastUse as LastUse-import Futhark.Binder.Class+import Futhark.Builder.Class import Futhark.Construct import Futhark.IR.GPUMem import qualified Futhark.Optimise.ReuseAllocations.GreedyColoring as GreedyColoring@@ -30,13 +30,13 @@ type Allocs = Map VName (SubExp, Space) getAllocsStm :: Stm GPUMem -> Allocs-getAllocsStm (Let (Pattern [] [PatElem name _]) _ (Op (Alloc se sp))) =+getAllocsStm (Let (Pat [PatElem name _]) _ (Op (Alloc se sp))) = M.singleton name (se, sp) getAllocsStm (Let _ _ (Op (Alloc _ _))) = error "impossible" getAllocsStm (Let _ _ (If _ then_body else_body _)) = foldMap getAllocsStm (bodyStms then_body) <> foldMap getAllocsStm (bodyStms else_body)-getAllocsStm (Let _ _ (DoLoop _ _ _ body)) =+getAllocsStm (Let _ _ (DoLoop _ _ body)) = foldMap getAllocsStm (bodyStms body) getAllocsStm _ = mempty @@ -51,7 +51,7 @@ foldMap getAllocsStm (kernelBodyStms body) setAllocsStm :: Map VName SubExp -> Stm GPUMem -> Stm GPUMem-setAllocsStm m stm@(Let (Pattern [] [PatElem name _]) _ (Op (Alloc _ _)))+setAllocsStm m stm@(Let (Pat [PatElem name _]) _ (Op (Alloc _ _))) | Just s <- M.lookup name m = stm {stmExp = BasicOp $ SubExp s} setAllocsStm _ stm@(Let _ _ (Op (Alloc _ _))) = stm@@ -66,14 +66,10 @@ (else_body {bodyStms = setAllocsStm m <$> bodyStms else_body}) dec }-setAllocsStm m stm@(Let _ _ (DoLoop ctx vals form body)) =+setAllocsStm m stm@(Let _ _ (DoLoop merge form body)) = stm { stmExp =- DoLoop- ctx- vals- form- (body {bodyStms = setAllocsStm m <$> bodyStms body})+ DoLoop merge form (body {bodyStms = setAllocsStm m <$> bodyStms body}) } setAllocsStm _ stm = stm @@ -94,7 +90,7 @@ SegHist lvl sp segbinops tps $ body {kernelBodyStms = setAllocsStm m <$> kernelBodyStms body} -maxSubExp :: MonadBinder m => Set SubExp -> m SubExp+maxSubExp :: MonadBuilder m => Set SubExp -> m SubExp maxSubExp = helper . S.toList where helper (s1 : s2 : sexps) = do@@ -110,16 +106,13 @@ definedInExp (If _ then_body else_body _) = foldMap definedInStm (bodyStms then_body) <> foldMap definedInStm (bodyStms else_body)-definedInExp (DoLoop _ _ _ body) =+definedInExp (DoLoop _ _ body) = foldMap definedInStm $ bodyStms body definedInExp _ = mempty definedInStm :: Stm GPUMem -> Set VName-definedInStm Let {stmPattern = Pattern ctx vals, stmExp} =- let definedInside =- ctx <> vals- & fmap patElemName- & S.fromList+definedInStm Let {stmPat = Pat merge, stmExp} =+ let definedInside = merge & fmap patElemName & S.fromList in definedInExp stmExp <> definedInside definedInSegOp :: SegOp lvl GPUMem -> Set VName@@ -138,7 +131,7 @@ isKernelInvariant _ _ = True onKernelBodyStms ::- MonadBinder m =>+ MonadBuilder m => SegOp lvl GPUMem -> (Stms GPUMem -> m (Stms GPUMem)) -> m (SegOp lvl GPUMem)@@ -155,11 +148,11 @@ stms <- f $ kernelBodyStms body return $ SegHist lvl space binops ts $ body {kernelBodyStms = stms} --- | This is the actual optimiser. Given an interference graph and a `SegOp`,+-- | This is the actual optimiser. Given an interference graph and a @SegOp@, -- replace allocations and references to memory blocks inside with a (hopefully) -- reduced number of allocations. optimiseKernel ::- (MonadBinder m, Rep m ~ GPUMem) =>+ (MonadBuilder m, Rep m ~ GPUMem) => Interference.Graph VName -> SegOp lvl GPUMem -> m (SegOp lvl GPUMem)@@ -221,10 +214,10 @@ (else_body {bodyStms = else_body_stms}) dec }- helper stm@Let {stmExp = DoLoop ctx vals form body} =+ helper stm@Let {stmExp = DoLoop merge form body} = inScopeOf stm $ do stms <- f `onKernels` bodyStms body- return $ stm {stmExp = DoLoop ctx vals form (body {bodyStms = stms})}+ return $ stm {stmExp = DoLoop merge form (body {bodyStms = stms})} helper stm = inScopeOf stm $ return stm @@ -252,4 +245,4 @@ PassM (Stms GPUMem) onStms graph scope stms = do let m = localScope scope $ optimiseKernel graph `onKernels` stms- fmap fst $ modifyNameSource $ runState (runBinderT m mempty)+ fmap fst $ modifyNameSource $ runState (runBuilderT m mempty)
src/Futhark/Optimise/ReuseAllocations/GreedyColoring.hs view
@@ -2,18 +2,16 @@ module Futhark.Optimise.ReuseAllocations.GreedyColoring (colorGraph, Coloring) where import Data.Function ((&))-import Data.Map (Map, (!?)) import qualified Data.Map as M import Data.Maybe (fromMaybe)-import Data.Set (Set) import qualified Data.Set as S import qualified Futhark.Analysis.Interference as Interference -- | A map of values to their color, identified by an integer.-type Coloring a = Map a Int+type Coloring a = M.Map a Int -- | A map of values to the set "neighbors" in the graph-type Neighbors a = Map a (Set a)+type Neighbors a = M.Map a (S.Set a) -- | Computes the neighbor map of a graph. neighbors :: Ord a => Interference.Graph a -> Neighbors a@@ -26,9 +24,9 @@ ) M.empty -firstAvailable :: Eq space => Map Int space -> Set Int -> Int -> space -> (Map Int space, Int)+firstAvailable :: Eq space => M.Map Int space -> S.Set Int -> Int -> space -> (M.Map Int space, Int) firstAvailable spaces xs i sp =- case (i `S.member` xs, spaces !? i) of+ case (i `S.member` xs, spaces M.!? i) of (False, Just sp') | sp' == sp -> (spaces, i) (False, Nothing) -> (M.insert i sp spaces, i) _ -> firstAvailable spaces xs (i + 1) sp@@ -37,24 +35,24 @@ (Ord a, Eq space) => Neighbors a -> (a, space) ->- (Map Int space, Coloring a) ->- (Map Int space, Coloring a)+ (M.Map Int space, Coloring a) ->+ (M.Map Int space, Coloring a) colorNode nbs (x, sp) (spaces, coloring) = let nb_colors =- foldMap (maybe S.empty S.singleton . (coloring !?)) $- fromMaybe mempty (nbs !? x)+ foldMap (maybe S.empty S.singleton . (coloring M.!?)) $+ fromMaybe mempty (nbs M.!? x) (spaces', color) = firstAvailable spaces nb_colors 0 sp in (spaces', M.insert x color coloring) --- | Graph coloring that takes into account the `space` of values. Two values+-- | Graph coloring that takes into account the @space@ of values. Two values -- can only share the same color if they live in the same space. The result is -- map from each color to a space and a map from each value in the input graph -- to it's new color. colorGraph :: (Ord a, Ord space) =>- Map a space ->+ M.Map a space -> Interference.Graph a ->- (Map Int space, Coloring a)+ (M.Map Int space, Coloring a) colorGraph spaces graph = let nodes = S.fromList $ M.toList spaces nbs = neighbors graph
src/Futhark/Optimise/Simplify/Engine.hs view
@@ -77,7 +77,7 @@ import Futhark.IR.Prop.Aliases import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule-import Futhark.Util (nubOrd, splitFromEnd)+import Futhark.Util (nubOrd) data HoistBlockers rep = HoistBlockers { -- | Blocker for hoisting out of parallel loops.@@ -111,12 +111,12 @@ envVtable = mempty } -type Protect m = SubExp -> Pattern (Rep m) -> Op (Rep m) -> Maybe (m ())+type Protect m = SubExp -> Pat (Rep m) -> Op (Rep m) -> Maybe (m ()) data SimpleOps rep = SimpleOps { mkExpDecS :: ST.SymbolTable (Wise rep) ->- Pattern (Wise rep) ->+ Pat (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep)), mkBodyS ::@@ -127,7 +127,7 @@ -- | Make a hoisted Op safe. The SubExp is a boolean -- that is true when the value of the statement will -- actually be used.- protectHoistedOpS :: Protect (Binder (Wise rep)),+ protectHoistedOpS :: Protect (Builder (Wise rep)), opUsageS :: Op (Wise rep) -> UT.UsageTable, simplifyOpS :: SimplifyOp rep (Op rep) }@@ -135,7 +135,7 @@ type SimplifyOp rep op = op -> SimpleM rep (OpWithWisdom op, Stms (Wise rep)) bindableSimpleOps ::- (SimplifiableRep rep, Bindable rep) =>+ (SimplifiableRep rep, Buildable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep bindableSimpleOps =@@ -149,7 +149,7 @@ = SimpleM ( ReaderT (SimpleOps rep, Env rep)- (State (VNameSource, Bool, Certificates))+ (State (VNameSource, Bool, Certs)) a ) deriving@@ -157,7 +157,7 @@ Functor, Monad, MonadReader (SimpleOps rep, Env rep),- MonadState (VNameSource, Bool, Certificates)+ MonadState (VNameSource, Bool, Certs) ) instance MonadFreshNames (SimpleM rep) where@@ -207,7 +207,7 @@ SimpleM rep a localVtable f = local $ \(ops, env) -> (ops, env {envVtable = f $ envVtable env}) -collectCerts :: SimpleM rep a -> SimpleM rep (a, Certificates)+collectCerts :: SimpleM rep a -> SimpleM rep (a, Certs) collectCerts m = do x <- m (a, b, cs) <- get@@ -219,7 +219,7 @@ changed :: SimpleM rep () changed = modify $ \(src, _, cs) -> (src, True, cs) -usedCerts :: Certificates -> SimpleM rep ()+usedCerts :: Certs -> SimpleM rep () usedCerts cs = modify $ \(a, b, c) -> (a, b, cs <> c) -- | Indicate in the symbol table that we have descended into a loop.@@ -244,7 +244,7 @@ bindMerge :: SimplifiableRep rep =>- [(FParam (Wise rep), SubExp, SubExp)] ->+ [(FParam (Wise rep), SubExp, SubExpRes)] -> SimpleM rep a -> SimpleM rep a bindMerge = localVtable . ST.insertLoopMerge@@ -269,7 +269,7 @@ protectIfHoisted cond side m = do (x, stms) <- m ops <- asks $ protectHoistedOpS . fst- runBinder $ do+ runBuilder $ do if not $ all (safeExp . stmExp) stms then do cond' <-@@ -288,14 +288,13 @@ protectLoopHoisted :: SimplifiableRep rep => [(FParam (Wise rep), SubExp)] ->- [(FParam (Wise rep), SubExp)] -> LoopForm (Wise rep) -> SimpleM rep (a, Stms (Wise rep)) -> SimpleM rep (a, Stms (Wise rep))-protectLoopHoisted ctx val form m = do+protectLoopHoisted merge form m = do (x, stms) <- m ops <- asks $ protectHoistedOpS . fst- runBinder $ do+ runBuilder $ do if not $ all (safeExp . stmExp) stms then do is_nonempty <- checkIfNonEmpty@@ -307,7 +306,7 @@ case form of WhileLoop cond | Just (_, cond_init) <-- find ((== cond) . paramName . fst) $ ctx ++ val ->+ find ((== cond) . paramName . fst) merge -> return cond_init | otherwise -> return $ constant True -- infinite loop ForLoop _ it bound _ ->@@ -315,26 +314,16 @@ BasicOp $ CmpOp (CmpSlt it) (intConst it 0) bound protectIf ::- MonadBinder m =>+ MonadBuilder m => Protect m -> (Exp (Rep m) -> Bool) -> SubExp -> Stm (Rep m) -> m ()-protectIf- _- _- taken- ( Let- pat- aux- (If cond taken_body untaken_body (IfDec if_ts IfFallback))- ) = do- cond' <- letSubExp "protect_cond_conj" $ BasicOp $ BinOp LogAnd taken cond- auxing aux $- letBind pat $- If cond' taken_body untaken_body $- IfDec if_ts IfFallback+protectIf _ _ taken (Let pat aux (If cond taken_body untaken_body (IfDec if_ts IfFallback))) = do+ cond' <- letSubExp "protect_cond_conj" $ BasicOp $ BinOp LogAnd taken cond+ auxing aux . letBind pat $+ If cond' taken_body untaken_body $ IfDec if_ts IfFallback protectIf _ _ taken (Let pat aux (BasicOp (Assert cond msg loc))) = do not_taken <- letSubExp "loop_not_taken" $ BasicOp $ UnOp Not taken cond' <- letSubExp "protect_assert_disj" $ BasicOp $ BinOp LogOr not_taken cond@@ -350,15 +339,10 @@ Nothing -> do taken_body <- eBody [pure e] untaken_body <-- eBody $- map- (emptyOfType $ patternContextNames pat)- (patternValueTypes pat)- if_ts <- expTypesFromPattern pat- auxing aux $- letBind pat $- If taken taken_body untaken_body $- IfDec if_ts IfFallback+ eBody $ map (emptyOfType $ patNames pat) (patTypes pat)+ if_ts <- expTypesFromPat pat+ auxing aux . letBind pat $+ If taken taken_body untaken_body $ IfDec if_ts IfFallback protectIf _ _ _ stm = addStm stm @@ -382,7 +366,7 @@ makeSafe _ = Nothing -emptyOfType :: MonadBinder m => [VName] -> Type -> m (Exp (Rep m))+emptyOfType :: MonadBuilder m => [VName] -> Type -> m (Exp (Rep m)) emptyOfType _ Mem {} = error "emptyOfType: Cannot hoist non-existential memory." emptyOfType _ Acc {} =@@ -401,7 +385,7 @@ -- further optimisation.. notWorthHoisting :: ASTRep rep => BlockPred rep notWorthHoisting _ _ (Let pat _ e) =- not (safeExp e) && any ((> 0) . arrayRank) (patternTypes pat)+ not (safeExp e) && any ((> 0) . arrayRank) (patTypes pat) hoistStms :: SimplifiableRep rep =>@@ -479,7 +463,7 @@ (blocked, Right need) provides :: Stm rep -> [VName]-provides = patternNames . stmPattern+provides = patNames . stmPat expandUsage :: (ASTRep rep, Aliased rep) =>@@ -490,7 +474,7 @@ UT.UsageTable expandUsage usageInStm vtable utable stm@(Let pat _ e) = UT.expand (`ST.lookupAliases` vtable) (usageInStm stm <> usageThroughAliases)- <> ( if any (`UT.isSize` utable) (patternNames pat)+ <> ( if any (`UT.isSize` utable) (patNames pat) then UT.sizeUsages (freeIn e) else mempty )@@ -499,7 +483,7 @@ usageThroughAliases = mconcat $ mapMaybe usageThroughBindeeAliases $- zip (patternNames pat) (patternAliases pat)+ zip (patNames pat) (patAliases pat) usageThroughBindeeAliases (name, aliases) = do uses <- UT.lookup name utable return $ mconcat $ map (`UT.usage` uses) $ namesToList aliases@@ -522,7 +506,7 @@ andAlso p1 p2 body vtable need = p1 body vtable need && p2 body vtable need isConsumed :: BlockPred rep-isConsumed _ utable = any (`UT.isConsumed` utable) . patternNames . stmPattern+isConsumed _ utable = any (`UT.isConsumed` utable) . patNames . stmPat isOp :: BlockPred rep isOp _ _ (Let _ _ Op {}) = True@@ -534,7 +518,7 @@ Result -> SimpleM rep (Body (Wise rep)) constructBody stms res =- fmap fst . runBinder . buildBody_ $ do+ fmap fst . runBuilder . buildBody_ $ do addStms stms pure res @@ -634,7 +618,7 @@ isNotHoistableBnd _ _ (Let _ _ (BasicOp ArrayLit {})) = False isNotHoistableBnd _ _ (Let _ _ (BasicOp SubExp {})) = False isNotHoistableBnd _ usages (Let pat _ _)- | any (`UT.isSize` usages) $ patternNames pat =+ | any (`UT.isSize` usages) $ patNames pat = False isNotHoistableBnd _ _ stm | is_alloc_fun stm = False@@ -675,40 +659,16 @@ -- | Simplify a single 'Result'. The @[Diet]@ only covers the value -- elements, because the context cannot be consumed. simplifyResult ::- SimplifiableRep rep =>- [Diet] ->- Result ->- SimpleM rep (Result, UT.UsageTable)+ SimplifiableRep rep => [Diet] -> Result -> SimpleM rep (Result, UT.UsageTable) simplifyResult ds res = do- let (ctx_res, val_res) = splitFromEnd (length ds) res- -- Copy propagation is a little trickier here, because there is no- -- place to put the certificates when copy-propagating a certified- -- statement. However, for results in the *context*, it is OK to- -- just throw away the certificates, because for the program to be- -- type-correct, those statements must anyway be used (or- -- copy-propagated into) the statements producing the value result.- (ctx_res', _ctx_res_cs) <- collectCerts $ mapM simplify ctx_res- val_res' <- mapM simplify' val_res-- let consumption = consumeResult $ zip ds val_res'- res' = ctx_res' <> val_res'+ res' <- mapM simplify res+ let consumption = consumeResult $ zip ds res' return (res', UT.usages (freeIn res') <> consumption)- where- simplify' (Var name) = do- bnd <- ST.lookupSubExp name <$> askVtable- case bnd of- Just (Constant v, cs)- | cs == mempty -> return $ Constant v- Just (Var id', cs)- | cs == mempty -> return $ Var id'- _ -> return $ Var name- simplify' (Constant v) =- return $ Constant v isDoLoopResult :: Result -> UT.UsageTable isDoLoopResult = mconcat . map checkForVar where- checkForVar (Var ident) = UT.inResultUsage ident+ checkForVar (SubExpRes _ (Var ident)) = UT.inResultUsage ident checkForVar _ = mempty simplifyStms ::@@ -722,7 +682,7 @@ Just (Let pat (StmAux stm_cs attrs dec) e, stms') -> do stm_cs' <- simplify stm_cs ((e', e_stms), e_cs) <- collectCerts $ simplifyExp e- (pat', pat_cs) <- collectCerts $ simplifyPattern pat+ (pat', pat_cs) <- collectCerts $ simplifyPat pat let cs = stm_cs' <> e_cs <> pat_cs inspectStms e_stms $ inspectStm (mkWiseLetStm pat' (StmAux cs attrs dec) e') $@@ -778,16 +738,12 @@ fbranch' <- simplifyBody ds fbranch (tbranch'', fbranch'', hoisted) <- hoistCommon cond' ifsort tbranch' fbranch' return (If cond' tbranch'' fbranch'' $ IfDec ts' ifsort, hoisted)-simplifyExp (DoLoop ctx val form loopbody) = do- let (ctxparams, ctxinit) = unzip ctx- (valparams, valinit) = unzip val- ctxparams' <- mapM (traverse simplify) ctxparams- ctxinit' <- mapM simplify ctxinit- valparams' <- mapM (traverse simplify) valparams- valinit' <- mapM simplify valinit- let ctx' = zip ctxparams' ctxinit'- val' = zip valparams' valinit'- diets = map (diet . paramDeclType) valparams'+simplifyExp (DoLoop merge form loopbody) = do+ let (params, args) = unzip merge+ params' <- mapM (traverse simplify) params+ args' <- mapM simplify args+ let merge' = zip params' args'+ diets = map (diet . paramDeclType) params' (form', boundnames, wrapbody) <- case form of ForLoop loopvar it boundexp loopvars -> do boundexp' <- simplify boundexp@@ -799,7 +755,7 @@ ( form', namesFromList (loopvar : map paramName loop_params') <> fparamnames, bindLoopVar loopvar it boundexp'- . protectLoopHoisted ctx' val' form'+ . protectLoopHoisted merge' form' . bindArrayLParams loop_params' ) WhileLoop cond -> do@@ -807,31 +763,30 @@ return ( WhileLoop cond', fparamnames,- protectLoopHoisted ctx' val' (WhileLoop cond')+ protectLoopHoisted merge' (WhileLoop cond') ) seq_blocker <- asksEngineEnv $ blockHoistSeq . envHoistBlockers ((loopstms, loopres), hoisted) <-- enterLoop $- consumeMerge $- bindMerge (zipWith withRes (ctx' ++ val') (bodyResult loopbody)) $- wrapbody $- blockIf- ( hasFree boundnames `orIf` isConsumed- `orIf` seq_blocker- `orIf` notWorthHoisting- )- $ do- ((res, uses), stms) <- simplifyBody diets loopbody- return ((res, uses <> isDoLoopResult res), stms)+ enterLoop . consumeMerge $+ bindMerge (zipWith withRes merge' (bodyResult loopbody)) $+ wrapbody $+ blockIf+ ( hasFree boundnames `orIf` isConsumed+ `orIf` seq_blocker+ `orIf` notWorthHoisting+ )+ $ do+ ((res, uses), stms) <- simplifyBody diets loopbody+ return ((res, uses <> isDoLoopResult res), stms) loopbody' <- constructBody loopstms loopres- return (DoLoop ctx' val' form' loopbody', hoisted)+ return (DoLoop merge' form' loopbody', hoisted) where fparamnames =- namesFromList (map (paramName . fst) $ ctx ++ val)+ namesFromList (map (paramName . fst) merge) consumeMerge = localVtable $ flip (foldl' (flip ST.consume)) $ namesToList consumed_by_merge consumed_by_merge =- freeIn $ map snd $ filter (unique . paramDeclType . fst) val+ freeIn $ map snd $ filter (unique . paramDeclType . fst) merge withRes (p, x) y = (p, x, y) simplifyExp (Op op) = do (op', stms) <- simplifyOp op@@ -896,7 +851,7 @@ Simplifiable (BranchType rep), CanBeWise (Op rep), ST.IndexOp (OpWithWisdom (Op rep)),- BinderOps (Wise rep),+ BuilderOps (Wise rep), IsOp (Op rep) ) @@ -939,14 +894,18 @@ simplify (Constant v) = return $ Constant v -simplifyPattern ::+instance Simplifiable SubExpRes where+ simplify (SubExpRes cs se) = do+ cs' <- simplify cs+ (se', se_cs) <- collectCerts $ simplify se+ pure $ SubExpRes (se_cs <> cs') se'++simplifyPat :: (SimplifiableRep rep, Simplifiable dec) =>- PatternT dec ->- SimpleM rep (PatternT dec)-simplifyPattern pat =- Pattern- <$> mapM inspect (patternContextElements pat)- <*> mapM inspect (patternValueElements pat)+ PatT dec ->+ SimpleM rep (PatT dec)+simplifyPat (Pat xs) =+ Pat <$> mapM inspect xs where inspect (PatElem name rep) = PatElem name <$> simplify rep @@ -991,6 +950,9 @@ simplify (DimFix i) = DimFix <$> simplify i simplify (DimSlice i n s) = DimSlice <$> simplify i <*> simplify n <*> simplify s +instance Simplifiable d => Simplifiable (Slice d) where+ simplify = traverse simplify+ simplifyLambda :: SimplifiableRep rep => Lambda rep ->@@ -1023,20 +985,20 @@ rettype' <- simplify rettype return (Lambda params' body' rettype', hoisted) -consumeResult :: [(Diet, SubExp)] -> UT.UsageTable+consumeResult :: [(Diet, SubExpRes)] -> UT.UsageTable consumeResult = mconcat . map inspect where- inspect (Consume, se) =+ inspect (Consume, SubExpRes _ se) = mconcat $ map UT.consumedUsage $ namesToList $ subExpAliases se inspect _ = mempty -instance Simplifiable Certificates where- simplify (Certificates ocs) = Certificates . nubOrd . concat <$> mapM check ocs+instance Simplifiable Certs where+ simplify (Certs ocs) = Certs . nubOrd . concat <$> mapM check ocs where check idd = do vv <- ST.lookupSubExp idd <$> askVtable case vv of- Just (Constant _, Certificates cs) -> return cs+ Just (Constant _, Certs cs) -> return cs Just (Var idd', _) -> return [idd'] _ -> return [idd]
src/Futhark/Optimise/Simplify/Rep.hs view
@@ -12,11 +12,11 @@ removeLambdaWisdom, removeFunDefWisdom, removeExpWisdom,- removePatternWisdom,+ removePatWisdom, removeBodyWisdom, removeScopeWisdom, addScopeWisdom,- addWisdomToPattern,+ addWisdomToPat, mkWiseBody, mkWiseLetStm, mkWiseExpDec,@@ -30,7 +30,7 @@ import qualified Data.Kind import qualified Data.Map.Strict as M import Futhark.Analysis.Rephrase-import Futhark.Binder+import Futhark.Builder import Futhark.IR import Futhark.IR.Aliases ( AliasDec (..),@@ -127,8 +127,8 @@ runReaderT m scope instance (ASTRep rep, CanBeWise (Op rep)) => ASTRep (Wise rep) where- expTypesFromPattern =- withoutWisdom . expTypesFromPattern . removePatternWisdom+ expTypesFromPat =+ withoutWisdom . expTypesFromPat . removePatWisdom instance Pretty VarWisdom where ppr _ = ppr ()@@ -187,18 +187,17 @@ removeExpWisdom :: CanBeWise (Op rep) => Exp (Wise rep) -> Exp rep removeExpWisdom = runIdentity . rephraseExp removeWisdom -removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a-removePatternWisdom = runIdentity . rephrasePattern (return . snd)+removePatWisdom :: PatT (VarWisdom, a) -> PatT a+removePatWisdom = runIdentity . rephrasePat (return . snd) -addWisdomToPattern ::+addWisdomToPat :: (ASTRep rep, CanBeWise (Op rep)) =>- Pattern rep ->+ Pat rep -> Exp (Wise rep) ->- Pattern (Wise rep)-addWisdomToPattern pat e =- Pattern (map f ctx) (map f val)+ Pat (Wise rep)+addWisdomToPat pat e =+ Pat $ map f $ Aliases.mkPatAliases pat e where- (ctx, val) = Aliases.mkPatternAliases pat e f pe = let (als, dec) = patElemDec pe in pe `setPatElemDec` (VarWisdom als, dec)@@ -221,17 +220,17 @@ mkWiseLetStm :: (ASTRep rep, CanBeWise (Op rep)) =>- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> Exp (Wise rep) -> Stm (Wise rep) mkWiseLetStm pat (StmAux cs attrs dec) e =- let pat' = addWisdomToPattern pat e+ let pat' = addWisdomToPat pat e in Let pat' (StmAux cs attrs $ mkWiseExpDec pat' dec e) e mkWiseExpDec :: (ASTRep rep, CanBeWise (Op rep)) =>- Pattern (Wise rep) ->+ Pat (Wise rep) -> ExpDec rep -> Exp (Wise rep) -> ExpDec (Wise rep)@@ -242,17 +241,12 @@ expdec ) -instance- ( Bindable rep,- CanBeWise (Op rep)- ) =>- Bindable (Wise rep)- where- mkExpPat ctx val e =- addWisdomToPattern (mkExpPat ctx val $ removeExpWisdom e) e+instance (Buildable rep, CanBeWise (Op rep)) => Buildable (Wise rep) where+ mkExpPat ids e =+ addWisdomToPat (mkExpPat ids $ removeExpWisdom e) e mkExpDec pat e =- mkWiseExpDec pat (mkExpDec (removePatternWisdom pat) $ removeExpWisdom e) e+ mkWiseExpDec pat (mkExpDec (removePatWisdom pat) $ removeExpWisdom e) e mkLetNames names e = do env <- asksScope removeScopeWisdom
src/Futhark/Optimise/Simplify/Rule.hs view
@@ -58,11 +58,11 @@ import Control.Monad.State import qualified Futhark.Analysis.SymbolTable as ST import qualified Futhark.Analysis.UsageTable as UT-import Futhark.Binder+import Futhark.Builder import Futhark.IR -- | The monad in which simplification rules are evaluated.-newtype RuleM rep a = RuleM (BinderT rep (StateT VNameSource Maybe) a)+newtype RuleM rep a = RuleM (BuilderT rep (StateT VNameSource Maybe) a) deriving ( Functor, Applicative,@@ -72,7 +72,7 @@ LocalScope rep ) -instance (ASTRep rep, BinderOps rep) => MonadBinder (RuleM rep) where+instance (ASTRep rep, BuilderOps rep) => MonadBuilder (RuleM rep) where type Rep (RuleM rep) = rep mkExpDecM pat e = RuleM $ mkExpDecM pat e mkBodyM bnds res = RuleM $ mkBodyM bnds res@@ -90,7 +90,7 @@ Maybe (Stms rep, VNameSource) simplify _ _ Skip = Nothing simplify scope src (Simplify (RuleM m)) =- runStateT (runBinderT_ m scope) src+ runStateT (runBuilderT_ m scope) src cannotSimplify :: RuleM rep a cannotSimplify = RuleM $ lift $ lift Nothing@@ -110,7 +110,7 @@ type RuleBasicOp rep a = ( a ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> BasicOp -> Rule rep@@ -118,7 +118,7 @@ type RuleIf rep a = a ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> ( SubExp, BodyT rep,@@ -129,10 +129,9 @@ type RuleDoLoop rep a = a ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> ( [(FParam rep, SubExp)],- [(FParam rep, SubExp)], LoopForm rep, BodyT rep ) ->@@ -140,7 +139,7 @@ type RuleOp rep a = a ->- Pattern rep ->+ Pat rep -> StmAux (ExpDec rep) -> Op rep -> Rule rep@@ -290,8 +289,8 @@ applyRule :: SimplificationRule rep a -> a -> Stm rep -> Rule rep applyRule (RuleGeneric f) a stm = f a stm applyRule (RuleBasicOp f) a (Let pat aux (BasicOp e)) = f a pat aux e-applyRule (RuleDoLoop f) a (Let pat aux (DoLoop ctx val form body)) =- f a pat aux (ctx, val, form, body)+applyRule (RuleDoLoop f) a (Let pat aux (DoLoop merge form body)) =+ f a pat aux (merge, form, body) applyRule (RuleIf f) a (Let pat aux (If cond tbody fbody ifsort)) = f a pat aux (cond, tbody, fbody, ifsort) applyRule (RuleOp f) a (Let pat aux (Op op)) =
src/Futhark/Optimise/Simplify/Rules.hs view
@@ -37,7 +37,7 @@ import Futhark.Optimise.Simplify.Rules.Loop import Futhark.Util -topDownRules :: BinderOps rep => [TopDownRule rep]+topDownRules :: BuilderOps rep => [TopDownRule rep] topDownRules = [ RuleGeneric constantFoldPrimFun, RuleIf ruleIf,@@ -45,7 +45,7 @@ RuleGeneric withAccTopDown ] -bottomUpRules :: BinderOps rep => [BottomUpRule rep]+bottomUpRules :: BuilderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleIf removeDeadBranchResult, RuleGeneric withAccBottomUp,@@ -55,15 +55,15 @@ -- | A set of standard simplification rules. These assume pure -- functional semantics, and so probably should not be applied after -- memory block merging.-standardRules :: (BinderOps rep, Aliased rep) => RuleBook rep+standardRules :: (BuilderOps rep, Aliased rep) => RuleBook rep standardRules = ruleBook topDownRules bottomUpRules <> loopRules <> basicOpRules -- | Turn @copy(x)@ into @x@ iff @x@ is not used after this copy -- statement and it can be consumed. -- -- This simplistic rule is only valid before we introduce memory.-removeUnnecessaryCopy :: (BinderOps rep, Aliased rep) => BottomUpRuleBasicOp rep-removeUnnecessaryCopy (vtable, used) (Pattern [] [d]) _ (Copy v)+removeUnnecessaryCopy :: (BuilderOps rep, Aliased rep) => BottomUpRuleBasicOp rep+removeUnnecessaryCopy (vtable, used) (Pat [d]) _ (Copy v) | not (v `UT.isConsumed` used), (not (v `UT.used` used) && consumable) || not (patElemName d `UT.isConsumed` used) = Simplify $ letBindNames [patElemName d] $ BasicOp $ SubExp $ Var v@@ -78,13 +78,13 @@ consumableFParam = Just . maybe False (unique . declTypeOf) . ST.entryFParam consumableStm e = do- pat <- stmPattern <$> ST.entryStm e- pe <- find ((== v) . patElemName) (patternElements pat)+ pat <- stmPat <$> ST.entryStm e+ pe <- find ((== v) . patElemName) (patElems pat) guard $ aliasesOf pe == mempty pure True removeUnnecessaryCopy _ _ _ _ = Skip -constantFoldPrimFun :: BinderOps rep => TopDownRuleGeneric rep+constantFoldPrimFun :: BuilderOps rep => TopDownRuleGeneric rep constantFoldPrimFun _ (Let pat (StmAux cs attrs _) (Apply fname args _ _)) | Just args' <- mapM (isConst . fst) args, Just (_, _, fun) <- M.lookup (nameToString fname) primFuns,@@ -98,32 +98,32 @@ isConst _ = Nothing constantFoldPrimFun _ _ = Skip -simplifyIndex :: BinderOps rep => BottomUpRuleBasicOp rep-simplifyIndex (vtable, used) pat@(Pattern [] [pe]) (StmAux cs attrs _) (Index idd inds)+simplifyIndex :: BuilderOps rep => BottomUpRuleBasicOp rep+simplifyIndex (vtable, used) pat@(Pat [pe]) (StmAux cs attrs _) (Index idd inds) | Just m <- simplifyIndexing vtable seType idd inds consumed = Simplify $ do res <- m attributing attrs $ case res of SubExpResult cs' se -> certifying (cs <> cs') $- letBindNames (patternNames pat) $ BasicOp $ SubExp se+ letBindNames (patNames pat) $ BasicOp $ SubExp se IndexResult extra_cs idd' inds' -> certifying (cs <> extra_cs) $- letBindNames (patternNames pat) $ BasicOp $ Index idd' inds'+ letBindNames (patNames pat) $ BasicOp $ Index idd' inds' where consumed = patElemName pe `UT.isConsumed` used seType (Var v) = ST.lookupType v vtable seType (Constant v) = Just $ Prim $ primValueType v simplifyIndex _ _ _ _ = Skip -ruleIf :: BinderOps rep => TopDownRuleIf rep+ruleIf :: BuilderOps rep => TopDownRuleIf rep ruleIf _ pat _ (e1, tb, fb, IfDec _ ifsort) | Just branch <- checkBranch, ifsort /= IfFallback || isCt1 e1 = Simplify $ do let ses = bodyResult branch addStms $ bodyStms branch sequence_- [ letBindNames [patElemName p] $ BasicOp $ SubExp se- | (p, se) <- zip (patternElements pat) ses+ [ certifying cs $ letBindNames [patElemName p] $ BasicOp $ SubExp se+ | (p, SubExpRes cs se) <- zip (patElems pat) ses ] where checkBranch@@ -141,18 +141,18 @@ pat _ ( cond,- Body _ tstms [Constant (BoolValue True)],- Body _ fstms [se],+ Body _ tstms [SubExpRes tcs (Constant (BoolValue True))],+ Body _ fstms [SubExpRes fcs se], IfDec ts _ ) | null tstms, null fstms, [Prim Bool] <- map extTypeOf ts =- Simplify $ letBind pat $ BasicOp $ BinOp LogOr cond se+ Simplify $ certifying (tcs <> fcs) $ letBind pat $ BasicOp $ BinOp LogOr cond se -- When type(x)==bool, if c then x else y == (c && x) || (!c && y) ruleIf _ pat _ (cond, tb, fb, IfDec ts _)- | Body _ tstms [tres] <- tb,- Body _ fstms [fres] <- fb,+ | Body _ tstms [SubExpRes tcs tres] <- tb,+ Body _ fstms [SubExpRes fcs fres] <- fb, all (safeExp . stmExp) $ tstms <> fstms, all ((== Prim Bool) . extTypeOf) ts = Simplify $ do addStms tstms@@ -166,20 +166,19 @@ (pure $ BasicOp $ UnOp Not cond) (pure $ BasicOp $ SubExp fres) )- letBind pat e+ certifying (tcs <> fcs) $ letBind pat e ruleIf _ pat _ (_, tbranch, _, IfDec _ IfFallback)- | null $ patternContextNames pat,- all (safeExp . stmExp) $ bodyStms tbranch = Simplify $ do+ | all (safeExp . stmExp) $ bodyStms tbranch = Simplify $ do let ses = bodyResult tbranch addStms $ bodyStms tbranch sequence_- [ letBindNames [patElemName p] $ BasicOp $ SubExp se- | (p, se) <- zip (patternElements pat) ses+ [ certifying cs $ letBindNames [patElemName p] $ BasicOp $ SubExp se+ | (p, SubExpRes cs se) <- zip (patElems pat) ses ] ruleIf _ pat _ (cond, tb, fb, _)- | Body _ _ [Constant (IntValue t)] <- tb,- Body _ _ [Constant (IntValue f)] <- fb =- if oneIshInt t && zeroIshInt f+ | Body _ _ [SubExpRes tcs (Constant (IntValue t))] <- tb,+ Body _ _ [SubExpRes fcs (Constant (IntValue f))] <- fb =+ if oneIshInt t && zeroIshInt f && tcs == mempty && fcs == mempty then Simplify $ letBind pat $ BasicOp $ ConvOp (BToI (intValueType t)) cond@@ -192,85 +191,72 @@ ruleIf _ _ _ _ = Skip -- | Move out results of a conditional expression whose computation is--- either invariant to the branches (only done for results in the--- context), or the same in both branches.-hoistBranchInvariant :: BinderOps rep => TopDownRuleIf rep+-- either invariant to the branches (only done for results used for+-- existentials), or the same in both branches.+hoistBranchInvariant :: BuilderOps rep => TopDownRuleIf rep hoistBranchInvariant _ pat _ (cond, tb, fb, IfDec ret ifsort) = Simplify $ do let tses = bodyResult tb fses = bodyResult fb (hoistings, (pes, ts, res)) <-- fmap (fmap unzip3 . partitionEithers) $- mapM branchInvariant $- zip3- (patternElements pat)- (map Left [0 .. num_ctx -1] ++ map Right ret)- (zip tses fses)+ fmap (fmap unzip3 . partitionEithers) . mapM branchInvariant $+ zip4 [0 ..] (patElems pat) ret (zip tses fses) let ctx_fixes = catMaybes hoistings (tses', fses') = unzip res tb' = tb {bodyResult = tses'} fb' = fb {bodyResult = fses'}- ret' = foldr (uncurry fixExt) (rights ts) ctx_fixes- (ctx_pes, val_pes) = splitFromEnd (length ret') pes+ ret' = foldr (uncurry fixExt) ts ctx_fixes if not $ null hoistings -- Was something hoisted? then do -- We may have to add some reshapes if we made the type -- less existential. tb'' <- reshapeBodyResults tb' $ map extTypeOf ret' fb'' <- reshapeBodyResults fb' $ map extTypeOf ret'- letBind (Pattern ctx_pes val_pes) $- If cond tb'' fb'' (IfDec ret' ifsort)+ letBind (Pat pes) $ If cond tb'' fb'' (IfDec ret' ifsort) else cannotSimplify where- num_ctx = length $ patternContextElements pat bound_in_branches =- namesFromList $- concatMap (patternNames . stmPattern) $- bodyStms tb <> bodyStms fb- mem_sizes = freeIn $ filter (isMem . patElemType) $ patternElements pat+ namesFromList . concatMap (patNames . stmPat) $+ bodyStms tb <> bodyStms fb invariant Constant {} = True invariant (Var v) = not $ v `nameIn` bound_in_branches - isMem Mem {} = True- isMem _ = False- sizeOfMem v = v `nameIn` mem_sizes-- branchInvariant (pe, t, (tse, fse))+ branchInvariant (i, pe, t, (tse, fse)) -- Do both branches return the same value? | tse == fse = do- letBindNames [patElemName pe] $ BasicOp $ SubExp tse- hoisted pe t+ certifying (resCerts tse <> resCerts fse) $+ letBindNames [patElemName pe] $ BasicOp $ SubExp $ resSubExp tse+ hoisted i pe -- Do both branches return values that are free in the -- branch, and are we not the only pattern element? The -- latter is to avoid infinite application of this rule.- | invariant tse,- invariant fse,- patternSize pat > 1,- Prim _ <- patElemType pe,- not $ sizeOfMem $ patElemName pe = do- bt <- expTypesFromPattern $ Pattern [] [pe]+ | invariant $ resSubExp tse,+ invariant $ resSubExp fse,+ patSize pat > 1,+ Prim _ <- patElemType pe = do+ bt <- expTypesFromPat $ Pat [pe] letBindNames [patElemName pe]- =<< ( If cond <$> resultBodyM [tse]- <*> resultBodyM [fse]+ =<< ( If cond <$> resultBodyM [resSubExp tse]+ <*> resultBodyM [resSubExp fse] <*> pure (IfDec bt ifsort) )- hoisted pe t+ hoisted i pe | otherwise =- return $ Right (pe, t, (tse, fse))+ pure $ Right (pe, t, (tse, fse)) - hoisted pe (Left i) = return $ Left $ Just (i, Var $ patElemName pe)- hoisted _ Right {} = return $ Left Nothing+ hoisted i pe = pure $ Left $ Just (i, Var $ patElemName pe) reshapeBodyResults body rets = buildBody_ $ do ses <- bodyBind body let (ctx_ses, val_ses) = splitFromEnd (length rets) ses (ctx_ses ++) <$> zipWithM reshapeResult val_ses rets- reshapeResult (Var v) t@Array {} = do+ reshapeResult (SubExpRes cs (Var v)) t@Array {} = do v_t <- lookupType v let newshape = arrayDims $ removeExistentials t v_t- if newshape /= arrayDims v_t- then letSubExp "branch_ctx_reshaped" $ shapeCoerce newshape v- else return $ Var v+ SubExpRes cs+ <$> if newshape /= arrayDims v_t+ then letSubExp "branch_ctx_reshaped" (shapeCoerce newshape v)+ else pure $ Var v reshapeResult se _ = return se @@ -278,12 +264,12 @@ -- after a branch. Standard dead code removal can remove the branch -- if *none* of the return values are used, but this rule is more -- precise.-removeDeadBranchResult :: BinderOps rep => BottomUpRuleIf rep+removeDeadBranchResult :: BuilderOps rep => BottomUpRuleIf rep removeDeadBranchResult (_, used) pat _ (e1, tb, fb, IfDec rettype ifsort)- | -- Only if there is no existential context...- patternSize pat == length rettype,+ | -- Only if there is no existential binding...+ not $ any (`nameIn` foldMap freeIn (patElems pat)) (patNames pat), -- Figure out which of the names in 'pat' are used...- patused <- map (`UT.isUsedDirectly` used) $ patternNames pat,+ patused <- map (`UT.isUsedDirectly` used) $ patNames pat, -- If they are not all used, then this rule applies. not (and patused) = -- Remove the parts of the branch-results that correspond to dead@@ -295,17 +281,17 @@ pick = map snd . filter fst . zip patused tb' = tb {bodyResult = pick tses} fb' = fb {bodyResult = pick fses}- pat' = pick $ patternElements pat+ pat' = pick $ patElems pat rettype' = pick rettype- in Simplify $ letBind (Pattern [] pat') $ If e1 tb' fb' $ IfDec rettype' ifsort+ in Simplify $ letBind (Pat pat') $ If e1 tb' fb' $ IfDec rettype' ifsort | otherwise = Skip -withAccTopDown :: BinderOps rep => TopDownRuleGeneric rep+withAccTopDown :: BuilderOps rep => TopDownRuleGeneric rep -- A WithAcc with no accumulators is sent to Valhalla. withAccTopDown _ (Let pat aux (WithAcc [] lam)) = Simplify . auxing aux $ do lam_res <- bodyBind $ lambdaBody lam- forM_ (zip (patternNames pat) lam_res) $ \(v, se) ->- letBindNames [v] $ BasicOp $ SubExp se+ forM_ (zip (patNames pat) lam_res) $ \(v, SubExpRes cs se) ->+ certifying cs $ letBindNames [v] $ BasicOp $ SubExp se -- Identify those results in 'lam' that are free and move them out. withAccTopDown vtable (Let pat aux (WithAcc inputs lam)) = Simplify . auxing aux $ do let (cert_params, acc_params) =@@ -313,7 +299,7 @@ (acc_res, nonacc_res) = splitFromEnd num_nonaccs $ bodyResult $ lambdaBody lam (acc_pes, nonacc_pes) =- splitFromEnd num_nonaccs $ patternElements pat+ splitFromEnd num_nonaccs $ patElems pat -- Look at accumulator results. (acc_pes', inputs', params', acc_res') <-@@ -335,38 +321,41 @@ mkLambda (cert_params' ++ acc_params') $ bodyBind $ (lambdaBody lam) {bodyResult = acc_res' <> nonacc_res'} - letBind (Pattern [] (concat acc_pes' <> nonacc_pes')) $ WithAcc inputs' lam'+ letBind (Pat (concat acc_pes' <> nonacc_pes')) $ WithAcc inputs' lam' where num_nonaccs = length (lambdaReturnType lam) - length inputs inputArrs (_, arrs, _) = length arrs - tryMoveAcc (pes, (_, arrs, _), (_, acc_p), Var v)- | paramName acc_p == v = do+ tryMoveAcc (pes, (_, arrs, _), (_, acc_p), SubExpRes cs (Var v))+ | paramName acc_p == v,+ cs == mempty = do forM_ (zip pes arrs) $ \(pe, arr) -> letBindNames [patElemName pe] $ BasicOp $ SubExp $ Var arr pure Nothing tryMoveAcc x = pure $ Just x - tryMoveNonAcc (pe, Var v)- | v `ST.elem` vtable = do+ tryMoveNonAcc (pe, SubExpRes cs (Var v))+ | v `ST.elem` vtable,+ cs == mempty = do letBindNames [patElemName pe] $ BasicOp $ SubExp $ Var v pure Nothing- tryMoveNonAcc (pe, Constant v) = do- letBindNames [patElemName pe] $ BasicOp $ SubExp $ Constant v- pure Nothing+ tryMoveNonAcc (pe, SubExpRes cs (Constant v))+ | cs == mempty = do+ letBindNames [patElemName pe] $ BasicOp $ SubExp $ Constant v+ pure Nothing tryMoveNonAcc x = pure $ Just x withAccTopDown _ _ = Skip -withAccBottomUp :: BinderOps rep => BottomUpRuleGeneric rep+withAccBottomUp :: BuilderOps rep => BottomUpRuleGeneric rep -- Eliminate dead results. withAccBottomUp (_, utable) (Let pat aux (WithAcc inputs lam))- | not $ all (`UT.used` utable) $ patternNames pat = Simplify $ do+ | not $ all (`UT.used` utable) $ patNames pat = Simplify $ do let (acc_res, nonacc_res) = splitFromEnd num_nonaccs $ bodyResult $ lambdaBody lam (acc_pes, nonacc_pes) =- splitFromEnd num_nonaccs $ patternElements pat+ splitFromEnd num_nonaccs $ patElems pat (cert_params, acc_params) = splitAt (length inputs) $ lambdaParams lam @@ -392,7 +381,7 @@ void $ bodyBind $ lambdaBody lam pure $ acc_res' ++ nonacc_res' - auxing aux $ letBind (Pattern [] pes') $ WithAcc inputs' lam'+ auxing aux $ letBind (Pat pes') $ WithAcc inputs' lam' where num_nonaccs = length (lambdaReturnType lam) - length inputs inputArrs (_, arrs, _) = length arrs
src/Futhark/Optimise/Simplify/Rules/BasicOp.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -Wno-overlapping-patterns -Wno-incomplete-patterns -Wno-incomplete-uni-patterns -Wno-incomplete-record-updates #-} --- | Some simplification rules for 'BasicOp'.+-- | Some simplification rules for t'BasicOp'. module Futhark.Optimise.Simplify.Rules.BasicOp ( basicOpRules, )@@ -35,7 +35,7 @@ | ArgReplicate [SubExp] SubExp | ArgVar VName -toConcatArg :: ST.SymbolTable rep -> VName -> (ConcatArg, Certificates)+toConcatArg :: ST.SymbolTable rep -> VName -> (ConcatArg, Certs) toConcatArg vtable v = case ST.lookupBasicOp v vtable of Just (ArrayLit ses _, cs) ->@@ -46,9 +46,9 @@ (ArgVar v, mempty) fromConcatArg ::- MonadBinder m =>+ MonadBuilder m => Type ->- (ConcatArg, Certificates) ->+ (ConcatArg, Certs) -> m VName fromConcatArg t (ArgArrayLit ses, cs) = certifying cs $ letExp "concat_lit" $ BasicOp $ ArrayLit ses $ rowType t@@ -61,9 +61,9 @@ pure v fuseConcatArg ::- [(ConcatArg, Certificates)] ->- (ConcatArg, Certificates) ->- [(ConcatArg, Certificates)]+ [(ConcatArg, Certs)] ->+ (ConcatArg, Certs) ->+ [(ConcatArg, Certs)] fuseConcatArg xs (ArgArrayLit [], _) = xs fuseConcatArg xs (ArgReplicate [w] se, cs)@@ -79,7 +79,7 @@ fuseConcatArg xs y = y : xs -simplifyConcat :: BinderOps rep => BottomUpRuleBasicOp rep+simplifyConcat :: BuilderOps rep => BottomUpRuleBasicOp rep -- concat@1(transpose(x),transpose(y)) == transpose(concat@0(x,y)) simplifyConcat (vtable, _) pat _ (Concat i x xs new_d) | Just r <- arrayRank <$> ST.lookupType x vtable,@@ -142,7 +142,7 @@ forSingleArray ys = ys simplifyConcat _ _ _ _ = Skip -ruleBasicOp :: BinderOps rep => TopDownRuleBasicOp rep+ruleBasicOp :: BuilderOps rep => TopDownRuleBasicOp rep ruleBasicOp vtable pat aux op | Just (op', cs) <- applySimpleRules defOf seType op = Simplify $ certifying (cs <> stmAuxCerts aux) $ letBind pat $ BasicOp op'@@ -150,22 +150,21 @@ defOf = (`ST.lookupExp` vtable) seType (Var v) = ST.lookupType v vtable seType (Constant v) = Just $ Prim $ primValueType v-ruleBasicOp vtable pat _ (Update src _ (Var v))+ruleBasicOp vtable pat _ (Update _ src _ (Var v)) | Just (BasicOp Scratch {}, _) <- ST.lookupExp v vtable = Simplify $ letBind pat $ BasicOp $ SubExp $ Var src -- If we are writing a single-element slice from some array, and the -- element of that array can be computed as a PrimExp based on the -- index, let's just write that instead.-ruleBasicOp vtable pat aux (Update src [DimSlice i n s] (Var v))+ruleBasicOp vtable pat aux (Update safety src (Slice [DimSlice i n s]) (Var v)) | isCt1 n, isCt1 s, Just (ST.Indexed cs e) <- ST.index v [intConst Int64 0] vtable = Simplify $ do e' <- toSubExp "update_elem" e- auxing aux $- certifying cs $- letBind pat $ BasicOp $ Update src [DimFix i] e'-ruleBasicOp vtable pat _ (Update dest destis (Var v))+ auxing aux . certifying cs $+ letBind pat $ BasicOp $ Update safety src (Slice [DimFix i]) e'+ruleBasicOp vtable pat _ (Update _ dest destis (Var v)) | Just (e, _) <- ST.lookupExp v vtable, arrayFrom e = Simplify $ letBind pat $ BasicOp $ SubExp $ Var dest@@ -182,7 +181,7 @@ True arrayFrom _ = False-ruleBasicOp vtable pat _ (Update dest is se)+ruleBasicOp vtable pat _ (Update _ dest is se) | Just dest_t <- ST.lookupType dest vtable, isFullSlice (arrayShape dest_t) is = Simplify $ case se of@@ -192,8 +191,8 @@ BasicOp $ Reshape (map DimNew $ arrayDims dest_t) v letBind pat $ BasicOp $ Copy v_reshaped _ -> letBind pat $ BasicOp $ ArrayLit [se] $ rowType dest_t-ruleBasicOp vtable pat (StmAux cs1 attrs _) (Update dest1 is1 (Var v1))- | Just (Update dest2 is2 se2, cs2) <- ST.lookupBasicOp v1 vtable,+ruleBasicOp vtable pat (StmAux cs1 attrs _) (Update safety1 dest1 is1 (Var v1))+ | Just (Update safety2 dest2 is2 se2, cs2) <- ST.lookupBasicOp v1 vtable, Just (Copy v3, cs3) <- ST.lookupBasicOp dest2 vtable, Just (Index v4 is4, cs4) <- ST.lookupBasicOp v3 vtable, is4 == is1,@@ -201,7 +200,7 @@ Simplify $ certifying (cs1 <> cs2 <> cs3 <> cs4) $ do is5 <- subExpSlice $ sliceSlice (primExpSlice is1) (primExpSlice is2)- attributing attrs $ letBind pat $ BasicOp $ Update dest1 is5 se2+ attributing attrs $ letBind pat $ BasicOp $ Update (max safety1 safety2) dest1 is5 se2 ruleBasicOp vtable pat _ (CmpOp (CmpEq t) se1 se2) | Just m <- simplifyWith se1 se2 = Simplify m | Just m <- simplifyWith se2 se1 = Simplify m@@ -210,7 +209,7 @@ | Just bnd <- ST.lookupStm v vtable, If p tbranch fbranch _ <- stmExp bnd, Just (y, z) <-- returns v (stmPattern bnd) tbranch fbranch,+ returns v (stmPat bnd) tbranch fbranch, not $ boundInBody tbranch `namesIntersect` freeIn y, not $ boundInBody fbranch `namesIntersect` freeIn z = Just $ do eq_x_y <-@@ -229,10 +228,9 @@ Nothing returns v ifpat tbranch fbranch =- fmap snd $- find ((== v) . patElemName . fst) $- zip (patternValueElements ifpat) $- zip (bodyResult tbranch) (bodyResult fbranch)+ fmap snd . find ((== v) . patElemName . fst) $+ zip (patElems ifpat) $+ zip (map resSubExp (bodyResult tbranch)) (map resSubExp (bodyResult fbranch)) ruleBasicOp _ pat _ (Replicate (Shape []) se@Constant {}) = Simplify $ letBind pat $ BasicOp $ SubExp se ruleBasicOp _ pat _ (Replicate (Shape []) (Var v)) = Simplify $ do@@ -270,12 +268,14 @@ (map pe64 inds) new_inds' <- mapM (toSubExp "new_index") new_inds- certifying idd_cs $- auxing aux $- letBind pat $ BasicOp $ Index idd2 $ map DimFix new_inds'-ruleBasicOp _ pat _ (BinOp (Pow t) e1 e2)- | e1 == intConst t 2 =- Simplify $ letBind pat $ BasicOp $ BinOp (Shl t) (intConst t 1) e2+ certifying idd_cs . auxing aux $+ letBind pat $ BasicOp $ Index idd2 $ Slice $ map DimFix new_inds'++-- Copying an iota is pointless; just make it an iota instead.+ruleBasicOp vtable pat aux (Copy v)+ | Just (Iota n x s it, v_cs) <- ST.lookupBasicOp v vtable =+ Simplify . certifying v_cs . auxing aux $+ letBind pat $ BasicOp $ Iota n x s it -- Handle identity permutation. ruleBasicOp _ pat _ (Rearrange perm v) | sort perm == perm =@@ -283,10 +283,8 @@ ruleBasicOp vtable pat aux (Rearrange perm v) | Just (BasicOp (Rearrange perm2 e), v_cs) <- ST.lookupExp v vtable = -- Rearranging a rearranging: compose the permutations.- Simplify $- certifying v_cs $- auxing aux $- letBind pat $ BasicOp $ Rearrange (perm `rearrangeCompose` perm2) e+ Simplify . certifying v_cs . auxing aux $+ letBind pat $ BasicOp $ Rearrange (perm `rearrangeCompose` perm2) e ruleBasicOp vtable pat aux (Rearrange perm v) | Just (BasicOp (Rotate offsets v2), v_cs) <- ST.lookupExp v vtable, Just (BasicOp (Rearrange perm3 v3), v2_cs) <- ST.lookupExp v2 vtable = Simplify $ do@@ -340,20 +338,19 @@ -- Update with a slice of that array. This matters when the arrays -- are far away (on the GPU, say), because it avoids a copy of the -- scalar to and from the host.-ruleBasicOp vtable pat aux (Update arr_x slice_x (Var v))- | Just _ <- sliceIndices slice_x,- Just (Index arr_y slice_y, cs_y) <- ST.lookupBasicOp v vtable,+ruleBasicOp vtable pat aux (Update safety arr_x (Slice slice_x) (Var v))+ | Just _ <- sliceIndices (Slice slice_x),+ Just (Index arr_y (Slice slice_y), cs_y) <- ST.lookupBasicOp v vtable, ST.available arr_y vtable, -- XXX: we should check for proper aliasing here instead. arr_y /= arr_x, Just (slice_x_bef, DimFix i, []) <- focusNth (length slice_x - 1) slice_x, Just (slice_y_bef, DimFix j, []) <- focusNth (length slice_y - 1) slice_y = Simplify $ do- let slice_x' = slice_x_bef ++ [DimSlice i (intConst Int64 1) (intConst Int64 1)]- slice_y' = slice_y_bef ++ [DimSlice j (intConst Int64 1) (intConst Int64 1)]+ let slice_x' = Slice $ slice_x_bef ++ [DimSlice i (intConst Int64 1) (intConst Int64 1)]+ slice_y' = Slice $ slice_y_bef ++ [DimSlice j (intConst Int64 1) (intConst Int64 1)] v' <- letExp (baseString v ++ "_slice") $ BasicOp $ Index arr_y slice_y'- certifying cs_y $- auxing aux $- letBind pat $ BasicOp $ Update arr_x slice_x' $ Var v'+ certifying cs_y . auxing aux $+ letBind pat $ BasicOp $ Update safety arr_x slice_x' $ Var v' -- Simplify away 0<=i when 'i' is from a loop of form 'for i < n'. ruleBasicOp vtable pat aux (CmpOp CmpSle {} x y)@@ -372,20 +369,30 @@ | isCt0 y, maybe False ST.entryIsSize $ ST.lookup x vtable = Simplify $ auxing aux $ letBind pat $ BasicOp $ SubExp $ constant False+-- Remove certificates for variables whose definition already contain+-- that certificate.+ruleBasicOp vtable pat aux (SubExp (Var v))+ | cs <- unCerts $ stmAuxCerts aux,+ not $ null cs,+ Just v_cs <- unCerts . stmCerts <$> ST.lookupStm v vtable,+ cs' <- filter (`notElem` v_cs) cs,+ cs' /= cs =+ Simplify . certifying (Certs cs') $+ letBind pat $ BasicOp $ SubExp $ Var v ruleBasicOp _ _ _ _ = Skip -topDownRules :: BinderOps rep => [TopDownRule rep]+topDownRules :: BuilderOps rep => [TopDownRule rep] topDownRules = [ RuleBasicOp ruleBasicOp ] -bottomUpRules :: BinderOps rep => [BottomUpRule rep]+bottomUpRules :: BuilderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleBasicOp simplifyConcat ] --- | A set of simplification rules for 'BasicOp's. Includes rules+-- | A set of simplification rules for t'BasicOp's. Includes rules -- from "Futhark.Optimise.Simplify.Rules.Simple".-basicOpRules :: (BinderOps rep, Aliased rep) => RuleBook rep+basicOpRules :: (BuilderOps rep, Aliased rep) => RuleBook rep basicOpRules = ruleBook topDownRules bottomUpRules <> loopRules
src/Futhark/Optimise/Simplify/Rules/ClosedForm.hs view
@@ -39,9 +39,9 @@ -- | @foldClosedForm look foldfun accargs arrargs@ determines whether -- each of the results of @foldfun@ can be expressed in a closed form. foldClosedForm ::- (ASTRep rep, BinderOps rep) =>+ (ASTRep rep, BuilderOps rep) => VarLookup rep ->- Pattern rep ->+ Pat rep -> Lambda rep -> [SubExp] -> [VName] ->@@ -49,13 +49,13 @@ foldClosedForm look pat lam accs arrs = do inputsize <- arraysSize 0 <$> mapM lookupType arrs - t <- case patternTypes pat of+ t <- case patTypes pat of [Prim t] -> return t _ -> cannotSimplify closedBody <- checkResults- (patternNames pat)+ (patNames pat) inputsize mempty Int64@@ -78,8 +78,8 @@ -- | @loopClosedForm pat respat merge bound bodys@ determines whether -- the do-loop can be expressed in a closed form. loopClosedForm ::- (ASTRep rep, BinderOps rep) =>- Pattern rep ->+ (ASTRep rep, BuilderOps rep) =>+ Pat rep -> [(FParam rep, SubExp)] -> Names -> IntType ->@@ -87,7 +87,7 @@ Body rep -> RuleM rep () loopClosedForm pat merge i it bound body = do- t <- case patternTypes pat of+ t <- case patTypes pat of [Prim t] -> return t _ -> cannotSimplify @@ -118,7 +118,7 @@ knownBnds = M.fromList $ zip mergenames mergeexp checkResults ::- BinderOps rep =>+ BuilderOps rep => [VName] -> SubExp -> Names ->@@ -133,7 +133,7 @@ ((), bnds) <- collectStms $ zipWithM_ checkResult (zip pat res) (zip accparams accs)- mkBodyM bnds $ map Var pat+ mkBodyM bnds $ varsRes pat where bndMap = makeBindMap body (accparams, _) = splitAt (length accs) params@@ -141,8 +141,9 @@ nonFree = boundInBody body <> namesFromList params <> untouchable - checkResult (p, Var v) (accparam, acc)- | Just (BasicOp (BinOp bop x y)) <- M.lookup v bndMap = do+ checkResult (p, SubExpRes _ (Var v)) (accparam, acc)+ | Just (BasicOp (BinOp bop x y)) <- M.lookup v bndMap,+ x /= y = do -- One of x,y must be *this* accumulator, and the other must -- be something that is free in the body. let isThisAccum = (== Var accparam)@@ -157,8 +158,8 @@ case bop of LogAnd -> letBindNames [p] $ BasicOp $ BinOp LogAnd this el- Add t w | Just properly_typed_size <- properIntSize t -> do- size' <- properly_typed_size+ Add t w -> do+ size' <- asIntS t size letBindNames [p] =<< eBinOp (Add t w)@@ -179,12 +180,6 @@ | v `nameIn` nonFree = M.lookup v knownBnds asFreeSubExp se = Just se - properIntSize Int64 = Just $ return size- properIntSize t =- Just $- letSubExp "converted_size" $- BasicOp $ ConvOp (SExt it t) size- properFloatSize t = Just $ letSubExp "converted_size" $@@ -218,6 +213,6 @@ makeBindMap :: Body rep -> M.Map VName (Exp rep) makeBindMap = M.fromList . mapMaybe isSingletonStm . stmsToList . bodyStms where- isSingletonStm (Let pat _ e) = case patternNames pat of+ isSingletonStm (Let pat _ e) = case patNames pat of [v] -> Just (v, e) _ -> Nothing
src/Futhark/Optimise/Simplify/Rules/Index.hs view
@@ -23,42 +23,43 @@ isCt0 (Constant v) = zeroIsh v isCt0 _ = False --- | Some index expressions can be simplified to 'SubExp's, while+-- | Some index expressions can be simplified to t'SubExp's, while -- others produce another index expression (which may be further -- simplifiable). data IndexResult- = IndexResult Certificates VName (Slice SubExp)- | SubExpResult Certificates SubExp+ = IndexResult Certs VName (Slice SubExp)+ | SubExpResult Certs SubExp -- | Try to simplify an index operation. simplifyIndexing ::- MonadBinder m =>+ MonadBuilder m => ST.SymbolTable (Rep m) -> TypeLookup -> VName -> Slice SubExp -> Bool -> Maybe (m IndexResult)-simplifyIndexing vtable seType idd inds consuming =+simplifyIndexing vtable seType idd (Slice inds) consuming = case defOf idd of _ | Just t <- seType (Var idd),- inds == fullSlice t [] ->+ Slice inds == fullSlice t [] -> Just $ pure $ SubExpResult mempty $ Var idd- | Just inds' <- sliceIndices inds,+ | Just inds' <- sliceIndices (Slice inds), Just (ST.Indexed cs e) <- ST.index idd inds' vtable, worthInlining e,- all (`ST.elem` vtable) (unCertificates cs) ->+ all (`ST.elem` vtable) (unCerts cs) -> Just $ SubExpResult cs <$> toSubExp "index_primexp" e- | Just inds' <- sliceIndices inds,+ | Just inds' <- sliceIndices (Slice inds), Just (ST.IndexedArray cs arr inds'') <- ST.index idd inds' vtable, all (worthInlining . untyped) inds'',- all (`ST.elem` vtable) (unCertificates cs) ->+ all (`ST.elem` vtable) (unCerts cs) -> Just $- IndexResult cs arr . map DimFix+ IndexResult cs arr . Slice . map DimFix <$> mapM (toSubExp "index_primexp") inds'' Nothing -> Nothing- Just (SubExp (Var v), cs) -> Just $ pure $ IndexResult cs v inds+ Just (SubExp (Var v), cs) ->+ Just $ pure $ IndexResult cs v $ Slice inds Just (Iota _ x s to_it, cs) | [DimFix ii] <- inds, Just (Prim (IntType from_it)) <- seType ii ->@@ -101,17 +102,23 @@ DimFix <$> adjustI i o d adjust (DimSlice i n s, o, d) = DimSlice <$> adjustI i o d <*> pure n <*> pure s- IndexResult cs a <$> mapM adjust (zip3 inds offsets dims)+ IndexResult cs a . Slice <$> mapM adjust (zip3 inds offsets dims) where rotateAndSlice r DimSlice {} = not $ isCt0 r rotateAndSlice _ _ = False Just (Index aa ais, cs) -> Just $ IndexResult cs aa- <$> subExpSlice (sliceSlice (primExpSlice ais) (primExpSlice inds))+ <$> subExpSlice (sliceSlice (primExpSlice ais) (primExpSlice (Slice inds))) Just (Replicate (Shape [_]) (Var vv), cs)- | [DimFix {}] <- inds, not consuming -> Just $ pure $ SubExpResult cs $ Var vv- | DimFix {} : is' <- inds, not consuming -> Just $ pure $ IndexResult cs vv is'+ | [DimFix {}] <- inds,+ not consuming,+ ST.available vv vtable ->+ Just $ pure $ SubExpResult cs $ Var vv+ | DimFix {} : is' <- inds,+ not consuming,+ ST.available vv vtable ->+ Just $ pure $ IndexResult cs vv $ Slice is' Just (Replicate (Shape [_]) val@(Constant _), cs) | [DimFix {}] <- inds, not consuming -> Just $ pure $ SubExpResult cs val Just (Replicate (Shape ds) v, cs)@@ -120,14 +127,14 @@ ds' /= ds -> Just $ do arr <- letExp "smaller_replicate" $ BasicOp $ Replicate (Shape ds') v- return $ IndexResult cs arr $ ds_inds' ++ rest_inds+ return $ IndexResult cs arr $ Slice $ ds_inds' ++ rest_inds where index DimFix {} = Nothing index (DimSlice _ n s) = Just (n, DimSlice (constant (0 :: Int64)) n s) Just (Rearrange perm src, cs) | rearrangeReach perm <= length (takeWhile isIndex inds) -> let inds' = rearrangeShape (rearrangeInverse perm) inds- in Just $ pure $ IndexResult cs src inds'+ in Just $ pure $ IndexResult cs src $ Slice inds' where isIndex DimFix {} = True isIndex _ = False@@ -136,25 +143,27 @@ length inds == length dims, -- It is generally not safe to simplify a slice of a copy, -- because the result may be used in an in-place update of the- -- original.- Just _ <- mapM dimFix inds,+ -- original. But we know this can only happen if the original+ -- is bound the same depth as we are!+ all (isJust . dimFix) inds+ || maybe True ((ST.loopDepth vtable /=) . ST.entryDepth) (ST.lookup src vtable), not consuming, ST.available src vtable ->- Just $ pure $ IndexResult cs src inds+ Just $ pure $ IndexResult cs src $ Slice inds Just (Reshape newshape src, cs) | Just newdims <- shapeCoercion newshape, Just olddims <- arrayDims <$> seType (Var src), changed_dims <- zipWith (/=) newdims olddims, not $ or $ drop (length inds) changed_dims ->- Just $ pure $ IndexResult cs src inds+ Just $ pure $ IndexResult cs src $ Slice inds | Just newdims <- shapeCoercion newshape, Just olddims <- arrayDims <$> seType (Var src), length newshape == length inds, length olddims == length newdims ->- Just $ pure $ IndexResult cs src inds+ Just $ pure $ IndexResult cs src $ Slice inds Just (Reshape [_] v2, cs) | Just [_] <- arrayDims <$> seType (Var v2) ->- Just $ pure $ IndexResult cs v2 inds+ Just $ pure $ IndexResult cs v2 $ Slice inds Just (Concat d x xs _, cs) | -- HACK: simplifying the indexing of an N-array concatenation -- is going to produce an N-deep if expression, which is bad@@ -166,7 +175,7 @@ not $ any isConcat $ x : xs, Just (ibef, DimFix i, iaft) <- focusNth d inds, Just (Prim res_t) <-- (`setArrayDims` sliceDims inds)+ (`setArrayDims` sliceDims (Slice inds)) <$> ST.lookupType x vtable -> Just $ do x_len <- arraySize d <$> lookupType x xs_lens <- mapM (fmap (arraySize d) . lookupType) xs@@ -178,15 +187,16 @@ let xs_and_starts = reverse $ zip xs starts let mkBranch [] =- letSubExp "index_concat" $ BasicOp $ Index x $ ibef ++ DimFix i : iaft+ letSubExp "index_concat" $ BasicOp $ Index x $ Slice $ ibef ++ DimFix i : iaft mkBranch ((x', start) : xs_and_starts') = do cmp <- letSubExp "index_concat_cmp" $ BasicOp $ CmpOp (CmpSle Int64) start i (thisres, thisbnds) <- collectStms $ do i' <- letSubExp "index_concat_i" $ BasicOp $ BinOp (Sub Int64 OverflowWrap) i start- letSubExp "index_concat" $ BasicOp $ Index x' $ ibef ++ DimFix i' : iaft- thisbody <- mkBodyM thisbnds [thisres]+ letSubExp "index_concat" . BasicOp . Index x' $+ Slice $ ibef ++ DimFix i' : iaft+ thisbody <- mkBodyM thisbnds [subExpRes thisres] (altres, altbnds) <- collectStms $ mkBranch xs_and_starts'- altbody <- mkBodyM altbnds [altres]+ altbody <- mkBodyM altbnds [subExpRes altres] letSubExp "index_concat_branch" $ If cmp thisbody altbody $ IfDec [primBodyType res_t] IfNormal@@ -196,7 +206,7 @@ Just se <- maybeNth i ses -> case inds' of [] -> Just $ pure $ SubExpResult cs se- _ | Var v2 <- se -> Just $ pure $ IndexResult cs v2 inds'+ _ | Var v2 <- se -> Just $ pure $ IndexResult cs v2 $ Slice inds' _ -> Nothing -- Indexing single-element arrays. We know the index must be 0. _@@ -204,7 +214,7 @@ isCt1 $ arraySize 0 t, DimFix i : inds' <- inds, not $ isCt0 i ->- Just . pure . IndexResult mempty idd $+ Just . pure . IndexResult mempty idd . Slice $ DimFix (constant (0 :: Int64)) : inds' _ -> Nothing where
src/Futhark/Optimise/Simplify/Rules/Loop.hs view
@@ -4,6 +4,7 @@ module Futhark.Optimise.Simplify.Rules.Loop (loopRules) where import Control.Monad+import Data.Bifunctor (second) import Data.List (partition) import Data.Maybe import Futhark.Analysis.DataDependencies@@ -25,18 +26,13 @@ -- I do not claim that the current implementation of this rule is -- perfect, but it should suffice for many cases, and should never -- generate wrong code.-removeRedundantMergeVariables :: BinderOps rep => BottomUpRuleDoLoop rep-removeRedundantMergeVariables (_, used) pat aux (ctx, val, form, body)- | not $ all (usedAfterLoop . fst) val,- null ctx -- FIXME: things get tricky if we can remove all vals- -- but some ctxs are still used. We take the easy way- -- out for now.- =- let (ctx_es, val_es) = splitAt (length ctx) $ bodyResult body- necessaryForReturned =+removeRedundantMergeVariables :: BuilderOps rep => BottomUpRuleDoLoop rep+removeRedundantMergeVariables (_, used) pat aux (merge, form, body)+ | not $ all (usedAfterLoop . fst) merge =+ let necessaryForReturned = findNecessaryForReturned usedAfterLoopOrInForm- (zip (map fst $ ctx ++ val) $ ctx_es ++ val_es)+ (zip (map fst merge) (map resSubExp $ bodyResult body)) (dataDependencies body) resIsNecessary ((v, _), _) =@@ -45,33 +41,18 @@ || referencedInPat v || referencedInForm v - (keep_ctx, discard_ctx) =- partition resIsNecessary $ zip ctx ctx_es (keep_valpart, discard_valpart) = partition (resIsNecessary . snd) $- zip (patternValueElements pat) $ zip val val_es+ zip (patElems pat) $ zip merge $ bodyResult body (keep_valpatelems, keep_val) = unzip keep_valpart (_discard_valpatelems, discard_val) = unzip discard_valpart- (ctx', ctx_es') = unzip keep_ctx- (val', val_es') = unzip keep_val-- body' = body {bodyResult = ctx_es' ++ val_es'}- free_in_keeps = freeIn keep_valpatelems+ (merge', val_es') = unzip keep_val - stillUsedContext pat_elem =- patElemName pat_elem- `nameIn` ( free_in_keeps- <> freeIn (filter (/= pat_elem) $ patternContextElements pat)- )+ body' = body {bodyResult = val_es'} - pat' =- pat- { patternValueElements = keep_valpatelems,- patternContextElements =- filter stillUsedContext $ patternContextElements pat- }- in if ctx' ++ val' == ctx ++ val+ pat' = Pat keep_valpatelems+ in if merge' == merge then Skip else Simplify $ do -- We can't just remove the bindings in 'discard', since the loop@@ -80,17 +61,16 @@ -- removal will eventually get rid of them. Some care is -- necessary to handle unique bindings. body'' <- insertStmsM $ do- mapM_ (uncurry letBindNames) $ dummyStms discard_ctx mapM_ (uncurry letBindNames) $ dummyStms discard_val- return body'- auxing aux $ letBind pat' $ DoLoop ctx' val' form body''+ pure body'+ auxing aux $ letBind pat' $ DoLoop merge' form body'' where- pat_used = map (`UT.isUsedDirectly` used) $ patternValueNames pat- used_vals = map fst $ filter snd $ zip (map (paramName . fst) val) pat_used+ pat_used = map (`UT.isUsedDirectly` used) $ patNames pat+ used_vals = map fst $ filter snd $ zip (map (paramName . fst) merge) pat_used usedAfterLoop = flip elem used_vals . paramName usedAfterLoopOrInForm p = usedAfterLoop p || paramName p `nameIn` freeIn form- patAnnotNames = freeIn $ map fst $ ctx ++ val+ patAnnotNames = freeIn $ map fst merge referencedInPat = (`nameIn` patAnnotNames) . paramName referencedInForm = (`nameIn` freeIn form) . paramName @@ -105,44 +85,27 @@ -- We may change the type of the loop if we hoist out a shape -- annotation, in which case we also need to tweak the bound pattern.-hoistLoopInvariantMergeVariables :: BinderOps rep => TopDownRuleDoLoop rep-hoistLoopInvariantMergeVariables vtable pat aux (ctx, val, form, loopbody) =+hoistLoopInvariantMergeVariables :: BuilderOps rep => TopDownRuleDoLoop rep+hoistLoopInvariantMergeVariables vtable pat aux (merge, form, loopbody) = do -- Figure out which of the elements of loopresult are -- loop-invariant, and hoist them out.+ let explpat = zip (patElems pat) $ map (paramName . fst) merge case foldr checkInvariance ([], explpat, [], []) $- zip3 (patternNames pat) merge res of+ zip3 (patNames pat) merge res of ([], _, _, _) -> -- Nothing is invariant. Skip (invariant, explpat', merge', res') -> Simplify $ do -- We have moved something invariant out of the loop. let loopbody' = loopbody {bodyResult = res'}- invariantShape :: (a, VName) -> Bool- invariantShape (_, shapemerge) =- shapemerge- `elem` map (paramName . fst) merge'- (implpat', implinvariant) = partition invariantShape implpat- implinvariant' = [(patElemIdent p, Var v) | (p, v) <- implinvariant]- implpat'' = map fst implpat' explpat'' = map fst explpat'- (ctx', val') = splitAt (length implpat') merge'- forM_ (invariant ++ implinvariant') $ \(v1, v2) ->+ forM_ invariant $ \(v1, v2) -> letBindNames [identName v1] $ BasicOp $ SubExp v2- auxing aux $- letBind (Pattern implpat'' explpat'') $- DoLoop ctx' val' form loopbody'+ auxing aux $ letBind (Pat explpat'') $ DoLoop merge' form loopbody' where- merge = ctx ++ val res = bodyResult loopbody - implpat =- zip (patternContextElements pat) $- map (paramName . fst) ctx- explpat =- zip (patternValueElements pat) $- map (paramName . fst) val-- namesOfMergeParams = namesFromList $ map (paramName . fst) $ ctx ++ val+ namesOfMergeParams = namesFromList $ map (paramName . fst) merge removeFromResult (mergeParam, mergeInit) explpat' = case partition ((== paramName mergeParam) . snd) explpat' of@@ -174,13 +137,13 @@ -- parameter, where all existential parameters are already -- known to be invariant isInvariant- | Var v2 <- resExp,+ | Var v2 <- resSubExp resExp, paramName mergeParam == v2 = allExistentialInvariant (namesFromList $ map (identName . fst) invariant) mergeParam -- (1) The result is identical to the initial parameter value.- | mergeInit == resExp = True+ | mergeInit == resSubExp resExp = True -- (2) The initial parameter value is equal to an outer -- loop parameter 'P', where the initial value of 'P' is -- equal to 'resExp', AND 'resExp' ultimately becomes the@@ -189,7 +152,7 @@ -- would not be too hard to generalise. | Var init_v <- mergeInit, Just (p_init, p_res) <- ST.lookupLoopParam init_v vtable,- p_init == resExp,+ p_init == resSubExp resExp, p_res == Var pat_name = True | otherwise = False@@ -206,13 +169,13 @@ not (name `nameIn` namesOfMergeParams) || name `nameIn` namesOfInvariant -simplifyClosedFormLoop :: BinderOps rep => TopDownRuleDoLoop rep-simplifyClosedFormLoop _ pat _ ([], val, ForLoop i it bound [], body) =+simplifyClosedFormLoop :: BuilderOps rep => TopDownRuleDoLoop rep+simplifyClosedFormLoop _ pat _ (val, ForLoop i it bound [], body) = Simplify $ loopClosedForm pat val (oneName i) it bound body simplifyClosedFormLoop _ _ _ _ = Skip -simplifyLoopVariables :: (BinderOps rep, Aliased rep) => TopDownRuleDoLoop rep-simplifyLoopVariables vtable pat aux (ctx, val, form@(ForLoop i it num_iters loop_vars), body)+simplifyLoopVariables :: (BuilderOps rep, Aliased rep) => TopDownRuleDoLoop rep+simplifyLoopVariables vtable pat aux (merge, form@(ForLoop i it num_iters loop_vars), body) | simplifiable <- map checkIfSimplifiable loop_vars, not $ all isNothing simplifiable = Simplify $ do -- Check if the simplifications throw away more information than@@ -226,13 +189,8 @@ body' <- buildBody_ $ do addStms $ mconcat body_prefix_stms bodyBind body- auxing aux $- letBind pat $- DoLoop- ctx- val- (ForLoop i it num_iters $ catMaybes maybe_loop_vars)- body'+ let form' = ForLoop i it num_iters $ catMaybes maybe_loop_vars+ auxing aux $ letBind pat $ DoLoop merge form' body' where seType (Var v) | v == i = Just $ Prim $ IntType it@@ -247,7 +205,7 @@ vtable' seType arr- (DimFix (Var i) : fullSlice (paramType p) [])+ (Slice (DimFix (Var i) : unSlice (fullSlice (paramType p) []))) $ paramName p `nameIn` consumed_in_body -- We only want this simplification if the result does not refer@@ -257,7 +215,7 @@ onLoopVar (p, arr) (Just m) = do (x, x_stms) <- collectStms m case x of- IndexResult cs arr' slice+ IndexResult cs arr' (Slice slice) | not $ any ((i `nameIn`) . freeIn) x_stms, DimFix (Var j) : slice' <- slice, j == i,@@ -266,10 +224,8 @@ w <- arraySize 0 <$> lookupType arr' for_in_partial <- certifying cs $- letExp "for_in_partial" $- BasicOp $- Index arr' $- DimSlice (intConst Int64 0) w (intConst Int64 1) : slice'+ letExp "for_in_partial" . BasicOp . Index arr' . Slice $+ DimSlice (intConst Int64 0) w (intConst Int64 1) : slice' return (Just (p, for_in_partial), mempty) SubExpResult cs se | all (notIndex . stmExp) x_stms -> do@@ -290,8 +246,8 @@ -- instead. We then move the sign extension inside the loop instead. -- This addresses loops of the form @for i in x..<y@ in the source -- language.-narrowLoopType :: (BinderOps rep) => TopDownRuleDoLoop rep-narrowLoopType vtable pat aux (ctx, val, ForLoop i Int64 n [], body)+narrowLoopType :: (BuilderOps rep) => TopDownRuleDoLoop rep+narrowLoopType vtable pat aux (merge, ForLoop i Int64 n [], body) | Just (n', it', cs) <- smallerType = Simplify $ do i' <- newVName $ baseString i@@ -299,9 +255,7 @@ body' <- insertStmsM . inScopeOf form' $ do letBindNames [i] $ BasicOp $ ConvOp (SExt it' Int64) (Var i') pure body- auxing aux $- certifying cs $- letBind pat $ DoLoop ctx val form' body'+ auxing aux $ certifying cs $ letBind pat $ DoLoop merge form' body' where smallerType | Var n' <- n,@@ -315,28 +269,26 @@ narrowLoopType _ _ _ _ = Skip unroll ::- BinderOps rep =>+ BuilderOps rep => Integer ->- [(FParam rep, SubExp)] ->+ [(FParam rep, SubExpRes)] -> (VName, IntType, Integer) -> [(LParam rep, VName)] -> Body rep ->- RuleM rep [SubExp]+ RuleM rep [SubExpRes] unroll n merge (iv, it, i) loop_vars body | i >= n = return $ map snd merge | otherwise = do iter_body <- insertStmsM $ do- forM_ merge $ \(mergevar, mergeinit) ->- letBindNames [paramName mergevar] $ BasicOp $ SubExp mergeinit+ forM_ merge $ \(mergevar, SubExpRes cs mergeinit) ->+ certifying cs $ letBindNames [paramName mergevar] $ BasicOp $ SubExp mergeinit letBindNames [iv] $ BasicOp $ SubExp $ intConst it i forM_ loop_vars $ \(p, arr) ->- letBindNames [paramName p] $- BasicOp $- Index arr $- DimFix (intConst Int64 i) : fullSlice (paramType p) []+ letBindNames [paramName p] . BasicOp . Index arr . Slice $+ DimFix (intConst Int64 i) : unSlice (fullSlice (paramType p) []) -- Some of the sizes in the types here might be temporarily wrong -- until copy propagation fixes it up.@@ -348,17 +300,17 @@ let merge' = zip (map fst merge) $ bodyResult iter_body' unroll n merge' (iv, it, i + 1) loop_vars body -simplifyKnownIterationLoop :: BinderOps rep => TopDownRuleDoLoop rep-simplifyKnownIterationLoop _ pat aux (ctx, val, ForLoop i it (Constant iters) loop_vars, body)+simplifyKnownIterationLoop :: BuilderOps rep => TopDownRuleDoLoop rep+simplifyKnownIterationLoop _ pat aux (merge, ForLoop i it (Constant iters) loop_vars, body) | IntValue n <- iters, zeroIshInt n || oneIshInt n || "unroll" `inAttrs` stmAuxAttrs aux = Simplify $ do- res <- unroll (valueIntegral n) (ctx ++ val) (i, it, 0) loop_vars body- forM_ (zip (patternNames pat) res) $ \(v, se) ->- letBindNames [v] $ BasicOp $ SubExp se+ res <- unroll (valueIntegral n) (map (second subExpRes) merge) (i, it, 0) loop_vars body+ forM_ (zip (patNames pat) res) $ \(v, SubExpRes cs se) ->+ certifying cs $ letBindNames [v] $ BasicOp $ SubExp se simplifyKnownIterationLoop _ _ _ _ = Skip -topDownRules :: (BinderOps rep, Aliased rep) => [TopDownRule rep]+topDownRules :: (BuilderOps rep, Aliased rep) => [TopDownRule rep] topDownRules = [ RuleDoLoop hoistLoopInvariantMergeVariables, RuleDoLoop simplifyClosedFormLoop,@@ -367,11 +319,11 @@ RuleDoLoop narrowLoopType ] -bottomUpRules :: BinderOps rep => [BottomUpRule rep]+bottomUpRules :: BuilderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleDoLoop removeRedundantMergeVariables ] -- | Standard loop simplification rules.-loopRules :: (BinderOps rep, Aliased rep) => RuleBook rep+loopRules :: (BuilderOps rep, Aliased rep) => RuleBook rep loopRules = ruleBook topDownRules bottomUpRules
src/Futhark/Optimise/Simplify/Rules/Simple.hs view
@@ -14,14 +14,14 @@ import Futhark.IR -- | A function that, given a variable name, returns its definition.-type VarLookup rep = VName -> Maybe (Exp rep, Certificates)+type VarLookup rep = VName -> Maybe (Exp rep, Certs) -- | A function that, given a subexpression, returns its type. type TypeLookup = SubExp -> Maybe Type -- | A simple rule is a top-down rule that can be expressed as a pure -- function.-type SimpleRule rep = VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)+type SimpleRule rep = VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certs) isCt1 :: SubExp -> Bool isCt1 (Constant v) = oneIsh v@@ -60,18 +60,18 @@ | Just res <- doBinOp op v1 v2 = constRes res simplifyBinOp look _ (BinOp Add {} e1 e2)- | isCt0 e1 = subExpRes e2- | isCt0 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e2+ | isCt0 e2 = resIsSubExp e1 -- x+(y-x) => y | Var v2 <- e2, Just (BasicOp (BinOp Sub {} e2_a e2_b), cs) <- look v2, e2_b == e1 = Just (SubExp e2_a, cs) simplifyBinOp _ _ (BinOp FAdd {} e1 e2)- | isCt0 e1 = subExpRes e2- | isCt0 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e2+ | isCt0 e2 = resIsSubExp e1 simplifyBinOp look _ (BinOp sub@(Sub t _) e1 e2)- | isCt0 e2 = subExpRes e1+ | isCt0 e2 = resIsSubExp e1 -- Cases for simplifying (a+b)-b and permutations. -- (e1_a+e1_b)-e1_a == e1_b@@ -95,17 +95,17 @@ e2_b == e1 = Just (BinOp sub (intConst t 0) e2_a, cs) simplifyBinOp _ _ (BinOp FSub {} e1 e2)- | isCt0 e2 = subExpRes e1+ | isCt0 e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp Mul {} e1 e2)- | isCt0 e1 = subExpRes e1- | isCt0 e2 = subExpRes e2- | isCt1 e1 = subExpRes e2- | isCt1 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e1+ | isCt0 e2 = resIsSubExp e2+ | isCt1 e1 = resIsSubExp e2+ | isCt1 e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp FMul {} e1 e2)- | isCt0 e1 = subExpRes e1- | isCt0 e2 = subExpRes e2- | isCt1 e1 = subExpRes e2- | isCt1 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e1+ | isCt0 e2 = resIsSubExp e2+ | isCt1 e1 = resIsSubExp e2+ | isCt1 e2 = resIsSubExp e1 simplifyBinOp look _ (BinOp (SMod t _) e1 e2) | isCt1 e2 = constRes $ IntValue $ intValue t (0 :: Int) | e1 == e2 = constRes $ IntValue $ intValue t (0 :: Int)@@ -114,48 +114,51 @@ e4 == e2 = Just (SubExp e1, v1_cs) simplifyBinOp _ _ (BinOp SDiv {} e1 e2)- | isCt0 e1 = subExpRes e1- | isCt1 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e1+ | isCt1 e2 = resIsSubExp e1 | isCt0 e2 = Nothing simplifyBinOp _ _ (BinOp SDivUp {} e1 e2)- | isCt0 e1 = subExpRes e1- | isCt1 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e1+ | isCt1 e2 = resIsSubExp e1 | isCt0 e2 = Nothing simplifyBinOp _ _ (BinOp FDiv {} e1 e2)- | isCt0 e1 = subExpRes e1- | isCt1 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e1+ | isCt1 e2 = resIsSubExp e1 | isCt0 e2 = Nothing simplifyBinOp _ _ (BinOp (SRem t _) e1 e2) | isCt1 e2 = constRes $ IntValue $ intValue t (0 :: Int) | e1 == e2 = constRes $ IntValue $ intValue t (1 :: Int) simplifyBinOp _ _ (BinOp SQuot {} e1 e2)- | isCt1 e2 = subExpRes e1+ | isCt1 e2 = resIsSubExp e1 | isCt0 e2 = Nothing+simplifyBinOp _ _ (BinOp (Pow t) e1 e2)+ | e1 == intConst t 2 =+ Just (BinOp (Shl t) (intConst t 1) e2, mempty) simplifyBinOp _ _ (BinOp (FPow t) e1 e2)- | isCt0 e2 = subExpRes $ floatConst t 1- | isCt0 e1 || isCt1 e1 || isCt1 e2 = subExpRes e1+ | isCt0 e2 = resIsSubExp $ floatConst t 1+ | isCt0 e1 || isCt1 e1 || isCt1 e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp (Shl t) e1 e2)- | isCt0 e2 = subExpRes e1- | isCt0 e1 = subExpRes $ intConst t 0+ | isCt0 e2 = resIsSubExp e1+ | isCt0 e1 = resIsSubExp $ intConst t 0 simplifyBinOp _ _ (BinOp AShr {} e1 e2)- | isCt0 e2 = subExpRes e1+ | isCt0 e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp (And t) e1 e2)- | isCt0 e1 = subExpRes $ intConst t 0- | isCt0 e2 = subExpRes $ intConst t 0- | e1 == e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp $ intConst t 0+ | isCt0 e2 = resIsSubExp $ intConst t 0+ | e1 == e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp Or {} e1 e2)- | isCt0 e1 = subExpRes e2- | isCt0 e2 = subExpRes e1- | e1 == e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e2+ | isCt0 e2 = resIsSubExp e1+ | e1 == e2 = resIsSubExp e1 simplifyBinOp _ _ (BinOp (Xor t) e1 e2)- | isCt0 e1 = subExpRes e2- | isCt0 e2 = subExpRes e1- | e1 == e2 = subExpRes $ intConst t 0+ | isCt0 e1 = resIsSubExp e2+ | isCt0 e2 = resIsSubExp e1+ | e1 == e2 = resIsSubExp $ intConst t 0 simplifyBinOp defOf _ (BinOp LogAnd e1 e2) | isCt0 e1 = constRes $ BoolValue False | isCt0 e2 = constRes $ BoolValue False- | isCt1 e1 = subExpRes e2- | isCt1 e2 = subExpRes e1+ | isCt1 e1 = resIsSubExp e2+ | isCt1 e2 = resIsSubExp e1 | Var v <- e1, Just (BasicOp (UnOp Not e1'), v_cs) <- defOf v, e1' == e2 =@@ -165,8 +168,8 @@ e2' == e1 = Just (SubExp $ Constant $ BoolValue False, v_cs) simplifyBinOp defOf _ (BinOp LogOr e1 e2)- | isCt0 e1 = subExpRes e2- | isCt0 e2 = subExpRes e1+ | isCt0 e1 = resIsSubExp e2+ | isCt0 e2 = resIsSubExp e1 | isCt1 e1 = constRes $ BoolValue True | isCt1 e2 = constRes $ BoolValue True | Var v <- e1,@@ -179,7 +182,7 @@ Just (SubExp $ Constant $ BoolValue True, v_cs) simplifyBinOp defOf _ (BinOp (SMax it) e1 e2) | e1 == e2 =- subExpRes e1+ resIsSubExp e1 | Var v1 <- e1, Just (BasicOp (BinOp (SMax _) e1_1 e1_2), v1_cs) <- defOf v1, e1_1 == e2 =@@ -198,11 +201,11 @@ Just (BinOp (SMax it) e2_1 e1, v2_cs) simplifyBinOp _ _ _ = Nothing -constRes :: PrimValue -> Maybe (BasicOp, Certificates)+constRes :: PrimValue -> Maybe (BasicOp, Certs) constRes = Just . (,mempty) . SubExp . Constant -subExpRes :: SubExp -> Maybe (BasicOp, Certificates)-subExpRes = Just . (,mempty) . SubExp+resIsSubExp :: SubExp -> Maybe (BasicOp, Certs)+resIsSubExp = Just . (,mempty) . SubExp simplifyUnOp :: SimpleRule rep simplifyUnOp _ _ (UnOp op (Constant v)) =@@ -219,7 +222,7 @@ simplifyConvOp _ _ (ConvOp op se) | (from, to) <- convOpType op, from == to =- subExpRes se+ resIsSubExp se simplifyConvOp lookupVar _ (ConvOp (SExt t2 t1) (Var v)) | Just (BasicOp (ConvOp (SExt t3 _) se), v_cs) <- lookupVar v, t2 >= t3 =@@ -255,7 +258,7 @@ | Just t <- seType $ Var v, newDims newshape == arrayDims t -- No-op reshape. =- subExpRes $ Var v+ resIsSubExp $ Var v simplifyIdentityReshape _ _ _ = Nothing simplifyReshapeReshape :: SimpleRule rep@@ -301,7 +304,7 @@ simplifyReshapeIndex defOf _ (Reshape newshape v) | Just ds <- shapeCoercion newshape, Just (BasicOp (Index v' slice), v_cs) <- defOf v,- slice' <- reshapeSlice slice ds,+ slice' <- Slice $ reshapeSlice (unSlice slice) ds, slice' /= slice = Just (Index v' slice', v_cs) simplifyReshapeIndex _ _ _ = Nothing@@ -309,13 +312,13 @@ -- If we are updating a slice with the result of a size coercion, we -- instead use the original array and update the slice dimensions. simplifyUpdateReshape :: SimpleRule rep-simplifyUpdateReshape defOf seType (Update dest slice (Var v))+simplifyUpdateReshape defOf seType (Update safety dest slice (Var v)) | Just (BasicOp (Reshape newshape v'), v_cs) <- defOf v, Just _ <- shapeCoercion newshape, Just ds <- arrayDims <$> seType (Var v'),- slice' <- reshapeSlice slice ds,+ slice' <- Slice $ reshapeSlice (unSlice slice) ds, slice' /= slice =- Just (Update dest slice' $ Var v', v_cs)+ Just (Update safety dest slice' $ Var v', v_cs) simplifyUpdateReshape _ _ _ = Nothing improveReshape :: SimpleRule rep@@ -369,6 +372,6 @@ VarLookup rep -> TypeLookup -> BasicOp ->- Maybe (BasicOp, Certificates)+ Maybe (BasicOp, Certs) applySimpleRules defOf seType op = msum [rule defOf seType op | rule <- simpleRules]
src/Futhark/Optimise/Sink.hs view
@@ -101,7 +101,7 @@ sunkHere v stm = v `nameIn` free_in_stms && all (`ST.available` vtable) (namesToList (freeIn stm))- sunk = namesFromList $ foldMap (patternNames . stmPattern) sunk_stms+ sunk = namesFromList $ foldMap (patNames . stmPat) sunk_stms optimiseStms :: Constraints rep =>@@ -125,7 +125,7 @@ optimiseStms' _ _ [] = ([], mempty) optimiseStms' vtable sinking (stm : stms) | BasicOp Index {} <- stmExp stm,- [pe] <- patternElements (stmPattern stm),+ [pe] <- patElems (stmPat stm), primType $ patElemType pe, maybe True (== 1) $ M.lookup (patElemName pe) multiplicities = let (stms', sunk) =
src/Futhark/Optimise/TileLoops.hs view
@@ -77,7 +77,7 @@ case maybe_tiled of Just (host_stms, tiling, tiledBody) -> do (res', stms') <-- runBinder $ mapM (tilingTileReturns tiling) =<< tiledBody mempty mempty+ runBuilder $ mapM (tilingTileReturns tiling) =<< tiledBody mempty mempty return ( host_stms, ( tilingLevel tiling,@@ -90,7 +90,7 @@ | otherwise = return (mempty, (lvl, initial_kspace, kbody)) where- isSimpleResult (Returns _ se) = Just se+ isSimpleResult (Returns _ cs se) = Just $ SubExpRes cs se isSimpleResult _ = Nothing tileInBody ::@@ -125,7 +125,7 @@ (tiling2d $ reverse $ zip top_gtids_rev top_kdims_rev) initial_lvl res_ts- (stmPattern stm_to_tile)+ (stmPat stm_to_tile) (gtid_x, gtid_y) (kdim_x, kdim_y) w@@ -147,7 +147,7 @@ (tiling1d $ reverse top_space_rev) initial_lvl res_ts- (stmPattern stm_to_tile)+ (stmPat stm_to_tile) gtid kdim w@@ -156,7 +156,7 @@ poststms' stms_res -- Tiling inside for-loop.- | DoLoop [] merge (ForLoop i it bound []) loopbody <- stmExp stm_to_tile,+ | DoLoop merge (ForLoop i it bound []) loopbody <- stmExp stm_to_tile, (prestms', poststms') <- preludeToPostlude variance prestms stm_to_tile (stmsFromList poststms) = do let branch_variant' =@@ -189,7 +189,7 @@ (freeIn loopbody <> freeIn merge) tiled res_ts- (stmPattern stm_to_tile)+ (stmPat stm_to_tile) (stmAux stm_to_tile) merge i@@ -224,7 +224,7 @@ used stm = any (`nameIn` used_in_stm_variant) $- patternNames $ stmPattern stm+ patNames $ stmPat stm (prelude_used, prelude_not_used) = Seq.partition used prelude@@ -255,21 +255,21 @@ (invariant_prestms, precomputed_variant_prestms, recomputed_variant_prestms) where invariantTo names stm =- case patternNames (stmPattern stm) of+ case patNames (stmPat stm) of [] -> True -- Does not matter. v : _ -> not $ any (`nameIn` names) $ namesToList $ M.findWithDefault mempty v variance consumed v = v `nameIn` consumed_in_prestms- consumedStm stm = any consumed (patternNames (stmPattern stm))+ consumedStm stm = any consumed (patNames (stmPat stm)) later_consumed = namesFromList $- concatMap (patternNames . stmPattern) $+ concatMap (patNames . stmPat) $ stmsToList $ Seq.filter consumedStm prestms groupInvariant stm = invariantTo private stm- && not (any (`nameIn` later_consumed) (patternNames (stmPattern stm)))+ && not (any (`nameIn` later_consumed) (patNames (stmPat stm))) && invariantTo later_consumed stm (invariant_prestms, variant_prestms) = Seq.partition groupInvariant prestms@@ -284,14 +284,14 @@ mustBeInlinedExp _ = False mustBeInlined stm = mustBeInlinedExp (stmExp stm)- && any (`nameIn` used_after) (patternNames (stmPattern stm))+ && any (`nameIn` used_after) (patNames (stmPat stm)) must_be_inlined = namesFromList $- concatMap (patternNames . stmPattern) $+ concatMap (patNames . stmPat) $ stmsToList $ Seq.filter mustBeInlined variant_prestms recompute stm =- any (`nameIn` must_be_inlined) (patternNames (stmPattern stm))+ any (`nameIn` must_be_inlined) (patNames (stmPat stm)) || not (invariantTo must_be_inlined stm) (recomputed_variant_prestms, precomputed_variant_prestms) = Seq.partition recompute variant_prestms@@ -342,7 +342,7 @@ Names -> (Stms GPU, Tiling, TiledBody) -> [Type] ->- Pattern GPU ->+ Pat GPU -> StmAux (ExpDec GPU) -> [(FParam GPU, SubExp)] -> VName ->@@ -392,21 +392,19 @@ certifying (stmAuxCerts aux) $ tilingSegMap tiling "tiled_loopinit" (scalarLevel tiling) ResultPrivate $ \in_bounds slice ->- fmap (map Var) $+ fmap varsRes $ protectOutOfBounds "loopinit" in_bounds merge_ts $ do addPrivStms slice inloop_privstms addPrivStms slice privstms- return mergeinits+ return $ subExpsRes mergeinits let merge' = zip mergeparams' mergeinit' let indexMergeParams slice = localScope (scopeOfFParams mergeparams') $ forM_ (zip mergeparams mergeparams') $ \(to, from) ->- letBindNames [paramName to] $- BasicOp $- Index (paramName from) $- fullSlice (paramType from) slice+ letBindNames [paramName to] . BasicOp . Index (paramName from) $+ fullSlice (paramType from) slice private' = private <> namesFromList (map paramName mergeparams ++ map paramName mergeparams')@@ -415,12 +413,12 @@ PrivStms mempty indexMergeParams <> privstms <> inloop_privstms loopbody' <-- localScope (scopeOfFParams mergeparams') . runBodyBinder $+ localScope (scopeOfFParams mergeparams') . runBodyBuilder $ resultBody . map Var <$> tiledBody private' privstms' accs' <- letTupExp "tiled_inside_loop" $- DoLoop [] merge' (ForLoop i it bound []) loopbody'+ DoLoop merge' (ForLoop i it bound []) loopbody' postludeGeneric tiling (privstms <> inloop_privstms) pat accs' poststms poststms_res res_ts @@ -432,21 +430,21 @@ filter (`notElem` unSegSpace (tilingSpace tiling)) $ unSegSpace initial_space -doPrelude :: Tiling -> PrivStms -> Stms GPU -> [VName] -> Binder GPU [VName]+doPrelude :: Tiling -> PrivStms -> Stms GPU -> [VName] -> Builder GPU [VName] doPrelude tiling privstms prestms prestms_live = -- Create a SegMap that takes care of the prelude for every thread. tilingSegMap tiling "prelude" (scalarLevel tiling) ResultPrivate $ \in_bounds slice -> do ts <- mapM lookupType prestms_live- fmap (map Var) $+ fmap varsRes $ protectOutOfBounds "pre" in_bounds ts $ do addPrivStms slice privstms addStms prestms- pure $ map Var prestms_live+ pure $ varsRes prestms_live liveSet :: FreeIn a => Stms GPU -> a -> Names liveSet stms after =- namesFromList (concatMap (patternNames . stmPattern) stms)+ namesFromList (concatMap (patNames . stmPat) stms) `namesIntersection` freeIn after tileable ::@@ -498,7 +496,7 @@ -- The atual tile size may be smaller for the last tile, so we have to -- be careful now. sliceUntiled ::- MonadBinder m =>+ MonadBuilder m => VName -> SubExp -> SubExp ->@@ -521,7 +519,7 @@ privStms :: Stms GPU -> PrivStms privStms stms = PrivStms stms $ const $ return () -addPrivStms :: Slice SubExp -> PrivStms -> Binder GPU ()+addPrivStms :: [DimIndex SubExp] -> PrivStms -> Builder GPU () addPrivStms local_slice (PrivStms stms readPrelude) = do readPrelude local_slice addStms stms@@ -536,7 +534,7 @@ instance Monoid PrivStms where mempty = privStms mempty -type ReadPrelude = Slice SubExp -> Binder GPU ()+type ReadPrelude = [DimIndex SubExp] -> Builder GPU () data ProcessTileArgs = ProcessTileArgs { processPrivStms :: PrivStms,@@ -567,8 +565,8 @@ String -> SegLevel -> ResultManifest ->- (PrimExp VName -> Slice SubExp -> Binder GPU [SubExp]) ->- Binder GPU [VName],+ (PrimExp VName -> [DimIndex SubExp] -> Builder GPU Result) ->+ Builder GPU [VName], -- The boolean PrimExp indicates whether they are in-bounds. tilingReadTile ::@@ -576,22 +574,22 @@ PrivStms -> SubExp -> [InputArray] ->- Binder GPU [InputTile],+ Builder GPU [InputTile], tilingProcessTile :: ProcessTileArgs ->- Binder GPU [VName],+ Builder GPU [VName], tilingProcessResidualTile :: ResidualTileArgs ->- Binder GPU [VName],- tilingTileReturns :: VName -> Binder GPU KernelResult,+ Builder GPU [VName],+ tilingTileReturns :: VName -> Builder GPU KernelResult, tilingSpace :: SegSpace, tilingTileShape :: Shape, tilingLevel :: SegLevel,- tilingNumWholeTiles :: Binder GPU SubExp+ tilingNumWholeTiles :: Builder GPU SubExp } type DoTiling gtids kdims =- SegLevel -> gtids -> kdims -> SubExp -> Binder GPU Tiling+ SegLevel -> gtids -> kdims -> SubExp -> Builder GPU Tiling scalarLevel :: Tiling -> SegLevel scalarLevel tiling =@@ -603,8 +601,8 @@ String -> PrimExp VName -> [Type] ->- Binder GPU [SubExp] ->- Binder GPU [VName]+ Builder GPU Result ->+ Builder GPU [VName] protectOutOfBounds desc in_bounds ts m = do -- This is more complicated than you might expect, because we need -- to be able to produce a blank accumulator, which eBlank cannot@@ -612,7 +610,7 @@ -- an accumulator of type 'acc_t', then a unique variable of type -- 'acc_t' must also be free in the body. This means we can find it -- based just on the type.- m_body <- insertStmsM $ resultBody <$> m+ m_body <- insertStmsM $ mkBody mempty <$> m let m_body_free = namesToList $ freeIn m_body t_to_v <- filter (isAcc . fst)@@ -626,16 +624,16 @@ postludeGeneric :: Tiling -> PrivStms ->- Pattern GPU ->+ Pat GPU -> [VName] -> Stms GPU -> Result -> [Type] ->- Binder GPU [VName]+ Builder GPU [VName] postludeGeneric tiling privstms pat accs' poststms poststms_res res_ts = tilingSegMap tiling "thread_res" (scalarLevel tiling) ResultPrivate $ \in_bounds slice -> do -- Read our per-thread result from the tiled loop.- forM_ (zip (patternNames pat) accs') $ \(us, everyone) -> do+ forM_ (zip (patNames pat) accs') $ \(us, everyone) -> do everyone_t <- lookupType everyone letBindNames [us] $ BasicOp $ Index everyone $ fullSlice everyone_t slice @@ -644,19 +642,19 @@ -- The privstms may still be necessary for the result. addPrivStms slice privstms return poststms_res- else fmap (map Var) $+ else fmap varsRes $ protectOutOfBounds "postlude" in_bounds res_ts $ do addPrivStms slice privstms addStms poststms return poststms_res -type TiledBody = Names -> PrivStms -> Binder GPU [VName]+type TiledBody = Names -> PrivStms -> Builder GPU [VName] tileGeneric :: DoTiling gtids kdims -> SegLevel -> [Type] ->- Pattern GPU ->+ Pat GPU -> gtids -> kdims -> SubExp ->@@ -666,13 +664,13 @@ Result -> TileM (Stms GPU, Tiling, TiledBody) tileGeneric doTiling initial_lvl res_ts pat gtids kdims w form inputs poststms poststms_res = do- (tiling, tiling_stms) <- runBinder $ doTiling initial_lvl gtids kdims w+ (tiling, tiling_stms) <- runBuilder $ doTiling initial_lvl gtids kdims w return (tiling_stms, tiling, tiledBody tiling) where (red_comm, red_lam, red_nes, map_lam) = form - tiledBody :: Tiling -> Names -> PrivStms -> Binder GPU [VName]+ tiledBody :: Tiling -> Names -> PrivStms -> Builder GPU [VName] tiledBody tiling _private privstms = do let tile_shape = tilingTileShape tiling @@ -683,11 +681,11 @@ mergeinits <- tilingSegMap tiling "mergeinit" (scalarLevel tiling) ResultPrivate $ \in_bounds slice -> -- Constant neutral elements (a common case) do not need protection from OOB. if freeIn red_nes == mempty- then return red_nes- else fmap (map Var) $+ then return $ subExpsRes red_nes+ else fmap varsRes $ protectOutOfBounds "neutral" in_bounds (lambdaReturnType red_lam) $ do addPrivStms slice privstms- return red_nes+ return $ subExpsRes red_nes merge <- forM (zip (lambdaParams red_lam) mergeinits) $ \(p, mergeinit) -> (,)@@ -698,7 +696,7 @@ tile_id <- newVName "tile_id" let loopform = ForLoop tile_id Int64 num_whole_tiles []- loopbody <- renameBody <=< runBodyBinder $+ loopbody <- renameBody <=< runBodyBuilder $ inScopeOf loopform $ localScope (scopeOfFParams $ map fst merge) $ do -- Collectively read a tile.@@ -712,7 +710,7 @@ ProcessTileArgs privstms red_comm red_lam map_lam tile accs (Var tile_id) resultBody . map Var <$> tilingProcessTile tiling tile_args - accs <- letTupExp "accs" $ DoLoop [] merge loopform loopbody+ accs <- letTupExp "accs" $ DoLoop merge loopform loopbody -- We possibly have to traverse a residual tile. red_lam' <- renameLambda red_lam@@ -733,7 +731,7 @@ arr_t <- lookupType arr letBindNames [v] $ BasicOp $ Index arr $ fullSlice arr_t slice -tileReturns :: [(VName, SubExp)] -> [(SubExp, SubExp)] -> VName -> Binder GPU KernelResult+tileReturns :: [(VName, SubExp)] -> [(SubExp, SubExp)] -> VName -> Builder GPU KernelResult tileReturns dims_on_top dims arr = do let unit_dims = replicate (length dims_on_top) (intConst Int64 1) arr_t <- lookupType arr@@ -744,7 +742,7 @@ let new_shape = unit_dims ++ arrayDims arr_t letExp (baseString arr) $ BasicOp $ Reshape (map DimNew new_shape) arr let tile_dims = zip (map snd dims_on_top) unit_dims ++ dims- return $ TileReturns tile_dims arr'+ return $ TileReturns mempty tile_dims arr' is1DTileable :: VName -> M.Map VName Names -> VName -> InputArray is1DTileable gtid variance arr@@ -758,7 +756,7 @@ VName -> VName -> VName ->- Binder GPU ()+ Builder GPU () reconstructGtids1D group_size gtid gid ltid = letBindNames [gtid] =<< toExp (le64 gid * pe64 (unCount group_size) + le64 ltid)@@ -773,7 +771,7 @@ PrivStms -> SubExp -> [InputArray] ->- Binder GPU [InputTile]+ Builder GPU [InputTile] readTile1D tile_size gid gtid num_groups group_size kind privstms tile_id inputs = fmap (inputsToTiles inputs) . segMap1D "full_tile" lvl ResultNoSimplify@@ -792,8 +790,8 @@ let readTileElem arr = -- No need for fullSlice because we are tiling only prims.- letExp "tile_elem" (BasicOp $ Index arr [DimFix j])- fmap (map Var) $+ letExp "tile_elem" (BasicOp $ Index arr $ Slice [DimFix j])+ fmap varsRes $ case kind of TilePartial -> letTupExp "pre"@@ -814,7 +812,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ProcessTileArgs ->- Binder GPU [VName]+ Builder GPU [VName] processTile1D gid gtid kdim tile_size num_groups group_size tile_args = do let red_comm = processComm tile_args privstms = processPrivStms tile_args@@ -832,7 +830,7 @@ -- OK because the parallel semantics are not used after this -- point). thread_accs <- forM accs $ \acc ->- letSubExp "acc" $ BasicOp $ Index acc [DimFix $ Var ltid]+ letSubExp "acc" $ BasicOp $ Index acc $ Slice [DimFix $ Var ltid] let sliceTile (InputTiled _ arr) = pure arr sliceTile (InputUntiled arr) =@@ -841,7 +839,7 @@ tiles' <- mapM sliceTile tiles let form' = redomapSOAC [Reduce red_comm red_lam thread_accs] map_lam- fmap (map Var) $+ fmap varsRes $ letTupExp "acc" =<< eIf (toExp $ le64 gtid .<. pe64 kdim)@@ -858,7 +856,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ResidualTileArgs ->- Binder GPU [VName]+ Builder GPU [VName] processResidualTile1D gid gtid kdim tile_size num_groups group_size args = do -- The number of residual elements that are not covered by -- the whole tiles.@@ -881,7 +879,7 @@ num_whole_tiles = residualNumWholeTiles args w = residualInputSize args - nonemptyTile residual_input = runBodyBinder $ do+ nonemptyTile residual_input = runBodyBuilder $ do -- Collectively construct a tile. Threads that are out-of-bounds -- provide a blank dummy value. full_tiles <-@@ -902,7 +900,7 @@ let slice = DimSlice (intConst Int64 0) residual_input (intConst Int64 1) InputTiled perm- <$> letExp "partial_tile" (BasicOp $ Index tile [slice])+ <$> letExp "partial_tile" (BasicOp $ Index tile $ Slice [slice]) tiles <- mapM sliceTile full_tiles @@ -989,7 +987,7 @@ (VName, VName) -> (VName, VName) -> (VName, VName) ->- Binder GPU ()+ Builder GPU () reconstructGtids2D tile_size (gtid_x, gtid_y) (gid_x, gid_y) (ltid_x, ltid_y) = do -- Reconstruct the original gtids from gid_x/gid_y and ltid_x/ltid_y. letBindNames [gtid_x]@@ -1008,7 +1006,7 @@ PrivStms -> SubExp -> [InputArray] ->- Binder GPU [InputTile]+ Builder GPU [InputTile] readTile2D (kdim_x, kdim_y) (gtid_x, gtid_y) (gid_x, gid_y) tile_size num_groups group_size kind privstms tile_id inputs = fmap (inputsToTiles inputs) . segMap2D@@ -1033,10 +1031,8 @@ -- No need for fullSlice because we are tiling only prims. letExp "tile_elem"- ( BasicOp $- Index- arr- [DimFix $ last $ rearrangeShape perm [i, j]]+ ( BasicOp . Index arr $+ Slice [DimFix $ last $ rearrangeShape perm [i, j]] ) readTileElemIfInBounds (arr, perm) = do@@ -1053,10 +1049,10 @@ ] eIf (toExp $ pe64 idx .<. pe64 w .&&. othercheck)- (eBody [return $ BasicOp $ Index arr [DimFix idx]])+ (eBody [return $ BasicOp $ Index arr $ Slice [DimFix idx]]) (eBody [eBlank tile_t]) - fmap (map Var) $+ fmap varsRes $ case kind of TilePartial -> mapM (letExp "pre" <=< readTileElemIfInBounds) arrs_and_perms@@ -1080,7 +1076,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ProcessTileArgs ->- Binder GPU [VName]+ Builder GPU [VName] processTile2D (gid_x, gid_y) (gtid_x, gtid_y) (kdim_x, kdim_y) tile_size num_groups group_size tile_args = do let privstms = processPrivStms tile_args red_comm = processComm tile_args@@ -1107,7 +1103,7 @@ -- OK because the parallel semantics are not used after this -- point). thread_accs <- forM accs $ \acc ->- letSubExp "acc" $ BasicOp $ Index acc [DimFix $ Var ltid_x, DimFix $ Var ltid_y]+ letSubExp "acc" $ BasicOp $ Index acc $ Slice [DimFix $ Var ltid_x, DimFix $ Var ltid_y] let form' = redomapSOAC [Reduce red_comm red_lam thread_accs] map_lam sliceTile (InputUntiled arr) =@@ -1120,7 +1116,7 @@ tiles' <- mapM sliceTile tiles - fmap (map Var) $+ fmap varsRes $ letTupExp "acc" =<< eIf ( toExp $ le64 gtid_x .<. pe64 kdim_x .&&. le64 gtid_y .<. pe64 kdim_y@@ -1136,7 +1132,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ResidualTileArgs ->- Binder GPU [VName]+ Builder GPU [VName] processResidualTile2D gids gtids@@ -1166,7 +1162,7 @@ num_whole_tiles = residualNumWholeTiles args w = residualInputSize args - nonemptyTile residual_input = renameBody <=< runBodyBinder $ do+ nonemptyTile residual_input = renameBody <=< runBodyBuilder $ do -- Collectively construct a tile. Threads that are out-of-bounds -- provide a blank dummy value. full_tile <-@@ -1187,7 +1183,7 @@ tiles <- forM full_tile $ \case InputTiled perm tile' -> InputTiled perm- <$> letExp "partial_tile" (BasicOp $ Index tile' [slice, slice])+ <$> letExp "partial_tile" (BasicOp $ Index tile' (Slice [slice, slice])) InputUntiled arr -> pure $ InputUntiled arr @@ -1242,8 +1238,7 @@ reconstructGtids2D tile_size (gtid_x, gtid_y) (gid_x, gid_y) (ltid_x, ltid_y) f ( untyped $- le64 gtid_x .<. pe64 kdim_x- .&&. le64 gtid_y .<. pe64 kdim_y+ le64 gtid_x .<. pe64 kdim_x .&&. le64 gtid_y .<. pe64 kdim_y ) [DimFix $ Var ltid_x, DimFix $ Var ltid_y], tilingReadTile = readTile2D (kdim_x, kdim_y) (gtid_x, gtid_y) (gid_x, gid_y) tile_size (segNumGroups lvl) (segGroupSize lvl),
@@ -25,23 +25,23 @@ String -> SegLevel -> ResultManifest ->- (VName -> Binder GPU [SubExp]) ->- Binder GPU [VName]+ (VName -> Builder GPU Result) ->+ Builder GPU [VName] segMap1D desc lvl manifest f = do ltid <- newVName "ltid" ltid_flat <- newVName "ltid_flat" let space = SegSpace ltid_flat [(ltid, unCount $ segGroupSize lvl)] - ((ts, res), stms) <- localScope (scopeOfSegSpace space) . runBinder $ do+ ((ts, res), stms) <- localScope (scopeOfSegSpace space) . runBuilder $ do res <- f ltid- ts <- mapM subExpType res+ ts <- mapM subExpResType res return (ts, res) Body _ stms' res' <- renameBody $ mkBody stms res + let ret (SubExpRes cs se) = Returns manifest cs se letTupExp desc $- Op $- SegOp $- SegMap lvl space ts $ KernelBody () stms' $ map (Returns manifest) res'+ Op . SegOp $+ SegMap lvl space ts $ KernelBody () stms' $ map ret res' segMap2D :: String -> -- desc@@ -49,24 +49,24 @@ ResultManifest -> -- manifest (SubExp, SubExp) -> -- (dim_x, dim_y) ( (VName, VName) -> -- f- Binder GPU [SubExp]+ Builder GPU Result ) ->- Binder GPU [VName]+ Builder GPU [VName] segMap2D desc lvl manifest (dim_y, dim_x) f = do ltid_xx <- newVName "ltid_x" ltid_flat <- newVName "ltid_flat" ltid_yy <- newVName "ltid_y" let segspace = SegSpace ltid_flat [(ltid_yy, dim_y), (ltid_xx, dim_x)] - ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBinder $ do+ ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBuilder $ do res <- f (ltid_yy, ltid_xx)- ts <- mapM subExpType res+ ts <- mapM subExpResType res return (ts, res) + let ret (SubExpRes cs se) = Returns manifest cs se letTupExp desc <=< renameExp $- Op $- SegOp $- SegMap lvl segspace ts $ KernelBody () stms $ map (Returns manifest) res+ Op . SegOp $+ SegMap lvl segspace ts $ KernelBody () stms $ map ret res segMap3D :: String -> -- desc@@ -74,9 +74,9 @@ ResultManifest -> -- manifest (SubExp, SubExp, SubExp) -> -- (dim_z, dim_y, dim_x) ( (VName, VName, VName) -> -- f- Binder GPU [SubExp]+ Builder GPU Result ) ->- Binder GPU [VName]+ Builder GPU [VName] segMap3D desc lvl manifest (dim_z, dim_y, dim_x) f = do ltid_x <- newVName "ltid_x" ltid_flat <- newVName "ltid_flat"@@ -84,15 +84,15 @@ ltid_z <- newVName "ltid_z" let segspace = SegSpace ltid_flat [(ltid_z, dim_z), (ltid_y, dim_y), (ltid_x, dim_x)] - ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBinder $ do+ ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBuilder $ do res <- f (ltid_z, ltid_y, ltid_x)- ts <- mapM subExpType res+ ts <- mapM subExpResType res return (ts, res) + let ret (SubExpRes cs se) = Returns manifest cs se letTupExp desc <=< renameExp $- Op $- SegOp $- SegMap lvl segspace ts $ KernelBody () stms $ map (Returns manifest) res+ Op . SegOp $+ SegMap lvl segspace ts $ KernelBody () stms $ map ret res segScatter2D :: String -> -- desc@@ -100,20 +100,20 @@ VName -> SegLevel -> -- lvl (SubExp, SubExp) -> -- (dim_y, dim_x)- ((VName, VName) -> Binder GPU (SubExp, SubExp)) -> -- f- Binder GPU [VName]+ ((VName, VName) -> Builder GPU (SubExp, SubExp)) -> -- f+ Builder GPU [VName] segScatter2D desc arr_size updt_arr lvl (dim_x, dim_y) f = do ltid_x <- newVName "ltid_x" ltid_y <- newVName "ltid_y" ltid_flat <- newVName "ltid_flat" let segspace = SegSpace ltid_flat [(ltid_x, dim_x), (ltid_y, dim_y)] - ((t_v, res_v, res_i), stms) <- runBinder $ do+ ((t_v, res_v, res_i), stms) <- runBuilder $ do (res_v, res_i) <- f (ltid_x, ltid_y) t_v <- subExpType res_v return (t_v, res_v, res_i) - let ret = WriteReturns (Shape [arr_size]) updt_arr [([DimFix res_i], res_v)]+ let ret = WriteReturns mempty (Shape [arr_size]) updt_arr [(Slice [DimFix res_i], res_v)] let body = KernelBody () stms [ret] letTupExp desc <=< renameExp $ Op $ SegOp $ SegMap lvl segspace [t_v] body@@ -148,7 +148,7 @@ defVarianceInStm :: VarianceTable -> Stm GPU -> VarianceTable defVarianceInStm variance bnd =- foldl' add variance $ patternNames $ stmPattern bnd+ foldl' add variance $ patNames $ stmPat bnd where add variance' v = M.insert v binding_variance variance' look variance' v = oneName v <> M.findWithDefault mempty v variance'
src/Futhark/Optimise/Unstream.hs view
@@ -61,7 +61,7 @@ type UnstreamM rep = ReaderT (Scope rep) (State VNameSource) type OnOp rep =- Pattern rep -> StmAux (ExpDec rep) -> Op rep -> UnstreamM rep [Stm rep]+ Pat rep -> StmAux (ExpDec rep) -> Op rep -> UnstreamM rep [Stm rep] optimiseStms :: ASTRep rep =>@@ -137,7 +137,7 @@ pure [Let pat aux $ Op $ ParOp par_op' op'] onMCOp stage pat aux (MC.OtherOp soac) | sequentialise stage soac = do- stms <- runBinder_ $ FOT.transformSOAC pat soac+ stms <- runBuilder_ $ FOT.transformSOAC pat soac fmap concat $ localScope (scopeOf stms) $ mapM (optimiseStm (onMCOp stage)) $ stmsToList stms@@ -158,7 +158,7 @@ onHostOp :: Stage -> OnOp GPU onHostOp stage pat aux (GPU.OtherOp soac) | sequentialise stage soac = do- stms <- runBinder_ $ FOT.transformSOAC pat soac+ stms <- runBuilder_ $ FOT.transformSOAC pat soac fmap concat $ localScope (scopeOf stms) $ mapM (optimiseStm (onHostOp stage)) $ stmsToList stms
src/Futhark/Pass/ExpandAllocations.hs view
@@ -96,11 +96,12 @@ (Left e, _) -> throwError e where- bindRes pe se = Let (Pattern [] [pe]) (defAux ()) $ BasicOp $ SubExp se+ bindRes pe (SubExpRes cs se) =+ certify cs $ Let (Pat [pe]) (defAux ()) $ BasicOp $ SubExp se useBranch b = bodyStms b- <> stmsFromList (zipWith bindRes (patternElements pat) (bodyResult b))+ <> stmsFromList (zipWith bindRes (patElems pat) (bodyResult b)) transformStm (Let pat aux e) = do (bnds, e') <- transformExp =<< mapExpM transform e return $ bnds <> oneStm (Let pat aux e')@@ -266,7 +267,7 @@ ExpandM (RebaseMap, Stms GPUMem) memoryRequirements lvl space kstms variant_allocs invariant_allocs = do (num_threads, num_threads_stms) <-- runBinder . letSubExp "num_threads" . BasicOp $+ runBuilder . letSubExp "num_threads" . BasicOp $ BinOp (Mul Int64 OverflowUndef) (unCount $ segNumGroups lvl)@@ -365,7 +366,7 @@ Names -> Stm GPUMem -> Writer Extraction (Maybe (Stm GPUMem))-extractStmAllocations user bound_outside bound_kernel (Let (Pattern [] [patElem]) _ (Op (Alloc size space)))+extractStmAllocations user bound_outside bound_kernel (Let (Pat [patElem]) _ (Op (Alloc size space))) | expandable space && expandableSize size -- FIXME: the '&& notScalar space' part is a hack because we -- don't otherwise hoist the sizes out far enough, and we@@ -421,13 +422,13 @@ genericExpandedInvariantAllocations getNumUsers invariant_allocs = do -- We expand the invariant allocations by adding an inner dimension -- equal to the number of kernel threads.- (rebases, alloc_stms) <- runBinder $ mapM expand $ M.toList invariant_allocs+ (rebases, alloc_stms) <- runBuilder $ mapM expand $ M.toList invariant_allocs return (alloc_stms, mconcat rebases) where expand (mem, (user, per_thread_size, space)) = do let num_users = fst $ getNumUsers user- allocpat = Pattern [] [PatElem mem $ MemMem space]+ allocpat = Pat [PatElem mem $ MemMem space] total_size <- letExp "total_size" <=< toExp . product $ pe64 per_thread_size : map pe64 (shapeDims num_users)@@ -444,13 +445,13 @@ permuted_ixfun = IxFun.permute root_ixfun perm offset_ixfun = IxFun.slice permuted_ixfun $- map DimFix user_ids ++ map untouched old_shape+ Slice $ map DimFix user_ids ++ map untouched old_shape in offset_ixfun newBase user@(SegGroup {}, _) (old_shape, _) = let (users_shape, user_ids) = getNumUsers user root_ixfun = IxFun.iota $ map pe64 (shapeDims users_shape) ++ old_shape offset_ixfun =- IxFun.slice root_ixfun $+ IxFun.slice root_ixfun . Slice $ map DimFix user_ids ++ map untouched old_shape in offset_ixfun @@ -505,7 +506,7 @@ return (slice_stms' <> stmsFromList alloc_bnds, mconcat rebases) where expand (mem, (offset, total_size, space)) = do- let allocpat = Pattern [] [PatElem mem $ MemMem space]+ let allocpat = Pat [PatElem mem $ MemMem space] return ( Let allocpat (defAux ()) $ Op $ Alloc total_size space, M.singleton mem $ newBase offset@@ -521,11 +522,8 @@ pe64 size_per_thread `quot` primByteSize pt root_ixfun = IxFun.iota [elems_per_thread, num_threads'] offset_ixfun =- IxFun.slice- root_ixfun- [ DimSlice 0 num_threads' 1,- DimFix gtid- ]+ IxFun.slice root_ixfun . Slice $+ [DimSlice 0 num_threads' 1, DimFix gtid] shapechange = if length old_shape == 1 then map DimCoercion old_shape@@ -558,6 +556,11 @@ askRebaseMap :: OffsetM RebaseMap askRebaseMap = OffsetM $ lift ask +localRebaseMap :: (RebaseMap -> RebaseMap) -> OffsetM a -> OffsetM a+localRebaseMap f (OffsetM m) = OffsetM $ do+ scope <- ask+ lift $ local f $ runReaderT m scope+ lookupNewBase :: VName -> ([TPrimExp Int64 VName], PrimType) -> OffsetM (Maybe IxFun) lookupNewBase name x = do offsets <- askRebaseMap@@ -587,16 +590,13 @@ offsetMemoryInStm :: Stm GPUMem -> OffsetM (Scope GPUMem, Stm GPUMem) offsetMemoryInStm (Let pat dec e) = do- pat' <- offsetMemoryInPattern pat- e' <- localScope (scopeOfPattern pat') $ offsetMemoryInExp e+ e' <- offsetMemoryInExp e+ pat' <- offsetMemoryInPat pat =<< expReturns e' scope <- askScope -- Try to recompute the index function. Fall back to creating rebase -- operations with the RebaseMap. rts <- runReaderT (expReturns e') scope- let pat'' =- Pattern- (patternContextElements pat')- (zipWith pick (patternValueElements pat') rts)+ let pat'' = Pat $ zipWith pick (patElems pat') rts stm = Let pat'' dec e' let scope' = scopeOf stm <> scope return (scope', stm)@@ -618,24 +618,20 @@ inst Ext {} = Nothing inst (Free x) = return x -offsetMemoryInPattern :: Pattern GPUMem -> OffsetM (Pattern GPUMem)-offsetMemoryInPattern (Pattern ctx vals) = do- mapM_ inspectCtx ctx- Pattern ctx <$> mapM inspectVal vals+offsetMemoryInPat :: Pat GPUMem -> [ExpReturns] -> OffsetM (Pat GPUMem)+offsetMemoryInPat (Pat pes) rets = do+ Pat <$> zipWithM onPE pes rets where- inspectVal patElem = do- new_dec <- offsetMemoryInMemBound $ patElemDec patElem- return patElem {patElemDec = new_dec}- inspectCtx patElem- | Mem space <- patElemType patElem,- expandable space =- throwError $- unwords- [ "Cannot deal with existential memory block",- pretty (patElemName patElem),- "when expanding inside kernels."- ]- | otherwise = return ()+ onPE+ (PatElem name (MemArray pt shape u (ArrayIn mem _)))+ (MemArray _ _ _ (Just (ReturnsNewBlock _ _ ixfun))) =+ pure . PatElem name . MemArray pt shape u . ArrayIn mem $+ fmap (fmap unExt) ixfun+ onPE pe _ = do+ new_dec <- offsetMemoryInMemBound $ patElemDec pe+ pure pe {patElemDec = new_dec}+ unExt (Ext i) = patElemName (pes !! i)+ unExt (Free v) = v offsetMemoryInParam :: Param (MemBound u) -> OffsetM (Param (MemBound u)) offsetMemoryInParam fparam = do@@ -645,23 +641,19 @@ offsetMemoryInMemBound :: MemBound u -> OffsetM (MemBound u) offsetMemoryInMemBound summary@(MemArray pt shape u (ArrayIn mem ixfun)) = do new_base <- lookupNewBase mem (IxFun.base ixfun, pt)- return $- fromMaybe summary $ do- new_base' <- new_base- return $ MemArray pt shape u $ ArrayIn mem $ IxFun.rebase new_base' ixfun+ return . fromMaybe summary $ do+ new_base' <- new_base+ return $ MemArray pt shape u $ ArrayIn mem $ IxFun.rebase new_base' ixfun offsetMemoryInMemBound summary = return summary offsetMemoryInBodyReturns :: BodyReturns -> OffsetM BodyReturns offsetMemoryInBodyReturns br@(MemArray pt shape u (ReturnsInBlock mem ixfun)) | Just ixfun' <- isStaticIxFun ixfun = do new_base <- lookupNewBase mem (IxFun.base ixfun', pt)- return $- fromMaybe br $ do- new_base' <- new_base- return $- MemArray pt shape u $- ReturnsInBlock mem $- IxFun.rebase (fmap (fmap Free) new_base') ixfun+ return . fromMaybe br $ do+ new_base' <- new_base+ return . MemArray pt shape u . ReturnsInBlock mem $+ IxFun.rebase (fmap (fmap Free) new_base') ixfun offsetMemoryInBodyReturns br = return br offsetMemoryInLambda :: Lambda GPUMem -> OffsetM (Lambda GPUMem)@@ -669,14 +661,34 @@ body <- offsetMemoryInBody $ lambdaBody lam return $ lam {lambdaBody = body} +-- A loop may have memory parameters, and those memory blocks may+-- be expanded. We assume (but do not check - FIXME) that if the+-- initial value of a loop parameter is an expanded memory block,+-- then so will the result be.+offsetMemoryInLoopParams ::+ [(FParam GPUMem, SubExp)] ->+ ([(FParam GPUMem, SubExp)] -> OffsetM a) ->+ OffsetM a+offsetMemoryInLoopParams merge f = do+ let (params, args) = unzip merge+ localRebaseMap extend $ do+ params' <- mapM offsetMemoryInParam params+ f $ zip params' args+ where+ extend rm = foldl' onParamArg rm merge+ onParamArg rm (param, Var arg)+ | Just x <- M.lookup arg rm =+ M.insert (paramName param) x rm+ onParamArg rm _ = rm+ offsetMemoryInExp :: Exp GPUMem -> OffsetM (Exp GPUMem)-offsetMemoryInExp (DoLoop ctx val form body) = do- let (ctxparams, ctxinit) = unzip ctx- (valparams, valinit) = unzip val- ctxparams' <- mapM offsetMemoryInParam ctxparams- valparams' <- mapM offsetMemoryInParam valparams- body' <- localScope (scopeOfFParams ctxparams' <> scopeOfFParams valparams' <> scopeOf form) (offsetMemoryInBody body)- return $ DoLoop (zip ctxparams' ctxinit) (zip valparams' valinit) form body'+offsetMemoryInExp (DoLoop merge form body) = do+ offsetMemoryInLoopParams merge $ \merge' -> do+ body' <-+ localScope+ (scopeOfFParams (map fst merge') <> scopeOf form)+ (offsetMemoryInBody body)+ return $ DoLoop merge' form body' offsetMemoryInExp e = mapExpM recurse e where recurse =@@ -714,16 +726,15 @@ | nested = throwError $ "Cannot handle nested allocation: " ++ pretty stm | otherwise = return Nothing unAllocStm _ (Let pat dec e) =- Just <$> (Let <$> unAllocPattern pat <*> pure dec <*> mapExpM unAlloc' e)+ Just <$> (Let <$> unAllocPat pat <*> pure dec <*> mapExpM unAlloc' e) unAllocLambda (Lambda params body ret) = Lambda (unParams params) <$> unAllocBody body <*> pure ret unParams = mapMaybe $ traverse unMem - unAllocPattern pat@(Pattern ctx val) =- Pattern <$> maybe bad return (mapM (rephrasePatElem unMem) ctx)- <*> maybe bad return (mapM (rephrasePatElem unMem) val)+ unAllocPat pat@(Pat merge) =+ Pat <$> maybe bad return (mapM (rephrasePatElem unMem) merge) where bad = Left $ "Cannot handle memory in pattern " ++ pretty pat @@ -793,23 +804,22 @@ kernels_scope <- asks unAllocScope - (max_lam, _) <- flip runBinderT kernels_scope $ do+ (max_lam, _) <- flip runBuilderT kernels_scope $ do xs <- replicateM num_sizes $ newParam "x" (Prim int64) ys <- replicateM num_sizes $ newParam "y" (Prim int64) (zs, stms) <- localScope (scopeOfLParams $ xs ++ ys) $ collectStms $ forM (zip xs ys) $ \(x, y) ->- letSubExp "z" $ BasicOp $ BinOp (SMax Int64) (Var $ paramName x) (Var $ paramName y)+ fmap subExpRes . letSubExp "z" . BasicOp $+ BinOp (SMax Int64) (Var $ paramName x) (Var $ paramName y) return $ Lambda (xs ++ ys) (mkBody stms zs) i64s flat_gtid_lparam <- Param <$> newVName "flat_gtid" <*> pure (Prim (IntType Int64)) - (size_lam', _) <- flip runBinderT kernels_scope $ do+ (size_lam', _) <- flip runBuilderT kernels_scope $ do params <- replicateM num_sizes $ newParam "x" (Prim int64) (zs, stms) <- localScope- ( scopeOfLParams params- <> scopeOfLParams [flat_gtid_lparam]- )+ (scopeOfLParams params <> scopeOfLParams [flat_gtid_lparam]) $ collectStms $ do -- Even though this SegRed is one-dimensional, we need to -- provide indexes corresponding to the original potentially@@ -822,17 +832,14 @@ zipWithM_ letBindNames (map pure kspace_gtids) =<< mapM toExp new_inds mapM_ addStm kstms'- return sizes+ return $ subExpsRes sizes localScope (scopeOfSegSpace space) $ GPU.simplifyLambda (Lambda [flat_gtid_lparam] (Body () stms zs) i64s) - ((maxes_per_thread, size_sums), slice_stms) <- flip runBinderT kernels_scope $ do+ ((maxes_per_thread, size_sums), slice_stms) <- flip runBuilderT kernels_scope $ do pat <-- basicPattern []- <$> replicateM- num_sizes- (newIdent "max_per_thread" $ Prim int64)+ basicPat <$> replicateM num_sizes (newIdent "max_per_thread" $ Prim int64) w <- letSubExp "size_slice_w"@@ -853,10 +860,10 @@ addStms =<< mapM renameStm =<< nonSegRed lvl pat w [red_op] size_lam' [thread_space_iota] - size_sums <- forM (patternNames pat) $ \threads_max ->+ size_sums <- forM (patNames pat) $ \threads_max -> letExp "size_sum" $ BasicOp $ BinOp (Mul Int64 OverflowUndef) (Var threads_max) num_threads - return (patternNames pat, size_sums)+ return (patNames pat, size_sums) return (slice_stms, maxes_per_thread, size_sums)
src/Futhark/Pass/ExplicitAllocations.hs view
@@ -1,9 +1,9 @@ {-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}@@ -17,7 +17,6 @@ ExpHint (..), defaultExpHints, Allocable,- Allocator (..), AllocM, AllocEnv (..), SizeSubst (..),@@ -27,6 +26,8 @@ arraySizeInBytesExp, mkLetNamesB', mkLetNamesB'',+ dimAllocationSize,+ ChunkMap, -- * Module re-exports @@ -44,7 +45,7 @@ import Control.Monad.Reader import Control.Monad.State import Control.Monad.Writer-import Data.List (foldl', partition, sort, zip4)+import Data.List (foldl', partition, zip4) import qualified Data.Map.Strict as M import Data.Maybe import qualified Data.Set as S@@ -57,90 +58,23 @@ import Futhark.Optimise.Simplify.Rep (mkWiseBody) import Futhark.Pass import Futhark.Tools-import Futhark.Util (splitAt3, splitFromEnd, takeLast)--data AllocStm- = SizeComputation VName (PrimExp VName)- | Allocation VName SubExp Space- | ArrayCopy VName VName- deriving (Eq, Ord, Show)--bindAllocStm ::- (MonadBinder m, Op (Rep m) ~ MemOp inner) =>- AllocStm ->- m ()-bindAllocStm (SizeComputation name pe) =- letBindNames [name] =<< toExp (coerceIntPrimExp Int64 pe)-bindAllocStm (Allocation name size space) =- letBindNames [name] $ Op $ Alloc size space-bindAllocStm (ArrayCopy name src) =- letBindNames [name] $ BasicOp $ Copy src--class- (MonadFreshNames m, LocalScope rep m, Mem rep) =>- Allocator rep m- where- addAllocStm :: AllocStm -> m ()- askDefaultSpace :: m Space-- default addAllocStm ::- ( Allocable fromrep rep,- m ~ AllocM fromrep rep- ) =>- AllocStm ->- m ()- addAllocStm (SizeComputation name se) =- letBindNames [name] =<< toExp (coerceIntPrimExp Int64 se)- addAllocStm (Allocation name size space) =- letBindNames [name] $ Op $ allocOp size space- addAllocStm (ArrayCopy name src) =- letBindNames [name] $ BasicOp $ Copy src-- -- | The subexpression giving the number of elements we should- -- allocate space for. See 'ChunkMap' comment.- dimAllocationSize :: SubExp -> m SubExp- default dimAllocationSize ::- m ~ AllocM fromrep rep =>- SubExp ->- m SubExp- dimAllocationSize (Var v) =- -- It is important to recurse here, as the substitution may itself- -- be a chunk size.- maybe (return $ Var v) dimAllocationSize =<< asks (M.lookup v . chunkMap)- dimAllocationSize size =- return size-- -- | Get those names that are known to be constants at run-time.- askConsts :: m (S.Set VName)-- expHints :: Exp rep -> m [ExpHint]- expHints = defaultExpHints--allocateMemory ::- Allocator rep m =>- String ->- SubExp ->- Space ->- m VName-allocateMemory desc size space = do- v <- newVName desc- addAllocStm $ Allocation v size space- return v+import Futhark.Util (maybeNth, splitAt3, splitFromEnd, takeLast) -computeSize ::- Allocator rep m =>- String ->- PrimExp VName ->- m SubExp-computeSize desc se = do- v <- newVName desc- addAllocStm $ SizeComputation v se- return $ Var v+-- | The subexpression giving the number of elements we should+-- allocate space for. See 'ChunkMap' comment.+dimAllocationSize :: ChunkMap -> SubExp -> SubExp+dimAllocationSize chunkmap (Var v) =+ -- It is important to recurse here, as the substitution may itself+ -- be a chunk size.+ maybe (Var v) (dimAllocationSize chunkmap) $ M.lookup v chunkmap+dimAllocationSize _ size =+ size -type Allocable fromrep torep =+type Allocable fromrep torep inner = ( PrettyRep fromrep, PrettyRep torep,- Mem torep,+ Mem torep inner,+ LetDec torep ~ LetDecMem, FParamInfo fromrep ~ DeclType, LParamInfo fromrep ~ Type, BranchType fromrep ~ ExtType,@@ -148,8 +82,8 @@ BodyDec fromrep ~ (), BodyDec torep ~ (), ExpDec torep ~ (),- SizeSubst (Op torep),- BinderOps torep+ SizeSubst inner,+ BuilderOps torep ) -- | A mapping from chunk names to their maximum size. XXX FIXME@@ -176,7 +110,7 @@ -- | Monad for adding allocations to an entire program. newtype AllocM fromrep torep a- = AllocM (BinderT torep (ReaderT (AllocEnv fromrep torep) (State VNameSource)) a)+ = AllocM (BuilderT torep (ReaderT (AllocEnv fromrep torep) (State VNameSource)) a) deriving ( Applicative, Functor,@@ -187,33 +121,30 @@ MonadReader (AllocEnv fromrep torep) ) -instance- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>- MonadBinder (AllocM fromrep torep)- where+instance (Allocable fromrep torep inner) => MonadBuilder (AllocM fromrep torep) where type Rep (AllocM fromrep torep) = torep - mkExpDecM _ _ = return ()+ mkExpDecM _ _ = pure () mkLetNamesM names e = do- pat <- patternWithAllocations names e+ def_space <- askDefaultSpace+ chunkmap <- asks chunkMap+ hints <- expHints e+ pat <- patWithAllocations def_space chunkmap names e hints return $ Let pat (defAux ()) e - mkBodyM bnds res = return $ Body () bnds res+ mkBodyM stms res = return $ Body () stms res addStms = AllocM . addStms collectStms (AllocM m) = AllocM $ collectStms m -instance- (Allocable fromrep torep) =>- Allocator torep (AllocM fromrep torep)- where- expHints e = do- f <- asks envExpHints- f e- askDefaultSpace = asks allocSpace+expHints :: Exp torep -> AllocM fromrep torep [ExpHint]+expHints e = do+ f <- asks envExpHints+ f e - askConsts = asks envConsts+askDefaultSpace :: AllocM fromrep torep Space+askDefaultSpace = asks allocSpace runAllocM :: MonadFreshNames m =>@@ -222,7 +153,7 @@ AllocM fromrep torep a -> m a runAllocM handleOp hints (AllocM m) =- fmap fst $ modifyNameSource $ runState $ runReaderT (runBinderT m mempty) env+ fmap fst $ modifyNameSource $ runState $ runReaderT (runBuilderT m mempty) env where env = AllocEnv@@ -234,41 +165,6 @@ envExpHints = hints } --- | Monad for adding allocations to a single pattern.-newtype PatAllocM rep a- = PatAllocM- ( RWS- (Scope rep)- [AllocStm]- VNameSource- a- )- deriving- ( Applicative,- Functor,- Monad,- HasScope rep,- LocalScope rep,- MonadWriter [AllocStm],- MonadFreshNames- )--instance Mem rep => Allocator rep (PatAllocM rep) where- addAllocStm = tell . pure- dimAllocationSize = return- askDefaultSpace = return DefaultSpace- askConsts = pure mempty--runPatAllocM ::- MonadFreshNames m =>- PatAllocM rep a ->- Scope rep ->- m (a, [AllocStm])-runPatAllocM (PatAllocM m) mems =- modifyNameSource $ frob . runRWS m mems- where- frob (a, s, w) = ((a, w), s)- elemSize :: Num a => Type -> a elemSize = primByteSize . elemType @@ -276,157 +172,121 @@ arraySizeInBytesExp t = untyped $ foldl' (*) (elemSize t) $ map pe64 (arrayDims t) -arraySizeInBytesExpM :: Allocator rep m => Type -> m (PrimExp VName)-arraySizeInBytesExpM t = do- dims <- mapM dimAllocationSize (arrayDims t)- let dim_prod_i64 = product $ map pe64 dims+arraySizeInBytesExpM :: MonadBuilder m => ChunkMap -> Type -> m (PrimExp VName)+arraySizeInBytesExpM chunkmap t = do+ let dim_prod_i64 = product $ map (pe64 . dimAllocationSize chunkmap) (arrayDims t) elm_size_i64 = elemSize t return $ BinOpExp (SMax Int64) (ValueExp $ IntValue $ Int64Value 0) $- untyped $- dim_prod_i64 * elm_size_i64+ untyped $ dim_prod_i64 * elm_size_i64 -arraySizeInBytes :: Allocator rep m => Type -> m SubExp-arraySizeInBytes = computeSize "bytes" <=< arraySizeInBytesExpM+arraySizeInBytes :: MonadBuilder m => ChunkMap -> Type -> m SubExp+arraySizeInBytes chunkmap = letSubExp "bytes" <=< toExp <=< arraySizeInBytesExpM chunkmap +allocForArray' ::+ (MonadBuilder m, Op (Rep m) ~ MemOp inner) =>+ ChunkMap ->+ Type ->+ Space ->+ m VName+allocForArray' chunkmap t space = do+ size <- arraySizeInBytes chunkmap t+ letExp "mem" $ Op $ Alloc size space+ -- | Allocate memory for a value of the given type. allocForArray ::- Allocator rep m =>+ Allocable fromrep torep inner => Type -> Space ->- m VName+ AllocM fromrep torep VName allocForArray t space = do- size <- arraySizeInBytes t- allocateMemory "mem" size space+ chunkmap <- asks chunkMap+ allocForArray' chunkmap t space allocsForStm ::- (Allocator rep m, ExpDec rep ~ ()) =>- [Ident] ->+ (Allocable fromrep torep inner) => [Ident] ->- Exp rep ->- m (Stm rep)-allocsForStm sizeidents validents e = do- rts <- expReturns e+ Exp torep ->+ AllocM fromrep torep (Stm torep)+allocsForStm idents e = do+ def_space <- askDefaultSpace+ chunkmap <- asks chunkMap hints <- expHints e- (ctxElems, valElems) <- allocsForPattern sizeidents validents rts hints- return $ Let (Pattern ctxElems valElems) (defAux ()) e+ rts <- expReturns e+ pes <- allocsForPat def_space chunkmap idents rts hints+ dec <- mkExpDecM (Pat pes) e+ pure $ Let (Pat pes) (defAux dec) e -patternWithAllocations ::- (Allocator rep m, ExpDec rep ~ ()) =>+patWithAllocations ::+ (MonadBuilder m, Mem (Rep m) inner) =>+ Space ->+ ChunkMap -> [VName] ->- Exp rep ->- m (Pattern rep)-patternWithAllocations names e = do- (ts', sizes) <- instantiateShapes' =<< expExtType e- let identForBindage name t =- pure $ Ident name t- vals <- sequence [identForBindage name t | (name, t) <- zip names ts']- stmPattern <$> allocsForStm sizes vals e+ Exp (Rep m) ->+ [ExpHint] ->+ m (PatT LetDecMem)+patWithAllocations def_space chunkmap names e hints = do+ ts' <- instantiateShapes' names <$> expExtType e+ let idents = zipWith Ident names ts'+ rts <- expReturns e+ Pat <$> allocsForPat def_space chunkmap idents rts hints -allocsForPattern ::- Allocator rep m =>- [Ident] ->+mkMissingIdents :: MonadFreshNames m => [Ident] -> [ExpReturns] -> m [Ident]+mkMissingIdents idents rts =+ reverse <$> zipWithM f (reverse rts) (map Just (reverse idents) ++ repeat Nothing)+ where+ f _ (Just ident) = pure ident+ f (MemMem space) Nothing = newIdent "ext_mem" $ Mem space+ f _ Nothing = newIdent "ext" $ Prim int64++allocsForPat ::+ (MonadBuilder m, Op (Rep m) ~ MemOp inner) =>+ Space ->+ ChunkMap -> [Ident] -> [ExpReturns] -> [ExpHint] ->- m- ( [PatElem rep],- [PatElem rep]- )-allocsForPattern sizeidents validents rts hints = do- let sizes' = [PatElem size $ MemPrim int64 | size <- map identName sizeidents]- (vals, (exts, mems)) <-- runWriterT $- forM (zip3 validents rts hints) $ \(ident, rt, hint) -> do- let ident_shape = arrayShape $ identType ident- case rt of- MemPrim _ -> do- summary <- lift $ summaryForBindage (identType ident) hint- return $ PatElem (identName ident) summary- MemMem space ->- return $- PatElem (identName ident) $- MemMem space- MemArray bt _ u (Just (ReturnsInBlock mem extixfun)) -> do- (patels, ixfn) <- instantiateExtIxFun ident extixfun- tell (patels, [])-- return $- PatElem (identName ident) $- MemArray bt ident_shape u $- ArrayIn mem ixfn- MemArray _ extshape _ Nothing- | Just _ <- knownShape extshape -> do- summary <- lift $ summaryForBindage (identType ident) hint- return $ PatElem (identName ident) summary- MemArray bt _ u (Just (ReturnsNewBlock space _ extixfn)) -> do- -- treat existential index function first- (patels, ixfn) <- instantiateExtIxFun ident extixfn- tell (patels, [])-- memid <- lift $ mkMemIdent ident space- tell ([], [PatElem (identName memid) $ MemMem space])- return $- PatElem (identName ident) $- MemArray bt ident_shape u $- ArrayIn (identName memid) ixfn- MemAcc acc ispace ts u ->- return $ PatElem (identName ident) $ MemAcc acc ispace ts u- _ -> error "Impossible case reached in allocsForPattern!"+ m [PatElemT LetDecMem]+allocsForPat def_space chunkmap some_idents rts hints = do+ idents <- mkMissingIdents some_idents rts - return- ( sizes' <> exts <> mems,- vals- )+ forM (zip3 idents rts hints) $ \(ident, rt, hint) -> do+ let ident_shape = arrayShape $ identType ident+ case rt of+ MemPrim _ -> do+ summary <- summaryForBindage def_space chunkmap (identType ident) hint+ pure $ PatElem (identName ident) summary+ MemMem space ->+ pure $ PatElem (identName ident) $ MemMem space+ MemArray bt _ u (Just (ReturnsInBlock mem extixfun)) -> do+ let ixfn = instantiateExtIxFun idents extixfun+ pure . PatElem (identName ident) . MemArray bt ident_shape u $ ArrayIn mem ixfn+ MemArray _ extshape _ Nothing+ | Just _ <- knownShape extshape -> do+ summary <- summaryForBindage def_space chunkmap (identType ident) hint+ pure $ PatElem (identName ident) summary+ MemArray bt _ u (Just (ReturnsNewBlock _ i extixfn)) -> do+ let ixfn = instantiateExtIxFun idents extixfn+ pure . PatElem (identName ident) . MemArray bt ident_shape u $+ ArrayIn (getIdent idents i) ixfn+ MemAcc acc ispace ts u ->+ pure $ PatElem (identName ident) $ MemAcc acc ispace ts u+ _ -> error "Impossible case reached in allocsForPat!" where knownShape = mapM known . shapeDims known (Free v) = Just v known Ext {} = Nothing - mkMemIdent :: (MonadFreshNames m) => Ident -> Space -> m Ident- mkMemIdent ident space = do- let memname = baseString (identName ident) <> "_mem"- newIdent memname $ Mem space-- instantiateExtIxFun ::- MonadFreshNames m =>- Ident ->- ExtIxFun ->- m ([PatElemT (MemInfo d u ret)], IxFun)- instantiateExtIxFun idd ext_ixfn = do- let isAndPtps =- S.toList $- foldMap onlyExts $- foldMap (leafExpTypes . untyped) ext_ixfn-- -- Find the existentials that reuse the sizeidents, and- -- those that need new pattern elements. Assumes that the- -- Exts form a contiguous interval of integers.- let (size_exts, new_exts) =- span ((< length sizeidents) . fst) $ sort isAndPtps- (new_substs, patels) <-- fmap unzip $- forM new_exts $ \(i, t) -> do- v <- newVName $ baseString (identName idd) <> "_ixfn"- return- ( (Ext i, LeafExp (Free v) t),- PatElem v $ MemPrim t- )- let size_substs =- zipWith- ( \(i, t) ident ->- (Ext i, LeafExp (Free (identName ident)) t)- )- size_exts- sizeidents- substs = M.fromList $ new_substs <> size_substs- ixfn <- instantiateIxFun $ IxFun.substituteInIxFun (fmap isInt64 substs) ext_ixfn-- return (patels, ixfn)+ getIdent idents i =+ case maybeNth i idents of+ Just ident -> identName ident+ Nothing ->+ error $ "getIdent: Ext " <> show i <> " but pattern has " <> show (length idents) <> " elements: " <> pretty idents -onlyExts :: (Ext a, PrimType) -> S.Set (Int, PrimType)-onlyExts (Free _, _) = S.empty-onlyExts (Ext i, t) = S.singleton (i, t)+ instantiateExtIxFun idents = fmap $ fmap inst+ where+ inst (Free v) = v+ inst (Ext i) = getIdent idents i instantiateIxFun :: Monad m => ExtIxFun -> m IxFun instantiateIxFun = traverse $ traverse inst@@ -435,28 +295,29 @@ inst (Free x) = return x summaryForBindage ::- Allocator rep m =>+ (MonadBuilder m, Op (Rep m) ~ MemOp inner) =>+ Space ->+ ChunkMap -> Type -> ExpHint -> m (MemBound NoUniqueness)-summaryForBindage (Prim bt) _ =+summaryForBindage _ _ (Prim bt) _ = return $ MemPrim bt-summaryForBindage (Mem space) _ =+summaryForBindage _ _ (Mem space) _ = return $ MemMem space-summaryForBindage (Acc acc ispace ts u) _ =+summaryForBindage _ _ (Acc acc ispace ts u) _ = return $ MemAcc acc ispace ts u-summaryForBindage t@(Array pt shape u) NoHint = do- m <- allocForArray t =<< askDefaultSpace+summaryForBindage def_space chunkmap t@(Array pt shape u) NoHint = do+ m <- allocForArray' chunkmap t def_space return $ directIxFun pt shape u m t-summaryForBindage t@(Array pt _ _) (Hint ixfun space) = do+summaryForBindage _ _ t@(Array pt _ _) (Hint ixfun space) = do bytes <-- computeSize "bytes" $- untyped $- product- [ product $ IxFun.base ixfun,- fromIntegral (primByteSize pt :: Int64)- ]- m <- allocateMemory "mem" bytes space+ letSubExp "bytes" <=< toExp . untyped $+ product+ [ product $ IxFun.base ixfun,+ fromIntegral (primByteSize pt :: Int64)+ ]+ m <- letExp "mem" $ Op $ Alloc bytes space return $ MemArray pt (arrayShape t) NoUniqueness $ ArrayIn m ixfun lookupMemSpace :: (HasScope rep m, Monad m) => VName -> m Space@@ -472,7 +333,7 @@ in MemArray bt shape u $ ArrayIn mem ixf allocInFParams ::- (Allocable fromrep torep) =>+ (Allocable fromrep torep inner) => [(FParam fromrep, Space)] -> ([FParam torep] -> AllocM fromrep torep a) -> AllocM fromrep torep a@@ -484,7 +345,7 @@ localScope summary $ m params' allocInFParam ::- (Allocable fromrep torep) =>+ (Allocable fromrep torep inner) => FParam fromrep -> Space -> WriterT@@ -507,86 +368,124 @@ return param {paramDec = MemAcc acc ispace ts u} allocInMergeParams ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => [(FParam fromrep, SubExp)] ->- ( [FParam torep] ->- [FParam torep] ->+ ( [(FParam torep, SubExp)] -> ([SubExp] -> AllocM fromrep torep ([SubExp], [SubExp])) -> AllocM fromrep torep a ) -> AllocM fromrep torep a allocInMergeParams merge m = do- ((valparams, handle_loop_subexps), (ctx_params, mem_params)) <-- runWriterT $ unzip <$> mapM allocInMergeParam merge+ ((valparams, valargs, handle_loop_subexps), (ctx_params, mem_params)) <-+ runWriterT $ unzip3 <$> mapM allocInMergeParam merge let mergeparams' = ctx_params <> mem_params <> valparams summary = scopeOfFParams mergeparams' mk_loop_res ses = do- (valargs, (ctxargs, memargs)) <-+ (ses', (ctxargs, memargs)) <- runWriterT $ zipWithM ($) handle_loop_subexps ses- return (ctxargs <> memargs, valargs)+ return (ctxargs <> memargs, ses') - localScope summary $ m (ctx_params <> mem_params) valparams mk_loop_res+ (valctx_args, valargs') <- mk_loop_res valargs+ let merge' =+ zip+ (ctx_params <> mem_params <> valparams)+ (valctx_args <> valargs')+ localScope summary $ m merge' mk_loop_res where+ param_names = namesFromList $ map (paramName . fst) merge+ anyIsLoopParam names = names `namesIntersect` param_names++ scalarRes param_t v_mem_space v_ixfun (Var res) = do+ -- Try really hard to avoid copying needlessly, but the result+ -- _must_ be in ScalarSpace and have the right index function.+ (res_mem, res_ixfun) <- lift $ lookupArraySummary res+ res_mem_space <- lift $ lookupMemSpace res_mem+ chunkmap <- asks chunkMap+ (res_mem', res') <-+ if (res_mem_space, res_ixfun) == (v_mem_space, v_ixfun)+ then pure (res_mem, res)+ else lift $ arrayWithIxFun chunkmap v_mem_space v_ixfun (fromDecl param_t) res+ tell ([], [Var res_mem'])+ pure $ Var res'+ scalarRes _ _ _ se = pure se+ allocInMergeParam ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => (Param DeclType, SubExp) -> WriterT ([FParam torep], [FParam torep]) (AllocM fromrep torep)- (FParam torep, SubExp -> WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp)+ ( FParam torep,+ SubExp,+ SubExp -> WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp+ ) allocInMergeParam (mergeparam, Var v)- | Array pt shape u <- paramDeclType mergeparam = do- (mem', _) <- lift $ lookupArraySummary v- mem_space <- lift $ lookupMemSpace mem'+ | param_t@(Array pt shape u) <- paramDeclType mergeparam = do+ (v_mem, v_ixfun) <- lift $ lookupArraySummary v+ v_mem_space <- lift $ lookupMemSpace v_mem - (_, ext_ixfun, substs, _) <- lift $ existentializeArray mem_space v+ -- Loop-invariant array parameters that are in scalar space+ -- are special - we do not wish to existentialise their index+ -- function at all (but the memory block is still existential).+ case v_mem_space of+ ScalarSpace {} ->+ if anyIsLoopParam (freeIn shape)+ then do+ -- Arrays with loop-variant shape cannot be in scalar+ -- space, so copy them elsewhere and try again.+ (_, v') <- lift $ allocLinearArray DefaultSpace (baseString v) v+ allocInMergeParam (mergeparam, Var v')+ else do+ mem_name <- newVName "mem_param"+ tell ([], [Param mem_name $ MemMem v_mem_space]) - (ctx_params, param_ixfun_substs) <-- unzip- <$> mapM- ( \e -> do- let e_t = primExpType $ untyped e- vname <- lift $ newVName "ctx_param_ext"- return- ( Param vname $ MemPrim e_t,- fmap Free $ pe64 $ Var vname- )- )- substs+ pure+ ( mergeparam {paramDec = MemArray pt shape u $ ArrayIn mem_name v_ixfun},+ Var v,+ scalarRes param_t v_mem_space v_ixfun+ )+ _ -> do+ (v', ext_ixfun, substs, v_mem') <-+ lift $ existentializeArray v_mem_space v+ v_mem_space' <- lift $ lookupMemSpace v_mem' - tell (ctx_params, [])+ (ctx_params, param_ixfun_substs) <-+ fmap unzip . forM substs $ \e -> do+ vname <- lift $ newVName "ctx_param_ext"+ pure+ ( Param vname $ MemPrim $ primExpType $ untyped e,+ fmap Free $ pe64 $ Var vname+ ) - param_ixfun <-- instantiateIxFun $- IxFun.substituteInIxFun- (M.fromList $ zip (fmap Ext [0 ..]) param_ixfun_substs)- ext_ixfun+ tell (ctx_params, []) - mem_name <- newVName "mem_param"- tell ([], [Param mem_name $ MemMem mem_space])+ param_ixfun <-+ instantiateIxFun $+ IxFun.substituteInIxFun+ (M.fromList $ zip (fmap Ext [0 ..]) param_ixfun_substs)+ ext_ixfun - return- ( mergeparam {paramDec = MemArray pt shape u $ ArrayIn mem_name param_ixfun},- ensureArrayIn mem_space- )- allocInMergeParam (mergeparam, _) = doDefault mergeparam =<< lift askDefaultSpace+ mem_name <- newVName "mem_param"+ tell ([], [Param mem_name $ MemMem v_mem_space']) - doDefault mergeparam space = do+ pure+ ( mergeparam {paramDec = MemArray pt shape u $ ArrayIn mem_name param_ixfun},+ v',+ ensureArrayIn v_mem_space'+ )+ allocInMergeParam (mergeparam, se) = doDefault mergeparam se =<< lift askDefaultSpace++ doDefault mergeparam se space = do mergeparam' <- allocInFParam mergeparam space- return (mergeparam', linearFuncallArg (paramType mergeparam) space)+ return (mergeparam', se, linearFuncallArg (paramType mergeparam) space) -- Returns the existentialized index function, the list of substituted values and the memory location. existentializeArray ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Space -> VName -> AllocM fromrep torep (SubExp, ExtIxFun, [TPrimExp Int64 VName], VName)-existentializeArray ScalarSpace {} v = do- (mem', ixfun) <- lookupArraySummary v- return (Var v, fmap (fmap Free) ixfun, mempty, mem') existentializeArray space v = do (mem', ixfun) <- lookupArraySummary v sp <- lookupMemSpace mem'@@ -596,15 +495,28 @@ case (ext_ixfun', sp == space) of (Just x, True) -> return (Var v, x, substs', mem') _ -> do- (mem, subexp) <- allocLinearArray space (baseString v) v- ixfun' <- fromJust <$> subExpIxFun subexp+ (mem, v') <- allocLinearArray space (baseString v) v+ ixfun' <- fromJust <$> lookupIxFun v' let (ext_ixfun, substs) = runState (IxFun.existentialize ixfun') []- return (subexp, fromJust ext_ixfun, substs, mem)+ return (Var v', fromJust ext_ixfun, substs, mem) +arrayWithIxFun ::+ (MonadBuilder m, Op (Rep m) ~ MemOp inner, LetDec (Rep m) ~ LetDecMem) =>+ ChunkMap ->+ Space ->+ IxFun ->+ Type ->+ VName ->+ m (VName, VName)+arrayWithIxFun chunkmap space ixfun v_t v = do+ let Array pt shape u = v_t+ mem <- allocForArray' chunkmap v_t space+ v_copy <- newVName $ baseString v <> "_scalcopy"+ letBind (Pat [PatElem v_copy $ MemArray pt shape u $ ArrayIn mem ixfun]) $ BasicOp $ Copy v+ pure (mem, v_copy)+ ensureArrayIn ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => Space -> SubExp -> WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp@@ -626,18 +538,16 @@ return sub_exp ensureDirectArray ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => Maybe Space -> VName ->- AllocM fromrep torep (VName, SubExp)+ AllocM fromrep torep (VName, VName) ensureDirectArray space_ok v = do (mem, ixfun) <- lookupArraySummary v mem_space <- lookupMemSpace mem default_space <- askDefaultSpace if IxFun.isDirect ixfun && maybe True (== mem_space) space_ok- then return (mem, Var v)+ then return (mem, v) else needCopy (fromMaybe default_space space_ok) where needCopy space =@@ -646,28 +556,26 @@ allocLinearArray space (baseString v) v allocLinearArray ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Space -> String -> VName ->- AllocM fromrep torep (VName, SubExp)+ AllocM fromrep torep (VName, VName) allocLinearArray space s v = do t <- lookupType v case t of Array pt shape u -> do mem <- allocForArray t space- v' <- newIdent (s ++ "_linear") t+ v' <- newVName $ s <> "_linear" let ixfun = directIxFun pt shape u mem t- pat = Pattern [] [PatElem (identName v') ixfun]+ pat = Pat [PatElem v' ixfun] addStm $ Let pat (defAux ()) $ BasicOp $ Copy v- return (mem, Var $ identName v')+ return (mem, v') _ -> error $ "allocLinearArray: " ++ pretty t funcallArgs ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => [(SubExp, Diet)] -> AllocM fromrep torep [(SubExp, Diet)] funcallArgs args = do@@ -680,9 +588,7 @@ return $ map (,Observe) (ctx_args <> mem_and_size_args) <> valargs linearFuncallArg ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => Type -> Space -> SubExp ->@@ -690,14 +596,12 @@ linearFuncallArg Array {} space (Var v) = do (mem, arg') <- lift $ ensureDirectArray (Just space) v tell ([], [Var mem])- return arg'+ pure $ Var arg' linearFuncallArg _ _ arg =- return arg+ pure arg explicitAllocationsGeneric ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> Pass fromrep torep@@ -709,19 +613,17 @@ runAllocM handleOp hints $ collectStms_ $ allocInStms stms $ pure () allocInFun consts (FunDef entry attrs fname rettype params fbody) =- runAllocM handleOp hints $- inScopeOf consts $- allocInFParams (zip params $ repeat DefaultSpace) $ \params' -> do- fbody' <-- allocInFunBody- (map (const $ Just DefaultSpace) rettype)- fbody- return $ FunDef entry attrs fname (memoryInDeclExtType rettype) params' fbody'+ runAllocM handleOp hints . inScopeOf consts $+ allocInFParams (zip params $ repeat DefaultSpace) $ \params' -> do+ (fbody', mem_rets) <-+ allocInFunBody (map (const $ Just DefaultSpace) rettype) fbody+ let rettype' = mem_rets ++ memoryInDeclExtType (length mem_rets) rettype+ return $ FunDef entry attrs fname rettype' params' fbody' explicitAllocationsInStmsGeneric :: ( MonadFreshNames m, HasScope torep m,- Allocable fromrep torep+ Allocable fromrep torep inner ) => (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) ->@@ -732,70 +634,73 @@ runAllocM handleOp hints $ localScope scope $ collectStms_ $ allocInStms stms $ pure () -memoryInDeclExtType :: [DeclExtType] -> [FunReturns]-memoryInDeclExtType dets = evalState (mapM addMem dets) $ startOfFreeIDRange dets+memoryInDeclExtType :: Int -> [DeclExtType] -> [FunReturns]+memoryInDeclExtType k dets = evalState (mapM addMem dets) 0 where addMem (Prim t) = return $ MemPrim t addMem Mem {} = error "memoryInDeclExtType: too much memory" addMem (Array pt shape u) = do i <- get <* modify (+ 1)- return $- MemArray pt shape u $- ReturnsNewBlock DefaultSpace i $- IxFun.iota $ map convert $ shapeDims shape+ let shape' = fmap shift shape+ return . MemArray pt shape' u . ReturnsNewBlock DefaultSpace i $+ IxFun.iota $ map convert $ shapeDims shape' addMem (Acc acc ispace ts u) = return $ MemAcc acc ispace ts u convert (Ext i) = le64 $ Ext i convert (Free v) = Free <$> pe64 v -startOfFreeIDRange :: [TypeBase ExtShape u] -> Int-startOfFreeIDRange = S.size . shapeContext+ shift (Ext i) = Ext (i + k)+ shift (Free x) = Free x bodyReturnMemCtx ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>- SubExp ->- AllocM fromrep torep [SubExp]-bodyReturnMemCtx Constant {} =+ (Allocable fromrep torep inner) =>+ SubExpRes ->+ AllocM fromrep torep [(SubExpRes, MemInfo ExtSize u MemReturn)]+bodyReturnMemCtx (SubExpRes _ Constant {}) = return []-bodyReturnMemCtx (Var v) = do+bodyReturnMemCtx (SubExpRes _ (Var v)) = do info <- lookupMemInfo v case info of MemPrim {} -> return [] MemAcc {} -> return [] MemMem {} -> return [] -- should not happen- MemArray _ _ _ (ArrayIn mem _) -> return [Var mem]+ MemArray _ _ _ (ArrayIn mem _) -> do+ mem_info <- lookupMemInfo mem+ case mem_info of+ MemMem space ->+ pure [(subExpRes $ Var mem, MemMem space)]+ _ -> error $ "bodyReturnMemCtx: not a memory block: " ++ pretty mem allocInFunBody ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => [Maybe Space] -> Body fromrep ->- AllocM fromrep torep (Body torep)+ AllocM fromrep torep (Body torep, [FunReturns]) allocInFunBody space_oks (Body _ bnds res) =- buildBody_ . allocInStms bnds $ do+ buildBody . allocInStms bnds $ do res' <- zipWithM ensureDirect space_oks' res- let (ctx_res, val_res) = splitFromEnd num_vals res'- mem_ctx_res <- concat <$> mapM bodyReturnMemCtx val_res- pure $ ctx_res <> mem_ctx_res <> val_res+ (mem_ctx_res, mem_ctx_rets) <- unzip . concat <$> mapM bodyReturnMemCtx res'+ pure (mem_ctx_res <> res', mem_ctx_rets) where num_vals = length space_oks space_oks' = replicate (length res - num_vals) Nothing ++ space_oks ensureDirect ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Maybe Space ->- SubExp ->- AllocM fromrep torep SubExp-ensureDirect space_ok se = do+ SubExpRes ->+ AllocM fromrep torep SubExpRes+ensureDirect space_ok (SubExpRes cs se) = do se_info <- subExpMemInfo se- case (se_info, se) of+ SubExpRes cs <$> case (se_info, se) of (MemArray {}, Var v) -> do (_, v') <- ensureDirectArray space_ok v- return v'+ pure $ Var v' _ ->- return se+ pure se allocInStms ::- (Allocable fromrep torep) =>+ (Allocable fromrep torep inner) => Stms fromrep -> AllocM fromrep torep a -> AllocM fromrep torep a@@ -815,53 +720,40 @@ local f $ allocInStms' stms allocInStm ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Stm fromrep -> AllocM fromrep torep ()-allocInStm (Let (Pattern sizeElems valElems) _ e) = do- e' <- allocInExp e- let sizeidents = map patElemIdent sizeElems- validents = map patElemIdent valElems- bnd <- allocsForStm sizeidents validents e'- addStm bnd+allocInStm (Let (Pat pes) _ e) =+ addStm =<< allocsForStm (map patElemIdent pes) =<< allocInExp e allocInLambda ::- Allocable fromrep torep =>+ Allocable fromrep torep inner => [LParam torep] -> Body fromrep -> AllocM fromrep torep (Lambda torep) allocInLambda params body =- mkLambda params . allocInStms (bodyStms body) $- pure $ bodyResult body+ mkLambda params . allocInStms (bodyStms body) $ pure $ bodyResult body allocInExp ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Exp fromrep -> AllocM fromrep torep (Exp torep)-allocInExp (DoLoop ctx val form (Body () bodybnds bodyres)) =- allocInMergeParams ctx $ \_ ctxparams' _ ->- allocInMergeParams val $- \new_ctx_params valparams' mk_loop_val -> do- form' <- allocInLoopForm form- localScope (scopeOf form') $ do- (valinit_ctx, valinit') <- mk_loop_val valinit- body' <-- buildBody_ . allocInStms bodybnds $ do- (val_ses, valres') <- mk_loop_val valres- pure $ ctxres ++ val_ses ++ valres'- return $- DoLoop- (zip (ctxparams' ++ new_ctx_params) (ctxinit ++ valinit_ctx))- (zip valparams' valinit')- form'- body'- where- (_ctxparams, ctxinit) = unzip ctx- (_valparams, valinit) = unzip val- (ctxres, valres) = splitAt (length ctx) bodyres+allocInExp (DoLoop merge form (Body () bodybnds bodyres)) =+ allocInMergeParams merge $ \merge' mk_loop_val -> do+ form' <- allocInLoopForm form+ localScope (scopeOf form') $ do+ body' <-+ buildBody_ . allocInStms bodybnds $ do+ (val_ses, valres') <- mk_loop_val $ map resSubExp bodyres+ pure $ subExpsRes val_ses <> zipWith SubExpRes (map resCerts bodyres) valres'+ pure $ DoLoop merge' form' body' allocInExp (Apply fname args rettype loc) = do args' <- funcallArgs args- return $ Apply fname args' (memoryInDeclExtType rettype) loc+ -- We assume that every array is going to be in its own memory.+ return $ Apply fname args' (mems ++ memoryInDeclExtType 0 rettype) loc+ where+ mems = replicate num_arrays (MemMem DefaultSpace)+ num_arrays = length $ filter ((> 0) . arrayRank . declExtTypeOf) rettype allocInExp (If cond tbranch0 fbranch0 (IfDec rets ifsort)) = do let num_rets = length rets -- switch to the explicit-mem rep, but do nothing about results@@ -892,7 +784,7 @@ (\(se, _, i) k -> (i - k, se)) ind_ses0 [0 .. length ind_ses0 - 1]- rets'' = foldl (\acc (i, se) -> fixExt i se acc) trets ind_ses+ rets'' = foldl (\acc (i, SubExpRes _ se) -> fixExt i se acc) trets ind_ses tbranch'' = tbranch' {bodyResult = r_then_ext ++ drop size_ext res_then} fbranch'' = fbranch' {bodyResult = r_else_ext ++ drop size_ext res_else} res_if_expr = If cond tbranch'' fbranch'' $ IfDec rets'' ifsort@@ -923,14 +815,14 @@ selectSub f (Just (ixfn, m)) = Just (ixfn, map f m) selectSub _ Nothing = Nothing allocInIfBody ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => Int -> Body fromrep -> AllocM fromrep torep (Body torep, [Maybe IxFun]) allocInIfBody num_vals (Body _ bnds res) = buildBody . allocInStms bnds $ do let (_, val_res) = splitFromEnd num_vals res- mem_ixfs <- mapM subExpIxFun val_res+ mem_ixfs <- mapM (subExpIxFun . resSubExp) val_res pure (res, mem_ixfs) allocInExp (WithAcc inputs bodylam) = WithAcc <$> mapM onInput inputs <*> onLambda bodylam@@ -963,7 +855,7 @@ mkP p pt shape u mem ixfun is = Param p . MemArray pt shape u . ArrayIn mem . IxFun.slice ixfun $- fmap (fmap pe64) $ is ++ map sliceDim (shapeDims shape)+ fmap pe64 $ Slice $ is ++ map sliceDim (shapeDims shape) onXParam _ (Param p (Prim t)) _ = return $ Param p (MemPrim t)@@ -997,90 +889,93 @@ handle op } -subExpIxFun ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>- SubExp ->+lookupIxFun ::+ (Allocable fromrep torep inner) =>+ VName -> AllocM fromrep torep (Maybe IxFun)-subExpIxFun Constant {} = return Nothing-subExpIxFun (Var v) = do+lookupIxFun v = do info <- lookupMemInfo v case info of MemArray _ptp _shp _u (ArrayIn _ ixf) -> return $ Just ixf _ -> return Nothing +subExpIxFun ::+ (Allocable fromrep torep inner) =>+ SubExp ->+ AllocM fromrep torep (Maybe IxFun)+subExpIxFun Constant {} = return Nothing+subExpIxFun (Var v) = lookupIxFun v++shiftShapeExts :: Int -> MemInfo ExtSize u r -> MemInfo ExtSize u r+shiftShapeExts k (MemArray pt shape u returns) =+ MemArray pt (fmap shift shape) u returns+ where+ shift (Ext i) = Ext (i + k)+ shift (Free x) = Free x+shiftShapeExts _ ret = ret+ addResCtxInIfBody ::- (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ (Allocable fromrep torep inner) => [ExtType] -> Body torep -> [Maybe Space] -> [Maybe (ExtIxFun, [TPrimExp Int64 VName])] -> AllocM fromrep torep (Body torep, [BodyReturns])-addResCtxInIfBody ifrets (Body _ bnds res) spaces substs = do- let num_vals = length ifrets- (ctx_res, val_res) = splitFromEnd num_vals res- ((res', bodyrets'), all_body_stms) <- collectStms $ do- mapM_ addStm bnds- (val_res', ext_ses_res, mem_ctx_res, bodyrets, total_existentials) <-- foldM helper ([], [], [], [], length ctx_res) (zip4 ifrets val_res substs spaces)- return- ( ctx_res <> ext_ses_res <> mem_ctx_res <> val_res',- -- We need to adjust the ReturnsNewBlock existentials, because they- -- should always be numbered _after_ all other existentials in the- -- return values.- reverse $ fst $ foldl adjustNewBlockExistential ([], total_existentials) bodyrets- )- body' <- mkBodyM all_body_stms res'- return (body', bodyrets')+addResCtxInIfBody ifrets (Body _ bnds res) spaces substs = buildBody $ do+ mapM_ addStm bnds+ (ctx, ctx_rets, res', res_rets, total_existentials) <-+ foldM helper ([], [], [], [], 0) (zip4 ifrets res substs spaces)+ pure+ ( ctx <> res',+ -- We need to adjust the existentials in shapes corresponding+ -- to the previous type, because we added more existentials in+ -- front.+ ctx_rets ++ map (shiftShapeExts total_existentials) res_rets+ ) where- helper (res_acc, ext_acc, ctx_acc, br_acc, k) (ifr, r, mbixfsub, sp) =+ helper (ctx_acc, ctx_rets_acc, res_acc, res_rets_acc, k) (ifr, r, mbixfsub, sp) = case mbixfsub of Nothing -> do -- does NOT generalize/antiunify; ensure direct r' <- ensureDirect sp r- mem_ctx_r <- bodyReturnMemCtx r'- let body_ret = inspect ifr sp- return- ( res_acc ++ [r'],- ext_acc,- ctx_acc ++ mem_ctx_r,- br_acc ++ [body_ret],- k+ (mem_ctx_ses, mem_ctx_rets) <- unzip <$> bodyReturnMemCtx r'+ let body_ret = inspect k ifr sp+ pure+ ( ctx_acc ++ mem_ctx_ses,+ ctx_rets_acc ++ mem_ctx_rets,+ res_acc ++ [r'],+ res_rets_acc ++ [body_ret],+ k + length mem_ctx_ses ) Just (ixfn, m) -> do -- generalizes let i = length m ext_ses <- mapM (toSubExp "ixfn_exist") m- mem_ctx_r <- bodyReturnMemCtx r+ (mem_ctx_ses, mem_ctx_rets) <- unzip <$> bodyReturnMemCtx r let sp' = fromMaybe DefaultSpace sp ixfn' = fmap (adjustExtPE k) ixfn exttp = case ifr of Array pt shp' u ->- MemArray pt shp' u $- ReturnsNewBlock sp' 0 ixfn'+ MemArray pt shp' u $ ReturnsNewBlock sp' (k + i) ixfn' _ -> error "Impossible case reached in addResCtxInIfBody"- return- ( res_acc ++ [r],- ext_acc ++ ext_ses,- ctx_acc ++ mem_ctx_r,- br_acc ++ [exttp],- k + i+ pure+ ( ctx_acc ++ subExpsRes ext_ses ++ mem_ctx_ses,+ ctx_rets_acc ++ map (const (MemPrim int64)) ext_ses ++ mem_ctx_rets,+ res_acc ++ [r],+ res_rets_acc ++ [exttp],+ k + i + 1 ) - adjustNewBlockExistential :: ([BodyReturns], Int) -> BodyReturns -> ([BodyReturns], Int)- adjustNewBlockExistential (acc, k) (MemArray pt shp u (ReturnsNewBlock space _ ixfun)) =- (MemArray pt shp u (ReturnsNewBlock space k ixfun) : acc, k + 1)- adjustNewBlockExistential (acc, k) x = (x : acc, k)-- inspect (Array pt shape u) space =+ inspect k (Array pt shape u) space = let space' = fromMaybe DefaultSpace space bodyret = MemArray pt shape u $- ReturnsNewBlock space' 0 $+ ReturnsNewBlock space' k $ IxFun.iota $ map convert $ shapeDims shape in bodyret- inspect (Acc acc ispace ts u) _ = MemAcc acc ispace ts u- inspect (Prim pt) _ = MemPrim pt- inspect (Mem space) _ = MemMem space+ inspect _ (Acc acc ispace ts u) _ = MemAcc acc ispace ts u+ inspect _ (Prim pt) _ = MemPrim pt+ inspect _ (Mem space) _ = MemMem space convert (Ext i) = le64 (Ext i) convert (Free v) = Free <$> pe64 v@@ -1093,13 +988,12 @@ adjustExtPE k = fmap (adjustExtV k) mkSpaceOks ::- (Mem torep, LocalScope torep m) =>+ (Mem torep inner, LocalScope torep m) => Int -> Body torep -> m [Maybe Space] mkSpaceOks num_vals (Body _ stms res) =- inScopeOf stms $- mapM mkSpaceOK $ takeLast num_vals res+ inScopeOf stms $ mapM (mkSpaceOK . resSubExp) $ takeLast num_vals res where mkSpaceOK (Var v) = do v_info <- lookupMemInfo v@@ -1113,9 +1007,7 @@ mkSpaceOK _ = return Nothing allocInLoopForm ::- ( Allocable fromrep torep,- Allocator torep (AllocM fromrep torep)- ) =>+ (Allocable fromrep torep inner) => LoopForm fromrep -> AllocM fromrep torep (LoopForm torep) allocInLoopForm (WhileLoop v) = return $ WhileLoop v@@ -1139,7 +1031,7 @@ return (p {paramDec = MemAcc acc ispace ts u}, a) class SizeSubst op where- opSizeSubst :: PatternT dec -> op -> ChunkMap+ opSizeSubst :: PatT dec -> op -> ChunkMap opIsConst :: op -> Bool opIsConst = const False @@ -1159,49 +1051,52 @@ stmConsts :: SizeSubst (Op rep) => Stm rep -> S.Set VName stmConsts (Let pat _ (Op op))- | opIsConst op = S.fromList $ patternNames pat+ | opIsConst op = S.fromList $ patNames pat stmConsts _ = mempty mkLetNamesB' ::- ( Op (Rep m) ~ MemOp inner,- MonadBinder m,- ExpDec (Rep m) ~ (),- Allocator (Rep m) (PatAllocM (Rep m))+ ( LetDec (Rep m) ~ LetDecMem,+ Mem (Rep m) inner,+ MonadBuilder m,+ ExpDec (Rep m) ~ () ) => ExpDec (Rep m) -> [VName] -> Exp (Rep m) -> m (Stm (Rep m)) mkLetNamesB' dec names e = do- scope <- askScope- pat <- bindPatternWithAllocations scope names e- return $ Let pat (defAux dec) e+ pat <- patWithAllocations DefaultSpace mempty names e nohints+ pure $ Let pat (defAux dec) e+ where+ nohints = map (const NoHint) names mkLetNamesB'' ::- ( Op (Rep m) ~ MemOp inner,+ ( BuilderOps rep,+ Mem rep inner,+ LetDec rep ~ LetDecMem,+ OpReturns (Engine.OpWithWisdom inner), ExpDec rep ~ (),+ Rep m ~ Engine.Wise rep, HasScope (Engine.Wise rep) m,- Allocator rep (PatAllocM rep),- MonadBinder m,- Engine.CanBeWise (Op rep)+ MonadBuilder m,+ Engine.CanBeWise inner ) => [VName] -> Exp (Engine.Wise rep) -> m (Stm (Engine.Wise rep)) mkLetNamesB'' names e = do- scope <- Engine.removeScopeWisdom <$> askScope- (pat, prestms) <- runPatAllocM (patternWithAllocations names $ Engine.removeExpWisdom e) scope- mapM_ bindAllocStm prestms- let pat' = Engine.addWisdomToPattern pat e+ pat <- patWithAllocations DefaultSpace mempty names e nohints+ let pat' = Engine.addWisdomToPat pat e dec = Engine.mkWiseExpDec pat' () e- return $ Let pat' (defAux dec) e+ pure $ Let pat' (defAux dec) e+ where+ nohints = map (const NoHint) names simplifiable :: ( Engine.SimplifiableRep rep, ExpDec rep ~ (), BodyDec rep ~ (),- Op rep ~ MemOp inner,- Allocator rep (PatAllocM rep)+ Mem rep inner ) => (Engine.OpWithWisdom inner -> UT.UsageTable) -> (inner -> Engine.SimpleM rep (Engine.OpWithWisdom inner, Stms (Engine.Wise rep))) ->@@ -1235,21 +1130,6 @@ simplifyOp (Inner k) = do (k', hoisted) <- simplifyInnerOp k return (Inner k', hoisted)--bindPatternWithAllocations ::- ( MonadBinder m,- ExpDec rep ~ (),- Op (Rep m) ~ MemOp inner,- Allocator rep (PatAllocM rep)- ) =>- Scope rep ->- [VName] ->- Exp rep ->- m (Pattern rep)-bindPatternWithAllocations types names e = do- (pat, prebnds) <- runPatAllocM (patternWithAllocations names e) types- mapM_ bindAllocStm prebnds- return pat data ExpHint = NoHint
src/Futhark/Pass/ExplicitAllocations/GPU.hs view
@@ -19,7 +19,7 @@ import Futhark.Pass.ExplicitAllocations.SegOp instance SizeSubst (HostOp rep op) where- opSizeSubst (Pattern _ [size]) (SizeOp (SplitSpace _ _ _ elems_per_thread)) =+ opSizeSubst (Pat [size]) (SizeOp (SplitSpace _ _ _ elems_per_thread)) = M.singleton (patElemName size) elems_per_thread opSizeSubst _ _ = mempty @@ -77,7 +77,7 @@ handleHostOp (SegOp op) = Inner . SegOp <$> handleSegOp op -kernelExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+kernelExpHints :: Exp GPUMem -> AllocM GPU GPUMem [ExpHint] kernelExpHints (BasicOp (Manifest perm v)) = do dims <- arrayDims <$> lookupType v let perm_inv = rearrangeInverse perm@@ -95,12 +95,11 @@ return $ replicate (expExtTypeSize e) NoHint mapResultHint ::- Allocator rep m => SegLevel -> SegSpace -> Type -> KernelResult ->- m ExpHint+ AllocM GPU GPUMem ExpHint mapResultHint lvl space = hint where num_threads =@@ -114,13 +113,15 @@ hint t Returns {} | coalesceReturnOfShape (primByteSize (elemType t)) $ arrayDims t = do+ chunkmap <- asks chunkMap let space_dims = segSpaceDims space- t_dims <- mapM dimAllocationSize $ arrayDims t+ t_dims = map (dimAllocationSize chunkmap) $ arrayDims t return $ Hint (innermost space_dims t_dims) DefaultSpace- hint t (ConcatReturns SplitStrided {} w _ _) = do- t_dims <- mapM dimAllocationSize $ arrayDims t+ hint t (ConcatReturns _ SplitStrided {} w _ _) = do+ chunkmap <- asks chunkMap+ let t_dims = map (dimAllocationSize chunkmap) $ arrayDims t return $ Hint (innermost [w] t_dims) DefaultSpace- hint Prim {} (ConcatReturns SplitContiguous w elems_per_thread _) = do+ hint Prim {} (ConcatReturns _ SplitContiguous w elems_per_thread _) = do let ixfun_base = IxFun.iota [sExt64 num_threads, pe64 elems_per_thread] ixfun_tr = IxFun.permute ixfun_base [1, 0] ixfun = IxFun.reshape ixfun_tr $ map (DimNew . pe64) [w]@@ -144,13 +145,13 @@ semiStatic _ Constant {} = True semiStatic consts (Var v) = v `S.member` consts -inGroupExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+inGroupExpHints :: Exp GPUMem -> AllocM GPU GPUMem [ExpHint] inGroupExpHints (Op (Inner (SegOp (SegMap _ space ts body)))) | any private $ kernelBodyResult body = do- consts <- askConsts- return $ do+ consts <- asks envConsts+ pure $ do (t, r) <- zip ts $ kernelBodyResult body- return $+ pure $ if private r && all (semiStatic consts) (arrayDims t) then let seg_dims = map pe64 $ segSpaceDims space@@ -163,22 +164,22 @@ $ ScalarSpace (arrayDims t) $ elemType t else NoHint where- private (Returns ResultPrivate _) = True+ private (Returns ResultPrivate _ _) = True private _ = False-inGroupExpHints e = return $ replicate (expExtTypeSize e) NoHint+inGroupExpHints e = pure $ replicate (expExtTypeSize e) NoHint -inThreadExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+inThreadExpHints :: Exp GPUMem -> AllocM GPU GPUMem [ExpHint] inThreadExpHints e = do- consts <- askConsts+ consts <- asks envConsts mapM (maybePrivate consts) =<< expExtType e where maybePrivate consts t | Just (Array pt shape _) <- hasStaticShape t, all (semiStatic consts) $ shapeDims shape = do let ixfun = IxFun.iota $ map pe64 $ shapeDims shape- return $ Hint ixfun $ ScalarSpace (shapeDims shape) pt+ pure $ Hint ixfun $ ScalarSpace (shapeDims shape) pt | otherwise =- return NoHint+ pure NoHint -- | The pass from 'GPU' to 'GPUMem'. explicitAllocations :: Pass GPU GPUMem
src/Futhark/Pass/ExplicitAllocations/MC.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} +-- | Converting 'MC' programs to 'MCMem'. module Futhark.Pass.ExplicitAllocations.MC (explicitAllocations) where import Futhark.IR.MC@@ -33,5 +34,6 @@ handleMCOp (OtherOp soac) = error $ "Cannot allocate memory in SOAC: " ++ pretty soac +-- | The pass from 'MC' to 'MCMem'. explicitAllocations :: Pass MC MCMem explicitAllocations = explicitAllocationsGeneric handleMCOp defaultExpHints
src/Futhark/Pass/ExplicitAllocations/SegOp.hs view
@@ -17,7 +17,7 @@ opSizeSubst _ _ = mempty allocInKernelBody ::- Allocable fromrep torep =>+ Allocable fromrep torep inner => KernelBody fromrep -> AllocM fromrep torep (KernelBody torep) allocInKernelBody (KernelBody () stms res) =@@ -25,7 +25,7 @@ <$> collectStms (allocInStms stms (pure res)) allocInLambda ::- Allocable fromrep torep =>+ Allocable fromrep torep inner => [LParam torep] -> Body fromrep -> AllocM fromrep torep (Lambda torep)@@ -34,7 +34,7 @@ pure $ bodyResult body allocInBinOpParams ::- Allocable fromrep torep =>+ Allocable fromrep torep inner => SubExp -> TPrimExp Int64 VName -> TPrimExp Int64 VName ->@@ -83,7 +83,7 @@ ) allocInBinOpLambda ::- Allocable fromrep torep =>+ Allocable fromrep torep inner => SubExp -> SegSpace -> Lambda fromrep ->
src/Futhark/Pass/ExtractKernels.hs view
@@ -166,7 +166,7 @@ import Data.Bifunctor (first) import Data.Maybe import qualified Futhark.IR.GPU as Out-import Futhark.IR.GPU.Kernel+import Futhark.IR.GPU.Op import Futhark.IR.SOACS import Futhark.IR.SOACS.Simplify (simplifyStms) import Futhark.MonadFreshNames@@ -300,7 +300,7 @@ unbalancedLambda lam2, lambdaContainsParallelism lam2 = do types <- asksScope scopeForSOACs- Just . snd <$> runBinderT (FOT.transformSOAC pat soac) types+ Just . snd <$> runBuilderT (FOT.transformSOAC pat soac) types sequentialisedUnbalancedStm _ = return Nothing @@ -313,7 +313,7 @@ x <- gets stateThresholdCounter modify $ \s -> s {stateThresholdCounter = x + 1} let size_key = nameFromString $ desc ++ "_" ++ show x- runBinder $ do+ runBuilder $ do to_what' <- letSubExp "comparatee" =<< foldBinOp (Mul Int64 OverflowUndef) (intConst Int64 1) to_what@@ -322,26 +322,25 @@ kernelAlternatives :: (MonadFreshNames m, HasScope Out.GPU m) =>- Out.Pattern Out.GPU ->+ Out.Pat Out.GPU -> Out.Body Out.GPU -> [(SubExp, Out.Body Out.GPU)] -> m (Out.Stms Out.GPU)-kernelAlternatives pat default_body [] = runBinder_ $ do+kernelAlternatives pat default_body [] = runBuilder_ $ do ses <- bodyBind default_body- forM_ (zip (patternNames pat) ses) $ \(name, se) ->- letBindNames [name] $ BasicOp $ SubExp se-kernelAlternatives pat default_body ((cond, alt) : alts) = runBinder_ $ do- alts_pat <- fmap (Pattern []) $- forM (patternElements pat) $ \pe -> do- name <- newVName $ baseString $ patElemName pe- return pe {patElemName = name}+ forM_ (zip (patNames pat) ses) $ \(name, SubExpRes cs se) ->+ certifying cs $ letBindNames [name] $ BasicOp $ SubExp se+kernelAlternatives pat default_body ((cond, alt) : alts) = runBuilder_ $ do+ alts_pat <- fmap Pat . forM (patElems pat) $ \pe -> do+ name <- newVName $ baseString $ patElemName pe+ return pe {patElemName = name} alt_stms <- kernelAlternatives alts_pat default_body alts- let alt_body = mkBody alt_stms $ map Var $ patternValueNames alts_pat+ let alt_body = mkBody alt_stms $ varsRes $ patNames alts_pat letBind pat $ If cond alt alt_body $- IfDec (staticShapes (patternTypes pat)) IfEquiv+ IfDec (staticShapes (patTypes pat)) IfEquiv transformLambda :: KernelPath -> Lambda -> DistribM (Out.Lambda Out.GPU) transformLambda path (Lambda params body ret) =@@ -352,11 +351,11 @@ transformStm :: KernelPath -> Stm -> DistribM GPUStms transformStm _ stm | "sequential" `inAttrs` stmAuxAttrs (stmAux stm) =- runBinder_ $ FOT.transformStmRecursively stm+ runBuilder_ $ FOT.transformStmRecursively stm transformStm path (Let pat aux (Op soac)) | "sequential_outer" `inAttrs` stmAuxAttrs aux = transformStms path . stmsToList . fmap (certify (stmAuxCerts aux))- =<< runBinder_ (FOT.transformSOAC pat soac)+ =<< runBuilder_ (FOT.transformSOAC pat soac) transformStm path (Let pat aux (If c tb fb rt)) = do tb' <- transformBody path tb fb' <- transformBody path fb@@ -367,14 +366,11 @@ where transformInput (shape, arrs, op) = (shape, arrs, fmap (first soacsLambdaToGPU) op)-transformStm path (Let pat aux (DoLoop ctx val form body)) =- localScope- ( castScope (scopeOf form)- <> scopeOfFParams mergeparams- )- $ oneStm . Let pat aux . DoLoop ctx val form' <$> transformBody path body+transformStm path (Let pat aux (DoLoop merge form body)) =+ localScope (castScope (scopeOf form) <> scopeOfFParams params) $+ oneStm . Let pat aux . DoLoop merge form' <$> transformBody path body where- mergeparams = map fst $ ctx ++ val+ params = map fst merge form' = case form of WhileLoop cond -> WhileLoop cond@@ -388,8 +384,8 @@ Scan scan_lam nes <- singleScan scans, Just do_iswim <- iswim res_pat w scan_lam $ zip nes arrs = do types <- asksScope scopeForSOACs- transformStms path . stmsToList . snd =<< runBinderT (certifying cs do_iswim) types- | Just (scans, map_lam) <- isScanomapSOAC form = runBinder_ $ do+ transformStms path . stmsToList . snd =<< runBuilderT (certifying cs do_iswim) types+ | Just (scans, map_lam) <- isScanomapSOAC form = runBuilder_ $ do scan_ops <- forM scans $ \(Scan scan_lam nes) -> do (scan_lam', nes', shape) <- determineReduceOp scan_lam nes let scan_lam'' = soacsLambdaToGPU scan_lam'@@ -405,11 +401,11 @@ | otherwise = comm, Just do_irwim <- irwim res_pat w comm' red_fun $ zip nes arrs = do types <- asksScope scopeForSOACs- (_, bnds) <- fst <$> runBinderT (simplifyStms =<< collectStms_ (auxing aux do_irwim)) types+ (_, bnds) <- fst <$> runBuilderT (simplifyStms =<< collectStms_ (auxing aux do_irwim)) types transformStms path $ stmsToList bnds transformStm path (Let pat aux@(StmAux cs _ _) (Op (Screma w arrs form))) | Just (reds, map_lam) <- isRedomapSOAC form = do- let paralleliseOuter = runBinder_ $ do+ let paralleliseOuter = runBuilder_ $ do red_ops <- forM reds $ \(Reduce comm red_lam nes) -> do (red_lam', nes', shape) <- determineReduceOp red_lam nes let comm'@@ -424,25 +420,20 @@ outerParallelBody = renameBody- =<< (mkBody <$> paralleliseOuter <*> pure (map Var (patternNames pat)))+ =<< (mkBody <$> paralleliseOuter <*> pure (varsRes (patNames pat))) paralleliseInner path' = do (mapstm, redstm) <-- redomapToMapAndReduce pat (w, comm', red_lam, map_lam, nes, arrs)+ redomapToMapAndReduce pat (w, reds, map_lam, arrs) types <- asksScope scopeForSOACs- transformStms path' . stmsToList <=< (`runBinderT_` types) $ do+ transformStms path' . stmsToList <=< (`runBuilderT_` types) $ do (_, stms) <- simplifyStms (stmsFromList [certify cs mapstm, certify cs redstm]) addStms stms- where- comm'- | commutativeLambda red_lam = Commutative- | otherwise = comm- (Reduce comm red_lam nes) = singleReduce reds innerParallelBody path' = renameBody- =<< (mkBody <$> paralleliseInner path' <*> pure (map Var (patternNames pat)))+ =<< (mkBody <$> paralleliseInner path' <*> pure (varsRes (patNames pat))) if not (lambdaContainsParallelism map_lam) || "sequential_inner" `inAttrs` stmAuxAttrs aux@@ -464,7 +455,7 @@ -- parallel. It will be distributed. types <- asksScope scopeForSOACs transformStms path . stmsToList . snd- =<< runBinderT (certifying cs $ sequentialStreamWholeArray pat w [] map_fun arrs) types+ =<< runBuilderT (certifying cs $ sequentialStreamWholeArray pat w [] map_fun arrs) types transformStm path (Let pat aux@(StmAux cs _ _) (Op (Stream w arrs (Parallel o comm red_fun) nes fold_fun))) | "sequential_inner" `inAttrs` stmAuxAttrs aux = paralleliseOuter path@@ -485,8 +476,8 @@ let fold_fun' = soacsLambdaToGPU fold_fun let (red_pat_elems, concat_pat_elems) =- splitAt (length nes) $ patternValueElements pat- red_pat = Pattern [] red_pat_elems+ splitAt (length nes) $ patElems pat+ red_pat = Pat red_pat_elems ((num_threads, red_results), stms) <- streamMap@@ -524,16 +515,16 @@ outerParallelBody path' = renameBody- =<< (mkBody <$> paralleliseOuter path' <*> pure (map Var (patternNames pat)))+ =<< (mkBody <$> paralleliseOuter path' <*> pure (varsRes (patNames pat))) paralleliseInner path' = do types <- asksScope scopeForSOACs transformStms path' . fmap (certify cs) . stmsToList . snd- =<< runBinderT (sequentialStreamWholeArray pat w nes fold_fun arrs) types+ =<< runBuilderT (sequentialStreamWholeArray pat w nes fold_fun arrs) types innerParallelBody path' = renameBody- =<< (mkBody <$> paralleliseInner path' <*> pure (map Var (patternNames pat)))+ =<< (mkBody <$> paralleliseInner path' <*> pure (varsRes (patNames pat))) comm' | commutativeLambda red_fun, o /= InOrder = Commutative@@ -543,22 +534,25 @@ -- anything, so split it up and try again. scope <- asksScope scopeForSOACs transformStms path . map (certify cs) . stmsToList . snd- =<< runBinderT (dissectScrema pat w form arrs) scope+ =<< runBuilderT (dissectScrema pat w form arrs) scope transformStm path (Let pat _ (Op (Stream w arrs Sequential nes fold_fun))) = do -- Remove the stream and leave the body parallel. It will be -- distributed. types <- asksScope scopeForSOACs transformStms path . stmsToList . snd- =<< runBinderT (sequentialStreamWholeArray pat w nes fold_fun arrs) types-transformStm _ (Let pat (StmAux cs _ _) (Op (Scatter w lam ivs as))) = runBinder_ $ do+ =<< runBuilderT (sequentialStreamWholeArray pat w nes fold_fun arrs) types+transformStm _ (Let pat (StmAux cs _ _) (Op (Scatter w lam ivs as))) = runBuilder_ $ do let lam' = soacsLambdaToGPU lam write_i <- newVName "write_i" let (as_ws, _, _) = unzip3 as kstms = bodyStms $ lambdaBody lam' krets = do- (a_w, a, is_vs) <-- groupScatterResults as $ bodyResult $ lambdaBody lam'- return $ WriteReturns a_w a [(map DimFix is, v) | (is, v) <- is_vs]+ (a_w, a, is_vs) <- groupScatterResults as $ bodyResult $ lambdaBody lam'+ let res_cs =+ foldMap (foldMap resCerts . fst) is_vs+ <> foldMap (resCerts . snd) is_vs+ is_vs' = [(Slice $ map (DimFix . resSubExp) is, resSubExp v) | (is, v) <- is_vs]+ return $ WriteReturns res_cs a_w a is_vs' body = KernelBody () kstms krets inputs = do (p, p_a) <- zip (lambdaParams lam') ivs@@ -568,7 +562,7 @@ segThreadCapped [(write_i, w)] inputs- (zipWith (stripArray . length) as_ws $ patternTypes pat)+ (zipWith (stripArray . length) as_ws $ patTypes pat) body certifying cs $ do addStms stms@@ -579,13 +573,13 @@ -- It is important not to launch unnecessarily many threads for -- histograms, because it may mean we unnecessarily need to reduce -- subhistograms as well.- runBinder_ $ do+ runBuilder_ $ do lvl <- segThreadCapped [w] "seghist" $ NoRecommendation SegNoVirt addStms =<< histKernel onLambda lvl orig_pat [] [] cs w ops bfun' imgs where onLambda = pure . soacsLambdaToGPU transformStm _ bnd =- runBinder_ $ FOT.transformStmRecursively bnd+ runBuilder_ $ FOT.transformStmRecursively bnd sufficientParallelism :: String ->@@ -612,7 +606,7 @@ mapLike w lam' | Op (Scatter w lam' _ _) <- stmExp stm = mapLike w lam'- | DoLoop _ _ _ body <- stmExp stm =+ | DoLoop _ _ body <- stmExp stm = bodyInterest body * 10 | If _ tbody fbody _ <- stmExp stm = max (bodyInterest tbody) (bodyInterest fbody)@@ -652,7 +646,7 @@ else bodyInterest (lambdaBody lam') | Op Scatter {} <- stmExp stm = 0 -- Basically a map.- | DoLoop _ _ ForLoop {} body <- stmExp stm =+ | DoLoop _ ForLoop {} body <- stmExp stm = bodyInterest body * 10 | WithAcc _ withacc_lam <- stmExp stm = bodyInterest (lambdaBody withacc_lam)@@ -686,7 +680,7 @@ DistEnv { distNest = singleNesting (Nesting mempty loopnest), distScope =- scopeOfPattern pat+ scopeOfPat pat <> scopeForGPU (scopeOf lam) <> types, distOnInnerMap = onInnerMap path',@@ -740,7 +734,7 @@ KernelPath -> (KernelPath -> DistribM (Out.Stms Out.GPU)) -> (KernelPath -> DistribM (Out.Stms Out.GPU)) ->- Pattern ->+ Pat -> Lambda -> DistribM (Out.Stms Out.GPU) onMap' loopnest path mk_seq_stms mk_par_stms pat lam = do@@ -816,7 +810,7 @@ [(outer_suff, seq_body), (intra_ok, group_par_body)] where nest_ws = kernelNestWidths loopnest- res = map Var $ patternNames pat+ res = varsRes $ patNames pat aux = loopNestingAux $ innermostKernelNesting loopnest attrs = stmAuxAttrs aux @@ -846,7 +840,7 @@ path' (Just intraMinInnerPar) - runBinder $ do+ runBuilder $ do addStms intra_prelude max_group_size <-@@ -925,7 +919,7 @@ let sequentialised_lam = soacsLambdaToGPU lam' constructKernel segThreadCapped nest' $ lambdaBody sequentialised_lam - let outer_pat = loopNestingPattern $ fst nest+ let outer_pat = loopNestingPat $ fst nest (nestw_bnds <>) <$> onMap' nest'
src/Futhark/Pass/ExtractKernels/BlockedKernel.hs view
@@ -32,9 +32,9 @@ -- | Constraints pertinent to performing distribution/flattening. type DistRep rep =- ( Bindable rep,+ ( Buildable rep, HasSegOp rep,- BinderOps rep,+ BuilderOps rep, LetDec rep ~ Type, ExpDec rep ~ (), BodyDec rep ~ (),@@ -44,13 +44,13 @@ data ThreadRecommendation = ManyThreads | NoRecommendation SegVirt type MkSegLevel rep m =- [SubExp] -> String -> ThreadRecommendation -> BinderT rep m (SegOpLevel rep)+ [SubExp] -> String -> ThreadRecommendation -> BuilderT rep m (SegOpLevel rep) mkSegSpace :: MonadFreshNames m => [(VName, SubExp)] -> m SegSpace mkSegSpace dims = SegSpace <$> newVName "phys_tid" <*> pure dims prepareRedOrScan ::- (MonadBinder m, DistRep (Rep m)) =>+ (MonadBuilder m, DistRep (Rep m)) => SubExp -> Lambda (Rep m) -> [VName] ->@@ -61,20 +61,21 @@ gtid <- newVName "gtid" space <- mkSegSpace $ ispace ++ [(gtid, w)] kbody <- fmap (uncurry (flip (KernelBody ()))) $- runBinder $+ runBuilder $ localScope (scopeOfSegSpace space) $ do mapM_ readKernelInput inps mapM_ readKernelInput $ do (p, arr) <- zip (lambdaParams map_lam) arrs pure $ KernelInput (paramName p) (paramType p) arr [Var gtid]- map (Returns ResultMaySimplify) <$> bodyBind (lambdaBody map_lam)+ res <- bodyBind (lambdaBody map_lam)+ forM res $ \(SubExpRes cs se) -> pure $ Returns ResultMaySimplify cs se return (space, kbody) segRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep ->- Pattern rep ->+ Pat rep -> SubExp -> -- segment size [SegBinOp rep] -> Lambda rep ->@@ -82,7 +83,7 @@ [(VName, SubExp)] -> -- ispace = pair of (gtid, size) for the maps on "top" of this reduction [KernelInput] -> -- inps = inputs that can be looked up by using the gtids from ispace m (Stms rep)-segRed lvl pat w ops map_lam arrs ispace inps = runBinder_ $ do+segRed lvl pat w ops map_lam arrs ispace inps = runBuilder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $ Op $@@ -92,7 +93,7 @@ segScan :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep ->- Pattern rep ->+ Pat rep -> SubExp -> -- segment size [SegBinOp rep] -> Lambda rep ->@@ -100,7 +101,7 @@ [(VName, SubExp)] -> -- ispace = pair of (gtid, size) for the maps on "top" of this scan [KernelInput] -> -- inps = inputs that can be looked up by using the gtids from ispace m (Stms rep)-segScan lvl pat w ops map_lam arrs ispace inps = runBinder_ $ do+segScan lvl pat w ops map_lam arrs ispace inps = runBuilder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $ Op $@@ -110,14 +111,14 @@ segMap :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep ->- Pattern rep ->+ Pat rep -> SubExp -> -- segment size Lambda rep -> [VName] -> [(VName, SubExp)] -> -- ispace = pair of (gtid, size) for the maps on "top" of this map [KernelInput] -> -- inps = inputs that can be looked up by using the gtids from ispace m (Stms rep)-segMap lvl pat w map_lam arrs ispace inps = runBinder_ $ do+segMap lvl pat w map_lam arrs ispace inps = runBuilder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $ Op $@@ -125,9 +126,9 @@ SegMap lvl kspace (lambdaReturnType map_lam) kbody dummyDim ::- (MonadFreshNames m, MonadBinder m, DistRep (Rep m)) =>- Pattern (Rep m) ->- m (Pattern (Rep m), [(VName, SubExp)], m ())+ (MonadFreshNames m, MonadBuilder m, DistRep (Rep m)) =>+ Pat (Rep m) ->+ m (Pat (Rep m), [(VName, SubExp)], m ()) dummyDim pat = do -- We add a unit-size segment on top to ensure that the result -- of the SegRed is an array, which we then immediately index.@@ -136,14 +137,14 @@ -- host-device copy (scalars are kept on the host, but arrays -- may be on the device). let addDummyDim t = t `arrayOfRow` intConst Int64 1- pat' <- fmap addDummyDim <$> renamePattern pat+ pat' <- fmap addDummyDim <$> renamePat pat dummy <- newVName "dummy" let ispace = [(dummy, intConst Int64 1)] return ( pat', ispace,- forM_ (zip (patternNames pat') (patternNames pat)) $ \(from, to) -> do+ forM_ (zip (patNames pat') (patNames pat)) $ \(from, to) -> do from_t <- lookupType from letBindNames [to] $ BasicOp $@@ -154,13 +155,13 @@ nonSegRed :: (MonadFreshNames m, DistRep rep, HasScope rep m) => SegOpLevel rep ->- Pattern rep ->+ Pat rep -> SubExp -> [SegBinOp rep] -> Lambda rep -> [VName] -> m (Stms rep)-nonSegRed lvl pat w ops map_lam arrs = runBinder_ $ do+nonSegRed lvl pat w ops map_lam arrs = runBuilder_ $ do (pat', ispace, read_dummy) <- dummyDim pat addStms =<< segRed lvl pat' w ops map_lam arrs ispace [] read_dummy@@ -168,7 +169,7 @@ segHist :: (DistRep rep, MonadFreshNames m, HasScope rep m) => SegOpLevel rep ->- Pattern rep ->+ Pat rep -> SubExp -> -- | Segment indexes and sizes. [(VName, SubExp)] ->@@ -177,19 +178,21 @@ Lambda rep -> [VName] -> m (Stms rep)-segHist lvl pat arr_w ispace inps ops lam arrs = runBinder_ $ do+segHist lvl pat arr_w ispace inps ops lam arrs = runBuilder_ $ do gtid <- newVName "gtid" space <- mkSegSpace $ ispace ++ [(gtid, arr_w)] kbody <- fmap (uncurry (flip $ KernelBody ())) $- runBinder $+ runBuilder $ localScope (scopeOfSegSpace space) $ do mapM_ readKernelInput inps forM_ (zip (lambdaParams lam) arrs) $ \(p, arr) -> do arr_t <- lookupType arr letBindNames [paramName p] $ BasicOp $ Index arr $ fullSlice arr_t [DimFix $ Var gtid]- map (Returns ResultMaySimplify) <$> bodyBind (lambdaBody lam)+ res <- bodyBind (lambdaBody lam)+ forM res $ \(SubExpRes cs se) ->+ pure $ Returns ResultMaySimplify cs se letBind pat $ Op $ segOp $ SegHist lvl space ops (lambdaReturnType lam) kbody @@ -199,7 +202,7 @@ [KernelInput] -> m (SegSpace, Stms rep) mapKernelSkeleton ispace inputs = do- read_input_bnds <- runBinder_ $ mapM readKernelInput inputs+ read_input_bnds <- runBuilder_ $ mapM readKernelInput inputs space <- mkSegSpace ispace return (space, read_input_bnds)@@ -212,7 +215,7 @@ [Type] -> KernelBody rep -> m (SegOp (SegOpLevel rep) rep, Stms rep)-mapKernel mk_lvl ispace inputs rts (KernelBody () kstms krets) = runBinderT' $ do+mapKernel mk_lvl ispace inputs rts (KernelBody () kstms krets) = runBuilderT' $ do (space, read_input_stms) <- mapKernelSkeleton ispace inputs let kbody' = KernelBody () (read_input_stms <> kstms) krets@@ -237,16 +240,16 @@ deriving (Show) readKernelInput ::- (DistRep (Rep m), MonadBinder m) =>+ (DistRep (Rep m), MonadBuilder m) => KernelInput -> m () readKernelInput inp = do let pe = PatElem (kernelInputName inp) $ kernelInputType inp- letBind (Pattern [] [pe]) . BasicOp $+ letBind (Pat [pe]) . BasicOp $ case kernelInputType inp of Acc {} -> SubExp $ Var $ kernelInputArray inp _ ->- Index (kernelInputArray inp) $+ Index (kernelInputArray inp) . Slice $ map DimFix (kernelInputIndices inp) ++ map sliceDim (arrayDims (kernelInputType inp))
src/Futhark/Pass/ExtractKernels/DistributeNests.hs view
@@ -65,7 +65,7 @@ scopeForSOACs :: SameScope rep SOACS => Scope rep -> Scope SOACS scopeForSOACs = castScope -data MapLoop = MapLoop SOACS.Pattern (StmAux ()) SubExp SOACS.Lambda [VName]+data MapLoop = MapLoop SOACS.Pat (StmAux ()) SubExp SOACS.Lambda [VName] mapLoopStm :: MapLoop -> Stm SOACS mapLoopStm (MapLoop pat aux w lam arrs) =@@ -79,8 +79,8 @@ MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep),- distOnSOACSStms :: Stm SOACS -> Binder rep (Stms rep),- distOnSOACSLambda :: Lambda SOACS -> Binder rep (Lambda rep),+ distOnSOACSStms :: Stm SOACS -> Builder rep (Stms rep),+ distOnSOACSLambda :: Lambda SOACS -> Builder rep (Lambda rep), distSegLevel :: MkSegLevel rep m } @@ -110,7 +110,7 @@ mempty = PostStms mempty typeEnvFromDistAcc :: DistRep rep => DistAcc rep -> Scope rep-typeEnvFromDistAcc = scopeOfPattern . fst . outerTarget . distTargets+typeEnvFromDistAcc = scopeOfPat . fst . outerTarget . distTargets addStmsToAcc :: Stms rep -> DistAcc rep -> DistAcc rep addStmsToAcc stms acc =@@ -123,7 +123,7 @@ DistNestT rep m (DistAcc rep) addStmToAcc stm acc = do onSoacs <- asks distOnSOACSStms- (stm', _) <- runBinder $ onSoacs stm+ (stm', _) <- runBuilder $ onSoacs stm return acc {distStms = stm' <> distStms acc} soacsLambda ::@@ -132,7 +132,7 @@ DistNestT rep m (Lambda rep) soacsLambda lam = do onLambda <- asks distOnSOACSLambda- fst <$> runBinder (onLambda lam)+ fst <$> runBuilder (onLambda lam) newtype DistNestT rep m a = DistNestT (ReaderT (DistEnv rep m) (WriterT (DistRes rep) m) a)@@ -178,9 +178,8 @@ -- There may be a few final targets remaining - these correspond to -- arrays that are identity mapped, and must have statements -- inserted here.- return $- unPostStms (accPostStms res)- <> identityStms (outerTarget $ distTargets acc)+ pure $+ unPostStms (accPostStms res) <> identityStms (outerTarget $ distTargets acc) where outermost = nestingLoop $ case distNest env of@@ -191,14 +190,13 @@ loopNestingParamsAndArrs outermost identityStms (rem_pat, res) =- stmsFromList $ zipWith identityStm (patternValueElements rem_pat) res- identityStm pe (Var v)+ stmsFromList $ zipWith identityStm (patElems rem_pat) res+ identityStm pe (SubExpRes cs (Var v)) | Just arr <- lookup v params_to_arrs =- Let (Pattern [] [pe]) (defAux ()) $ BasicOp $ Copy arr- identityStm pe se =- Let (Pattern [] [pe]) (defAux ()) $- BasicOp $- Replicate (Shape [loopNestingWidth outermost]) se+ certify cs $ Let (Pat [pe]) (defAux ()) $ BasicOp $ Copy arr+ identityStm pe (SubExpRes cs se) =+ certify cs . Let (Pat [pe]) (defAux ()) . BasicOp $+ Replicate (Shape [loopNestingWidth outermost]) se addPostStms :: Monad m => PostStms rep -> DistNestT rep m () addPostStms ks = tell $ mempty {accPostStms = ks}@@ -220,7 +218,7 @@ distNest env } where- provided = namesFromList $ patternNames $ stmPattern stm+ provided = namesFromList $ patNames $ stmPat stm leavingNesting :: (MonadFreshNames m, DistRep rep) =>@@ -248,10 +246,10 @@ Lambda { lambdaParams = used_params, lambdaBody = body,- lambdaReturnType = map rowType $ patternTypes pat+ lambdaReturnType = map rowType $ patTypes pat } stms <-- runBinder_ . auxing aux . FOT.transformSOAC pat $+ runBuilder_ . auxing aux . FOT.transformSOAC pat $ Screma w used_arrs $ mapSOAC lam' return $ acc {distTargets = newtargets, distStms = stms}@@ -264,22 +262,20 @@ aux = loopNestingAux inner_nesting inps = loopNestingParamsAndArrs inner_nesting - remnantStm pe (Var v)+ remnantStm pe (SubExpRes cs (Var v)) | Just (_, arr) <- find ((== v) . paramName . fst) inps =- Let (Pattern [] [pe]) aux $- BasicOp $ Copy arr- remnantStm pe se =- Let (Pattern [] [pe]) aux $- BasicOp $ Replicate (Shape [w]) se+ certify cs $ Let (Pat [pe]) aux $ BasicOp $ Copy arr+ remnantStm pe (SubExpRes cs se) =+ certify cs $ Let (Pat [pe]) aux $ BasicOp $ Replicate (Shape [w]) se stms =- stmsFromList $ zipWith remnantStm (patternElements pat) res+ stmsFromList $ zipWith remnantStm (patElems pat) res return $ acc {distTargets = newtargets, distStms = stms} mapNesting :: (MonadFreshNames m, DistRep rep) =>- PatternT Type ->+ PatT Type -> StmAux () -> SubExp -> Lambda SOACS ->@@ -325,8 +321,8 @@ isMap BasicOp {} = False isMap Apply {} = False isMap If {} = False- isMap (DoLoop _ _ ForLoop {} body) = bodyContainsParallelism body- isMap (DoLoop _ _ WhileLoop {} _) = False+ isMap (DoLoop _ ForLoop {} body) = bodyContainsParallelism body+ isMap (DoLoop _ WhileLoop {} _) = False isMap (WithAcc _ lam) = bodyContainsParallelism $ lambdaBody lam isMap Op {} = True @@ -344,7 +340,7 @@ onStms acc (Let pat (StmAux cs _ _) (Op (Stream w arrs Sequential accs lam)) : stms) = do types <- asksScope scopeForSOACs stream_stms <-- snd <$> runBinderT (sequentialStreamWholeArray pat w accs lam arrs) types+ snd <$> runBuilderT (sequentialStreamWholeArray pat w accs lam arrs) types (_, stream_stms') <- runReaderT (copyPropagateInStms simpleSOACS types stream_stms) types onStms acc $ stmsToList (fmap (certify cs) stream_stms') ++ stms@@ -375,7 +371,7 @@ maybeDistributeStm (Let pat aux (Op soac)) acc | "sequential_outer" `inAttrs` stmAuxAttrs aux = distributeMapBodyStms acc . fmap (certify (stmAuxCerts aux))- =<< runBinder_ (FOT.transformSOAC pat soac)+ =<< runBuilder_ (FOT.transformSOAC pat soac) maybeDistributeStm stm@(Let pat _ (Op (Screma w arrs form))) acc | Just lam <- isMapSOAC form = -- Only distribute inside the map if we can distribute everything@@ -383,8 +379,8 @@ distributeIfPossible acc >>= \case Nothing -> addStmToAcc stm acc Just acc' -> distribute =<< onInnerMap (MapLoop pat (stmAux stm) w lam arrs) acc'-maybeDistributeStm bnd@(Let pat aux (DoLoop [] val form@ForLoop {} body)) acc- | null (patternContextElements pat),+maybeDistributeStm bnd@(Let pat aux (DoLoop merge form@ForLoop {} body)) acc+ | not $ any (`nameIn` freeIn pat) $ patNames pat, bodyContainsParallelism body = distributeSingleStm acc bnd >>= \case Just (kernels, res, nest, acc')@@ -411,13 +407,13 @@ stms <- (`runReaderT` types) $ fmap snd . simplifyStms- =<< interchangeLoops nest' (SeqLoop perm pat val form body)+ =<< interchangeLoops nest' (SeqLoop perm pat merge form body) onTopLevelStms stms return acc' _ -> addStmToAcc bnd acc maybeDistributeStm stm@(Let pat _ (If cond tbranch fbranch ret)) acc- | null (patternContextElements pat),+ | not $ any (`nameIn` freeIn pat) $ patNames pat, bodyContainsParallelism tbranch || bodyContainsParallelism fbranch || not (all primType (ifReturns ret)) = distributeSingleStm acc stm >>= \case@@ -468,7 +464,7 @@ | Just [Reduce comm lam nes] <- isReduceSOAC form, Just m <- irwim pat w comm lam $ zip nes arrs = do types <- asksScope scopeForSOACs- (_, bnds) <- runBinderT (auxing aux m) types+ (_, bnds) <- runBuilderT (auxing aux m) types distributeMapBodyStms acc bnds -- Parallelise segmented scatters.@@ -500,23 +496,17 @@ -- Parallelise Index slices if the result is going to be returned -- directly from the kernel. This is because we would otherwise have -- to sequentialise writing the result, which may be costly.-maybeDistributeStm- stm@( Let- (Pattern [] [pe])- aux- (BasicOp (Index arr slice))- )- acc- | not $ null $ sliceDims slice,- Var (patElemName pe) `elem` snd (innerTarget (distTargets acc)) =- distributeSingleStm acc stm >>= \case- Just (kernels, _res, nest, acc') ->- localScope (typeEnvFromDistAcc acc') $ do- addPostStms kernels- postStm =<< segmentedGatherKernel nest (stmAuxCerts aux) arr slice- return acc'- _ ->- addStmToAcc stm acc+maybeDistributeStm stm@(Let (Pat [pe]) aux (BasicOp (Index arr slice))) acc+ | not $ null $ sliceDims slice,+ Var (patElemName pe) `elem` map resSubExp (snd (innerTarget (distTargets acc))) =+ distributeSingleStm acc stm >>= \case+ Just (kernels, _res, nest, acc') ->+ localScope (typeEnvFromDistAcc acc') $ do+ addPostStms kernels+ postStm =<< segmentedGatherKernel nest (stmAuxCerts aux) arr slice+ return acc'+ _ ->+ addStmToAcc stm acc -- If the scan can be distributed by itself, we will turn it into a -- segmented scan. --@@ -571,20 +561,19 @@ -- anything, so split it up and try again. scope <- asksScope scopeForSOACs distributeMapBodyStms acc . fmap (certify cs) . snd- =<< runBinderT (dissectScrema pat w form arrs) scope+ =<< runBuilderT (dissectScrema pat w form arrs) scope maybeDistributeStm (Let pat aux (BasicOp (Replicate (Shape (d : ds)) v))) acc- | [t] <- patternTypes pat = do+ | [t] <- patTypes pat = do tmp <- newVName "tmp" let rowt = rowType t newbnd = Let pat aux $ Op $ Screma d [] $ mapSOAC lam tmpbnd =- Let (Pattern [] [PatElem tmp rowt]) aux $- BasicOp $ Replicate (Shape ds) v+ Let (Pat [PatElem tmp rowt]) aux $ BasicOp $ Replicate (Shape ds) v lam = Lambda { lambdaReturnType = [rowt], lambdaParams = [],- lambdaBody = mkBody (oneStm tmpbnd) [Var tmp]+ lambdaBody = mkBody (oneStm tmpbnd) [varRes tmp] } maybeDistributeStm newbnd acc maybeDistributeStm stm@(Let _ aux (BasicOp (Copy stm_arr))) acc =@@ -592,7 +581,7 @@ return $ oneStm $ Let outerpat aux $ BasicOp $ Copy arr -- Opaques are applied to the full array, because otherwise they can -- drastically inhibit parallelisation in some cases.-maybeDistributeStm stm@(Let (Pattern [] [pe]) aux (BasicOp (Opaque (Var stm_arr)))) acc+maybeDistributeStm stm@(Let (Pat [pe]) aux (BasicOp (Opaque _ (Var stm_arr)))) acc | not $ primType $ typeOf pe = distributeSingleUnaryStm acc stm stm_arr $ \_ outerpat arr -> return $ oneStm $ Let outerpat aux $ BasicOp $ Copy arr@@ -606,7 +595,7 @@ arr_t <- lookupType arr return $ stmsFromList- [ Let (Pattern [] [PatElem arr' arr_t]) aux $ BasicOp $ Copy arr,+ [ Let (Pat [PatElem arr' arr_t]) aux $ BasicOp $ Copy arr, Let outerpat aux $ BasicOp $ Rearrange perm' arr' ] maybeDistributeStm stm@(Let _ aux (BasicOp (Reshape reshape stm_arr))) acc =@@ -619,11 +608,11 @@ distributeSingleUnaryStm acc stm stm_arr $ \nest outerpat arr -> do let rots' = map (const $ intConst Int64 0) (kernelNestWidths nest) ++ rots return $ oneStm $ Let outerpat aux $ BasicOp $ Rotate rots' arr-maybeDistributeStm stm@(Let pat aux (BasicOp (Update arr slice (Var v)))) acc+maybeDistributeStm stm@(Let pat aux (BasicOp (Update _ arr slice (Var v)))) acc | not $ null $ sliceDims slice = distributeSingleStm acc stm >>= \case Just (kernels, res, nest, acc')- | res == map Var (patternNames $ stmPattern stm),+ | map resSubExp res == map Var (patNames $ stmPat stm), Just (perm, pat_unused) <- permutationAndMissing pat res -> do addPostStms kernels localScope (typeEnvFromDistAcc acc') $ do@@ -654,19 +643,19 @@ DistAcc rep -> Stm SOACS -> VName ->- (KernelNest -> PatternT Type -> VName -> DistNestT rep m (Stms rep)) ->+ (KernelNest -> PatT Type -> VName -> DistNestT rep m (Stms rep)) -> DistNestT rep m (DistAcc rep) distributeSingleUnaryStm acc stm stm_arr f = distributeSingleStm acc stm >>= \case Just (kernels, res, nest, acc')- | res == map Var (patternNames $ stmPattern stm),+ | map resSubExp res == map Var (patNames $ stmPat stm), (outer, _) <- nest, [(arr_p, arr)] <- loopNestingParamsAndArrs outer, boundInKernelNest nest `namesIntersection` freeIn stm == oneName (paramName arr_p), perfectlyMapped arr nest -> do addPostStms kernels- let outerpat = loopNestingPattern $ fst nest+ let outerpat = loopNestingPat $ fst nest localScope (typeEnvFromDistAcc acc') $ do postStm =<< f nest outerpat arr return acc'@@ -694,7 +683,7 @@ mkSegLevel = do mk_lvl <- asks distSegLevel return $ \w desc r -> do- (lvl, stms) <- lift $ liftInner $ runBinderT' $ mk_lvl w desc r+ (lvl, stms) <- lift $ liftInner $ runBuilderT' $ mk_lvl w desc r addStms stms return lvl @@ -754,8 +743,8 @@ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] ->- PatternT Type ->- Certificates ->+ PatT Type ->+ Certs -> SubExp -> Lambda rep -> [VName] ->@@ -791,13 +780,9 @@ drop (sum indexes) $ lambdaReturnType lam (is, vs) = splitAt (sum indexes) $ bodyResult $ lambdaBody lam - -- Maybe add certificates to the indices.- (is', k_body_stms) <- runBinder $ do+ (is', k_body_stms) <- runBuilder $ do addStms $ bodyStms $ lambdaBody lam- forM is $ \i ->- if cs == mempty- then return i- else certifying cs $ letSubExp "scatter_i" $ BasicOp $ SubExp i+ pure is let k_body = groupScatterResults (zip3 as_ws as_ns as_inps) (is' ++ vs)@@ -810,13 +795,12 @@ (k, k_bnds) <- mapKernel mk_lvl ispace kernel_inps' rts k_body - traverse renameStm <=< runBinder_ $ do+ traverse renameStm <=< runBuilder_ $ do addStms k_bnds let pat =- Pattern [] $- rearrangeShape perm $- patternValueElements $ loopNestingPattern $ fst nest+ Pat . rearrangeShape perm $+ patElems $ loopNestingPat $ fst nest letBind pat $ Op $ segOp k where@@ -826,9 +810,14 @@ inPlaceReturn ispace (aw, inp, is_vs) = WriteReturns+ ( foldMap (foldMap resCerts . fst) is_vs+ <> foldMap (resCerts . snd) is_vs+ ) (Shape (init ws ++ shapeDims aw)) (kernelInputArray inp)- [(map DimFix $ map Var (init gtids) ++ is, v) | (is, v) <- is_vs]+ [ (Slice $ map DimFix $ map Var (init gtids) ++ map resSubExp is, resSubExp v)+ | (is, v) <- is_vs+ ] where (gtids, ws) = unzip ispace @@ -836,7 +825,7 @@ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] ->- Certificates ->+ Certs -> VName -> Slice SubExp -> VName ->@@ -848,14 +837,14 @@ let ispace = base_ispace ++ zip slice_gtids slice_dims - ((res_t, res), kstms) <- runBinder $ do+ ((res_t, res), kstms) <- runBuilder $ do -- Compute indexes into full array. v' <- certifying cs $- letSubExp "v" $ BasicOp $ Index v $ map (DimFix . Var) slice_gtids+ letSubExp "v" $ BasicOp $ Index v $ Slice $ map (DimFix . Var) slice_gtids slice_is <- traverse (toSubExp "index") $- fixSlice (map (fmap pe64) slice) $ map (pe64 . Var) slice_gtids+ fixSlice (fmap pe64 slice) $ map (pe64 . Var) slice_gtids let write_is = map (Var . fst) base_ispace ++ slice_is arr' =@@ -865,33 +854,32 @@ v_t <- subExpType v' return ( v_t,- WriteReturns (arrayShape arr_t) arr' [(map DimFix write_is, v')]+ WriteReturns mempty (arrayShape arr_t) arr' [(Slice $ map DimFix write_is, v')] ) -- Remove unused kernel inputs, since some of these might -- reference the array we are scattering into. let kernel_inps' =- filter ((`nameIn` freeIn kstms) . kernelInputName) kernel_inps+ filter ((`nameIn` (freeIn kstms <> freeIn res)) . kernelInputName) kernel_inps mk_lvl <- mkSegLevel (k, prestms) <- mapKernel mk_lvl ispace kernel_inps' [res_t] $ KernelBody () kstms [res] - traverse renameStm <=< runBinder_ $ do+ traverse renameStm <=< runBuilder_ $ do addStms prestms let pat =- Pattern [] $- rearrangeShape perm $- patternValueElements $ loopNestingPattern $ fst nest+ Pat . rearrangeShape perm $+ patElems $ loopNestingPat $ fst nest letBind pat $ Op $ segOp k segmentedGatherKernel :: (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest ->- Certificates ->+ Certs -> VName -> Slice SubExp -> DistNestT rep m (Stms rep)@@ -902,25 +890,24 @@ (base_ispace, kernel_inps) <- flatKernel nest let ispace = base_ispace ++ zip slice_gtids slice_dims - ((res_t, res), kstms) <- runBinder $ do+ ((res_t, res), kstms) <- runBuilder $ do -- Compute indexes into full array. slice'' <-- subExpSlice $- sliceSlice (primExpSlice slice) $- primExpSlice $ map (DimFix . Var) slice_gtids+ subExpSlice . sliceSlice (primExpSlice slice) $+ primExpSlice $ Slice $ map (DimFix . Var) slice_gtids v' <- certifying cs $ letSubExp "v" $ BasicOp $ Index arr slice'' v_t <- subExpType v'- return (v_t, Returns ResultMaySimplify v')+ return (v_t, Returns ResultMaySimplify mempty v') mk_lvl <- mkSegLevel (k, prestms) <- mapKernel mk_lvl ispace kernel_inps [res_t] $ KernelBody () kstms [res] - traverse renameStm <=< runBinder_ $ do+ traverse renameStm <=< runBuilder_ $ do addStms prestms - let pat = Pattern [] $ patternValueElements $ loopNestingPattern $ fst nest+ let pat = Pat $ patElems $ loopNestingPat $ fst nest letBind pat $ Op $ segOp k @@ -928,7 +915,7 @@ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] ->- Certificates ->+ Certs -> SubExp -> [SOACS.HistOp SOACS] -> Lambda rep ->@@ -940,9 +927,8 @@ -- scan. (ispace, inputs) <- flatKernel nest let orig_pat =- Pattern [] $- rearrangeShape perm $- patternValueElements $ loopNestingPattern $ fst nest+ Pat . rearrangeShape perm $+ patElems $ loopNestingPat $ fst nest -- The input/output arrays _must_ correspond to some kernel input, -- or else the original nested Hist would have been ill-typed.@@ -955,9 +941,9 @@ mk_lvl <- asks distSegLevel onLambda <- asks distOnSOACSLambda- let onLambda' = fmap fst . runBinder . onLambda+ let onLambda' = fmap fst . runBuilder . onLambda liftInner $- runBinderT'_ $ do+ runBuilderT'_ $ do -- It is important not to launch unnecessarily many threads for -- histograms, because it may mean we unnecessarily need to reduce -- subhistograms as well.@@ -970,19 +956,19 @@ bad = error "Ill-typed nested Hist encountered." histKernel ::- (MonadBinder m, DistRep (Rep m)) =>+ (MonadBuilder m, DistRep (Rep m)) => (Lambda SOACS -> m (Lambda (Rep m))) -> SegOpLevel (Rep m) ->- PatternT Type ->+ PatT Type -> [(VName, SubExp)] -> [KernelInput] ->- Certificates ->+ Certs -> SubExp -> [SOACS.HistOp SOACS] -> Lambda (Rep m) -> [VName] -> m (Stms (Rep m))-histKernel onLambda lvl orig_pat ispace inputs cs hist_w ops lam arrs = runBinderT'_ $ do+histKernel onLambda lvl orig_pat ispace inputs cs hist_w ops lam arrs = runBuilderT'_ $ do ops' <- forM ops $ \(SOACS.HistOp num_bins rf dests nes op) -> do (op', nes', shape) <- determineReduceOp op nes op'' <- lift $ onLambda op'@@ -996,7 +982,7 @@ =<< segHist lvl orig_pat hist_w ispace inputs' ops' lam arrs determineReduceOp ::- MonadBinder m =>+ MonadBuilder m => Lambda SOACS -> [SubExp] -> m (Lambda SOACS, [SubExp], Shape)@@ -1019,9 +1005,9 @@ isVectorMap :: Lambda SOACS -> (Shape, Lambda SOACS) isVectorMap lam- | [Let (Pattern [] pes) _ (Op (Screma w arrs form))] <-+ | [Let (Pat pes) _ (Op (Screma w arrs form))] <- stmsToList $ bodyStms $ lambdaBody lam,- bodyResult (lambdaBody lam) == map (Var . patElemName) pes,+ map resSubExp (bodyResult (lambdaBody lam)) == map (Var . patElemName) pes, Just map_lam <- isMapSOAC form, arrs == map paramName (lambdaParams lam) = let (shape, lam') = isVectorMap map_lam@@ -1075,12 +1061,12 @@ Names -> [SubExp] -> [VName] ->- ( PatternT Type ->+ ( PatT Type -> [(VName, SubExp)] -> [KernelInput] -> [SubExp] -> [VName] ->- BinderT rep m ()+ BuilderT rep m () ) -> DistNestT rep m (Maybe (Stms rep)) isSegmentedOp nest perm free_in_op _free_in_fold_op nes arrs m = runMaybeT $ do@@ -1129,22 +1115,21 @@ lift $ liftInner $- runBinderT'_ $ do+ runBuilderT'_ $ do nested_arrs <- sequence mk_arrs let pat =- Pattern [] $- rearrangeShape perm $- patternValueElements $ loopNestingPattern $ fst nest+ Pat . rearrangeShape perm $+ patElems $ loopNestingPat $ fst nest m pat ispace kernel_inps nes' nested_arrs -permutationAndMissing :: PatternT Type -> [SubExp] -> Maybe ([Int], [PatElemT Type])-permutationAndMissing pat res = do- let pes = patternValueElements pat- (_used, unused) =+permutationAndMissing :: PatT Type -> Result -> Maybe ([Int], [PatElemT Type])+permutationAndMissing (Pat pes) res = do+ let (_used, unused) = partition ((`nameIn` freeIn res) . patElemName) pes- res_expanded = res ++ map (Var . patElemName) unused+ res' = map resSubExp res+ res_expanded = res' ++ map (Var . patElemName) unused perm <- map (Var . patElemName) pes `isPermutationOf` res_expanded return (perm, unused) @@ -1167,9 +1152,8 @@ pes' <- mapM (expandPatElemWith dims) pes return nest- { loopNestingPattern =- Pattern [] $- patternElements (loopNestingPattern nest) <> pes'+ { loopNestingPat =+ Pat $ patElems (loopNestingPat nest) <> pes' } expandPatElemWith dims pe = do@@ -1182,7 +1166,7 @@ kernelOrNot :: (MonadFreshNames m, DistRep rep) =>- Certificates ->+ Certs -> Stm SOACS -> DistAcc rep -> PostStms rep ->
src/Futhark/Pass/ExtractKernels/Distribution.hs view
@@ -45,6 +45,7 @@ import Control.Monad.RWS.Strict import Control.Monad.Trans.Maybe+import Data.Bifunctor (second) import Data.Foldable import Data.List (elemIndex, sortOn) import qualified Data.Map.Strict as M@@ -64,7 +65,7 @@ import Futhark.Util import Futhark.Util.Log -type Target = (PatternT Type, Result)+type Target = (PatT Type, Result) -- | First pair element is the very innermost ("current") target. In -- the list, the outermost target comes first. Invariant: Every@@ -101,8 +102,8 @@ pushInnerTarget (pat, res) (Targets inner_target targets) = Targets (pat', res') (targets ++ [inner_target]) where- (pes', res') = unzip $ filter (used . fst) $ zip (patternElements pat) res- pat' = Pattern [] pes'+ (pes', res') = unzip $ filter (used . fst) $ zip (patElems pat) res+ pat' = Pat pes' inner_used = freeIn $ snd inner_target used pe = patElemName pe `nameIn` inner_used @@ -113,13 +114,13 @@ [] -> Nothing targetScope :: DistRep rep => Target -> Scope rep-targetScope = scopeOfPattern . fst+targetScope = scopeOfPat . fst targetsScope :: DistRep rep => Targets -> Scope rep targetsScope (Targets t ts) = mconcat $ map targetScope $ t : ts data LoopNesting = MapNesting- { loopNestingPattern :: PatternT Type,+ { loopNestingPat :: PatT Type, loopNestingAux :: StmAux (), loopNestingWidth :: SubExp, loopNestingParamsAndArrs :: [(Param Type, VName)]@@ -202,7 +203,7 @@ -- list, also taking care to swap patterns if necessary. pushKernelNesting :: Target -> LoopNesting -> KernelNest -> KernelNest pushKernelNesting target newnest (nest, nests) =- ( fixNestingPatternOrder newnest target (loopNestingPattern nest),+ ( fixNestingPatOrder newnest target (loopNestingPat nest), nest : nests ) @@ -211,20 +212,20 @@ -- (non-permuted compared to what is expected by the outer nests). pushInnerKernelNesting :: Target -> LoopNesting -> KernelNest -> KernelNest pushInnerKernelNesting target newnest (nest, nests) =- (nest, nests ++ [fixNestingPatternOrder newnest target (loopNestingPattern innermost)])+ (nest, nests ++ [fixNestingPatOrder newnest target (loopNestingPat innermost)]) where innermost = case reverse nests of [] -> nest n : _ -> n -fixNestingPatternOrder :: LoopNesting -> Target -> PatternT Type -> LoopNesting-fixNestingPatternOrder nest (_, res) inner_pat =- nest {loopNestingPattern = basicPattern [] pat'}+fixNestingPatOrder :: LoopNesting -> Target -> PatT Type -> LoopNesting+fixNestingPatOrder nest (_, res) inner_pat =+ nest {loopNestingPat = basicPat pat'} where- pat = loopNestingPattern nest+ pat = loopNestingPat nest pat' = map fst fixed_target- fixed_target = sortOn posInInnerPat $ zip (patternValueIdents pat) res- posInInnerPat (_, Var v) = fromMaybe 0 $ elemIndex v $ patternNames inner_pat+ fixed_target = sortOn posInInnerPat $ zip (patIdents pat) res+ posInInnerPat (_, SubExpRes _ (Var v)) = fromMaybe 0 $ elemIndex v $ patNames inner_pat posInInnerPat _ = 0 newKernel :: LoopNesting -> KernelNest@@ -254,18 +255,19 @@ KernelNest -> Body rep -> m (Stm rep, Stms rep)-constructKernel mk_lvl kernel_nest inner_body = runBinderT' $ do+constructKernel mk_lvl kernel_nest inner_body = runBuilderT' $ do (ispace, inps) <- flatKernel kernel_nest let aux = loopNestingAux first_nest ispace_scope = M.fromList $ zip (map fst ispace) $ repeat $ IndexName Int64- pat = loopNestingPattern first_nest- rts = map (stripArray (length ispace)) $ patternTypes pat+ pat = loopNestingPat first_nest+ rts = map (stripArray (length ispace)) $ patTypes pat inner_body' <- fmap (uncurry (flip (KernelBody ()))) $- runBinder $+ runBuilder $ localScope ispace_scope $ do mapM_ readKernelInput $ filter inputIsUsed inps- map (Returns ResultMaySimplify) <$> bodyBind inner_body+ res <- bodyBind inner_body+ forM res $ \(SubExpRes cs se) -> pure $ Returns ResultMaySimplify cs se (segop, aux_stms) <- lift $ mapKernel mk_lvl ispace [] rts inner_body' @@ -327,8 +329,8 @@ distributionExpandTarget :: Target -> Target } -distributionInnerPattern :: DistributionBody -> PatternT Type-distributionInnerPattern = fst . innerTarget . distributionTarget+distributionInnerPat :: DistributionBody -> PatT Type+distributionInnerPat = fst . innerTarget . distributionTarget distributionBodyFromStms :: ASTRep rep =>@@ -382,7 +384,7 @@ distributeAtNesting :: Nesting ->- PatternT Type ->+ PatT Type -> (LoopNesting -> KernelNest, Names) -> M.Map VName Ident -> [Ident] ->@@ -431,9 +433,7 @@ ) let free_arrs_pat =- basicPattern [] $- map snd $- filter fst $ zip bind_in_target free_arrs+ basicPat $ map snd $ filter fst $ zip bind_in_target free_arrs free_params_pat = map snd $ filter fst $ zip bind_in_target free_params @@ -459,7 +459,7 @@ return ( add_to_kernel nest'', free_in_kernel'',- addTarget (free_arrs_pat, map (Var . paramName) free_params_pat)+ addTarget (free_arrs_pat, varsRes $ map paramName free_params_pat) ) recurse ::@@ -468,7 +468,7 @@ recurse [] = distributeAtNesting inner_nest- (distributionInnerPattern distrib_body)+ (distributionInnerPat distrib_body) ( newKernel, distributionFreeInBody distrib_body `namesIntersection` bound_in_nest )@@ -480,7 +480,7 @@ let (pat', res', identity_map, expand_target) = removeIdentityMappingFromNesting- (namesFromList $ patternNames $ loopNestingPattern outer)+ (namesFromList $ patNames $ loopNestingPat outer) pat res @@ -491,7 +491,7 @@ kernel_free ) identity_map- (patternIdents $ fst $ outerTarget kernel_targets)+ (patIdents $ fst $ outerTarget kernel_targets) ((`pushOuterTarget` kernel_targets) . expand_target) removeUnusedNestingParts :: Names -> LoopNesting -> LoopNesting@@ -506,41 +506,39 @@ removeIdentityMappingGeneral :: Names ->- PatternT Type ->+ PatT Type -> Result ->- ( PatternT Type,+ ( PatT Type, Result, M.Map VName Ident, Target -> Target ) removeIdentityMappingGeneral bound pat res = let (identities, not_identities) =- mapEither isIdentity $ zip (patternElements pat) res+ mapEither isIdentity $ zip (patElems pat) res (not_identity_patElems, not_identity_res) = unzip not_identities (identity_patElems, identity_res) = unzip identities expandTarget (tpat, tres) =- ( Pattern [] $ patternElements tpat ++ identity_patElems,- tres ++ map Var identity_res+ ( Pat $ patElems tpat ++ identity_patElems,+ tres ++ map (uncurry SubExpRes . second Var) identity_res ) identity_map =- M.fromList $- zip identity_res $- map patElemIdent identity_patElems- in ( Pattern [] not_identity_patElems,+ M.fromList $ zip (map snd identity_res) $ map patElemIdent identity_patElems+ in ( Pat not_identity_patElems, not_identity_res, identity_map, expandTarget ) where- isIdentity (patElem, Var v)- | not (v `nameIn` bound) = Left (patElem, v)+ isIdentity (patElem, SubExpRes cs (Var v))+ | not (v `nameIn` bound) = Left (patElem, (cs, v)) isIdentity x = Right x removeIdentityMappingFromNesting :: Names ->- PatternT Type ->+ PatT Type -> Result ->- ( PatternT Type,+ ( PatT Type, Result, M.Map VName Ident, Target -> Target
src/Futhark/Pass/ExtractKernels/ISRWIM.hs view
@@ -18,8 +18,8 @@ -- | Interchange Scan With Inner Map. Tries to turn a @scan(map)@ into a -- @map(scan) iswim ::- (MonadBinder m, Rep m ~ SOACS) =>- Pattern ->+ (MonadBuilder m, Rep m ~ SOACS) =>+ Pat -> SubExp -> Lambda -> [(SubExp, VName)] ->@@ -51,38 +51,33 @@ let map_body = mkBody ( oneStm $- Let (setPatternOuterDimTo w map_pat) (defAux ()) $+ Let (setPatOuterDimTo w map_pat) (defAux ()) $ Op $ Screma w scan_arrs scan_soac )- $ map Var $ patternNames map_pat+ $ varsRes $ patNames map_pat map_fun' = Lambda map_params map_body map_rettype res_pat' <-- fmap (basicPattern []) $+ fmap basicPat $ mapM (newIdent' (<> "_transposed") . transposeIdentType) $- patternValueIdents res_pat+ patIdents res_pat addStm $ Let res_pat' (StmAux map_cs mempty ()) $ Op $ Screma map_w map_arrs' (mapSOAC map_fun') - forM_- ( zip- (patternValueIdents res_pat)- (patternValueIdents res_pat')- )- $ \(to, from) -> do- let perm = [1, 0] ++ [2 .. arrayRank (identType from) -1]- addStm $- Let (basicPattern [] [to]) (defAux ()) $- BasicOp $ Rearrange perm $ identName from+ forM_ (zip (patIdents res_pat) (patIdents res_pat')) $ \(to, from) -> do+ let perm = [1, 0] ++ [2 .. arrayRank (identType from) -1]+ addStm $+ Let (basicPat [to]) (defAux ()) $+ BasicOp $ Rearrange perm $ identName from | otherwise = Nothing -- | Interchange Reduce With Inner Map. Tries to turn a @reduce(map)@ into a -- @map(reduce) irwim ::- (MonadBinder m, Rep m ~ SOACS) =>- Pattern ->+ (MonadBuilder m, Rep m ~ SOACS) =>+ Pat -> SubExp -> Commutativity -> Lambda ->@@ -114,7 +109,7 @@ red_rettype = lambdaReturnType map_fun red_fun' = Lambda red_params red_body red_rettype red_input' = zip accs' $ map paramName map_params- red_pat = stripPatternOuterDim map_pat+ red_pat = stripPatOuterDim map_pat map_body <- case irwim red_pat w comm red_fun' red_input' of@@ -126,10 +121,10 @@ Let red_pat (defAux ()) $ Op $ Screma w (map snd red_input') reduce_soac )- $ map Var $ patternNames map_pat+ $ varsRes $ patNames map_pat Just m -> localScope (scopeOfLParams map_params) $ do map_body_bnds <- collectStms_ m- return $ mkBody map_body_bnds $ map Var $ patternNames map_pat+ return $ mkBody map_body_bnds $ varsRes $ patNames map_pat let map_fun' = Lambda map_params map_body map_rettype @@ -142,12 +137,12 @@ -- does that map look like? rwimPossible :: Lambda ->- Maybe (Pattern, Certificates, SubExp, Lambda)+ Maybe (Pat, Certs, SubExp, Lambda) rwimPossible fun | Body _ stms res <- lambdaBody fun, [bnd] <- stmsToList stms, -- Body has a single binding- map_pat <- stmPattern bnd,- map Var (patternNames map_pat) == res, -- Returned verbatim+ map_pat <- stmPat bnd,+ map Var (patNames map_pat) == map resSubExp res, -- Returned verbatim Op (Screma map_w map_arrs form) <- stmExp bnd, Just map_fun <- isMapSOAC form, map paramName (lambdaParams fun) == map_arrs =@@ -155,7 +150,7 @@ | otherwise = Nothing -transposedArrays :: MonadBinder m => [VName] -> m [VName]+transposedArrays :: MonadBuilder m => [VName] -> m [VName] transposedArrays arrs = forM arrs $ \arr -> do t <- lookupType arr let perm = [1, 0] ++ [2 .. arrayRank t -1]@@ -180,9 +175,9 @@ setOuterDimTo w t = arrayOfRow (rowType t) w -setPatternOuterDimTo :: SubExp -> Pattern -> Pattern-setPatternOuterDimTo w pat =- basicPattern [] $ map (setIdentOuterDimTo w) $ patternValueIdents pat+setPatOuterDimTo :: SubExp -> Pat -> Pat+setPatOuterDimTo w pat =+ basicPat $ map (setIdentOuterDimTo w) $ patIdents pat transposeIdentType :: Ident -> Ident transposeIdentType ident =@@ -192,6 +187,6 @@ stripIdentOuterDim ident = ident {identType = rowType $ identType ident} -stripPatternOuterDim :: Pattern -> Pattern-stripPatternOuterDim pat =- basicPattern [] $ map stripIdentOuterDim $ patternValueIdents pat+stripPatOuterDim :: Pat -> Pat+stripPatOuterDim pat =+ basicPat $ map stripIdentOuterDim $ patIdents pat
src/Futhark/Pass/ExtractKernels/Interchange.hs view
@@ -33,14 +33,14 @@ -- | An encoding of a sequential do-loop with no existential context, -- alongside its result pattern.-data SeqLoop = SeqLoop [Int] Pattern [(FParam, SubExp)] (LoopForm SOACS) Body+data SeqLoop = SeqLoop [Int] Pat [(FParam, SubExp)] (LoopForm SOACS) Body seqLoopStm :: SeqLoop -> Stm seqLoopStm (SeqLoop _ pat merge form body) =- Let pat (defAux ()) $ DoLoop [] merge form body+ Let pat (defAux ()) $ DoLoop merge form body interchangeLoop ::- (MonadBinder m, LocalScope SOACS m) =>+ (MonadBuilder m, LocalScope SOACS m) => (VName -> Maybe VName) -> SeqLoop -> LoopNesting ->@@ -54,13 +54,11 @@ mapM expand merge let loop_pat_expanded =- Pattern [] $ map expandPatElem $ patternElements loop_pat+ Pat $ map expandPatElem $ patElems loop_pat new_params =- [ Param pname $ fromDecl ptype- | (Param pname ptype, _) <- merge- ]+ [Param pname $ fromDecl ptype | (Param pname ptype, _) <- merge] new_arrs = map (paramName . fst) merge_expanded- rettype = map rowType $ patternTypes loop_pat_expanded+ rettype = map rowType $ patTypes loop_pat_expanded -- If the map consumes something that is bound outside the loop -- (i.e. is not a merge parameter), we have to copy() it. As a@@ -68,7 +66,7 @@ -- it is not used anymore. This might happen if the parameter was -- used just as the inital value of a merge parameter. ((params', arrs'), pre_copy_bnds) <-- runBinder $+ runBuilder $ localScope (scopeOfLParams new_params) $ unzip . catMaybes <$> mapM copyOrRemoveParam params_and_arrs @@ -76,8 +74,8 @@ map_bnd = Let loop_pat_expanded aux $ Op $ Screma w (arrs' <> new_arrs) (mapSOAC lam)- res = map Var $ patternNames loop_pat_expanded- pat' = Pattern [] $ rearrangeShape perm $ patternValueElements pat+ res = varsRes $ patNames loop_pat_expanded+ pat' = Pat $ rearrangeShape perm $ patElems pat return $ SeqLoop perm pat' merge_expanded form $@@ -122,7 +120,7 @@ m (Stms SOACS) interchangeLoops nest loop = do (loop', bnds) <-- runBinder $+ runBuilder $ foldM (interchangeLoop isMapParameter) loop $ reverse $ kernelNestLoops nest return $ bnds <> oneStm (seqLoopStm loop')@@ -132,14 +130,14 @@ find ((== v) . paramName . fst) $ concatMap loopNestingParamsAndArrs $ kernelNestLoops nest -data Branch = Branch [Int] Pattern SubExp Body Body (IfDec (BranchType SOACS))+data Branch = Branch [Int] Pat SubExp Body Body (IfDec (BranchType SOACS)) branchStm :: Branch -> Stm branchStm (Branch _ pat cond tbranch fbranch ret) = Let pat (defAux ()) $ If cond tbranch fbranch ret interchangeBranch1 ::- (MonadBinder m) =>+ (MonadBuilder m) => Branch -> LoopNesting -> m Branch@@ -147,24 +145,24 @@ (Branch perm branch_pat cond tbranch fbranch (IfDec ret if_sort)) (MapNesting pat aux w params_and_arrs) = do let ret' = map (`arrayOfRow` Free w) ret- pat' = Pattern [] $ rearrangeShape perm $ patternValueElements pat+ pat' = Pat $ rearrangeShape perm $ patElems pat (params, arrs) = unzip params_and_arrs- lam_ret = rearrangeShape perm $ map rowType $ patternTypes pat+ lam_ret = rearrangeShape perm $ map rowType $ patTypes pat branch_pat' =- Pattern [] $ map (fmap (`arrayOfRow` w)) $ patternElements branch_pat+ Pat $ map (fmap (`arrayOfRow` w)) $ patElems branch_pat mkBranch branch = (renameBody =<<) $ do let lam = Lambda params branch lam_ret- res = map Var $ patternNames branch_pat'+ res = varsRes $ patNames branch_pat' map_bnd = Let branch_pat' aux $ Op $ Screma w arrs $ mapSOAC lam return $ mkBody (oneStm map_bnd) res tbranch' <- mkBranch tbranch fbranch' <- mkBranch fbranch return $- Branch [0 .. patternSize pat -1] pat' cond tbranch' fbranch' $+ Branch [0 .. patSize pat -1] pat' cond tbranch' fbranch' $ IfDec ret' if_sort interchangeBranch ::@@ -174,18 +172,18 @@ m (Stms SOACS) interchangeBranch nest loop = do (loop', bnds) <-- runBinder $ foldM interchangeBranch1 loop $ reverse $ kernelNestLoops nest+ runBuilder $ foldM interchangeBranch1 loop $ reverse $ kernelNestLoops nest return $ bnds <> oneStm (branchStm loop') data WithAccStm- = WithAccStm [Int] Pattern [(Shape, [VName], Maybe (Lambda, [SubExp]))] Lambda+ = WithAccStm [Int] Pat [(Shape, [VName], Maybe (Lambda, [SubExp]))] Lambda withAccStm :: WithAccStm -> Stm withAccStm (WithAccStm _ pat inputs lam) = Let pat (defAux ()) $ WithAcc inputs lam interchangeWithAcc1 ::- (MonadBinder m, Rep m ~ SOACS) =>+ (MonadBuilder m, Rep m ~ SOACS) => WithAccStm -> LoopNesting -> m WithAccStm@@ -204,10 +202,10 @@ let (params, arrs) = unzip params_and_arrs maplam_ret = lambdaReturnType acc_lam maplam = Lambda (iota_p : orig_acc_params ++ params) (lambdaBody acc_lam) maplam_ret- auxing map_aux . letTupExp' "withacc_inter" $+ auxing map_aux . fmap subExpsRes . letTupExp' "withacc_inter" $ Op $ Screma w (iota_w : map paramName acc_params ++ arrs) (mapSOAC maplam)- let pat = Pattern [] $ rearrangeShape perm $ patternValueElements map_pat- perm' = [0 .. patternSize pat -1]+ let pat = Pat $ rearrangeShape perm $ patElems map_pat+ perm' = [0 .. patSize pat -1] pure $ WithAccStm perm' pat inputs' acc_lam' where newAccLamParams ps = do@@ -284,5 +282,5 @@ m (Stms SOACS) interchangeWithAcc nest withacc = do (withacc', stms) <-- runBinder $ foldM interchangeWithAcc1 withacc $ reverse $ kernelNestLoops nest+ runBuilder $ foldM interchangeWithAcc1 withacc $ reverse $ kernelNestLoops nest return $ stms <> oneStm (withAccStm withacc')
src/Futhark/Pass/ExtractKernels/Intragroup.hs view
@@ -14,7 +14,7 @@ import qualified Data.Set as S import Futhark.Analysis.PrimExp.Convert import qualified Futhark.IR.GPU as Out-import Futhark.IR.GPU.Kernel hiding (HistOp)+import Futhark.IR.GPU.Op hiding (HistOp) import Futhark.IR.SOACS import Futhark.MonadFreshNames import Futhark.Pass.ExtractKernels.BlockedKernel@@ -56,7 +56,7 @@ (num_groups, w_stms) <- lift $- runBinder $+ runBuilder $ letSubExp "intra_num_groups" =<< foldBinOp (Mul Int64 OverflowUndef) (intConst Int64 1) (map snd ispace) @@ -80,7 +80,7 @@ fail "Irregular parallelism" ((intra_avail_par, kspace, read_input_stms), prelude_stms) <- lift $- runBinder $ do+ runBuilder $ do let foldBinOp' _ [] = eSubExp $ intConst Int64 0 foldBinOp' bop (x : xs) = foldBinOp bop x xs ws_min <-@@ -110,14 +110,14 @@ used_inps = filter inputIsUsed inps addStms w_stms- read_input_stms <- runBinder_ $ mapM readGroupKernelInput used_inps+ read_input_stms <- runBuilder_ $ mapM readGroupKernelInput used_inps space <- mkSegSpace ispace return (intra_avail_par, space, read_input_stms) let kbody' = kbody {kernelBodyStms = read_input_stms <> kernelBodyStms kbody} - let nested_pat = loopNestingPattern first_nest- rts = map (length ispace `stripArray`) $ patternTypes nested_pat+ let nested_pat = loopNestingPat first_nest+ rts = map (length ispace `stripArray`) $ patTypes nested_pat lvl = SegGroup (Count num_groups) (Count $ Var group_size) SegNoVirt kstm = Let nested_pat aux $@@ -136,7 +136,7 @@ aux = loopNestingAux first_nest readGroupKernelInput ::- (DistRep (Rep m), MonadBinder m) =>+ (DistRep (Rep m), MonadBuilder m) => KernelInput -> m () readGroupKernelInput inp@@ -161,7 +161,7 @@ mempty = IntraAcc mempty mempty mempty type IntraGroupM =- BinderT Out.GPU (RWS () IntraAcc VNameSource)+ BuilderT Out.GPU (RWS () IntraAcc VNameSource) instance MonadLogger IntraGroupM where addLog log = tell mempty {accLog = log}@@ -173,7 +173,7 @@ runIntraGroupM m = do scope <- castScope <$> askScope modifyNameSource $ \src ->- let (((), kstms), src', acc) = runRWS (runBinderT m scope) () src+ let (((), kstms), src', acc) = runRWS (runBuilderT m scope) () src in ((acc, kstms), src') parallelMin :: [SubExp] -> IntraGroupM ()@@ -195,12 +195,12 @@ let lvl' = SegThread (segNumGroups lvl) (segGroupSize lvl) SegNoVirt case e of- DoLoop ctx val form loopbody ->+ DoLoop merge form loopbody -> localScope (scopeOf form') $- localScope (scopeOfFParams $ map fst $ ctx ++ val) $ do+ localScope (scopeOfFParams $ map fst merge) $ do loopbody' <- intraGroupBody lvl loopbody certifying (stmAuxCerts aux) $- letBind pat $ DoLoop ctx val form' loopbody'+ letBind pat $ DoLoop merge form' loopbody' where form' = case form of ForLoop i it bound inps -> ForLoop i it bound inps@@ -213,7 +213,7 @@ Op soac | "sequential_outer" `inAttrs` stmAuxAttrs aux -> intraGroupStms lvl . fmap (certify (stmAuxCerts aux))- =<< runBinder_ (FOT.transformSOAC pat soac)+ =<< runBuilder_ (FOT.transformSOAC pat soac) Op (Screma w arrs form) | Just lam <- isMapSOAC form -> do let loopnest = MapNesting pat aux w $ zip (lambdaParams lam) arrs@@ -222,7 +222,7 @@ { distNest = singleNesting $ Nesting mempty loopnest, distScope =- scopeOfPattern pat+ scopeOfPat pat <> scopeForGPU (scopeOf lam) <> scope, distOnInnerMap =@@ -275,7 +275,7 @@ | chunk_size_param : _ <- lambdaParams lam -> do types <- asksScope castScope ((), stream_bnds) <-- runBinderT (sequentialStreamWholeArray pat w accs lam arrs) types+ runBuilderT (sequentialStreamWholeArray pat w accs lam arrs) types let replace (Var v) | v == paramName chunk_size_param = w replace se = se replaceSets (IntraAcc x y log) =@@ -290,18 +290,22 @@ krets = do (a_w, a, is_vs) <- groupScatterResults dests $ bodyResult $ lambdaBody lam'- return $ WriteReturns a_w a [(map DimFix is, v) | (is, v) <- is_vs]+ let cs =+ foldMap (foldMap resCerts . fst) is_vs+ <> foldMap (resCerts . snd) is_vs+ is_vs' = [(Slice $ map (DimFix . resSubExp) is, resSubExp v) | (is, v) <- is_vs]+ return $ WriteReturns cs a_w a is_vs' inputs = do (p, p_a) <- zip (lambdaParams lam') ivs return $ KernelInput (paramName p) (paramType p) p_a [Var write_i] - kstms <- runBinder_ $+ kstms <- runBuilder_ $ localScope (scopeOfSegSpace space) $ do mapM_ readKernelInput inputs addStms $ bodyStms $ lambdaBody lam' certifying (stmAuxCerts aux) $ do- let ts = zipWith (stripArray . length) dests_ws $ patternTypes pat+ let ts = zipWith (stripArray . length) dests_ws $ patTypes pat body = KernelBody () kstms krets letBind pat $ Op $ SegOp $ SegMap lvl' space ts body @@ -324,5 +328,7 @@ ( S.toList min_ws, S.toList avail_ws, log,- KernelBody () kstms $ map (Returns ResultMaySimplify) $ bodyResult body+ KernelBody () kstms $ map ret $ bodyResult body )+ where+ ret (SubExpRes cs se) = Returns ResultMaySimplify cs se
src/Futhark/Pass/ExtractKernels/StreamKernel.hs view
@@ -22,8 +22,8 @@ FunDef, LParam, Lambda,+ Pat, PatElem,- Pattern, Prog, RetType, Stm,@@ -43,7 +43,7 @@ deriving (Eq, Ord, Show) numberOfGroups ::- (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) =>+ (MonadBuilder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SubExp -> SubExp ->@@ -59,7 +59,7 @@ return (num_groups, num_threads) blockedKernelSize ::- (MonadBinder m, Rep m ~ GPU) =>+ (MonadBuilder m, Rep m ~ GPU) => String -> SubExp -> m KernelSize@@ -75,7 +75,7 @@ return $ KernelSize per_thread_elements num_threads splitArrays ::- (MonadBinder m, Rep m ~ GPU) =>+ (MonadBuilder m, Rep m ~ GPU) => VName -> [VName] -> SplitOrdering ->@@ -113,7 +113,7 @@ error "partitionChunkedKernelFoldParameters: lambda takes too few parameters" blockedPerThread ::- (MonadBinder m, Rep m ~ GPU) =>+ (MonadBuilder m, Rep m ~ GPU) => VName -> SubExp -> KernelSize ->@@ -156,12 +156,12 @@ addStms $ bodyStms (lambdaBody lam) <> stmsFromList- [ Let (Pattern [] [pe]) (defAux ()) $ BasicOp $ SubExp se- | (pe, se) <- zip chunk_red_pes chunk_red_ses+ [ certify cs $ Let (Pat [pe]) (defAux ()) $ BasicOp $ SubExp se+ | (pe, SubExpRes cs se) <- zip chunk_red_pes chunk_red_ses ] <> stmsFromList- [ Let (Pattern [] [pe]) (defAux ()) $ BasicOp $ SubExp se- | (pe, se) <- zip chunk_map_pes chunk_map_ses+ [ certify cs $ Let (Pat [pe]) (defAux ()) $ BasicOp $ SubExp se+ | (pe, SubExpRes cs se) <- zip chunk_map_pes chunk_map_ses ] return (chunk_red_pes, chunk_map_pes)@@ -182,22 +182,17 @@ mkAccInit p (Var v) | not $ primType $ paramType p =- mkLet [] [paramIdent p] $ BasicOp $ Copy v- mkAccInit p x = mkLet [] [paramIdent p] $ BasicOp $ SubExp x+ mkLet [paramIdent p] $ BasicOp $ Copy v+ mkAccInit p x = mkLet [paramIdent p] $ BasicOp $ SubExp x acc_init_bnds = stmsFromList $ zipWith mkAccInit fold_acc_params nes return lam- { lambdaBody =- insertStms acc_init_bnds $- lambdaBody lam,- lambdaParams =- thread_index_param :- fold_chunk_param :- fold_inp_params+ { lambdaBody = insertStms acc_init_bnds $ lambdaBody lam,+ lambdaParams = thread_index_param : fold_chunk_param : fold_inp_params } prepareStream ::- (MonadBinder m, Rep m ~ GPU) =>+ (MonadBuilder m, Rep m ~ GPU) => KernelSize -> [(VName, SubExp)] -> SubExp ->@@ -218,14 +213,14 @@ gtid <- newVName "gtid" space <- mkSegSpace $ ispace ++ [(gtid, num_threads)] kbody <- fmap (uncurry (flip (KernelBody ()))) $- runBinder $+ runBuilder $ localScope (scopeOfSegSpace space) $ do (chunk_red_pes, chunk_map_pes) <- blockedPerThread gtid w size ordering fold_lam' (length nes) arrs let concatReturns pe =- ConcatReturns split_ordering w elems_per_thread $ patElemName pe+ ConcatReturns mempty split_ordering w elems_per_thread $ patElemName pe return- ( map (Returns ResultMaySimplify . Var . patElemName) chunk_red_pes+ ( map (Returns ResultMaySimplify mempty . Var . patElemName) chunk_red_pes ++ map concatReturns chunk_map_pes ) @@ -237,7 +232,7 @@ streamRed :: (MonadFreshNames m, HasScope GPU m) => MkSegLevel GPU m ->- Pattern GPU ->+ Pat GPU -> SubExp -> Commutativity -> Lambda GPU ->@@ -245,28 +240,21 @@ [SubExp] -> [VName] -> m (Stms GPU)-streamRed mk_lvl pat w comm red_lam fold_lam nes arrs = runBinderT'_ $ do+streamRed mk_lvl pat w comm red_lam fold_lam nes arrs = runBuilderT'_ $ do -- The strategy here is to rephrase the stream reduction as a -- non-segmented SegRed that does explicit chunking within its body. -- First, figure out how many threads to use for this. size <- blockedKernelSize "stream_red" w - let (redout_pes, mapout_pes) = splitAt (length nes) $ patternElements pat- (redout_pat, ispace, read_dummy) <- dummyDim $ Pattern [] redout_pes- let pat' = Pattern [] $ patternElements redout_pat ++ mapout_pes+ let (redout_pes, mapout_pes) = splitAt (length nes) $ patElems pat+ (redout_pat, ispace, read_dummy) <- dummyDim $ Pat redout_pes+ let pat' = Pat $ patElems redout_pat ++ mapout_pes (_, kspace, ts, kbody) <- prepareStream size ispace w comm fold_lam nes arrs lvl <- mk_lvl [w] "stream_red" $ NoRecommendation SegNoVirt- letBind pat' $- Op $- SegOp $- SegRed- lvl- kspace- [SegBinOp comm red_lam nes mempty]- ts- kbody+ letBind pat' . Op . SegOp $+ SegRed lvl kspace [SegBinOp comm red_lam nes mempty] ts kbody read_dummy @@ -282,7 +270,7 @@ [SubExp] -> [VName] -> m ((SubExp, [VName]), Stms GPU)-streamMap mk_lvl out_desc mapout_pes w comm fold_lam nes arrs = runBinderT' $ do+streamMap mk_lvl out_desc mapout_pes w comm fold_lam nes arrs = runBuilderT' $ do size <- blockedKernelSize "stream_map" w (threads, kspace, ts, kbody) <- prepareStream size [] w comm fold_lam nes arrs@@ -292,7 +280,7 @@ redout_pes <- forM (zip out_desc redout_ts) $ \(desc, t) -> PatElem <$> newVName desc <*> pure (t `arrayOfRow` threads) - let pat = Pattern [] $ redout_pes ++ mapout_pes+ let pat = Pat $ redout_pes ++ mapout_pes lvl <- mk_lvl [w] "stream_map" $ NoRecommendation SegNoVirt letBind pat $ Op $ SegOp $ SegMap lvl kspace ts kbody
src/Futhark/Pass/ExtractKernels/ToGPU.hs view
@@ -23,7 +23,7 @@ import Futhark.Tools getSize ::- (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) =>+ (MonadBuilder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SizeClass -> m SubExp@@ -32,7 +32,7 @@ letSubExp desc $ Op $ SizeOp $ GetSize size_key size_class segThread ::- (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) =>+ (MonadBuilder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> m SegLevel segThread desc =
src/Futhark/Pass/ExtractMulticore.hs view
@@ -3,6 +3,9 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} +-- | Extraction of parallelism from a SOACs program. This generates+-- parallel constructs aimed at CPU execution, which in particular may+-- involve ad-hoc irregular nested parallelism. module Futhark.Pass.ExtractMulticore (extractMulticore) where import Control.Monad.Identity@@ -18,7 +21,7 @@ Exp, LParam, Lambda,- Pattern,+ Pat, Stm, ) import qualified Futhark.IR.SOACS as SOACS@@ -48,10 +51,10 @@ indexArray :: VName -> LParam SOACS -> VName -> Stm MC indexArray i (Param p t) arr =- Let (Pattern [] [PatElem p t]) (defAux ()) . BasicOp $+ Let (Pat [PatElem p t]) (defAux ()) . BasicOp $ case t of Acc {} -> SubExp $ Var arr- _ -> Index arr $ DimFix (Var i) : map sliceDim (arrayDims t)+ _ -> Index arr $ Slice $ DimFix (Var i) : map sliceDim (arrayDims t) mapLambdaToBody :: (Body SOACS -> ExtractM (Body MC)) ->@@ -72,23 +75,24 @@ ExtractM (KernelBody MC) mapLambdaToKernelBody onBody i lam arrs = do Body () stms res <- mapLambdaToBody onBody i lam arrs- return $ KernelBody () stms $ map (Returns ResultMaySimplify) res+ let ret (SubExpRes cs se) = Returns ResultMaySimplify cs se+ return $ KernelBody () stms $ map ret res reduceToSegBinOp :: Reduce SOACS -> ExtractM (Stms MC, SegBinOp MC) reduceToSegBinOp (Reduce comm lam nes) = do- ((lam', nes', shape), stms) <- runBinder $ determineReduceOp lam nes+ ((lam', nes', shape), stms) <- runBuilder $ determineReduceOp lam nes lam'' <- transformLambda lam' return (stms, SegBinOp comm lam'' nes' shape) scanToSegBinOp :: Scan SOACS -> ExtractM (Stms MC, SegBinOp MC) scanToSegBinOp (Scan lam nes) = do- ((lam', nes', shape), stms) <- runBinder $ determineReduceOp lam nes+ ((lam', nes', shape), stms) <- runBuilder $ determineReduceOp lam nes lam'' <- transformLambda lam' return (stms, SegBinOp Noncommutative lam'' nes' shape) histToSegBinOp :: SOACS.HistOp SOACS -> ExtractM (Stms MC, MC.HistOp MC) histToSegBinOp (SOACS.HistOp num_bins rf dests nes op) = do- ((op', nes', shape), stms) <- runBinder $ determineReduceOp op nes+ ((op', nes', shape), stms) <- runBuilder $ determineReduceOp op nes op'' <- transformLambda op' return (stms, MC.HistOp num_bins rf dests nes' shape op'') @@ -108,16 +112,12 @@ pure $ oneStm $ Let pat aux $ BasicOp op transformStm (Let pat aux (Apply f args ret info)) = pure $ oneStm $ Let pat aux $ Apply f args ret info-transformStm (Let pat aux (DoLoop ctx val form body)) = do+transformStm (Let pat aux (DoLoop merge form body)) = do let form' = transformLoopForm form body' <-- localScope- ( scopeOfFParams (map fst ctx)- <> scopeOfFParams (map fst val)- <> scopeOf form'- )- $ transformBody body- return $ oneStm $ Let pat aux $ DoLoop ctx val form' body'+ localScope (scopeOfFParams (map fst merge) <> scopeOf form') $+ transformBody body+ return $ oneStm $ Let pat aux $ DoLoop merge form' body' transformStm (Let pat aux (If cond tbranch fbranch ret)) = oneStm . Let pat aux <$> (If cond <$> transformBody tbranch <*> transformBody fbranch <*> pure ret)@@ -167,7 +167,7 @@ inp_params <- forM slice_params $ \(Param p t) -> newParam (baseString p) (rowType t) - body <- runBodyBinder $+ body <- runBodyBuilder $ localScope (scopeOfLParams inp_params) $ do letBindNames [paramName chunk_param] $ BasicOp $ SubExp $ intConst Int64 1@@ -181,15 +181,13 @@ (red_res, map_res) <- splitAt (length nes) <$> bodyBind (lambdaBody lam) - map_res' <- forM map_res $ \se -> do+ map_res' <- forM map_res $ \(SubExpRes cs se) -> do v <- letExp "map_res" $ BasicOp $ SubExp se v_t <- lookupType v- letSubExp "chunk" $- BasicOp $- Index v $- fullSlice v_t [DimFix $ intConst Int64 0]+ certifying cs . letSubExp "chunk" . BasicOp $+ Index v $ fullSlice v_t [DimFix $ intConst Int64 0] - pure $ resultBody $ red_res <> map_res'+ pure $ mkBody mempty $ red_res <> subExpsRes map_res' let (red_ts, map_ts) = splitAt (length nes) $ lambdaReturnType lam map_lam =@@ -282,7 +280,7 @@ SegRed () space [red] (lambdaReturnType map_lam) kbody return (red_stms, op) -transformSOAC :: Pattern SOACS -> Attrs -> SOAC SOACS -> ExtractM (Stms MC)+transformSOAC :: Pat SOACS -> Attrs -> SOAC SOACS -> ExtractM (Stms MC) transformSOAC pat _ (Screma w arrs form) | Just lam <- isMapSOAC form = do seq_op <- transformMap DoNotRename sequentialiseBody w lam arrs@@ -321,7 +319,7 @@ -- This screma is too complicated for us to immediately do -- anything, so split it up and try again. scope <- castScope <$> askScope- transformStms =<< runBinderT_ (dissectScrema pat w form arrs) scope+ transformStms =<< runBuilderT_ (dissectScrema pat w form arrs) scope transformSOAC pat _ (Scatter w lam ivs dests) = do (gtid, space) <- mkSegSpace w @@ -329,9 +327,12 @@ let rets = takeLast (length dests) $ lambdaReturnType lam kres = do- (a_w, a, is_vs) <-- groupScatterResults dests res- return $ WriteReturns a_w a [(map DimFix is, v) | (is, v) <- is_vs]+ (a_w, a, is_vs) <- groupScatterResults dests res+ let cs =+ foldMap (foldMap resCerts . fst) is_vs+ <> foldMap (resCerts . snd) is_vs+ is_vs' = [(Slice $ map (DimFix . resSubExp) is, resSubExp v) | (is, v) <- is_vs]+ return $ WriteReturns cs a_w a is_vs' kbody = KernelBody () kstms kres return $ oneStm $@@ -383,7 +384,7 @@ -- Just remove the stream and transform the resulting stms. soacs_scope <- castScope <$> askScope stream_stms <-- flip runBinderT_ soacs_scope $+ flip runBuilderT_ soacs_scope $ sequentialStreamWholeArray pat w nes lam arrs transformStms stream_stms @@ -396,6 +397,8 @@ funs' <- inScopeOf consts' $ mapM transformFunDef funs return $ Prog consts' funs' +-- | Transform a program using SOACs to a program in the 'MC'+-- representation, using some amount of flattening. extractMulticore :: Pass SOACS MC extractMulticore = Pass
src/Futhark/Pass/KernelBabysitting.hs view
@@ -19,8 +19,8 @@ FunDef, LParam, Lambda,+ Pat, PatElem,- Pattern, Prog, RetType, Stm,@@ -40,9 +40,9 @@ where onStms scope stms = do let m = localScope scope $ transformStms mempty stms- fmap fst $ modifyNameSource $ runState (runBinderT m M.empty)+ fmap fst $ modifyNameSource $ runState (runBuilderT m M.empty) -type BabysitM = Binder GPU+type BabysitM = Builder GPU transformStms :: ExpMap -> Stms GPU -> BabysitM (Stms GPU) transformStms expmap stms = collectStms_ $ foldM_ transformStm expmap stms@@ -62,7 +62,7 @@ nonlinearInMemory :: VName -> ExpMap -> Maybe (Maybe [Int]) nonlinearInMemory name m = case M.lookup name m of- Just (Let _ _ (BasicOp (Opaque (Var arr)))) -> nonlinearInMemory arr m+ Just (Let _ _ (BasicOp (Opaque _ (Var arr)))) -> nonlinearInMemory arr m Just (Let _ _ (BasicOp (Rearrange perm _))) -> Just $ Just $ rearrangeInverse perm Just (Let _ _ (BasicOp (Reshape _ arr))) -> nonlinearInMemory arr m Just (Let _ _ (BasicOp (Manifest perm _))) -> Just $ Just perm@@ -70,7 +70,7 @@ nonlinear =<< find ((== name) . patElemName . fst)- (zip (patternElements pat) ts)+ (zip (patElems pat) ts) _ -> Nothing where nonlinear (pe, t)@@ -95,12 +95,12 @@ op' <- mapSegOpM mapper op let stm' = Let pat aux $ Op $ SegOp op' addStm stm'- return $ M.fromList [(name, stm') | name <- patternNames pat] <> expmap+ return $ M.fromList [(name, stm') | name <- patNames pat] <> expmap transformStm expmap (Let pat aux e) = do e' <- mapExpM (transform expmap) e let bnd' = Let pat aux e' addStm bnd'- return $ M.fromList [(name, bnd') | name <- patternNames pat] <> expmap+ return $ M.fromList [(name, bnd') | name <- patNames pat] <> expmap transform :: ExpMap -> Mapper GPU GPU BabysitM transform expmap =@@ -218,14 +218,14 @@ mkSizeSubsts = foldMap mkStmSizeSubst where- mkStmSizeSubst (Let (Pattern [] [pe]) _ (Op (SizeOp (SplitSpace _ _ _ elems_per_i)))) =+ mkStmSizeSubst (Let (Pat [pe]) _ (Op (SizeOp (SplitSpace _ _ _ elems_per_i)))) = M.singleton (patElemName pe) elems_per_i mkStmSizeSubst _ = mempty type Replacements = M.Map (VName, Slice SubExp) VName ensureCoalescedAccess ::- MonadBinder m =>+ MonadBuilder m => ExpMap -> [(VName, SubExp)] -> SubExp ->@@ -268,7 +268,7 @@ not $ null thread_gids, inner_gid <- last thread_gids, length slice >= length perm,- slice' <- map (slice !!) perm,+ slice' <- map (unSlice slice !!) perm, DimFix inner_ind <- last slice', not $ null thread_gids, isGidVariant inner_gid inner_ind ->@@ -309,7 +309,7 @@ -- padding. | (is, rem_slice) <- splitSlice slice, and $ zipWith (==) is $ map Var thread_gids,- DimSlice offset len (Constant stride) : _ <- rem_slice,+ DimSlice offset len (Constant stride) : _ <- unSlice rem_slice, isThreadLocalSubExp offset, Just {} <- sizeSubst len, oneIsh stride -> do@@ -352,14 +352,14 @@ comb (_, x) _ = (False, x) splitSlice :: Slice SubExp -> ([SubExp], Slice SubExp)-splitSlice [] = ([], [])-splitSlice (DimFix i : is) = first (i :) $ splitSlice is+splitSlice (Slice []) = ([], Slice [])+splitSlice (Slice (DimFix i : is)) = first (i :) $ splitSlice (Slice is) splitSlice is = ([], is) allDimAreSlice :: Slice SubExp -> Bool-allDimAreSlice [] = True-allDimAreSlice (DimFix _ : _) = False-allDimAreSlice (_ : is) = allDimAreSlice is+allDimAreSlice (Slice []) = True+allDimAreSlice (Slice (DimFix _ : _)) = False+allDimAreSlice (Slice (_ : is)) = allDimAreSlice (Slice is) -- Try to move thread indexes into their proper position. coalescedIndexes :: Names -> (VName -> SubExp -> Bool) -> [SubExp] -> [SubExp] -> Maybe [SubExp]@@ -418,7 +418,7 @@ [num_is .. rank -1] ++ [0 .. num_is -1] rearrangeInput ::- MonadBinder m =>+ MonadBuilder m => Maybe (Maybe [Int]) -> [Int] -> VName ->@@ -441,7 +441,7 @@ BasicOp $ Manifest perm manifested rowMajorArray ::- MonadBinder m =>+ MonadBuilder m => VName -> m VName rowMajorArray arr = do@@ -449,7 +449,7 @@ letExp (baseString arr ++ "_rowmajor") $ BasicOp $ Manifest [0 .. rank -1] arr rearrangeSlice ::- MonadBinder m =>+ MonadBuilder m => Int -> SubExp -> PrimExp VName ->@@ -498,7 +498,7 @@ =<< eSliceArray d arr_inv_tr (eSubExp $ constant (0 :: Int64)) (eSubExp w) paddedScanReduceInput ::- MonadBinder m =>+ MonadBuilder m => SubExp -> SubExp -> m (SubExp, SubExp)@@ -518,7 +518,7 @@ varianceInStm :: VarianceTable -> Stm GPU -> VarianceTable varianceInStm variance bnd =- foldl' add variance $ patternNames $ stmPattern bnd+ foldl' add variance $ patNames $ stmPat bnd where add variance' v = M.insert v binding_variance variance' look variance' v = oneName v <> M.findWithDefault mempty v variance'
src/Futhark/Passes.hs view
@@ -44,7 +44,9 @@ standardPipeline = passes [ simplifySOACS,- inlineFunctions,+ inlineConservatively,+ simplifySOACS,+ inlineAggressively, simplifySOACS, performCSE True, simplifySOACS,
src/Futhark/Script.hs view
@@ -131,7 +131,7 @@ parseExp sep = choice [ lexeme sep "let" $> Let- <*> pPattern <* lexeme sep "="+ <*> pPat <* lexeme sep "=" <*> parseExp sep <* lexeme sep "in" <*> parseExp sep, try $ Call <$> parseFunc <*> many pAtom,@@ -155,7 +155,7 @@ Call <$> parseFunc <*> pure [] ] - pPattern =+ pPat = choice [ inParens sep $ pVarName `sepBy` pComma, pure <$> pVarName@@ -321,7 +321,7 @@ pure $ M.fromList (zip vs vals) | otherwise = throwError $- "Pattern: " <> prettyTextOneLine vs+ "Pat: " <> prettyTextOneLine vs <> "\nDoes not match value of type: " <> prettyTextOneLine (fmap scriptValueType val)
src/Futhark/Test.hs view
@@ -623,8 +623,12 @@ forM_ (zip gen_fs names_and_types) $ \(file, (v, t)) -> cmdMaybe $ cmdRestore server (dir </> file) [(v, t)] valuesAsVars server names_and_types _ _ (Values vs) = do- unless (length vs == length names_and_types) $- throwError "Mismatch between number of expected and provided values."+ let types = map snd names_and_types+ vs_types = map (V.valueTypeTextNoDims . V.valueType) vs+ unless (types == vs_types) . throwError . T.unlines $+ [ "Expected input of types: " <> prettyTextOneLine types,+ "Provided input of types: " <> prettyTextOneLine vs_types+ ] cmdMaybe . withSystemTempFile "futhark-input" $ \tmpf tmpf_h -> do mapM_ (BS.hPutStr tmpf_h . Bin.encode) vs hClose tmpf_h
src/Futhark/Tools.hs view
@@ -27,52 +27,44 @@ -- -- Reuses the original pattern for the @reduce@, and creates a new -- pattern with new 'Ident's for the result of the @map@.------ Only handles a pattern with an empty 'patternContextElements'. redomapToMapAndReduce :: ( MonadFreshNames m,- Bindable rep,+ Buildable rep, ExpDec rep ~ (), Op rep ~ SOAC rep ) =>- Pattern rep ->+ Pat rep -> ( SubExp,- Commutativity,- LambdaT rep,+ [Reduce rep], LambdaT rep,- [SubExp], [VName] ) -> m (Stm rep, Stm rep)-redomapToMapAndReduce- (Pattern [] patelems)- (w, comm, redlam, map_lam, accs, arrs) = do- (map_pat, red_pat, red_args) <-- splitScanOrRedomap patelems w map_lam accs- let map_bnd = mkLet [] map_pat $ Op $ Screma w arrs (mapSOAC map_lam)- (nes, red_arrs) = unzip red_args- red_bnd <-- Let red_pat (defAux ()) . Op- <$> (Screma w red_arrs <$> reduceSOAC [Reduce comm redlam nes])- return (map_bnd, red_bnd)-redomapToMapAndReduce _ _ =- error "redomapToMapAndReduce does not handle a non-empty 'patternContextElements'"+redomapToMapAndReduce (Pat pes) (w, reds, map_lam, arrs) = do+ (map_pat, red_pat, red_arrs) <-+ splitScanOrRedomap pes w map_lam $ map redNeutral reds+ let map_stm = mkLet map_pat $ Op $ Screma w arrs (mapSOAC map_lam)+ red_stm <-+ Let red_pat (defAux ()) . Op+ <$> (Screma w red_arrs <$> reduceSOAC reds)+ return (map_stm, red_stm) splitScanOrRedomap :: (Typed dec, MonadFreshNames m) => [PatElemT dec] -> SubExp -> LambdaT rep ->- [SubExp] ->- m ([Ident], PatternT dec, [(SubExp, VName)])-splitScanOrRedomap patelems w map_lam accs = do- let (acc_patelems, arr_patelems) = splitAt (length accs) patelems- (acc_ts, _arr_ts) = splitAt (length accs) $ lambdaReturnType map_lam- map_accpat <- zipWithM accMapPatElem acc_patelems acc_ts- map_arrpat <- mapM arrMapPatElem arr_patelems+ [[SubExp]] ->+ m ([Ident], PatT dec, [VName])+splitScanOrRedomap pes w map_lam nes = do+ let (acc_pes, arr_pes) =+ splitAt (length $ concat nes) pes+ (acc_ts, _arr_ts) =+ splitAt (length (concat nes)) $ lambdaReturnType map_lam+ map_accpat <- zipWithM accMapPatElem acc_pes acc_ts+ map_arrpat <- mapM arrMapPatElem arr_pes let map_pat = map_accpat ++ map_arrpat- red_args = zip accs $ map identName map_accpat- return (map_pat, Pattern [] acc_patelems, red_args)+ return (map_pat, Pat acc_pes, map identName map_accpat) where accMapPatElem pe acc_t = newIdent (baseString (patElemName pe) ++ "_map_acc") $ acc_t `arrayOfRow` w@@ -83,11 +75,11 @@ -- that we cannot directly generate efficient parallel code for them. -- In essense, what happens is the opposite of horisontal fusion. dissectScrema ::- ( MonadBinder m,+ ( MonadBuilder m, Op (Rep m) ~ SOAC (Rep m),- Bindable (Rep m)+ Buildable (Rep m) ) =>- Pattern (Rep m) ->+ Pat (Rep m) -> SubExp -> ScremaForm (Rep m) -> [VName] ->@@ -96,7 +88,7 @@ let num_reds = redResults reds num_scans = scanResults scans (scan_res, red_res, map_res) =- splitAt3 num_scans num_reds $ patternNames pat+ splitAt3 num_scans num_reds $ patNames pat to_red <- replicateM num_reds $ newVName "to_red" @@ -110,8 +102,8 @@ -- | Turn a stream SOAC into statements that apply the stream lambda -- to the entire input. sequentialStreamWholeArray ::- (MonadBinder m, Bindable (Rep m)) =>- Pattern (Rep m) ->+ (MonadBuilder m, Buildable (Rep m)) =>+ Pat (Rep m) -> SubExp -> [SubExp] -> LambdaT (Rep m) ->@@ -143,8 +135,8 @@ -- The number of results in the body matches exactly the size (and -- order) of 'pat', so we bind them up here, again with a reshape to -- make the types work out.- forM_ (zip (patternElements pat) $ bodyResult $ lambdaBody lam) $ \(pe, se) ->- case (arrayDims $ patElemType pe, se) of+ forM_ (zip (patElems pat) $ bodyResult $ lambdaBody lam) $ \(pe, SubExpRes cs se) ->+ certifying cs $ case (arrayDims $ patElemType pe, se) of (dims, Var v) | not $ null dims -> letBindNames [patElemName pe] $ BasicOp $ Reshape (map DimCoercion dims) v
src/Futhark/Transform/FirstOrderTransform.hs view
@@ -33,8 +33,8 @@ -- | The constraints that must hold for a rep in order to be the -- target of first-order transformation. type FirstOrderRep rep =- ( Bindable rep,- BinderOps rep,+ ( Buildable rep,+ BuilderOps rep, LetDec SOACS ~ LetDec rep, LParamInfo SOACS ~ LParamInfo rep, CanBeAliased (Op rep)@@ -48,7 +48,7 @@ FunDef SOACS -> m (AST.FunDef torep) transformFunDef consts_scope (FunDef entry attrs fname rettype params body) = do- (body', _) <- modifyNameSource $ runState $ runBinderT m consts_scope+ (body', _) <- modifyNameSource $ runState $ runBuilderT m consts_scope return $ FunDef entry attrs fname rettype params body' where m = localScope (scopeOfFParams params) $ transformBody body@@ -59,17 +59,17 @@ Stms SOACS -> m (AST.Stms torep) transformConsts stms =- fmap snd $ modifyNameSource $ runState $ runBinderT m mempty+ fmap snd $ modifyNameSource $ runState $ runBuilderT m mempty where m = mapM_ transformStmRecursively stms -- | The constraints that a monad must uphold in order to be used for -- first-order transformation. type Transformer m =- ( MonadBinder m,+ ( MonadBuilder m, LocalScope (Rep m) m,- Bindable (Rep m),- BinderOps (Rep m),+ Buildable (Rep m),+ BuilderOps (Rep m), LParamInfo SOACS ~ LParamInfo (Rep m), CanBeAliased (Op (Rep m)) )@@ -122,7 +122,7 @@ -- on the given rep. transformSOAC :: Transformer m =>- AST.Pattern (Rep m) ->+ AST.Pat (Rep m) -> SOAC (Rep m) -> m () transformSOAC pat (Screma w arrs form@(ScremaForm scans reds map_lam)) = do@@ -161,7 +161,7 @@ let loopform = ForLoop i Int64 w [] lam_cons = consumedByLambda $ Alias.analyseLambda mempty map_lam - loop_body <- runBodyBinder+ loop_body <- runBodyBuilder . localScope (scopeOfFParams (map fst merge) <> scopeOf loopform) $ do -- Bind the parameters to the lambda.@@ -193,35 +193,35 @@ scan_res' <- eLambda scan_lam $ map (pure . BasicOp . SubExp) $- map (Var . paramName) scanacc_params ++ scan_res+ map (Var . paramName) scanacc_params ++ map resSubExp scan_res red_res' <- eLambda red_lam $ map (pure . BasicOp . SubExp) $- map (Var . paramName) redout_params ++ red_res+ map (Var . paramName) redout_params ++ map resSubExp red_res -- Write the scan accumulator to the scan result arrays. scan_outarrs <-- letwith (map paramName scanout_params) (Var i) scan_res'+ certifying (foldMap resCerts scan_res) $+ letwith (map paramName scanout_params) (Var i) $ map resSubExp scan_res' -- Write the map results to the map result arrays. map_outarrs <-- letwith (map paramName mapout_params) (Var i) map_res+ certifying (foldMap resCerts map_res) $+ letwith (map paramName mapout_params) (Var i) $ map resSubExp map_res - return $- resultBody $- concat- [ scan_res',- map Var scan_outarrs,- red_res',- map Var map_outarrs- ]+ return . mkBody mempty . concat $+ [ scan_res',+ varsRes scan_outarrs,+ red_res',+ varsRes map_outarrs+ ] -- We need to discard the final scan accumulators, as they are not -- bound in the original pattern. names <-- (++ patternNames pat)+ (++ patNames pat) <$> replicateM (length scanacc_params) (newVName "discard")- letBindNames names $ DoLoop [] merge loopform loop_body+ letBindNames names $ DoLoop merge loopform loop_body transformSOAC pat (Stream w arrs _ nes lam) = do -- Create a loop that repeatedly applies the lambda body to a -- chunksize of 1. Hopefully this will lead to this outer loop@@ -258,7 +258,7 @@ letBindNames [paramName chunk_size_param] $ BasicOp $ SubExp $ intConst Int64 1 - loop_body <- runBodyBinder $+ loop_body <- runBodyBuilder $ localScope (scopeOf loop_form <> scopeOfFParams merge_params) $ do let slice = [DimSlice (Var i) (Var (paramName chunk_size_param)) (intConst Int64 1)] forM_ (zip chunk_params arrs) $ \(p, arr) ->@@ -267,13 +267,13 @@ (res, mapout_res) <- splitAt (length nes) <$> bodyBind (lambdaBody lam) - mapout_res' <- forM (zip mapout_params mapout_res) $ \(p, se) ->- letSubExp "mapout_res" . BasicOp $- Update (paramName p) (fullSlice (paramType p) slice) se+ mapout_res' <- forM (zip mapout_params mapout_res) $ \(p, SubExpRes cs se) ->+ certifying cs . letSubExp "mapout_res" . BasicOp $+ Update Unsafe (paramName p) (fullSlice (paramType p) slice) se - resultBodyM $ res ++ mapout_res'+ mkBodyM mempty $ res ++ subExpsRes mapout_res' - letBind pat $ DoLoop [] merge loop_form loop_body+ letBind pat $ DoLoop merge loop_form loop_body transformSOAC pat (Scatter len lam ivs as) = do iter <- newVName "write_iter" @@ -283,7 +283,7 @@ -- Scatter is in-place, so we use the input array as the output array. let merge = loopMerge asOuts $ map Var as_vs- loopBody <- runBodyBinder $+ loopBody <- runBodyBuilder $ localScope (M.insert iter (IndexName Int64) $ scopeOfFParams $ map fst merge) $ do ivs' <- forM ivs $ \iv -> do iv_t <- lookupType iv@@ -293,12 +293,14 @@ let indexes = groupScatterResults (zip3 as_ws as_ns $ map identName asOuts) ivs'' ress <- forM indexes $ \(_, arr, indexes') -> do- let saveInArray arr' (indexCur, valueCur) =- letExp "write_out" =<< eWriteArray arr' (map eSubExp indexCur) (eSubExp valueCur)+ arr_t <- lookupType arr+ let saveInArray arr' (indexCur, SubExpRes value_cs valueCur) =+ certifying (foldMap resCerts indexCur <> value_cs) . letExp "write_out" $+ BasicOp $ Update Safe arr' (fullSlice arr_t $ map (DimFix . resSubExp) indexCur) valueCur foldM saveInArray arr indexes' return $ resultBody (map Var ress)- letBind pat $ DoLoop [] merge (ForLoop iter Int64 len []) loopBody+ letBind pat $ DoLoop merge (ForLoop iter Int64 len []) loopBody transformSOAC pat (Hist len ops bucket_fun imgs) = do iter <- newVName "iter" @@ -309,12 +311,12 @@ -- Bind lambda-bodies for operators. let iter_scope = M.insert iter (IndexName Int64) $ scopeOfFParams $ map fst merge- loopBody <- runBodyBinder . localScope iter_scope $ do+ loopBody <- runBodyBuilder . localScope iter_scope $ do -- Bind images to parameters of bucket function. imgs' <- forM imgs $ \img -> do img_t <- lookupType img letSubExp "pixel" $ BasicOp $ Index img $ fullSlice img_t [DimFix $ Var iter]- imgs'' <- bindLambda bucket_fun $ map (BasicOp . SubExp) imgs'+ imgs'' <- map resSubExp <$> bindLambda bucket_fun (map (BasicOp . SubExp) imgs') -- Split out values from bucket function. let lens = length ops@@ -327,7 +329,7 @@ hists_out'' <- forM (zip4 hists_out' ops inds vals) $ \(hist, op, idx, val) -> do -- Check whether the indexes are in-bound. If they are not, we -- return the histograms unchanged.- let outside_bounds_branch = buildBody_ $ pure $ map Var hist+ let outside_bounds_branch = buildBody_ $ pure $ varsRes hist oob = case hist of [] -> eSubExp $ constant True arr : _ -> eOutOfBounds arr [eSubExp idx]@@ -345,23 +347,23 @@ map (BasicOp . SubExp) $ h_val ++ val -- Write values back to histograms.- hist' <- forM (zip hist h_val') $ \(arr, v) -> do+ hist' <- forM (zip hist h_val') $ \(arr, SubExpRes cs v) -> do arr_t <- lookupType arr- letInPlace "hist_out" arr (fullSlice arr_t [DimFix idx]) $+ certifying cs . letInPlace "hist_out" arr (fullSlice arr_t [DimFix idx]) $ BasicOp $ SubExp v - pure $ map Var hist'+ pure $ varsRes hist' return $ resultBody $ map Var $ concat hists_out'' -- Wrap up the above into a for-loop.- letBind pat $ DoLoop [] merge (ForLoop iter Int64 len []) loopBody+ letBind pat $ DoLoop merge (ForLoop iter Int64 len []) loopBody -- | Recursively first-order-transform a lambda. transformLambda :: ( MonadFreshNames m,- Bindable rep,- BinderOps rep,+ Buildable rep,+ BuilderOps rep, LocalScope somerep m, SameScope somerep rep, LetDec rep ~ LetDec SOACS,@@ -371,7 +373,7 @@ m (AST.Lambda rep) transformLambda (Lambda params body rettype) = do body' <-- runBodyBinder $+ runBodyBuilder $ localScope (scopeOfLParams params) $ transformBody body return $ Lambda params body' rettype@@ -391,7 +393,7 @@ Transformer m => AST.Lambda (Rep m) -> [AST.Exp (Rep m)] ->- m [SubExp]+ m Result bindLambda (Lambda params body _) args = do forM_ (zip params args) $ \(param, arg) -> if primType $ paramType param
src/Futhark/Transform/Rename.hs view
@@ -19,7 +19,7 @@ renameStm, renameBody, renameLambda,- renamePattern,+ renamePat, renameSomething, -- * Renaming annotations@@ -105,13 +105,13 @@ -- | Produce an equivalent pattern but with each pattern element given -- a new name.-renamePattern ::+renamePat :: (Rename dec, MonadFreshNames m) =>- PatternT dec ->- m (PatternT dec)-renamePattern = modifyNameSource . runRenamer . rename'+ PatT dec ->+ m (PatT dec)+renamePat = modifyNameSource . runRenamer . rename' where- rename' pat = bind (patternNames pat) $ rename pat+ rename' pat = bind (patNames pat) $ rename pat -- | Rename the bound variables in something (does not affect free variables). renameSomething ::@@ -201,7 +201,7 @@ where descend stms' rem_stms = case stmsHead rem_stms of Nothing -> m stms'- Just (stm, rem_stms') -> bind (patternNames $ stmPattern stm) $ do+ Just (stm, rem_stms') -> bind (patNames $ stmPat stm) $ do stm' <- rename stm descend (stms' <> oneStm stm') rem_stms' @@ -220,14 +220,14 @@ instance Rename dec => Rename (Param dec) where rename (Param name dec) = Param <$> rename name <*> rename dec -instance Rename dec => Rename (PatternT dec) where- rename (Pattern context values) = Pattern <$> rename context <*> rename values+instance Rename dec => Rename (PatT dec) where+ rename (Pat xs) = Pat <$> rename xs instance Rename dec => Rename (PatElemT dec) where rename (PatElem ident dec) = PatElem <$> rename ident <*> rename dec -instance Rename Certificates where- rename (Certificates cs) = Certificates <$> rename cs+instance Rename Certs where+ rename (Certs cs) = Certs <$> rename cs instance Rename Attrs where rename = pure@@ -236,6 +236,9 @@ rename (StmAux cs attrs dec) = StmAux <$> rename cs <*> rename attrs <*> rename dec +instance Rename SubExpRes where+ rename (SubExpRes cs se) = SubExpRes <$> rename cs <*> rename se+ instance Renameable rep => Rename (Body rep) where rename (Body dec stms res) = do dec' <- rename dec@@ -248,49 +251,33 @@ instance Renameable rep => Rename (Exp rep) where rename (WithAcc inputs lam) = WithAcc <$> rename inputs <*> rename lam- rename (DoLoop ctx val form loopbody) = do- let (ctxparams, ctxinit) = unzip ctx- (valparams, valinit) = unzip val- ctxinit' <- mapM rename ctxinit- valinit' <- mapM rename valinit+ rename (DoLoop merge form loopbody) = do+ let (params, args) = unzip merge+ args' <- mapM rename args case form of -- It is important that 'i' is renamed before the loop_vars, as -- 'i' may be used in the annotations for loop_vars (e.g. index -- functions). ForLoop i it boundexp loop_vars -> bind [i] $ do- let (loop_params, loop_arrs) = unzip loop_vars+ let (arr_params, loop_arrs) = unzip loop_vars boundexp' <- rename boundexp loop_arrs' <- rename loop_arrs- bind- ( map paramName (ctxparams ++ valparams)- ++ map paramName loop_params- )- $ do- ctxparams' <- mapM rename ctxparams- valparams' <- mapM rename valparams- loop_params' <- mapM rename loop_params- i' <- rename i- loopbody' <- rename loopbody- return $- DoLoop- (zip ctxparams' ctxinit')- (zip valparams' valinit')- ( ForLoop i' it boundexp' $- zip loop_params' loop_arrs'- )- loopbody'- WhileLoop cond ->- bind (map paramName $ ctxparams ++ valparams) $ do- ctxparams' <- mapM rename ctxparams- valparams' <- mapM rename valparams+ bind (map paramName params ++ map paramName arr_params) $ do+ params' <- mapM rename params+ arr_params' <- mapM rename arr_params+ i' <- rename i loopbody' <- rename loopbody- cond' <- rename cond return $ DoLoop- (zip ctxparams' ctxinit')- (zip valparams' valinit')- (WhileLoop cond')+ (zip params' args')+ (ForLoop i' it boundexp' $ zip arr_params' loop_arrs') loopbody'+ WhileLoop cond ->+ bind (map paramName params) $ do+ params' <- mapM rename params+ loopbody' <- rename loopbody+ cond' <- rename cond+ return $ DoLoop (zip params' args') (WhileLoop cond') loopbody' rename e = mapExpM mapper e where mapper =
src/Futhark/Transform/Substitute.hs view
@@ -95,14 +95,18 @@ (substituteNames substs name) (substituteNames substs dec) -instance Substitute dec => Substitute (PatternT dec) where- substituteNames substs (Pattern context values) =- Pattern (substituteNames substs context) (substituteNames substs values)+instance Substitute SubExpRes where+ substituteNames substs (SubExpRes cs se) =+ SubExpRes (substituteNames substs cs) (substituteNames substs se) -instance Substitute Certificates where- substituteNames substs (Certificates cs) =- Certificates $ substituteNames substs cs+instance Substitute dec => Substitute (PatT dec) where+ substituteNames substs (Pat xs) =+ Pat (substituteNames substs xs) +instance Substitute Certs where+ substituteNames substs (Certs cs) =+ Certs $ substituteNames substs cs+ instance Substitutable rep => Substitute (Stm rep) where substituteNames substs (Let pat annot e) = Let@@ -182,6 +186,15 @@ substituteNames substs = fmap $ substituteNames substs instance Substitute d => Substitute (DimIndex d) where+ substituteNames substs = fmap $ substituteNames substs++instance Substitute d => Substitute (Slice d) where+ substituteNames substs = fmap $ substituteNames substs++instance Substitute d => Substitute (FlatDimIndex d) where+ substituteNames substs = fmap $ substituteNames substs++instance Substitute d => Substitute (FlatSlice d) where substituteNames substs = fmap $ substituteNames substs instance Substitute v => Substitute (PrimExp v) where
src/Futhark/TypeCheck.hs view
@@ -33,12 +33,13 @@ requireI, requirePrimExp, checkSubExp,+ checkCerts, checkExp, checkStms, checkStm, checkType, checkExtType,- matchExtPattern,+ matchExtPat, matchExtBranchType, argType, argAliases,@@ -76,8 +77,8 @@ | ReturnTypeError Name [ExtType] [ExtType] | DupDefinitionError Name | DupParamError Name VName- | DupPatternError VName- | InvalidPatternError (Pattern (Aliases rep)) [ExtType] (Maybe String)+ | DupPatError VName+ | InvalidPatError (Pat (Aliases rep)) [ExtType] (Maybe String) | UnknownVariableError VName | UnknownFunctionError Name | ParameterMismatch (Maybe Name) [Type] [Type]@@ -116,10 +117,10 @@ ++ " mentioned multiple times in argument list of function " ++ nameToString funname ++ "."- show (DupPatternError name) =+ show (DupPatError name) = "Variable " ++ pretty name ++ " bound twice in pattern."- show (InvalidPatternError pat t desc) =- "Pattern\n" ++ pretty pat+ show (InvalidPatError pat t desc) =+ "Pat\n" ++ pretty pat ++ "\ncannot match value of type\n" ++ prettyTuple t ++ end@@ -705,6 +706,14 @@ observe ident lookupType ident +checkCerts :: Checkable rep => Certs -> TypeM rep ()+checkCerts (Certs cs) = mapM_ (requireI [Prim Unit]) cs++checkSubExpRes :: Checkable rep => SubExpRes -> TypeM rep Type+checkSubExpRes (SubExpRes cs se) = do+ checkCerts cs+ checkSubExp se+ checkStms :: Checkable rep => Stms (Aliases rep) ->@@ -724,7 +733,7 @@ Checkable rep => Result -> TypeM rep ()-checkResult = mapM_ checkSubExp+checkResult = mapM_ checkSubExpRes checkFunBody :: Checkable rep =>@@ -737,7 +746,7 @@ context "When checking body result" $ checkResult res context "When matching declared return type to result of body" $ matchReturnType rt res- map (`namesSubtract` bound_here) <$> mapM subExpAliasesM res+ map (`namesSubtract` bound_here) <$> mapM (subExpAliasesM . resSubExp) res where bound_here = namesFromList $ M.keys $ scopeOf bnds @@ -750,7 +759,7 @@ checkBodyDec rep checkStms bnds $ do checkLambdaResult ret res- map (`namesSubtract` bound_here) <$> mapM subExpAliasesM res+ map (`namesSubtract` bound_here) <$> mapM (subExpAliasesM . resSubExp) res where bound_here = namesFromList $ M.keys $ scopeOf bnds @@ -771,7 +780,7 @@ ++ " values: " ++ prettyTuple es | otherwise = forM_ (zip ts es) $ \(t, e) -> do- et <- checkSubExp e+ et <- checkSubExpRes e unless (et == t) $ bad $ TypeError $@@ -787,14 +796,14 @@ checkBodyDec rep checkStms bnds $ do checkResult res- map (`namesSubtract` bound_here) <$> mapM subExpAliasesM res+ map (`namesSubtract` bound_here) <$> mapM (subExpAliasesM . resSubExp) res where bound_here = namesFromList $ M.keys $ scopeOf bnds checkBasicOp :: Checkable rep => BasicOp -> TypeM rep () checkBasicOp (SubExp es) = void $ checkSubExp es-checkBasicOp (Opaque es) =+checkBasicOp (Opaque _ es) = void $ checkSubExp es checkBasicOp (ArrayLit [] _) = return ()@@ -818,13 +827,13 @@ checkBasicOp (BinOp op e1 e2) = checkBinOpArgs (binOpType op) e1 e2 checkBasicOp (CmpOp op e1 e2) = checkCmpOp op e1 e2 checkBasicOp (ConvOp op e) = require [Prim $ fst $ convOpType op] e-checkBasicOp (Index ident idxes) = do+checkBasicOp (Index ident (Slice idxes)) = do vt <- lookupType ident observe ident when (arrayRank vt /= length idxes) $ bad $ SlicingError (arrayRank vt) (length idxes) mapM_ checkDimIndex idxes-checkBasicOp (Update src idxes se) = do+checkBasicOp (Update _ src (Slice idxes) se) = do src_t <- checkArrIdent src when (arrayRank src_t /= length idxes) $ bad $ SlicingError (arrayRank src_t) (length idxes)@@ -834,8 +843,26 @@ bad $ TypeError "The target of an Update must not alias the value to be written." mapM_ checkDimIndex idxes- require [arrayOf (Prim (elemType src_t)) (Shape (sliceDims idxes)) NoUniqueness] se+ require [arrayOf (Prim (elemType src_t)) (Shape (sliceDims (Slice idxes))) NoUniqueness] se consume =<< lookupAliases src+checkBasicOp (FlatIndex ident slice) = do+ vt <- lookupType ident+ observe ident+ when (arrayRank vt /= 1) $+ bad $ SlicingError (arrayRank vt) 1+ checkFlatSlice slice+checkBasicOp (FlatUpdate src slice v) = do+ src_t <- checkArrIdent src+ when (arrayRank src_t /= 1) $+ bad $ SlicingError (arrayRank src_t) 1++ v_aliases <- lookupAliases v+ when (src `nameIn` v_aliases) $+ bad $ TypeError "The target of an Update must not alias the value to be written."++ checkFlatSlice slice+ requireI [arrayOf (Prim (elemType src_t)) (Shape (flatSliceDims slice)) NoUniqueness] v+ consume =<< lookupAliases src checkBasicOp (Iota e x s et) = do require [Prim int64] e require [Prim $ IntType et] x@@ -907,8 +934,7 @@ mapM_ checkPart parts where checkPart ErrorString {} = return ()- checkPart (ErrorInt32 x) = require [Prim int32] x- checkPart (ErrorInt64 x) = require [Prim int64] x+ checkPart (ErrorVal t x) = require [Prim t] x checkBasicOp (UpdateAcc acc is ses) = do (shape, ts) <- checkAccIdent acc @@ -936,17 +962,16 @@ matchLoopResultExt :: Checkable rep => [Param DeclType] ->- [Param DeclType] ->- [SubExp] ->+ Result -> TypeM rep ()-matchLoopResultExt ctx val loopres = do+matchLoopResultExt merge loopres = do let rettype_ext =- existentialiseExtTypes (map paramName ctx) $- staticShapes $ map typeOf $ ctx ++ val+ existentialiseExtTypes (map paramName merge) $+ staticShapes $ map typeOf merge - bodyt <- mapM subExpType loopres+ bodyt <- mapM subExpResType loopres - case instantiateShapes (`maybeNth` loopres) rettype_ext of+ case instantiateShapes (fmap resSubExp . (`maybeNth` loopres)) rettype_ext of Nothing -> bad $ ReturnTypeError@@ -977,27 +1002,18 @@ (rettype_derived, paramtypes) <- lookupFun fname $ map fst args argflows <- mapM (checkArg . fst) args when (rettype_derived /= rettype_annot) $- bad $- TypeError $- "Expected apply result type " ++ pretty rettype_derived- ++ " but annotation is "- ++ pretty rettype_annot+ bad . TypeError . pretty $+ "Expected apply result type:"+ </> indent 2 (ppr rettype_derived)+ </> "But annotation is:"+ </> indent 2 (ppr rettype_annot) consumeArgs paramtypes argflows-checkExp (DoLoop ctxmerge valmerge form loopbody) = do- let merge = ctxmerge ++ valmerge- (mergepat, mergeexps) = unzip merge+checkExp (DoLoop merge form loopbody) = do+ let (mergepat, mergeexps) = unzip merge mergeargs <- mapM checkArg mergeexps - let val_free = freeIn $ map fst valmerge- usedInVal p = paramName p `nameIn` val_free- case find (not . usedInVal . fst) ctxmerge of- Just p ->- bad $ TypeError $ "Loop context parameter " ++ pretty p ++ " unused."- Nothing ->- return ()- binding (scopeOf form) $ do- form_consumable <- checkForm merge mergeargs form+ form_consumable <- checkForm mergeargs form let rettype = map paramDeclType mergepat consumable =@@ -1022,15 +1038,14 @@ checkResult $ bodyResult loopbody context "When matching result of body with loop parameters" $- matchLoopResult (map fst ctxmerge) (map fst valmerge) $- bodyResult loopbody+ matchLoopResult (map fst merge) $ bodyResult loopbody let bound_here = namesFromList $ M.keys $ scopeOf $ bodyStms loopbody map (`namesSubtract` bound_here)- <$> mapM subExpAliasesM (bodyResult loopbody)+ <$> mapM (subExpAliasesM . resSubExp) (bodyResult loopbody) where checkLoopVar (p, a) = do a_t <- lookupType a@@ -1054,7 +1069,7 @@ "Cannot loop over " ++ pretty a ++ " of type " ++ pretty a_t- checkForm merge mergeargs (ForLoop loopvar it boundexp loopvars) = do+ checkForm mergeargs (ForLoop loopvar it boundexp loopvars) = do iparam <- primFParam loopvar $ IntType it let mergepat = map fst merge funparams = iparam : mergepat@@ -1064,7 +1079,7 @@ boundarg <- checkArg boundexp checkFuncall Nothing paramts $ boundarg : mergeargs pure consumable- checkForm merge mergeargs (WhileLoop cond) = do+ checkForm mergeargs (WhileLoop cond) = do case find ((== cond) . paramName . fst) merge of Just (condparam, _) -> unless (paramType condparam == Prim Bool) $@@ -1206,6 +1221,20 @@ context ("When checking pattern element " ++ pretty name) $ checkLetBoundDec name dec +checkFlatDimIndex ::+ Checkable rep =>+ FlatDimIndex SubExp ->+ TypeM rep ()+checkFlatDimIndex (FlatDimIndex n s) = mapM_ (require [Prim int64]) [n, s]++checkFlatSlice ::+ Checkable rep =>+ FlatSlice SubExp ->+ TypeM rep ()+checkFlatSlice (FlatSlice offset idxs) = do+ require [Prim int64] offset+ mapM_ checkFlatDimIndex idxs+ checkDimIndex :: Checkable rep => DimIndex SubExp ->@@ -1218,13 +1247,13 @@ Stm (Aliases rep) -> TypeM rep a -> TypeM rep a-checkStm stm@(Let pat (StmAux (Certificates cs) _ (_, dec)) e) m = do+checkStm stm@(Let pat (StmAux (Certs cs) _ (_, dec)) e) m = do context "When checking certificates" $ mapM_ (requireI [Prim Unit]) cs context "When checking expression annotation" $ checkExpDec dec context ("When matching\n" ++ message " " pat ++ "\nwith\n" ++ message " " e) $- matchPattern pat e+ matchPat pat e binding (maybeWithoutAliases $ scopeOf stm) $ do- mapM_ checkPatElem (patternElements $ removePatternAliases pat)+ mapM_ checkPatElem (patElems $ removePatAliases pat) m where -- FIXME: this is wrong. However, the core language type system@@ -1241,14 +1270,14 @@ withoutAliases (LetName (_, ldec)) = LetName (mempty, ldec) withoutAliases info = info -matchExtPattern ::+matchExtPat :: Checkable rep =>- Pattern (Aliases rep) ->+ Pat (Aliases rep) -> [ExtType] -> TypeM rep ()-matchExtPattern pat ts =- unless (expExtTypesFromPattern pat == ts) $- bad $ InvalidPatternError pat ts Nothing+matchExtPat pat ts =+ unless (expExtTypesFromPat pat == ts) $+ bad $ InvalidPatError pat ts Nothing matchExtReturnType :: Checkable rep =>@@ -1256,7 +1285,7 @@ Result -> TypeM rep () matchExtReturnType rettype res = do- ts <- mapM subExpType res+ ts <- mapM subExpResType res matchExtReturns rettype res ts matchExtBranchType ::@@ -1265,7 +1294,7 @@ Body (Aliases rep) -> TypeM rep () matchExtBranchType rettype (Body _ stms res) = do- ts <- extendedScope (traverse subExpType res) stmscope+ ts <- extendedScope (traverse subExpResType res) stmscope matchExtReturns rettype res ts where stmscope = scopeOf stms@@ -1283,32 +1312,16 @@ " " ++ prettyTuple ts ] - let (ctx_res, val_res) = splitFromEnd (length rettype) res- (ctx_ts, val_ts) = splitFromEnd (length rettype) ts-- unless (length val_res == length rettype) problem-- let num_exts =- length $- S.fromList $- concatMap (mapMaybe isExt . arrayExtDims) rettype- unless (num_exts == length ctx_res) $- bad $- TypeError $- "Number of context results does not match number of existentials in the return type.\n"- ++ "Type:\n "- ++ prettyTuple rettype- ++ "\ncannot match context parameters:\n "- ++ prettyTuple ctx_res+ unless (length res == length rettype) problem - let ctx_vals = zip ctx_res ctx_ts+ let ctx_vals = zip res ts instantiateExt i = case maybeNth i ctx_vals of- Just (se, Prim (IntType Int64)) -> return se+ Just (SubExpRes _ se, Prim (IntType Int64)) -> return se _ -> problem rettype' <- instantiateShapes instantiateExt rettype - unless (rettype' == val_ts) problem+ unless (rettype' == ts) problem validApply :: ArrayShape shape =>@@ -1462,15 +1475,11 @@ checkLParamDec :: VName -> LParamInfo rep -> TypeM rep () checkLetBoundDec :: VName -> LetDec rep -> TypeM rep () checkRetType :: [RetType rep] -> TypeM rep ()- matchPattern :: Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()+ matchPat :: Pat (Aliases rep) -> Exp (Aliases rep) -> TypeM rep () primFParam :: VName -> PrimType -> TypeM rep (FParam (Aliases rep)) matchReturnType :: [RetType rep] -> Result -> TypeM rep () matchBranchType :: [BranchType rep] -> Body (Aliases rep) -> TypeM rep ()- matchLoopResult ::- [FParam (Aliases rep)] ->- [FParam (Aliases rep)] ->- [SubExp] ->- TypeM rep ()+ matchLoopResult :: [FParam (Aliases rep)] -> Result -> TypeM rep () default checkExpDec :: ExpDec rep ~ () => ExpDec rep -> TypeM rep () checkExpDec = return@@ -1490,8 +1499,8 @@ default checkRetType :: RetType rep ~ DeclExtType => [RetType rep] -> TypeM rep () checkRetType = mapM_ $ checkExtType . declExtTypeOf - default matchPattern :: Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()- matchPattern pat = matchExtPattern pat <=< expExtType+ default matchPat :: Pat (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()+ matchPat pat = matchExtPat pat <=< expExtType default primFParam :: FParamInfo rep ~ DeclType => VName -> PrimType -> TypeM rep (FParam (Aliases rep)) primFParam name t = return $ Param name (Prim t)@@ -1505,7 +1514,6 @@ default matchLoopResult :: FParamInfo rep ~ DeclType => [FParam (Aliases rep)] ->- [FParam (Aliases rep)] ->- [SubExp] ->+ Result -> TypeM rep () matchLoopResult = matchLoopResultExt
src/Futhark/Util.hs view
@@ -23,7 +23,7 @@ splitFromEnd, splitAt3, focusNth,- hashIntText,+ hashText, unixEnvironment, isEnvVarAtLeast, fancyTerminal,@@ -46,6 +46,7 @@ trim, pmapIO, readFileSafely,+ convFloat, UserString, EncodedString, zEncodeString,@@ -58,17 +59,17 @@ import Control.Concurrent import Control.Exception import Control.Monad+import Crypto.Hash.MD5 as MD5 import qualified Data.ByteString as BS+import qualified Data.ByteString.Base16 as Base16 import Data.Char import Data.Either import Data.Function ((&)) import Data.List (foldl', genericDrop, genericSplitAt, sort) import qualified Data.List.NonEmpty as NE-import Data.Map (Map)-import qualified Data.Map as Map+import qualified Data.Map as M import Data.Maybe-import Data.Set (Set)-import qualified Data.Set as Set+import qualified Data.Set as S import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Encoding.Error as T@@ -84,7 +85,6 @@ import System.IO.Error (isDoesNotExistError) import System.IO.Unsafe import System.Process.ByteString-import Text.Printf import Text.Read (readMaybe) -- | Like 'nub', but without the quadratic runtime.@@ -171,10 +171,11 @@ | (bef, x : aft) <- genericSplitAt i xs = Just (bef, x, aft) | otherwise = Nothing --- | Convert the given integer (implied to be a hash digest) to a--- hexadecimal non-negative number.-hashIntText :: Int -> T.Text-hashIntText x = T.pack $ printf "%x" (fromIntegral x :: Word)+-- | Compute a hash of a text that is stable across OS versions.+-- Returns the hash as a text as well, ready for human consumption.+hashText :: T.Text -> T.Text+hashText =+ T.decodeUtf8With T.lenientDecode . Base16.encode . MD5.hash . T.encodeUtf8 {-# NOINLINE unixEnvironment #-} @@ -358,6 +359,15 @@ | otherwise = return $ Just $ Left $ show e +-- | Convert between different floating-point types, preserving+-- infinities and NaNs.+convFloat :: (RealFloat from, RealFloat to) => from -> to+convFloat v+ | isInfinite v, v > 0 = 1 / 0+ | isInfinite v, v < 0 = -1 / 0+ | isNaN v = 0 / 0+ | otherwise = fromRational $ toRational v+ -- Z-encoding from https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/SymbolNames -- -- Slightly simplified as we do not need it to deal with tuples and@@ -440,8 +450,8 @@ | length s > n = take (n -3) s ++ "..." | otherwise = s -invertMap :: (Ord v, Ord k) => Map k v -> Map v (Set k)+invertMap :: (Ord v, Ord k) => M.Map k v -> M.Map v (S.Set k) invertMap m =- Map.toList m- & fmap (swap . first Set.singleton)- & foldr (uncurry $ Map.insertWith (<>)) mempty+ M.toList m+ & fmap (swap . first S.singleton)+ & foldr (uncurry $ M.insertWith (<>)) mempty
src/Futhark/Util/Console.hs view
@@ -2,7 +2,6 @@ module Futhark.Util.Console ( color, inRed,- inGreen, inBold, ) where@@ -16,10 +15,6 @@ -- | Make the string red. inRed :: String -> String inRed s = setSGRCode [SetColor Foreground Vivid Red] ++ s ++ setSGRCode [Reset]---- | Make the string green.-inGreen :: String -> String-inGreen s = setSGRCode [SetColor Foreground Vivid Red] ++ s ++ setSGRCode [Reset] -- | Make the string bold. inBold :: String -> String
src/Futhark/Util/Options.hs view
@@ -8,6 +8,7 @@ where import Control.Monad.IO.Class+import Data.List (sortBy) import Futhark.Version import System.Console.GetOpt import System.Exit@@ -51,7 +52,13 @@ helpStr :: String -> String -> [OptDescr a] -> IO String helpStr prog usage opts = do let header = unlines ["Usage: " ++ prog ++ " " ++ usage, "Options:"]- return $ usageInfo header opts+ return $ usageInfo header $ sortBy cmp opts+ where+ -- Sort first by long option, then by short name, then by description. Hopefully+ -- everything has a long option.+ cmp (Option _ (a : _) _ _) (Option _ (b : _) _ _) = compare a b+ cmp (Option (a : _) _ _ _) (Option (b : _) _ _ _) = compare a b+ cmp (Option _ _ _ a) (Option _ _ _ b) = compare a b badOptions :: String -> [String] -> [String] -> [String] -> IO () badOptions usage nonopts errs unrecs = do
src/Futhark/Util/Pretty.hs view
@@ -22,6 +22,7 @@ import Data.Text (Text) import qualified Data.Text.Lazy as LT+import Numeric.Half import Text.PrettyPrint.Mainland hiding (pretty) import qualified Text.PrettyPrint.Mainland as PP import Text.PrettyPrint.Mainland.Class@@ -47,7 +48,7 @@ prettyDoc = PP.pretty ppTuple' :: Pretty a => [a] -> Doc-ppTuple' ets = braces $ commasep $ map ppr ets+ppTuple' ets = braces $ commasep $ map (align . ppr) ets -- | Prettyprint a list enclosed in curly braces. prettyTuple :: Pretty a => [a] -> String@@ -94,3 +95,6 @@ -- | Like 'commasep', but a newline after every comma. commastack :: [Doc] -> Doc commastack = align . stack . punctuate comma++instance Pretty Half where+ ppr = text . show
src/Futhark/Version.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE Trustworthy #-} -- | This module exports version information about the Futhark -- compiler.@@ -9,36 +8,48 @@ ) where +import qualified Data.ByteString.Char8 as BS+import Data.FileEmbed import Data.Version-import Development.GitRev+import Futhark.Util (trim)+import GitHash import qualified Paths_futhark +{-# NOINLINE version #-}+ -- | The version of Futhark that we are using. This is equivalent to -- the version defined in the .cabal file. version :: Version version = Paths_futhark.version --- | The version of Futhark that we are using, as a 'String'+{-# NOINLINE versionString #-}++-- | The version of Futhark that we are using, as a 'String'. versionString :: String versionString = showVersion version- ++ if used_hash /= "UNKNOWN"- then "\n" ++ gitversion- else ""+ ++ gitversion $$tGitInfoCwdTry where- used_hash = take 7 $(gitHash)-- gitversion =+ gitversion (Left _) =+ case commitIdFromFile of+ Nothing -> ""+ Just commit -> "\ngit: " <> commit+ gitversion (Right gi) = concat- [ "git: ",+ [ "\n",+ "git: ", branch,- used_hash,+ take 7 $ giHash gi, " (",- $(gitCommitDate),+ giCommitDate gi, ")", dirty ]- branch- | $(gitBranch) == "master" = ""- | otherwise = $(gitBranch) ++ " @ "- dirty = if $(gitDirtyTracked) then " [modified]" else ""+ where+ branch+ | giBranch gi == "master" = ""+ | otherwise = giBranch gi ++ " @ "+ dirty = if giDirty gi then " [modified]" else ""++commitIdFromFile :: Maybe String+commitIdFromFile = trim . BS.unpack <$> $(embedFileIfExists "./commit-id")
src/Language/Futhark.hs view
@@ -8,7 +8,7 @@ Slice, AppExp, Exp,- Pattern,+ Pat, ModExp, ModParam, SigExp,@@ -47,7 +47,7 @@ type AppExp = AppExpBase Info VName -- | A pattern with type information.-type Pattern = PatternBase Info VName+type Pat = PatBase Info VName -- | An constant declaration with type information. type ValBind = ValBindBase Info VName
src/Language/Futhark/Core.hs view
@@ -33,7 +33,7 @@ -- * Special identifiers defaultEntryPoint, - -- * Integer re-export+ -- * Number re-export Int8, Int16, Int32,@@ -42,6 +42,7 @@ Word16, Word32, Word64,+ Half, ) where @@ -52,6 +53,7 @@ import Data.Word (Word16, Word32, Word64, Word8) import Futhark.Util.Loc import Futhark.Util.Pretty+import Numeric.Half import Prelude hiding (id, (.)) -- | The uniqueness attribute of a type. This essentially indicates
src/Language/Futhark/Interpreter.hs view
@@ -69,13 +69,13 @@ BreakNaN data ExtOp a- = ExtOpTrace Loc String a- | ExtOpBreak BreakReason (NE.NonEmpty StackFrame) a+ = ExtOpTrace String String a+ | ExtOpBreak Loc BreakReason (NE.NonEmpty StackFrame) a | ExtOpError InterpreterError instance Functor ExtOp where fmap f (ExtOpTrace w s x) = ExtOpTrace w s $ f x- fmap f (ExtOpBreak why backtrace x) = ExtOpBreak why backtrace $ f x+ fmap f (ExtOpBreak w why backtrace x) = ExtOpBreak w why backtrace $ f x fmap _ (ExtOpError err) = ExtOpError err type Stack = [StackFrame]@@ -455,13 +455,9 @@ ss <- map (locStr . srclocOf) <$> stacktrace liftF $ ExtOpError $ InterpreterError $ "Error at\n" ++ prettyStacktrace 0 ss ++ s -trace :: Value -> EvalM ()-trace v = do- -- We take the second-to-top element of the stack, because any- -- actual call to 'implicits.trace' is going to be in the trace- -- function in the prelude, which is not interesting.- top <- fromMaybe noLoc . maybeHead . drop 1 <$> stacktrace- liftF $ ExtOpTrace top (prettyOneLine v) ()+trace :: String -> Value -> EvalM ()+trace w v = do+ liftF $ ExtOpTrace w (prettyOneLine v) () typeCheckerEnv :: Env -> T.Env typeCheckerEnv env =@@ -477,16 +473,12 @@ T.envVtable = vtable } -break :: EvalM ()-break = do- -- We don't want the env of the function that is calling- -- intrinsics.break, since that is just going to be the boring- -- wrapper function (intrinsics are never called directly).- -- This is why we go a step up the stack.- backtrace <- asks $ drop 1 . fst+break :: Loc -> EvalM ()+break loc = do+ backtrace <- asks fst case NE.nonEmpty backtrace of Nothing -> return ()- Just backtrace' -> liftF $ ExtOpBreak BreakPoint backtrace' ()+ Just backtrace' -> liftF $ ExtOpBreak loc BreakPoint backtrace' () fromArray :: Value -> (ValueShape, [Value]) fromArray (ValueArray shape as) = (shape, elems as)@@ -509,30 +501,30 @@ f' <- apply noLoc mempty f x apply noLoc mempty f' y -matchPattern :: Env -> Pattern -> Value -> EvalM Env-matchPattern env p v = do+matchPat :: Env -> Pat -> Value -> EvalM Env+matchPat env p v = do m <- runMaybeT $ patternMatch env p v case m of- Nothing -> error $ "matchPattern: missing case for " ++ pretty p ++ " and " ++ pretty v+ Nothing -> error $ "matchPat: missing case for " ++ pretty p ++ " and " ++ pretty v Just env' -> return env' -patternMatch :: Env -> Pattern -> Value -> MaybeT EvalM Env+patternMatch :: Env -> Pat -> Value -> MaybeT EvalM Env patternMatch env (Id v (Info t) _) val = lift $ pure $ valEnv (M.singleton v (Just $ T.BoundV [] $ toStruct t, val)) <> env patternMatch env Wildcard {} _ = lift $ pure env-patternMatch env (TuplePattern ps _) (ValueRecord vs) =+patternMatch env (TuplePat ps _) (ValueRecord vs) = foldM (\env' (p, v) -> patternMatch env' p v) env $ zip ps (map snd $ sortFields vs)-patternMatch env (RecordPattern ps _) (ValueRecord vs) =+patternMatch env (RecordPat ps _) (ValueRecord vs) = foldM (\env' (p, v) -> patternMatch env' p v) env $ M.intersectionWith (,) (M.fromList ps) vs-patternMatch env (PatternParens p _) v = patternMatch env p v-patternMatch env (PatternAscription p _ _) v =+patternMatch env (PatParens p _) v = patternMatch env p v+patternMatch env (PatAscription p _ _) v = patternMatch env p v-patternMatch env (PatternLit l t _) v = do+patternMatch env (PatLit l t _) v = do l' <- case l of PatLitInt x -> lift $ eval env $ IntLit x t mempty PatLitFloat x -> lift $ eval env $ FloatLit x t mempty@@ -540,7 +532,7 @@ if v == l' then pure env else mzero-patternMatch env (PatternConstr n _ ps _) (ValueSum _ n' vs)+patternMatch env (PatConstr n _ ps _) (ValueSum _ n' vs) | n == n' = foldM (\env' (p, v) -> patternMatch env' p v) env $ zip ps vs patternMatch _ _ _ = mzero@@ -723,7 +715,7 @@ dim (ConstDim x) = Just $ fromIntegral x dim _ = Nothing -evalFunction :: Env -> [VName] -> [Pattern] -> Exp -> StructType -> EvalM Value+evalFunction :: Env -> [VName] -> [Pat] -> Exp -> StructType -> EvalM Value -- We treat zero-parameter lambdas as simply an expression to -- evaluate immediately. Note that this is *not* the same as a lambda -- that takes an empty tuple '()' as argument! Zero-parameter lambdas@@ -736,7 +728,7 @@ etaExpand vs env' (Scalar (Arrow _ _ pt rt)) = return $ ValueFun $ \v -> do- env'' <- matchPattern env' (Wildcard (Info $ fromStruct pt) noLoc) v+ env'' <- matchPat env' (Wildcard (Info $ fromStruct pt) noLoc) v etaExpand (v : vs) env'' rt etaExpand vs env' _ = do f <- eval env' body@@ -744,7 +736,7 @@ evalFunction env missing_sizes (p : ps) body rettype = return $ ValueFun $ \v -> do- env' <- matchPattern env p v+ env' <- matchPat env p v -- Fix up the last sizes, if any. let p_t = evalType env $ patternStructType p env''@@ -756,7 +748,7 @@ evalFunctionBinding :: Env -> [TypeParam] ->- [Pattern] ->+ [Pat] -> StructType -> [VName] -> Exp ->@@ -864,7 +856,7 @@ <> "`)" evalAppExp env (LetPat sizes p e body _) = do v <- eval env e- env' <- matchPattern env p v+ env' <- matchPat env p v let p_t = evalType env $ patternStructType p v_s = valueShape v env'' = env' <> i64Env (resolveExistentials (map sizeName sizes) p_t v_s)@@ -938,7 +930,7 @@ sparams (patternStructType pat) (valueShape v)- in matchPattern (i64Env sparams' <> env) pat v+ in matchPat (i64Env sparams' <> env) pat v inc = (`P.doAdd` Int64Value 1) zero = (`P.doMul` Int64Value 0)@@ -969,14 +961,14 @@ forInLoop in_pat v in_v = do env' <- withLoopParams v- env'' <- matchPattern env' in_pat in_v+ env'' <- matchPat env' in_pat in_v eval env'' body evalAppExp env (Match e cs _) = do v <- eval env e match v (NE.toList cs) where match _ [] =- error "Pattern match failure."+ error "Pat match failure." match v (c : cs') = do c' <- evalCase v env c case c' of@@ -1041,9 +1033,17 @@ ValuePrim (UnsignedValue (Int16Value v)) -> return $ UnsignedValue $ Int16Value (- v) ValuePrim (UnsignedValue (Int32Value v)) -> return $ UnsignedValue $ Int32Value (- v) ValuePrim (UnsignedValue (Int64Value v)) -> return $ UnsignedValue $ Int64Value (- v)+ ValuePrim (FloatValue (Float16Value v)) -> return $ FloatValue $ Float16Value (- v) ValuePrim (FloatValue (Float32Value v)) -> return $ FloatValue $ Float32Value (- v) ValuePrim (FloatValue (Float64Value v)) -> return $ FloatValue $ Float64Value (- v) _ -> error $ "Cannot negate " ++ pretty ev+eval env (Not e _) = do+ ev <- eval env e+ ValuePrim <$> case ev of+ ValuePrim (BoolValue b) -> pure $ BoolValue $ not b+ ValuePrim (SignedValue iv) -> pure $ SignedValue $ P.doComplement iv+ ValuePrim (UnsignedValue iv) -> pure $ UnsignedValue $ P.doComplement iv+ _ -> error $ "Cannot logically negate " ++ pretty ev eval env (Update src is v loc) = maybe oob return =<< updateArray <$> mapM (evalDimIndex env) is <*> eval env src <*> eval env v@@ -1097,7 +1097,19 @@ vs <- mapM (eval env) es shape <- typeValueShape env $ toStruct t return $ ValueSum shape c vs-eval env (Attr _ e _) = eval env e+eval env (Attr (AttrAtom "break") e loc) = do+ break (locOf loc)+ eval env e+eval env (Attr (AttrAtom "trace") e loc) = do+ v <- eval env e+ trace (locStr (locOf loc)) v+ pure v+eval env (Attr (AttrComp "trace" [AttrAtom tag]) e _) = do+ v <- eval env e+ trace (nameToString tag) v+ pure v+eval env (Attr _ e _) =+ eval env e evalCase :: Value ->@@ -1217,6 +1229,7 @@ nanValue :: PrimValue -> Bool nanValue (FloatValue v) = case v of+ Float16Value x -> isNaN x Float32Value x -> isNaN x Float64Value x -> isNaN x nanValue _ = False@@ -1227,7 +1240,9 @@ backtrace <- asks fst case NE.nonEmpty backtrace of Nothing -> return ()- Just backtrace' -> liftF $ ExtOpBreak BreakNaN backtrace' ()+ Just backtrace' ->+ let loc = stackFrameLoc $ NE.head backtrace'+ in liftF $ ExtOpBreak loc BreakNaN backtrace' () breakOnNaN _ _ = return () @@ -1263,7 +1278,8 @@ ] intOp f = sintOp f ++ uintOp f floatOp f =- [ (getF, putF, P.doBinOp (f Float32)),+ [ (getF, putF, P.doBinOp (f Float16)),+ (getF, putF, P.doBinOp (f Float32)), (getF, putF, P.doBinOp (f Float64)) ] arithOp f g = Just $ bopDef $ intOp f ++ floatOp g@@ -1282,7 +1298,8 @@ (getU, Just . BoolValue, P.doCmpOp (f Int64)) ] floatCmp f =- [ (getF, Just . BoolValue, P.doCmpOp (f Float32)),+ [ (getF, Just . BoolValue, P.doCmpOp (f Float16)),+ (getF, Just . BoolValue, P.doCmpOp (f Float32)), (getF, Just . BoolValue, P.doCmpOp (f Float64)) ] boolCmp f = [(getB, Just . BoolValue, P.doCmpOp f)]@@ -1349,6 +1366,27 @@ Just [x, y, z, a, b, c] -> f x y z a b c _ -> error $ "Expected sextuple; got: " ++ pretty v + fun7t f =+ TermValue Nothing $+ ValueFun $ \v ->+ case fromTuple v of+ Just [x, y, z, a, b, c, d] -> f x y z a b c d+ _ -> error $ "Expected septuple; got: " ++ pretty v++ fun8t f =+ TermValue Nothing $+ ValueFun $ \v ->+ case fromTuple v of+ Just [x, y, z, a, b, c, d, e] -> f x y z a b c d e+ _ -> error $ "Expected sextuple; got: " ++ pretty v++ fun10t fun =+ TermValue Nothing $+ ValueFun $ \v ->+ case fromTuple v of+ Just [x, y, z, a, b, c, d, e, f, g] -> fun x y z a b c d e f g+ _ -> error $ "Expected octuple; got: " ++ pretty v+ bopDef fs = fun2 $ \x y -> case (x, y) of (ValuePrim x', ValuePrim y')@@ -1677,6 +1715,127 @@ else pure acc _ -> error $ "acc_write invalid arguments: " ++ pretty (acc, i, v)+ --+ def "flat_index_2d" = Just . fun6t $ \arr offset n1 s1 n2 s2 -> do+ let offset' = asInt64 offset+ n1' = asInt64 n1+ n2' = asInt64 n2+ s1' = asInt64 s1+ s2' = asInt64 s2+ shapeFromDims = foldr ShapeDim ShapeLeaf+ mk1 = fmap (toArray (shapeFromDims [n1', n2'])) . sequence+ mk2 = fmap (toArray $ shapeFromDims [n2']) . sequence+ iota x = [0 .. x -1]+ f i j =+ indexArray [IndexingFix $ offset' + i * s1' + j * s2'] arr++ case mk1 [mk2 [f i j | j <- iota n2'] | i <- iota n1'] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1', s1', n2', s2')]+ --+ def "flat_update_2d" = Just . fun5t $ \arr offset s1 s2 v -> do+ let offset' = asInt64 offset+ s1' = asInt64 s1+ s2' = asInt64 s2+ case valueShape v of+ ShapeDim n1 (ShapeDim n2 _) -> do+ let iota x = [0 .. x -1]+ f arr' (i, j) =+ updateArray [IndexingFix $ offset' + i * s1' + j * s2'] arr'+ =<< indexArray [IndexingFix i, IndexingFix j] v+ case foldM f arr [(i, j) | i <- iota n1, j <- iota n2] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1, s1', n2, s2')]+ s -> error $ "flat_update_2d: invalid arg shape: " ++ show s+ --+ def "flat_index_3d" = Just . fun8t $ \arr offset n1 s1 n2 s2 n3 s3 -> do+ let offset' = asInt64 offset+ n1' = asInt64 n1+ n2' = asInt64 n2+ n3' = asInt64 n3+ s1' = asInt64 s1+ s2' = asInt64 s2+ s3' = asInt64 s3+ shapeFromDims = foldr ShapeDim ShapeLeaf+ mk1 = fmap (toArray (shapeFromDims [n1', n2', n3'])) . sequence+ mk2 = fmap (toArray $ shapeFromDims [n2', n3']) . sequence+ mk3 = fmap (toArray $ shapeFromDims [n3']) . sequence+ iota x = [0 .. x -1]+ f i j l =+ indexArray [IndexingFix $ offset' + i * s1' + j * s2' + l * s3'] arr++ case mk1 [mk2 [mk3 [f i j l | l <- iota n3'] | j <- iota n2'] | i <- iota n1'] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1', s1', n2', s2', n3', s3')]+ --+ def "flat_update_3d" = Just . fun6t $ \arr offset s1 s2 s3 v -> do+ let offset' = asInt64 offset+ s1' = asInt64 s1+ s2' = asInt64 s2+ s3' = asInt64 s3+ case valueShape v of+ ShapeDim n1 (ShapeDim n2 (ShapeDim n3 _)) -> do+ let iota x = [0 .. x -1]+ f arr' (i, j, l) =+ updateArray [IndexingFix $ offset' + i * s1' + j * s2' + l * s3'] arr'+ =<< indexArray [IndexingFix i, IndexingFix j, IndexingFix l] v+ case foldM f arr [(i, j, l) | i <- iota n1, j <- iota n2, l <- iota n3] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1, s1', n2, s2', n3, s3')]+ s -> error $ "flat_update_3d: invalid arg shape: " ++ show s+ --+ def "flat_index_4d" = Just . fun10t $ \arr offset n1 s1 n2 s2 n3 s3 n4 s4 -> do+ let offset' = asInt64 offset+ n1' = asInt64 n1+ n2' = asInt64 n2+ n3' = asInt64 n3+ n4' = asInt64 n4+ s1' = asInt64 s1+ s2' = asInt64 s2+ s3' = asInt64 s3+ s4' = asInt64 s4+ shapeFromDims = foldr ShapeDim ShapeLeaf+ mk1 = fmap (toArray (shapeFromDims [n1', n2', n3', n4'])) . sequence+ mk2 = fmap (toArray $ shapeFromDims [n2', n3', n4']) . sequence+ mk3 = fmap (toArray $ shapeFromDims [n3', n4']) . sequence+ mk4 = fmap (toArray $ shapeFromDims [n4']) . sequence+ iota x = [0 .. x -1]+ f i j l m =+ indexArray [IndexingFix $ offset' + i * s1' + j * s2' + l * s3' + m * s4'] arr++ case mk1 [mk2 [mk3 [mk4 [f i j l m | m <- iota n4'] | l <- iota n3'] | j <- iota n2'] | i <- iota n1'] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1', s1', n2', s2', n3', s3', n4', s4')]+ --+ def "flat_update_4d" = Just . fun7t $ \arr offset s1 s2 s3 s4 v -> do+ let offset' = asInt64 offset+ s1' = asInt64 s1+ s2' = asInt64 s2+ s3' = asInt64 s3+ s4' = asInt64 s4+ case valueShape v of+ ShapeDim n1 (ShapeDim n2 (ShapeDim n3 (ShapeDim n4 _))) -> do+ let iota x = [0 .. x -1]+ f arr' (i, j, l, m) =+ updateArray [IndexingFix $ offset' + i * s1' + j * s2' + l * s3' + m * s4'] arr'+ =<< indexArray [IndexingFix i, IndexingFix j, IndexingFix l, IndexingFix m] v+ case foldM f arr [(i, j, l, m) | i <- iota n1, j <- iota n2, l <- iota n3, m <- iota n4] of+ Just arr' -> pure arr'+ Nothing ->+ bad mempty mempty $+ "Index out of bounds: " ++ pretty [(n1, s1', n2, s2', n3, s3', n4, s4')]+ s -> error $ "flat_update_4d: invalid arg shape: " ++ show s+ -- def "unzip" = Just $ fun1 $ \x -> do let ShapeDim _ (ShapeRecord fs) = valueShape x@@ -1728,12 +1887,6 @@ rowshape = ShapeDim (asInt64 m) innershape shape = ShapeDim (asInt64 n) rowshape return $ toArray shape $ map (toArray rowshape) $ chunk (asInt m) xs'- def "opaque" = Just $ fun1 return- def "trace" = Just $ fun1 $ \v -> trace v >> return v- def "break" = Just $- fun1 $ \v -> do- break- return v def "acc" = Nothing def s | nameFromString s `M.member` namesToPrimTypes = Nothing def s = error $ "Missing intrinsic: " ++ s
src/Language/Futhark/Parser/Lexer.x view
@@ -23,7 +23,7 @@ import Data.List import Data.Monoid import Data.Either-import Numeric+import Numeric.Half import Language.Futhark.Core (Int8, Int16, Int32, Int64, Word8, Word16, Word32, Word64,@@ -51,9 +51,6 @@ @identifier = [a-zA-Z] [a-zA-Z0-9_']* | "_" [a-zA-Z0-9] [a-zA-Z0-9_']* @qualidentifier = (@identifier ".")+ @identifier -@unop = "!"-@qualunop = (@identifier ".")+ @unop- $opchar = [\+\-\*\/\%\=\!\>\<\|\&\^\.] @binop = ($opchar # \.) $opchar* @qualbinop = (@identifier ".")+ @binop@@ -94,6 +91,7 @@ "..." { tokenC THREE_DOTS } ".." { tokenC TWO_DOTS } "." { tokenC DOT }+ "!" { tokenC BANG } @intlit i8 { tokenM $ return . I8LIT . readIntegral . T.filter (/= '_') . T.takeWhile (/='i') } @intlit i16 { tokenM $ return . I16LIT . readIntegral . T.filter (/= '_') . T.takeWhile (/='i') }@@ -105,14 +103,16 @@ @intlit u64 { tokenM $ return . U64LIT . readIntegral . T.filter (/= '_') . T.takeWhile (/='u') } @intlit { tokenM $ return . INTLIT . readIntegral . T.filter (/= '_') } + @reallit f16 { tokenM $ fmap F16LIT . tryRead "f16" . suffZero . T.filter (/= '_') . T.takeWhile (/='f') } @reallit f32 { tokenM $ fmap F32LIT . tryRead "f32" . suffZero . T.filter (/= '_') . T.takeWhile (/='f') } @reallit f64 { tokenM $ fmap F64LIT . tryRead "f64" . suffZero . T.filter (/= '_') . T.takeWhile (/='f') } @reallit { tokenM $ fmap FLOATLIT . tryRead "f64" . suffZero . T.filter (/= '_') }+ @hexreallit f16 { tokenM $ fmap F16LIT . readHexRealLit . T.filter (/= '_') . T.dropEnd 3 } @hexreallit f32 { tokenM $ fmap F32LIT . readHexRealLit . T.filter (/= '_') . T.dropEnd 3 } @hexreallit f64 { tokenM $ fmap F64LIT . readHexRealLit . T.filter (/= '_') . T.dropEnd 3 } @hexreallit { tokenM $ fmap FLOATLIT . readHexRealLit . T.filter (/= '_') } "'" @charlit "'" { tokenM $ fmap CHARLIT . tryRead "char" }- \" @stringcharlit* \" { tokenM $ fmap STRINGLIT . tryRead "string" }+ \" @stringcharlit* \" { tokenM $ fmap (STRINGLIT . T.pack) . tryRead "string" } @identifier { tokenS keyword } @identifier "[" { tokenM $ fmap INDEXING . indexing . T.takeWhile (/='[') }@@ -121,9 +121,6 @@ @qualidentifier "." "(" { tokenM $ fmap (uncurry QUALPAREN) . mkQualId . T.init . T.takeWhile (/='(') } "#" @identifier { tokenS $ CONSTRUCTOR . nameFromText . T.drop 1 } - @unop { tokenS $ UNOP . nameFromText }- @qualunop { tokenM $ fmap (uncurry QUALUNOP) . mkQualId }- @binop { tokenM $ return . symbol [] . nameFromText } @qualbinop { tokenM $ \s -> do (qs,k) <- mkQualId s; return (symbol qs k) } @@ -287,14 +284,12 @@ | INDEXING Name | QUALINDEXING [Name] Name | QUALPAREN [Name] Name- | UNOP Name- | QUALUNOP [Name] Name | SYMBOL BinOp [Name] Name | CONSTRUCTOR Name | PROJ_INTFIELD Name | INTLIT Integer- | STRINGLIT String+ | STRINGLIT T.Text | I8LIT Int8 | I16LIT Int16 | I32LIT Int32@@ -304,6 +299,7 @@ | U32LIT Word32 | U64LIT Word64 | FLOATLIT Double+ | F16LIT Half | F32LIT Float | F64LIT Double | CHARLIT Char@@ -335,6 +331,7 @@ | EQU | ASTERISK | NEGATE+ | BANG | LTH | HAT | TILDE
src/Language/Futhark/Parser/Parser.y view
@@ -24,8 +24,9 @@ import Control.Monad.Reader import Control.Monad.Trans.State import Data.Array+import qualified Data.ByteString as BS import qualified Data.Text as T-import Codec.Binary.UTF8.String (encode)+import qualified Data.Text.Encoding as T import Data.Char (ord) import Data.Maybe (fromMaybe, fromJust) import Data.List (genericLength)@@ -72,9 +73,6 @@ 'qid.(' { L _ (QUALPAREN _ _) } - unop { L _ (UNOP _) }- qunop { L _ (QUALUNOP _ _) }- constructor { L _ (CONSTRUCTOR _) } '.int' { L _ (PROJ_INTFIELD _) }@@ -89,6 +87,7 @@ u32lit { L _ (U32LIT _) } u64lit { L _ (U64LIT _) } floatlit { L _ (FLOATLIT _) }+ f16lit { L _ (F16LIT _) } f32lit { L _ (F32LIT _) } f64lit { L _ (F64LIT _) } stringlit { L _ (STRINGLIT _) }@@ -103,6 +102,7 @@ '*' { L $$ ASTERISK } '-' { L $$ NEGATE }+ '!' { L $$ BANG } '<' { L $$ LTH } '^' { L $$ HAT } '~' { L $$ TILDE }@@ -222,7 +222,7 @@ | ModBind { ModDec $1 } | open ModExp { OpenDec $2 $1 } | import stringlit- { let L _ (STRINGLIT s) = $2 in ImportDec s NoInfo (srcspan $1 $>) }+ { let L _ (STRINGLIT s) = $2 in ImportDec (T.unpack s) NoInfo (srcspan $1 $>) } | local Dec { LocalDec $2 (srcspan $1 $>) } | '#[' AttrInfo ']' Dec_ { addAttr $2 $4 }@@ -254,7 +254,7 @@ | '\\' ModParam maybeAscription(SimpleSigExp) '->' ModExp { ModLambda $2 (fmap (,NoInfo) $3) $5 (srcspan $1 $>) } | import stringlit- { let L _ (STRINGLIT s) = $2 in ModImport s NoInfo (srcspan $1 $>) }+ { let L _ (STRINGLIT s) = $2 in ModImport (T.unpack s) NoInfo (srcspan $1 $>) } | ModExpApply { $1 } | ModExpAtom@@ -302,8 +302,6 @@ in ValSpec name $3 $5 Nothing (srcspan $1 $>) } | val BindingBinOp TypeParams ':' TypeExpDecl { ValSpec $2 $3 $5 Nothing (srcspan $1 $>) }- | val BindingUnOp TypeParams ':' TypeExpDecl- { ValSpec $2 $3 $5 Nothing (srcspan $1 $>) } | TypeAbbr { TypeAbbrSpec $1 } @@ -345,10 +343,6 @@ : TypeParam TypeParams { $1 : $2 } | { [] } -UnOp :: { (QualName Name, SrcLoc) }- : qunop { let L loc (QUALUNOP qs v) = $1 in (QualName qs v, loc) }- | unop { let L loc (UNOP v) = $1 in (qualName v, loc) }- -- Note that this production does not include Minus, but does include -- operator sections. BinOp :: { (QualName Name, SrcLoc) }@@ -381,12 +375,6 @@ | '<' { (qualName (nameFromString "<"), $1) } | '`' QualName '`' { $2 } -BindingUnOp :: { Name }- : UnOp {% let (QualName qs name, loc) = $1 in do- unless (null qs) $ parseErrorAt loc $- Just "Cannot use a qualified name in binding position."- return name }- BindingBinOp :: { Name } : BinOp {% let (QualName qs name, loc) = $1 in do unless (null qs) $ parseErrorAt loc $@@ -397,7 +385,6 @@ BindingId :: { (Name, SrcLoc) } : id { let L loc (ID name) = $1 in (name, loc) } | '(' BindingBinOp ')' { ($2, $1) }- | '(' BindingUnOp ')' { ($2, $1) } Val :: { ValBindBase NoInfo Name } Val : let BindingId TypeParams FunParams maybeAscription(TypeExpDecl) '=' Exp@@ -416,11 +403,6 @@ Nothing mempty (srcspan $1 $>) } - | let BindingUnOp TypeParams FunParams maybeAscription(TypeExpDecl) '=' Exp- { ValBind Nothing $2 (fmap declaredType $5) NoInfo $3 $4 $7- Nothing mempty (srcspan $1 $>)- }- TypeExpDecl :: { TypeDeclBase NoInfo Name } : TypeExp %prec bottom { TypeDecl $1 NoInfo } @@ -518,14 +500,14 @@ { let L loc (INTLIT n) = $1 in DimExpConst (fromIntegral n) loc } -FunParam :: { PatternBase NoInfo Name }-FunParam : InnerPattern { $1 }+FunParam :: { PatBase NoInfo Name }+FunParam : InnerPat { $1 } -FunParams1 :: { (PatternBase NoInfo Name, [PatternBase NoInfo Name]) }+FunParams1 :: { (PatBase NoInfo Name, [PatBase NoInfo Name]) } FunParams1 : FunParam { ($1, []) } | FunParam FunParams1 { ($1, fst $2 : snd $2) } -FunParams :: { [PatternBase NoInfo Name] }+FunParams :: { [PatBase NoInfo Name] } FunParams : { [] } | FunParam FunParams { $1 : $2 } @@ -549,10 +531,10 @@ : if Exp then Exp else Exp %prec ifprec { AppExp (If $2 $4 $6 (srcspan $1 $>)) NoInfo } - | loop Pattern LoopForm do Exp %prec ifprec+ | loop Pat LoopForm do Exp %prec ifprec {% fmap (\t -> AppExp (DoLoop [] $2 t $3 $5 (srcspan $1 $>)) NoInfo) (patternExp $2) } - | loop Pattern '=' Exp LoopForm do Exp %prec ifprec+ | loop Pat '=' Exp LoopForm do Exp %prec ifprec { AppExp (DoLoop [] $2 $4 $5 $7 (srcspan $1 $>)) NoInfo } | LetExp %prec letprec { $1 }@@ -602,9 +584,10 @@ | Exp2 '..' Exp2 '..>' Exp2 { AppExp (Range $1 (Just $3) (DownToExclusive $5) (srcspan $1 $>)) NoInfo } | Exp2 '..' Atom {% twoDotsRange $2 } | Atom '..' Exp2 {% twoDotsRange $2 }- | '-' Exp2- { Negate $2 $1 }+ | '-' Exp2 %prec juxtprec { Negate $2 $1 }+ | '!' Exp2 %prec juxtprec { Not $2 $1 } + | Exp2 with '[' DimIndices ']' '=' Exp2 { Update $1 $4 $7 (srcspan $1 $>) } @@ -622,8 +605,6 @@ ApplyList :: { [UncheckedExp] } : ApplyList Atom %prec juxtprec { $1 ++ [$2] }- | UnOp Atom %prec juxtprec- { [Var (fst $1) NoInfo (snd $1), $2] } | Atom %prec juxtprec { [$1] } @@ -635,7 +616,7 @@ | intlit { let L loc (INTLIT x) = $1 in IntLit x NoInfo loc } | floatlit { let L loc (FLOATLIT x) = $1 in FloatLit x NoInfo loc } | stringlit { let L loc (STRINGLIT s) = $1 in- StringLit (encode s) loc }+ StringLit (BS.unpack (T.encodeUtf8 s)) loc } | '(' Exp ')' FieldAccesses { foldl (\x (y, _) -> Project y x NoInfo (srclocOf x)) (Parens $2 (srcspan $1 ($3:map snd $>)))@@ -659,8 +640,8 @@ QualParens (QualName qs name, loc) $2 (srcspan $1 $>) } -- Operator sections.- | '(' UnOp ')'- { Var (fst $2) NoInfo (srcspan (snd $2) $>) }+ | '(' '!' ')'+ { Var (qualName "!") NoInfo (srcspan $2 $>) } | '(' '-' ')' { OpSection (qualName (nameFromString "-")) NoInfo (srcspan $1 $>) } | '(' Exp2 '-' ')'@@ -694,6 +675,7 @@ | u32lit { let L loc (U32LIT num) = $1 in (UnsignedValue $ Int32Value $ fromIntegral num, loc) } | u64lit { let L loc (U64LIT num) = $1 in (UnsignedValue $ Int64Value $ fromIntegral num, loc) } + | f16lit { let L loc (F16LIT num) = $1 in (FloatValue $ Float16Value num, loc) } | f32lit { let L loc (F32LIT num) = $1 in (FloatValue $ Float32Value num, loc) } | f64lit { let L loc (F64LIT num) = $1 in (FloatValue $ Float64Value num, loc) } @@ -730,9 +712,9 @@ | Field { [$1] } LetExp :: { UncheckedExp }- : let SizeBinders1 Pattern '=' Exp LetBody+ : let SizeBinders1 Pat '=' Exp LetBody { AppExp (LetPat $2 $3 $5 $6 (srcspan $1 $>)) NoInfo }- | let Pattern '=' Exp LetBody+ | let Pat '=' Exp LetBody { AppExp (LetPat [] $2 $4 $5 (srcspan $1 $>)) NoInfo } | let id TypeParams FunParams1 maybeAscription(TypeExpDecl) '=' Exp LetBody@@ -760,52 +742,51 @@ | Case Cases { NE.cons $1 $2 } Case :: { CaseBase NoInfo Name }- : case CPattern '->' Exp+ : case CPat '->' Exp { let loc = srcspan $1 $> in CasePat $2 $> loc } -CPattern :: { PatternBase NoInfo Name }- : CInnerPattern ':' TypeExpDecl { PatternAscription $1 $3 (srcspan $1 $>) }- | CInnerPattern { $1 }+CPat :: { PatBase NoInfo Name }+ : CInnerPat ':' TypeExpDecl { PatAscription $1 $3 (srcspan $1 $>) }+ | CInnerPat { $1 } | Constr ConstrFields { let (n, loc) = $1; loc' = srcspan loc $>- in PatternConstr n NoInfo $2 loc'}+ in PatConstr n NoInfo $2 loc'} -CPatterns1 :: { [PatternBase NoInfo Name] }- : CPattern { [$1] }- | CPattern ',' CPatterns1 { $1 : $3 }+CPats1 :: { [PatBase NoInfo Name] }+ : CPat { [$1] }+ | CPat ',' CPats1 { $1 : $3 } -CInnerPattern :: { PatternBase NoInfo Name }+CInnerPat :: { PatBase NoInfo Name } : id { let L loc (ID name) = $1 in Id name NoInfo loc } | '(' BindingBinOp ')' { Id $2 NoInfo (srcspan $1 $>) }- | '(' BindingUnOp ')' { Id $2 NoInfo (srcspan $1 $>) } | '_' { Wildcard NoInfo $1 }- | '(' ')' { TuplePattern [] (srcspan $1 $>) }- | '(' CPattern ')' { PatternParens $2 (srcspan $1 $>) }- | '(' CPattern ',' CPatterns1 ')' { TuplePattern ($2:$4) (srcspan $1 $>) }- | '{' CFieldPatterns '}' { RecordPattern $2 (srcspan $1 $>) }- | CaseLiteral { PatternLit (fst $1) NoInfo (snd $1) }+ | '(' ')' { TuplePat [] (srcspan $1 $>) }+ | '(' CPat ')' { PatParens $2 (srcspan $1 $>) }+ | '(' CPat ',' CPats1 ')' { TuplePat ($2:$4) (srcspan $1 $>) }+ | '{' CFieldPats '}' { RecordPat $2 (srcspan $1 $>) }+ | CaseLiteral { PatLit (fst $1) NoInfo (snd $1) } | Constr { let (n, loc) = $1- in PatternConstr n NoInfo [] loc }+ in PatConstr n NoInfo [] loc } -ConstrFields :: { [PatternBase NoInfo Name] }- : CInnerPattern { [$1] }- | ConstrFields CInnerPattern { $1 ++ [$2] }+ConstrFields :: { [PatBase NoInfo Name] }+ : CInnerPat { [$1] }+ | ConstrFields CInnerPat { $1 ++ [$2] } -CFieldPattern :: { (Name, PatternBase NoInfo Name) }- : FieldId '=' CPattern+CFieldPat :: { (Name, PatBase NoInfo Name) }+ : FieldId '=' CPat { (fst $1, $3) } | FieldId ':' TypeExpDecl- { (fst $1, PatternAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }+ { (fst $1, PatAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) } | FieldId { (fst $1, Id (fst $1) NoInfo (snd $1)) } -CFieldPatterns :: { [(Name, PatternBase NoInfo Name)] }- : CFieldPatterns1 { $1 }+CFieldPats :: { [(Name, PatBase NoInfo Name)] }+ : CFieldPats1 { $1 } | { [] } -CFieldPatterns1 :: { [(Name, PatternBase NoInfo Name)] }- : CFieldPattern ',' CFieldPatterns1 { $1 : $3 }- | CFieldPattern { [$1] }+CFieldPats1 :: { [(Name, PatBase NoInfo Name)] }+ : CFieldPat ',' CFieldPats1 { $1 : $3 }+ | CFieldPat { [$1] } CaseLiteral :: { (PatLit, SrcLoc) } : PrimLit { (PatLitPrim (fst $1), snd $1) }@@ -817,7 +798,7 @@ LoopForm :: { LoopFormBase NoInfo Name } LoopForm : for VarId '<' Exp { For $2 $4 }- | for Pattern in Exp+ | for Pat in Exp { ForIn $2 $4 } | while Exp { While $2 }@@ -860,39 +841,38 @@ : id { let L loc (ID name) = $1 in (name, loc) } | intlit { let L loc (INTLIT n) = $1 in (nameFromString (show n), loc) } -Pattern :: { PatternBase NoInfo Name }-Pattern : InnerPattern ':' TypeExpDecl { PatternAscription $1 $3 (srcspan $1 $>) }- | InnerPattern { $1 }+Pat :: { PatBase NoInfo Name }+Pat : InnerPat ':' TypeExpDecl { PatAscription $1 $3 (srcspan $1 $>) }+ | InnerPat { $1 } -Patterns1 :: { [PatternBase NoInfo Name] }- : Pattern { [$1] }- | Pattern ',' Patterns1 { $1 : $3 }+Pats1 :: { [PatBase NoInfo Name] }+ : Pat { [$1] }+ | Pat ',' Pats1 { $1 : $3 } -InnerPattern :: { PatternBase NoInfo Name }-InnerPattern : id { let L loc (ID name) = $1 in Id name NoInfo loc }+InnerPat :: { PatBase NoInfo Name }+InnerPat : id { let L loc (ID name) = $1 in Id name NoInfo loc } | '(' BindingBinOp ')' { Id $2 NoInfo (srcspan $1 $>) }- | '(' BindingUnOp ')' { Id $2 NoInfo (srcspan $1 $>) } | '_' { Wildcard NoInfo $1 }- | '(' ')' { TuplePattern [] (srcspan $1 $>) }- | '(' Pattern ')' { PatternParens $2 (srcspan $1 $>) }- | '(' Pattern ',' Patterns1 ')' { TuplePattern ($2:$4) (srcspan $1 $>) }- | '{' FieldPatterns '}' { RecordPattern $2 (srcspan $1 $>) }+ | '(' ')' { TuplePat [] (srcspan $1 $>) }+ | '(' Pat ')' { PatParens $2 (srcspan $1 $>) }+ | '(' Pat ',' Pats1 ')' { TuplePat ($2:$4) (srcspan $1 $>) }+ | '{' FieldPats '}' { RecordPat $2 (srcspan $1 $>) } -FieldPattern :: { (Name, PatternBase NoInfo Name) }- : FieldId '=' Pattern+FieldPat :: { (Name, PatBase NoInfo Name) }+ : FieldId '=' Pat { (fst $1, $3) } | FieldId ':' TypeExpDecl- { (fst $1, PatternAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }+ { (fst $1, PatAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) } | FieldId { (fst $1, Id (fst $1) NoInfo (snd $1)) } -FieldPatterns :: { [(Name, PatternBase NoInfo Name)] }- : FieldPatterns1 { $1 }+FieldPats :: { [(Name, PatBase NoInfo Name)] }+ : FieldPats1 { $1 } | { [] } -FieldPatterns1 :: { [(Name, PatternBase NoInfo Name)] }- : FieldPattern ',' FieldPatterns1 { $1 : $3 }- | FieldPattern { [$1] }+FieldPats1 :: { [(Name, PatBase NoInfo Name)] }+ : FieldPat ',' FieldPats1 { $1 : $3 }+ | FieldPat { [$1] } maybeAscription(p) : ':' p { Just $2 }@@ -932,7 +912,7 @@ StringValue :: { Value } StringValue : stringlit { let L pos (STRINGLIT s) = $1 in- ArrayValue (arrayFromList $ map (PrimValue . UnsignedValue . Int8Value . fromIntegral) $ encode s) $ Scalar $ Prim $ Signed Int32 }+ ArrayValue (arrayFromList $ map (PrimValue . UnsignedValue . Int8Value . fromIntegral) $ BS.unpack $ T.encodeUtf8 s) $ Scalar $ Prim $ Signed Int32 } BoolValue :: { Value } BoolValue : true { PrimValue $ BoolValue True }@@ -953,10 +933,13 @@ | u64lit { let L pos (U64LIT num) = $1 in (Int64Value $ fromIntegral num, pos) } FloatLit :: { (FloatValue, SrcLoc) }- : f32lit { let L loc (F32LIT num) = $1 in (Float32Value num, loc) }+ : f16lit { let L loc (F16LIT num) = $1 in (Float16Value num, loc) }+ | f32lit { let L loc (F32LIT num) = $1 in (Float32Value num, loc) } | f64lit { let L loc (F64LIT num) = $1 in (Float64Value num, loc) } | QualName {% let (qn, loc) = $1 in case qn of+ QualName ["f16"] "inf" -> return (Float16Value (1/0), loc)+ QualName ["f16"] "nan" -> return (Float16Value (0/0), loc) QualName ["f32"] "inf" -> return (Float32Value (1/0), loc) QualName ["f32"] "nan" -> return (Float32Value (0/0), loc) QualName ["f64"] "inf" -> return (Float64Value (1/0), loc)@@ -1107,13 +1090,13 @@ ap f x = return $ AppExp (Apply f x NoInfo (srcspan f x)) NoInfo -patternExp :: UncheckedPattern -> ParserMonad UncheckedExp+patternExp :: UncheckedPat -> ParserMonad UncheckedExp patternExp (Id v _ loc) = return $ Var (qualName v) NoInfo loc-patternExp (TuplePattern pats loc) = TupLit <$> (mapM patternExp pats) <*> return loc+patternExp (TuplePat pats loc) = TupLit <$> (mapM patternExp pats) <*> return loc patternExp (Wildcard _ loc) = parseErrorAt loc $ Just "cannot have wildcard here."-patternExp (PatternAscription pat _ _) = patternExp pat-patternExp (PatternParens pat _) = patternExp pat-patternExp (RecordPattern fs loc) = RecordLit <$> mapM field fs <*> pure loc+patternExp (PatAscription pat _ _) = patternExp pat+patternExp (PatParens pat _) = patternExp pat+patternExp (RecordPat fs loc) = RecordLit <$> mapM field fs <*> pure loc where field (name, pat) = RecordFieldExplicit name <$> patternExp pat <*> pure loc eof :: Pos -> L Token@@ -1144,6 +1127,7 @@ intNegate (Int64Value v) = Int64Value (-v) floatNegate :: FloatValue -> FloatValue+floatNegate (Float16Value v) = Float16Value (-v) floatNegate (Float32Value v) = Float32Value (-v) floatNegate (Float64Value v) = Float64Value (-v)
src/Language/Futhark/Pretty.hs view
@@ -15,9 +15,9 @@ ) where -import Codec.Binary.UTF8.String (decode) import Control.Monad import Data.Array+import Data.Char (chr) import Data.Functor import Data.List (intersperse) import qualified Data.List.NonEmpty as NE@@ -320,9 +320,10 @@ text "@" <> parens (align $ ppr t) _ -> mempty pprPrec _ (StringLit s _) =- text $ show $ decode s+ text $ show $ map (chr . fromIntegral) s pprPrec _ (Project k e _ _) = ppr e <> text "." <> ppr k pprPrec _ (Negate e _) = text "-" <> ppr e+ pprPrec _ (Not e _) = text "-" <> ppr e pprPrec _ (Update src idxs ve _) = ppr src <+> text "with" <+> brackets (commasep (map ppr idxs))@@ -379,21 +380,21 @@ ppr (PatLitFloat f) = ppr f ppr (PatLitPrim v) = ppr v -instance (Eq vn, IsName vn, Annot f) => Pretty (PatternBase f vn) where- ppr (PatternAscription p t _) = ppr p <> colon <+> align (ppr t)- ppr (PatternParens p _) = parens $ ppr p+instance (Eq vn, IsName vn, Annot f) => Pretty (PatBase f vn) where+ ppr (PatAscription p t _) = ppr p <> colon <+> align (ppr t)+ ppr (PatParens p _) = parens $ ppr p ppr (Id v t _) = case unAnnot t of Just t' -> parens $ pprName v <> colon <+> align (ppr t') Nothing -> pprName v- ppr (TuplePattern pats _) = parens $ commasep $ map ppr pats- ppr (RecordPattern fs _) = braces $ commasep $ map ppField fs+ ppr (TuplePat pats _) = parens $ commasep $ map ppr pats+ ppr (RecordPat fs _) = braces $ commasep $ map ppField fs where ppField (name, t) = text (nameToString name) <> equals <> ppr t ppr (Wildcard t _) = case unAnnot t of Just t' -> parens $ text "_" <> colon <+> ppr t' Nothing -> text "_"- ppr (PatternLit e _ _) = ppr e- ppr (PatternConstr n _ ps _) = text "#" <> ppr n <+> sep (map ppr ps)+ ppr (PatLit e _ _) = ppr e+ ppr (PatConstr n _ ps _) = text "#" <> ppr n <+> sep (map ppr ps) ppAscription :: Pretty t => Maybe t -> Doc ppAscription Nothing = mempty
src/Language/Futhark/Prop.hs view
@@ -31,8 +31,8 @@ funType, -- * Queries on patterns and params- patternIdents,- patternNames,+ patIdents,+ patNames, patternMap, patternType, patternStructType,@@ -53,7 +53,6 @@ foldFunType, typeVars, typeDimNames,- primByteSize, -- * Operations on types peelArray,@@ -96,7 +95,7 @@ UncheckedModExp, UncheckedSigExp, UncheckedTypeParam,- UncheckedPattern,+ UncheckedPat, UncheckedValBind, UncheckedDec, UncheckedSpec,@@ -514,6 +513,7 @@ intValueType Int64Value {} = Int64 floatValueType :: FloatValue -> FloatType+floatValueType Float16Value {} = Float16 floatValueType Float32Value {} = Float32 floatValueType Float64Value {} = Float64 @@ -529,17 +529,10 @@ valueType (PrimValue bv) = Scalar $ Prim $ primValueType bv valueType (ArrayValue _ t) = t --- | The size of values of this type, in bytes.-primByteSize :: Num a => PrimType -> a-primByteSize (Signed it) = Primitive.intByteSize it-primByteSize (Unsigned it) = Primitive.intByteSize it-primByteSize (FloatType ft) = Primitive.floatByteSize ft-primByteSize Bool = 1- -- | The type is leaving a scope, so clean up any aliases that -- reference the bound variables, and turn any dimensions that name -- them into AnyDim instead.-unscopeType :: S.Set VName -> PatternType -> PatternType+unscopeType :: S.Set VName -> PatType -> PatType unscopeType bound_here t = first onDim $ t `addAliases` S.map unbind where unbind (AliasBound v) | v `S.member` bound_here = AliasFree v@@ -551,7 +544,7 @@ -- | The type of an Futhark term. The aliasing will refer to itself, if -- the term is a non-tuple-typed variable.-typeOf :: ExpBase Info VName -> PatternType+typeOf :: ExpBase Info VName -> PatType typeOf (Literal val _) = Scalar $ Prim $ primValueType val typeOf (IntLit _ (Info t) _) = t typeOf (FloatLit _ (Info t) _) = t@@ -578,6 +571,7 @@ typeOf (Var _ (Info t) _) = t typeOf (Ascript e _ _) = typeOf e typeOf (Negate e _) = typeOf e+typeOf (Not e _) = typeOf e typeOf (Update e _ _ _) = typeOf e `setAliases` mempty typeOf (RecordUpdate _ _ _ (Info t) _) = t typeOf (Assert _ e _ _) = typeOf e@@ -585,7 +579,7 @@ unscopeType bound_here $ foldr (arrow . patternParam) t params `setAliases` als where bound_here =- S.map identName (mconcat $ map patternIdents params)+ S.map identName (mconcat $ map patIdents params) `S.difference` S.fromList (mapMaybe (named . patternParam) params) arrow (px, tx) y = Scalar $ Arrow () px tx y named (Named x, _) = Just x@@ -626,7 +620,7 @@ ) -- | The type of a function with the given parameters and return type.-funType :: [PatternBase Info VName] -> StructType -> StructType+funType :: [PatBase Info VName] -> StructType -> StructType funType params ret = foldr (arrow . patternParam) ret params where arrow (xp, xt) yt = Scalar $ Arrow () xp xt yt@@ -659,16 +653,16 @@ orderZero (Scalar (Sum cs)) = all (all orderZero) cs -- | Extract all the shape names that occur in a given pattern.-patternDimNames :: PatternBase Info VName -> S.Set VName-patternDimNames (TuplePattern ps _) = foldMap patternDimNames ps-patternDimNames (RecordPattern fs _) = foldMap (patternDimNames . snd) fs-patternDimNames (PatternParens p _) = patternDimNames p+patternDimNames :: PatBase Info VName -> S.Set VName+patternDimNames (TuplePat ps _) = foldMap patternDimNames ps+patternDimNames (RecordPat fs _) = foldMap (patternDimNames . snd) fs+patternDimNames (PatParens p _) = patternDimNames p patternDimNames (Id _ (Info tp) _) = typeDimNames tp patternDimNames (Wildcard (Info tp) _) = typeDimNames tp-patternDimNames (PatternAscription p (TypeDecl _ (Info t)) _) =+patternDimNames (PatAscription p (TypeDecl _ (Info t)) _) = patternDimNames p <> typeDimNames t-patternDimNames (PatternLit _ (Info tp) _) = typeDimNames tp-patternDimNames (PatternConstr _ _ ps _) = foldMap patternDimNames ps+patternDimNames (PatLit _ (Info tp) _) = typeDimNames tp+patternDimNames (PatConstr _ _ ps _) = foldMap patternDimNames ps -- | Extract all the shape names that occur in a given type. typeDimNames :: TypeBase (DimDecl VName) als -> S.Set VName@@ -680,67 +674,67 @@ -- | @patternOrderZero pat@ is 'True' if all of the types in the given pattern -- have order 0.-patternOrderZero :: PatternBase Info vn -> Bool+patternOrderZero :: PatBase Info vn -> Bool patternOrderZero pat = case pat of- TuplePattern ps _ -> all patternOrderZero ps- RecordPattern fs _ -> all (patternOrderZero . snd) fs- PatternParens p _ -> patternOrderZero p+ TuplePat ps _ -> all patternOrderZero ps+ RecordPat fs _ -> all (patternOrderZero . snd) fs+ PatParens p _ -> patternOrderZero p Id _ (Info t) _ -> orderZero t Wildcard (Info t) _ -> orderZero t- PatternAscription p _ _ -> patternOrderZero p- PatternLit _ (Info t) _ -> orderZero t- PatternConstr _ _ ps _ -> all patternOrderZero ps+ PatAscription p _ _ -> patternOrderZero p+ PatLit _ (Info t) _ -> orderZero t+ PatConstr _ _ ps _ -> all patternOrderZero ps -- | The set of identifiers bound in a pattern.-patternIdents :: (Functor f, Ord vn) => PatternBase f vn -> S.Set (IdentBase f vn)-patternIdents (Id v t loc) = S.singleton $ Ident v t loc-patternIdents (PatternParens p _) = patternIdents p-patternIdents (TuplePattern pats _) = mconcat $ map patternIdents pats-patternIdents (RecordPattern fs _) = mconcat $ map (patternIdents . snd) fs-patternIdents Wildcard {} = mempty-patternIdents (PatternAscription p _ _) = patternIdents p-patternIdents PatternLit {} = mempty-patternIdents (PatternConstr _ _ ps _) = mconcat $ map patternIdents ps+patIdents :: (Functor f, Ord vn) => PatBase f vn -> S.Set (IdentBase f vn)+patIdents (Id v t loc) = S.singleton $ Ident v t loc+patIdents (PatParens p _) = patIdents p+patIdents (TuplePat pats _) = mconcat $ map patIdents pats+patIdents (RecordPat fs _) = mconcat $ map (patIdents . snd) fs+patIdents Wildcard {} = mempty+patIdents (PatAscription p _ _) = patIdents p+patIdents PatLit {} = mempty+patIdents (PatConstr _ _ ps _) = mconcat $ map patIdents ps -- | The set of names bound in a pattern.-patternNames :: (Functor f, Ord vn) => PatternBase f vn -> S.Set vn-patternNames (Id v _ _) = S.singleton v-patternNames (PatternParens p _) = patternNames p-patternNames (TuplePattern pats _) = mconcat $ map patternNames pats-patternNames (RecordPattern fs _) = mconcat $ map (patternNames . snd) fs-patternNames Wildcard {} = mempty-patternNames (PatternAscription p _ _) = patternNames p-patternNames PatternLit {} = mempty-patternNames (PatternConstr _ _ ps _) = mconcat $ map patternNames ps+patNames :: (Functor f, Ord vn) => PatBase f vn -> S.Set vn+patNames (Id v _ _) = S.singleton v+patNames (PatParens p _) = patNames p+patNames (TuplePat pats _) = mconcat $ map patNames pats+patNames (RecordPat fs _) = mconcat $ map (patNames . snd) fs+patNames Wildcard {} = mempty+patNames (PatAscription p _ _) = patNames p+patNames PatLit {} = mempty+patNames (PatConstr _ _ ps _) = mconcat $ map patNames ps -- | A mapping from names bound in a map to their identifier.-patternMap :: (Functor f) => PatternBase f VName -> M.Map VName (IdentBase f VName)+patternMap :: (Functor f) => PatBase f VName -> M.Map VName (IdentBase f VName) patternMap pat = M.fromList $ zip (map identName idents) idents where- idents = S.toList $ patternIdents pat+ idents = S.toList $ patIdents pat -- | The type of values bound by the pattern.-patternType :: PatternBase Info VName -> PatternType+patternType :: PatBase Info VName -> PatType patternType (Wildcard (Info t) _) = t-patternType (PatternParens p _) = patternType p+patternType (PatParens p _) = patternType p patternType (Id _ (Info t) _) = t-patternType (TuplePattern pats _) = tupleRecord $ map patternType pats-patternType (RecordPattern fs _) = Scalar $ Record $ patternType <$> M.fromList fs-patternType (PatternAscription p _ _) = patternType p-patternType (PatternLit _ (Info t) _) = t-patternType (PatternConstr _ (Info t) _ _) = t+patternType (TuplePat pats _) = tupleRecord $ map patternType pats+patternType (RecordPat fs _) = Scalar $ Record $ patternType <$> M.fromList fs+patternType (PatAscription p _ _) = patternType p+patternType (PatLit _ (Info t) _) = t+patternType (PatConstr _ (Info t) _ _) = t -- | The type matched by the pattern, including shape declarations if present.-patternStructType :: PatternBase Info VName -> StructType+patternStructType :: PatBase Info VName -> StructType patternStructType = toStruct . patternType -- | When viewed as a function parameter, does this pattern correspond -- to a named parameter of some type?-patternParam :: PatternBase Info VName -> (PName, StructType)-patternParam (PatternParens p _) =+patternParam :: PatBase Info VName -> (PName, StructType)+patternParam (PatParens p _) = patternParam p-patternParam (PatternAscription (Id v _ _) td _) =+patternParam (PatAscription (Id v _ _) td _) = (Named v, unInfo $ expandedType td) patternParam (Id v (Info t) _) = (Named v, toStruct t)@@ -790,7 +784,6 @@ M.fromList $ zipWith namify [20 ..] $ map primFun (M.toList Primitive.primFuns)- ++ [("opaque", IntrinsicPolyFun [tp_a] [Scalar t_a] $ Scalar t_a)] ++ map unOpFun Primitive.allUnOps ++ map binOpFun Primitive.allBinOps ++ map cmpOpFun Primitive.allCmpOps@@ -1022,12 +1015,91 @@ arr_b $ shape [n] ] $ uarr_a $ shape [k]- ),- ("trace", IntrinsicPolyFun [tp_a] [Scalar t_a] $ Scalar t_a),- ("break", IntrinsicPolyFun [tp_a] [Scalar t_a] $ Scalar t_a)+ ) ]+ +++ -- Experimental LMAD ones.+ [ ( "flat_index_2d",+ IntrinsicPolyFun+ [tp_a, sp_n]+ [ arr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64)+ ]+ $ arr_a $ ShapeDecl [AnyDim Nothing, AnyDim Nothing]+ ),+ ( "flat_update_2d",+ IntrinsicPolyFun+ [tp_a, sp_n, sp_k, sp_l]+ [ uarr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ arr_a $ shape [k, l]+ ]+ $ uarr_a $ shape [n]+ ),+ ( "flat_index_3d",+ IntrinsicPolyFun+ [tp_a, sp_n]+ [ arr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64)+ ]+ $ arr_a $ ShapeDecl [AnyDim Nothing, AnyDim Nothing, AnyDim Nothing]+ ),+ ( "flat_update_3d",+ IntrinsicPolyFun+ [tp_a, sp_n, sp_k, sp_l, sp_p]+ [ uarr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ arr_a $ shape [k, l, p]+ ]+ $ uarr_a $ shape [n]+ ),+ ( "flat_index_4d",+ IntrinsicPolyFun+ [tp_a, sp_n]+ [ arr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64)+ ]+ $ arr_a $ ShapeDecl [AnyDim Nothing, AnyDim Nothing, AnyDim Nothing, AnyDim Nothing]+ ),+ ( "flat_update_4d",+ IntrinsicPolyFun+ [tp_a, sp_n, sp_k, sp_l, sp_p, sp_q]+ [ uarr_a $ shape [n],+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ Scalar (Prim $ Signed Int64),+ arr_a $ shape [k, l, p, q]+ ]+ $ uarr_a $ shape [n]+ )+ ] where- [a, b, n, m, k, l, p] = zipWith VName (map nameFromString ["a", "b", "n", "m", "k", "l", "p"]) [0 ..]+ [a, b, n, m, k, l, p, q] = zipWith VName (map nameFromString ["a", "b", "n", "m", "k", "l", "p", "q"]) [0 ..] t_a = TypeVar () Nonunique (typeName a) [] arr_a = Array () Nonunique t_a@@ -1039,7 +1111,7 @@ uarr_b = Array () Unique t_b tp_b = TypeParamType Unlifted b mempty - [sp_n, sp_m, sp_k, sp_l, _sp_p] = map (`TypeParamDim` mempty) [n, m, k, l, p]+ [sp_n, sp_m, sp_k, sp_l, sp_p, sp_q] = map (`TypeParamDim` mempty) [n, m, k, l, p, q] shape = ShapeDecl . map (NamedDim . qualName) @@ -1266,7 +1338,7 @@ type UncheckedTypeParam = TypeParamBase Name -- | A pattern with no type annotations.-type UncheckedPattern = PatternBase NoInfo Name+type UncheckedPat = PatBase NoInfo Name -- | A function declaration with no type annotations. type UncheckedValBind = ValBindBase NoInfo Name
src/Language/Futhark/Query.hs view
@@ -48,20 +48,20 @@ sizeDefs (SizeBinder v loc) = M.singleton v $ DefBound $ BoundTerm (Scalar (Prim (Signed Int64))) (locOf loc) -patternDefs :: Pattern -> Defs+patternDefs :: Pat -> Defs patternDefs (Id vn (Info t) loc) = M.singleton vn $ DefBound $ BoundTerm (toStruct t) (locOf loc)-patternDefs (TuplePattern pats _) =+patternDefs (TuplePat pats _) = mconcat $ map patternDefs pats-patternDefs (RecordPattern fields _) =+patternDefs (RecordPat fields _) = mconcat $ map (patternDefs . snd) fields-patternDefs (PatternParens pat _) =+patternDefs (PatParens pat _) = patternDefs pat patternDefs Wildcard {} = mempty-patternDefs PatternLit {} = mempty-patternDefs (PatternAscription pat _ _) =+patternDefs PatLit {} = mempty+patternDefs (PatAscription pat _ _) = patternDefs pat-patternDefs (PatternConstr _ _ pats _) =+patternDefs (PatConstr _ _ pats _) = mconcat $ map patternDefs pats typeParamDefs :: TypeParamBase VName -> Defs@@ -80,7 +80,7 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = pure,- mapOnPatternType = pure+ mapOnPatType = pure } onExp e' = do modify (<> expDefs e')@@ -241,22 +241,22 @@ Just $ RawAtName qn $ locOf loc inDim _ = Nothing -atPosInPattern :: Pattern -> Pos -> Maybe RawAtPos-atPosInPattern (Id vn _ loc) pos = do+atPosInPat :: Pat -> Pos -> Maybe RawAtPos+atPosInPat (Id vn _ loc) pos = do guard $ loc `contains` pos Just $ RawAtName (qualName vn) $ locOf loc-atPosInPattern (TuplePattern pats _) pos =- msum $ map (`atPosInPattern` pos) pats-atPosInPattern (RecordPattern fields _) pos =- msum $ map ((`atPosInPattern` pos) . snd) fields-atPosInPattern (PatternParens pat _) pos =- atPosInPattern pat pos-atPosInPattern (PatternAscription pat tdecl _) pos =- atPosInPattern pat pos `mplus` atPosInTypeExp (declaredType tdecl) pos-atPosInPattern (PatternConstr _ _ pats _) pos =- msum $ map (`atPosInPattern` pos) pats-atPosInPattern PatternLit {} _ = Nothing-atPosInPattern Wildcard {} _ = Nothing+atPosInPat (TuplePat pats _) pos =+ msum $ map (`atPosInPat` pos) pats+atPosInPat (RecordPat fields _) pos =+ msum $ map ((`atPosInPat` pos) . snd) fields+atPosInPat (PatParens pat _) pos =+ atPosInPat pat pos+atPosInPat (PatAscription pat tdecl _) pos =+ atPosInPat pat pos `mplus` atPosInTypeExp (declaredType tdecl) pos+atPosInPat (PatConstr _ _ pats _) pos =+ msum $ map (`atPosInPat` pos) pats+atPosInPat PatLit {} _ = Nothing+atPosInPat Wildcard {} _ = Nothing atPosInExp :: Exp -> Pos -> Maybe RawAtPos atPosInExp (Var qn _ loc) pos = do@@ -269,12 +269,12 @@ atPosInExp IntLit {} _ = Nothing atPosInExp FloatLit {} _ = Nothing atPosInExp (AppExp (LetPat _ pat _ _ _) _) pos- | pat `contains` pos = atPosInPattern pat pos+ | pat `contains` pos = atPosInPat pat pos atPosInExp (AppExp (LetWith a b _ _ _ _) _) pos | a `contains` pos = Just $ RawAtName (qualName $ identName a) (locOf a) | b `contains` pos = Just $ RawAtName (qualName $ identName b) (locOf b) atPosInExp (AppExp (DoLoop _ merge _ _ _ _) _) pos- | merge `contains` pos = atPosInPattern merge pos+ | merge `contains` pos = atPosInPat merge pos atPosInExp (Ascript _ tdecl _) pos | tdecl `contains` pos = atPosInTypeExp (declaredType tdecl) pos atPosInExp (AppExp (Coerce _ tdecl _) _) pos@@ -293,7 +293,7 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = pure,- mapOnPatternType = pure+ mapOnPatType = pure } onExp e' = case atPosInExp e' pos of@@ -339,7 +339,7 @@ atPosInValBind :: ValBind -> Pos -> Maybe RawAtPos atPosInValBind vbind pos =- msum (map (`atPosInPattern` pos) (valBindParams vbind))+ msum (map (`atPosInPat` pos) (valBindParams vbind)) `mplus` atPosInExp (valBindBody vbind) pos `mplus` join (atPosInTypeExp <$> valBindRetDecl vbind <*> pure pos)
src/Language/Futhark/Syntax.hs view
@@ -24,7 +24,6 @@ ShapeDecl (..), shapeRank, stripDims,- unifyShapes, TypeName (..), typeNameFromQualName, qualNameFromTypeName,@@ -35,7 +34,7 @@ TypeArgExp (..), PName (..), ScalarTypeBase (..),- PatternType,+ PatType, StructType, ValueType, Diet (..),@@ -63,7 +62,7 @@ CaseBase (..), LoopFormBase (..), PatLit (..),- PatternBase (..),+ PatBase (..), -- * Module language SpecBase (..),@@ -128,8 +127,8 @@ Show (f String), Show (f [VName]), Show (f ([VName], [VName])),- Show (f PatternType),- Show (f (PatternType, [VName])),+ Show (f PatType),+ Show (f (PatType, [VName])), Show (f (StructType, [VName])), Show (f EntryPoint), Show (f StructType),@@ -316,13 +315,6 @@ | i < length l = Just $ ShapeDecl $ drop i l | otherwise = Nothing --- | @unifyShapes x y@ combines @x@ and @y@ to contain their maximum--- common information, and fails if they conflict.-unifyShapes :: ArrayDim dim => ShapeDecl dim -> ShapeDecl dim -> Maybe (ShapeDecl dim)-unifyShapes (ShapeDecl xs) (ShapeDecl ys) = do- guard $ length xs == length ys- ShapeDecl <$> zipWithM unifyDims xs ys- -- | A type name consists of qualifiers (for error messages) and a -- 'VName' (for equality checking). data TypeName = TypeName {typeQuals :: [VName], typeLeaf :: VName}@@ -433,7 +425,7 @@ -- | A type with aliasing information and shape annotations, used for -- describing the type patterns and expressions.-type PatternType = TypeBase (DimDecl VName) Aliasing+type PatType = TypeBase (DimDecl VName) Aliasing -- | A "structural" type with shape annotations and no aliasing -- information, used for declarations.@@ -556,7 +548,7 @@ -- bound to the identifier. data IdentBase f vn = Ident { identName :: vn,- identType :: f PatternType,+ identType :: f PatType, identSrcLoc :: SrcLoc } @@ -696,8 +688,10 @@ -- need, so we can pretend that an application expression was really -- bound to a name. data AppExpBase f vn- = -- | The @Maybe VName@ is a possible existential size- -- that is instantiated by this argument..+ = -- | The @Maybe VName@ is a possible existential size that is+ -- instantiated by this argument. May have duplicates across the+ -- program, but they will all produce the same value (the+ -- expressions will be identical). Apply (ExpBase f vn) (ExpBase f vn)@@ -712,14 +706,14 @@ SrcLoc | LetPat [SizeBinder vn]- (PatternBase f vn)+ (PatBase f vn) (ExpBase f vn) (ExpBase f vn) SrcLoc | LetFun vn ( [TypeParamBase vn],- [PatternBase f vn],+ [PatBase f vn], Maybe (TypeExp vn), f StructType, ExpBase f vn@@ -729,14 +723,14 @@ | If (ExpBase f vn) (ExpBase f vn) (ExpBase f vn) SrcLoc | DoLoop [VName] -- Size parameters.- (PatternBase f vn) -- Merge variable pattern.+ (PatBase f vn) -- Merge variable pattern. (ExpBase f vn) -- Initial values of merge variables. (LoopFormBase f vn) -- Do or while loop. (ExpBase f vn) -- Loop body. SrcLoc | BinOp (QualName vn, SrcLoc)- (f PatternType)+ (f PatType) (ExpBase f vn, f (StructType, Maybe VName)) (ExpBase f vn, f (StructType, Maybe VName)) SrcLoc@@ -775,7 +769,7 @@ -- annotation encodes the result type, as well as any existential -- sizes that are generated here. data AppRes = AppRes- { appResType :: PatternType,+ { appResType :: PatType, appResExt :: [VName] } deriving (Eq, Ord, Show)@@ -790,13 +784,13 @@ data ExpBase f vn = Literal PrimValue SrcLoc | -- | A polymorphic integral literal.- IntLit Integer (f PatternType) SrcLoc+ IntLit Integer (f PatType) SrcLoc | -- | A polymorphic decimal literal.- FloatLit Double (f PatternType) SrcLoc+ FloatLit Double (f PatType) SrcLoc | -- | A string literal is just a fancy syntax for an array -- of bytes. StringLit [Word8] SrcLoc- | Var (QualName vn) (f PatternType) SrcLoc+ | Var (QualName vn) (f PatType) SrcLoc | -- | A parenthesized expression. Parens (ExpBase f vn) SrcLoc | QualParens (QualName vn, SrcLoc) (ExpBase f vn) SrcLoc@@ -806,48 +800,50 @@ RecordLit [FieldBase f vn] SrcLoc | -- | Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@. -- Second arg is the row type of the rows of the array.- ArrayLit [ExpBase f vn] (f PatternType) SrcLoc+ ArrayLit [ExpBase f vn] (f PatType) SrcLoc | -- | An attribute applied to the following expression. Attr AttrInfo (ExpBase f vn) SrcLoc- | Project Name (ExpBase f vn) (f PatternType) SrcLoc+ | Project Name (ExpBase f vn) (f PatType) SrcLoc | -- | Numeric negation (ugly special case; Haskell did it first). Negate (ExpBase f vn) SrcLoc+ | -- | Logical and bitwise negation.+ Not (ExpBase f vn) SrcLoc | -- | Fail if the first expression does not return true, -- and return the value of the second expression if it -- does. Assert (ExpBase f vn) (ExpBase f vn) (f String) SrcLoc | -- | An n-ary value constructor.- Constr Name [ExpBase f vn] (f PatternType) SrcLoc+ Constr Name [ExpBase f vn] (f PatType) SrcLoc | Update (ExpBase f vn) (SliceBase f vn) (ExpBase f vn) SrcLoc- | RecordUpdate (ExpBase f vn) [Name] (ExpBase f vn) (f PatternType) SrcLoc+ | RecordUpdate (ExpBase f vn) [Name] (ExpBase f vn) (f PatType) SrcLoc | Lambda- [PatternBase f vn]+ [PatBase f vn] (ExpBase f vn) (Maybe (TypeExp vn)) (f (Aliasing, StructType)) SrcLoc | -- | @+@; first two types are operands, third is result.- OpSection (QualName vn) (f PatternType) SrcLoc+ OpSection (QualName vn) (f PatType) SrcLoc | -- | @2+@; first type is operand, second is result. OpSectionLeft (QualName vn)- (f PatternType)+ (f PatType) (ExpBase f vn) (f (PName, StructType, Maybe VName), f (PName, StructType))- (f PatternType, f [VName])+ (f PatType, f [VName]) SrcLoc | -- | @+2@; first type is operand, second is result. OpSectionRight (QualName vn)- (f PatternType)+ (f PatType) (ExpBase f vn) (f (PName, StructType), f (PName, StructType, Maybe VName))- (f PatternType)+ (f PatType) SrcLoc | -- | Field projection as a section: @(.x.y.z)@.- ProjectSection [Name] (f PatternType) SrcLoc+ ProjectSection [Name] (f PatType) SrcLoc | -- | Array indexing as a section: @(.[i,j])@.- IndexSection (SliceBase f vn) (f PatternType) SrcLoc+ IndexSection (SliceBase f vn) (f PatType) SrcLoc | -- | Type ascription: @e : t@. Ascript (ExpBase f vn) (TypeDeclBase f vn) SrcLoc | AppExp (AppExpBase f vn) (f AppRes)@@ -872,6 +868,7 @@ locOf (Var _ _ loc) = locOf loc locOf (Ascript _ _ loc) = locOf loc locOf (Negate _ pos) = locOf pos+ locOf (Not _ pos) = locOf pos locOf (Update _ _ _ pos) = locOf pos locOf (RecordUpdate _ _ _ _ pos) = locOf pos locOf (Lambda _ _ _ _ loc) = locOf loc@@ -888,7 +885,7 @@ -- | An entry in a record literal. data FieldBase f vn = RecordFieldExplicit Name (ExpBase f vn) SrcLoc- | RecordFieldImplicit vn (f PatternType) SrcLoc+ | RecordFieldImplicit vn (f PatType) SrcLoc deriving instance Showable f vn => Show (FieldBase f vn) @@ -901,7 +898,7 @@ locOf (RecordFieldImplicit _ _ loc) = locOf loc -- | A case in a match expression.-data CaseBase f vn = CasePat (PatternBase f vn) (ExpBase f vn) SrcLoc+data CaseBase f vn = CasePat (PatBase f vn) (ExpBase f vn) SrcLoc deriving instance Showable f vn => Show (CaseBase f vn) @@ -915,7 +912,7 @@ -- | Whether the loop is a @for@-loop or a @while@-loop. data LoopFormBase f vn = For (IdentBase f vn) (ExpBase f vn)- | ForIn (PatternBase f vn) (ExpBase f vn)+ | ForIn (PatBase f vn) (ExpBase f vn) | While (ExpBase f vn) deriving instance Showable f vn => Show (LoopFormBase f vn)@@ -933,31 +930,31 @@ -- | A pattern as used most places where variables are bound (function -- parameters, @let@ expressions, etc).-data PatternBase f vn- = TuplePattern [PatternBase f vn] SrcLoc- | RecordPattern [(Name, PatternBase f vn)] SrcLoc- | PatternParens (PatternBase f vn) SrcLoc- | Id vn (f PatternType) SrcLoc- | Wildcard (f PatternType) SrcLoc -- Nothing, i.e. underscore.- | PatternAscription (PatternBase f vn) (TypeDeclBase f vn) SrcLoc- | PatternLit PatLit (f PatternType) SrcLoc- | PatternConstr Name (f PatternType) [PatternBase f vn] SrcLoc+data PatBase f vn+ = TuplePat [PatBase f vn] SrcLoc+ | RecordPat [(Name, PatBase f vn)] SrcLoc+ | PatParens (PatBase f vn) SrcLoc+ | Id vn (f PatType) SrcLoc+ | Wildcard (f PatType) SrcLoc -- Nothing, i.e. underscore.+ | PatAscription (PatBase f vn) (TypeDeclBase f vn) SrcLoc+ | PatLit PatLit (f PatType) SrcLoc+ | PatConstr Name (f PatType) [PatBase f vn] SrcLoc -deriving instance Showable f vn => Show (PatternBase f vn)+deriving instance Showable f vn => Show (PatBase f vn) -deriving instance Eq (PatternBase NoInfo VName)+deriving instance Eq (PatBase NoInfo VName) -deriving instance Ord (PatternBase NoInfo VName)+deriving instance Ord (PatBase NoInfo VName) -instance Located (PatternBase f vn) where- locOf (TuplePattern _ loc) = locOf loc- locOf (RecordPattern _ loc) = locOf loc- locOf (PatternParens _ loc) = locOf loc+instance Located (PatBase f vn) where+ locOf (TuplePat _ loc) = locOf loc+ locOf (RecordPat _ loc) = locOf loc+ locOf (PatParens _ loc) = locOf loc locOf (Id _ _ loc) = locOf loc locOf (Wildcard _ loc) = locOf loc- locOf (PatternAscription _ _ loc) = locOf loc- locOf (PatternLit _ _ loc) = locOf loc- locOf (PatternConstr _ _ _ loc) = locOf loc+ locOf (PatAscription _ _ loc) = locOf loc+ locOf (PatLit _ _ loc) = locOf loc+ locOf (PatConstr _ _ _ loc) = locOf loc -- | Documentation strings, including source location. data DocComment = DocComment String SrcLoc@@ -996,7 +993,7 @@ valBindRetDecl :: Maybe (TypeExp vn), valBindRetType :: f (StructType, [VName]), valBindTypeParams :: [TypeParamBase vn],- valBindParams :: [PatternBase f vn],+ valBindParams :: [PatBase f vn], valBindBody :: ExpBase f vn, valBindDoc :: Maybe DocComment, valBindAttrs :: [AttrInfo],
src/Language/Futhark/Traversals.hs view
@@ -41,7 +41,7 @@ mapOnName :: VName -> m VName, mapOnQualName :: QualName VName -> m (QualName VName), mapOnStructType :: StructType -> m StructType,- mapOnPatternType :: PatternType -> m PatternType+ mapOnPatType :: PatType -> m PatType } -- | An 'ASTMapper' that just leaves its input unchanged.@@ -52,7 +52,7 @@ mapOnName = return, mapOnQualName = return, mapOnStructType = return,- mapOnPatternType = return+ mapOnPatType = return } -- | The class of things that we can map an 'ASTMapper' across.@@ -97,7 +97,7 @@ Coerce <$> mapOnExp tv e <*> astMap tv tdecl <*> pure loc astMap tv (BinOp (fname, fname_loc) t (x, Info (xt, xext)) (y, Info (yt, yext)) loc) = BinOp <$> ((,) <$> mapOnQualName tv fname <*> pure fname_loc)- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> ( (,) <$> mapOnExp tv x <*> (Info <$> ((,) <$> mapOnStructType tv xt <*> pure xext)) )@@ -116,16 +116,16 @@ instance ASTMappable (ExpBase Info VName) where astMap tv (Var name t loc) =- Var <$> mapOnQualName tv name <*> traverse (mapOnPatternType tv) t+ Var <$> mapOnQualName tv name <*> traverse (mapOnPatType tv) t <*> pure loc astMap _ (Literal val loc) = pure $ Literal val loc astMap _ (StringLit vs loc) = pure $ StringLit vs loc astMap tv (IntLit val t loc) =- IntLit val <$> traverse (mapOnPatternType tv) t <*> pure loc+ IntLit val <$> traverse (mapOnPatType tv) t <*> pure loc astMap tv (FloatLit val t loc) =- FloatLit val <$> traverse (mapOnPatternType tv) t <*> pure loc+ FloatLit val <$> traverse (mapOnPatType tv) t <*> pure loc astMap tv (Parens e loc) = Parens <$> mapOnExp tv e <*> pure loc astMap tv (QualParens (name, nameloc) e loc) =@@ -137,11 +137,13 @@ astMap tv (RecordLit fields loc) = RecordLit <$> astMap tv fields <*> pure loc astMap tv (ArrayLit els t loc) =- ArrayLit <$> mapM (mapOnExp tv) els <*> traverse (mapOnPatternType tv) t <*> pure loc+ ArrayLit <$> mapM (mapOnExp tv) els <*> traverse (mapOnPatType tv) t <*> pure loc astMap tv (Ascript e tdecl loc) = Ascript <$> mapOnExp tv e <*> astMap tv tdecl <*> pure loc astMap tv (Negate x loc) = Negate <$> mapOnExp tv x <*> pure loc+ astMap tv (Not x loc) =+ Not <$> mapOnExp tv x <*> pure loc astMap tv (Update src slice v loc) = Update <$> mapOnExp tv src <*> mapM (astMap tv) slice <*> mapOnExp tv v@@ -149,10 +151,10 @@ astMap tv (RecordUpdate src fs v (Info t) loc) = RecordUpdate <$> mapOnExp tv src <*> pure fs <*> mapOnExp tv v- <*> (Info <$> mapOnPatternType tv t)+ <*> (Info <$> mapOnPatType tv t) <*> pure loc astMap tv (Project field e t loc) =- Project field <$> mapOnExp tv e <*> traverse (mapOnPatternType tv) t <*> pure loc+ Project field <$> mapOnExp tv e <*> traverse (mapOnPatType tv) t <*> pure loc astMap tv (Assert e1 e2 desc loc) = Assert <$> mapOnExp tv e1 <*> mapOnExp tv e2 <*> pure desc <*> pure loc astMap tv (Lambda params body ret t loc) =@@ -163,36 +165,36 @@ <*> pure loc astMap tv (OpSection name t loc) = OpSection <$> mapOnQualName tv name- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> pure loc astMap tv (OpSectionLeft name t arg (Info (pa, t1a, argext), Info (pb, t1b)) (t2, retext) loc) = OpSectionLeft <$> mapOnQualName tv name- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> mapOnExp tv arg <*> ( (,) <$> (Info <$> ((pa,,) <$> mapOnStructType tv t1a <*> pure argext)) <*> (Info <$> ((pb,) <$> mapOnStructType tv t1b)) )- <*> ((,) <$> traverse (mapOnPatternType tv) t2 <*> pure retext)+ <*> ((,) <$> traverse (mapOnPatType tv) t2 <*> pure retext) <*> pure loc astMap tv (OpSectionRight name t arg (Info (pa, t1a), Info (pb, t1b, argext)) t2 loc) = OpSectionRight <$> mapOnQualName tv name- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> mapOnExp tv arg <*> ( (,) <$> (Info <$> ((pa,) <$> mapOnStructType tv t1a)) <*> (Info <$> ((pb,,) <$> mapOnStructType tv t1b <*> pure argext)) )- <*> traverse (mapOnPatternType tv) t2+ <*> traverse (mapOnPatType tv) t2 <*> pure loc astMap tv (ProjectSection fields t loc) =- ProjectSection fields <$> traverse (mapOnPatternType tv) t <*> pure loc+ ProjectSection fields <$> traverse (mapOnPatType tv) t <*> pure loc astMap tv (IndexSection idxs t loc) = IndexSection <$> mapM (astMap tv) idxs- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> pure loc astMap tv (Constr name es ts loc) =- Constr name <$> traverse (mapOnExp tv) es <*> traverse (mapOnPatternType tv) ts <*> pure loc+ Constr name <$> traverse (mapOnExp tv) es <*> traverse (mapOnPatType tv) ts <*> pure loc astMap tv (Attr attr e loc) = Attr attr <$> mapOnExp tv e <*> pure loc astMap tv (AppExp e res) =@@ -255,7 +257,7 @@ instance ASTMappable AppRes where astMap tv (AppRes t ext) =- AppRes <$> mapOnPatternType tv t <*> pure ext+ AppRes <$> mapOnPatType tv t <*> pure ext type TypeTraverser f t dim1 als1 dim2 als2 = (TypeName -> f TypeName) ->@@ -302,7 +304,7 @@ where f = fmap typeNameFromQualName . mapOnQualName tv . qualNameFromTypeName -instance ASTMappable PatternType where+instance ASTMappable PatType where astMap tv = traverseType f (astMap tv) (astMap tv) where f = fmap typeNameFromQualName . mapOnQualName tv . qualNameFromTypeName@@ -313,36 +315,36 @@ instance ASTMappable (IdentBase Info VName) where astMap tv (Ident name (Info t) loc) =- Ident <$> mapOnName tv name <*> (Info <$> mapOnPatternType tv t) <*> pure loc+ Ident <$> mapOnName tv name <*> (Info <$> mapOnPatType tv t) <*> pure loc instance ASTMappable (SizeBinder VName) where astMap tv (SizeBinder name loc) = SizeBinder <$> mapOnName tv name <*> pure loc -instance ASTMappable (PatternBase Info VName) where+instance ASTMappable (PatBase Info VName) where astMap tv (Id name (Info t) loc) =- Id <$> mapOnName tv name <*> (Info <$> mapOnPatternType tv t) <*> pure loc- astMap tv (TuplePattern pats loc) =- TuplePattern <$> mapM (astMap tv) pats <*> pure loc- astMap tv (RecordPattern fields loc) =- RecordPattern <$> mapM (traverse $ astMap tv) fields <*> pure loc- astMap tv (PatternParens pat loc) =- PatternParens <$> astMap tv pat <*> pure loc- astMap tv (PatternAscription pat t loc) =- PatternAscription <$> astMap tv pat <*> astMap tv t <*> pure loc+ Id <$> mapOnName tv name <*> (Info <$> mapOnPatType tv t) <*> pure loc+ astMap tv (TuplePat pats loc) =+ TuplePat <$> mapM (astMap tv) pats <*> pure loc+ astMap tv (RecordPat fields loc) =+ RecordPat <$> mapM (traverse $ astMap tv) fields <*> pure loc+ astMap tv (PatParens pat loc) =+ PatParens <$> astMap tv pat <*> pure loc+ astMap tv (PatAscription pat t loc) =+ PatAscription <$> astMap tv pat <*> astMap tv t <*> pure loc astMap tv (Wildcard (Info t) loc) =- Wildcard <$> (Info <$> mapOnPatternType tv t) <*> pure loc- astMap tv (PatternLit v (Info t) loc) =- PatternLit v <$> (Info <$> mapOnPatternType tv t) <*> pure loc- astMap tv (PatternConstr n (Info t) ps loc) =- PatternConstr n <$> (Info <$> mapOnPatternType tv t) <*> mapM (astMap tv) ps <*> pure loc+ Wildcard <$> (Info <$> mapOnPatType tv t) <*> pure loc+ astMap tv (PatLit v (Info t) loc) =+ PatLit v <$> (Info <$> mapOnPatType tv t) <*> pure loc+ astMap tv (PatConstr n (Info t) ps loc) =+ PatConstr n <$> (Info <$> mapOnPatType tv t) <*> mapM (astMap tv) ps <*> pure loc instance ASTMappable (FieldBase Info VName) where astMap tv (RecordFieldExplicit name e loc) = RecordFieldExplicit name <$> mapOnExp tv e <*> pure loc astMap tv (RecordFieldImplicit name t loc) = RecordFieldImplicit <$> mapOnName tv name- <*> traverse (mapOnPatternType tv) t+ <*> traverse (mapOnPatType tv) t <*> pure loc instance ASTMappable (CaseBase Info VName) where@@ -380,16 +382,16 @@ bareField (RecordFieldImplicit name _ loc) = RecordFieldImplicit name NoInfo loc -barePat :: PatternBase Info VName -> PatternBase NoInfo VName-barePat (TuplePattern ps loc) = TuplePattern (map barePat ps) loc-barePat (RecordPattern fs loc) = RecordPattern (map (fmap barePat) fs) loc-barePat (PatternParens p loc) = PatternParens (barePat p) loc+barePat :: PatBase Info VName -> PatBase NoInfo VName+barePat (TuplePat ps loc) = TuplePat (map barePat ps) loc+barePat (RecordPat fs loc) = RecordPat (map (fmap barePat) fs) loc+barePat (PatParens p loc) = PatParens (barePat p) loc barePat (Id v _ loc) = Id v NoInfo loc barePat (Wildcard _ loc) = Wildcard NoInfo loc-barePat (PatternAscription pat (TypeDecl t _) loc) =- PatternAscription (barePat pat) (TypeDecl t NoInfo) loc-barePat (PatternLit v _ loc) = PatternLit v NoInfo loc-barePat (PatternConstr c _ ps loc) = PatternConstr c NoInfo (map barePat ps) loc+barePat (PatAscription pat (TypeDecl t _) loc) =+ PatAscription (barePat pat) (TypeDecl t NoInfo) loc+barePat (PatLit v _ loc) = PatLit v NoInfo loc+barePat (PatConstr c _ ps loc) = PatConstr c NoInfo (map barePat ps) loc bareDimIndex :: DimIndexBase Info VName -> DimIndexBase NoInfo VName bareDimIndex (DimFix e) =@@ -421,6 +423,7 @@ bareExp (Ascript e tdecl loc) = Ascript (bareExp e) (bareTypeDecl tdecl) loc bareExp (Negate x loc) = Negate (bareExp x) loc+bareExp (Not x loc) = Not (bareExp x) loc bareExp (Update src slice v loc) = Update (bareExp src) (map bareDimIndex slice) (bareExp v) loc bareExp (RecordUpdate src fs v _ loc) =
src/Language/Futhark/TypeChecker.hs view
@@ -103,7 +103,9 @@ ModExpBase NoInfo Name -> (Warnings, Either TypeError (MTy, ModExpBase Info VName)) checkModExp files src env me =- second (fmap fst) $ runTypeM env files' (mkInitialImport "") src $ checkOneModExp me+ second (fmap fst) . runTypeM env files' (mkInitialImport "") src $ do+ (_abs, mty, me') <- checkOneModExp me+ pure (mty, me') where files' = M.map fileEnv $ M.fromList files @@ -270,7 +272,7 @@ checkSpecs (ModSpec name sig doc loc : specs) = bindSpaced [(Term, name)] $ do name' <- checkName Term name loc- (mty, sig') <- checkSigExp sig+ (_sig_abs, mty, sig') <- checkSigExp sig let senv = mempty { envNameMap = M.singleton (Term, name) $ qualName name',@@ -283,13 +285,13 @@ ModSpec name' sig' doc loc : specs' ) checkSpecs (IncludeSpec e loc : specs) = do- (e_abs, e_env, e') <- checkSigExpToEnv e+ (e_abs, env_abs, e_env, e') <- checkSigExpToEnv e - mapM_ (warnIfShadowing . fmap baseName) $ M.keys e_abs+ mapM_ (warnIfShadowing . fmap baseName) $ M.keys env_abs (abstypes, env, specs') <- localEnv e_env $ checkSpecs specs return- ( abstypes <> e_abs,+ ( e_abs <> env_abs <> abstypes, env <> e_env, IncludeSpec e' loc : specs' )@@ -300,26 +302,26 @@ warnAbout qn = warn loc $ "Inclusion shadows type" <+> pquote (ppr qn) <+> "." -checkSigExp :: SigExpBase NoInfo Name -> TypeM (MTy, SigExpBase Info VName)+checkSigExp :: SigExpBase NoInfo Name -> TypeM (TySet, MTy, SigExpBase Info VName) checkSigExp (SigParens e loc) = do- (mty, e') <- checkSigExp e- return (mty, SigParens e' loc)+ (abs, mty, e') <- checkSigExp e+ return (abs, mty, SigParens e' loc) checkSigExp (SigVar name NoInfo loc) = do (name', mty) <- lookupMTy loc name (mty', substs) <- newNamesForMTy mty- return (mty', SigVar name' (Info substs) loc)+ return (mtyAbs mty', mty', SigVar name' (Info substs) loc) checkSigExp (SigSpecs specs loc) = do checkForDuplicateSpecs specs (abstypes, env, specs') <- checkSpecs specs- return (MTy abstypes $ ModEnv env, SigSpecs specs' loc)+ return (abstypes, MTy abstypes $ ModEnv env, SigSpecs specs' loc) checkSigExp (SigWith s (TypeRef tname ps td trloc) loc) = do- (s_abs, s_env, s') <- checkSigExpToEnv s+ (abs, s_abs, s_env, s') <- checkSigExpToEnv s checkTypeParams ps $ \ps' -> do (td', _) <- bindingTypeParams ps' $ checkTypeDecl td (tname', s_abs', s_env') <- refineEnv loc s_abs s_env tname ps' $ unInfo $ expandedType td'- return (MTy s_abs' $ ModEnv s_env', SigWith s' (TypeRef tname' ps' td' trloc) loc)+ return (abs, MTy s_abs' $ ModEnv s_env', SigWith s' (TypeRef tname' ps' td' trloc) loc) checkSigExp (SigArrow maybe_pname e1 e2 loc) = do- (MTy s_abs e1_mod, e1') <- checkSigExp e1+ (e1_abs, MTy s_abs e1_mod, e1') <- checkSigExp e1 (env_for_e2, maybe_pname') <- case maybe_pname of Just pname -> bindSpaced [(Term, pname)] $ do@@ -333,41 +335,48 @@ ) Nothing -> return (mempty, Nothing)- (e2_mod, e2') <- localEnv env_for_e2 $ checkSigExp e2+ (e2_abs, e2_mod, e2') <- localEnv env_for_e2 $ checkSigExp e2 return- ( MTy mempty $ ModFun $ FunSig s_abs e1_mod e2_mod,+ ( e1_abs <> e2_abs,+ MTy mempty $ ModFun $ FunSig s_abs e1_mod e2_mod, SigArrow maybe_pname' e1' e2' loc ) -checkSigExpToEnv :: SigExpBase NoInfo Name -> TypeM (TySet, Env, SigExpBase Info VName)+checkSigExpToEnv ::+ SigExpBase NoInfo Name ->+ TypeM (TySet, TySet, Env, SigExpBase Info VName) checkSigExpToEnv e = do- (MTy abs mod, e') <- checkSigExp e+ (abs, MTy mod_abs mod, e') <- checkSigExp e case mod of- ModEnv env -> return (abs, env, e')+ ModEnv env -> return (abs, mod_abs, env, e') ModFun {} -> unappliedFunctor $ srclocOf e -checkSigBind :: SigBindBase NoInfo Name -> TypeM (Env, SigBindBase Info VName)+checkSigBind :: SigBindBase NoInfo Name -> TypeM (TySet, Env, SigBindBase Info VName) checkSigBind (SigBind name e doc loc) = do- (env, e') <- checkSigExp e+ (abs, env, e') <- checkSigExp e bindSpaced [(Signature, name)] $ do name' <- checkName Signature name loc return- ( mempty+ ( abs,+ mempty { envSigTable = M.singleton name' env, envNameMap = M.singleton (Signature, name) (qualName name') }, SigBind name' e' doc loc ) -checkOneModExp :: ModExpBase NoInfo Name -> TypeM (MTy, ModExpBase Info VName)+checkOneModExp ::+ ModExpBase NoInfo Name ->+ TypeM (TySet, MTy, ModExpBase Info VName) checkOneModExp (ModParens e loc) = do- (mty, e') <- checkOneModExp e- return (mty, ModParens e' loc)+ (abs, mty, e') <- checkOneModExp e+ return (abs, mty, ModParens e' loc) checkOneModExp (ModDecs decs loc) = do checkForDuplicateDecs decs (abstypes, env, decs') <- checkDecs decs return- ( MTy abstypes $ ModEnv env,+ ( abstypes,+ MTy abstypes $ ModEnv env, ModDecs decs' loc ) checkOneModExp (ModVar v loc) = do@@ -377,40 +386,47 @@ && baseTag (qualLeaf v') <= maxIntrinsicTag ) $ typeError loc mempty "The 'intrinsics' module may not be used in module expressions."- return (MTy mempty env, ModVar v' loc)+ return (mempty, MTy mempty env, ModVar v' loc) checkOneModExp (ModImport name NoInfo loc) = do (name', env) <- lookupImport loc name return- ( MTy mempty $ ModEnv env,+ ( mempty,+ MTy mempty $ ModEnv env, ModImport name (Info name') loc ) checkOneModExp (ModApply f e NoInfo NoInfo loc) = do- (f_mty, f') <- checkOneModExp f+ (f_abs, f_mty, f') <- checkOneModExp f case mtyMod f_mty of ModFun functor -> do- (e_mty, e') <- checkOneModExp e+ (e_abs, e_mty, e') <- checkOneModExp e (mty, psubsts, rsubsts) <- applyFunctor loc functor e_mty- return (mty, ModApply f' e' (Info psubsts) (Info rsubsts) loc)+ return+ ( mtyAbs mty <> f_abs <> e_abs,+ mty,+ ModApply f' e' (Info psubsts) (Info rsubsts) loc+ ) _ -> typeError loc mempty "Cannot apply non-parametric module." checkOneModExp (ModAscript me se NoInfo loc) = do- (me_mod, me') <- checkOneModExp me- (se_mty, se') <- checkSigExp se+ (me_abs, me_mod, me') <- checkOneModExp me+ (se_abs, se_mty, se') <- checkSigExp se match_subst <- badOnLeft $ matchMTys me_mod se_mty loc- return (se_mty, ModAscript me' se' (Info match_subst) loc)+ return (se_abs <> me_abs, se_mty, ModAscript me' se' (Info match_subst) loc) checkOneModExp (ModLambda param maybe_fsig_e body_e loc) = withModParam param $ \param' param_abs param_mod -> do- (maybe_fsig_e', body_e', mty) <- checkModBody (fst <$> maybe_fsig_e) body_e loc+ (abs, maybe_fsig_e', body_e', mty) <-+ checkModBody (fst <$> maybe_fsig_e) body_e loc return- ( MTy mempty $ ModFun $ FunSig param_abs param_mod mty,+ ( abs,+ MTy mempty $ ModFun $ FunSig param_abs param_mod mty, ModLambda param' maybe_fsig_e' body_e' loc ) checkOneModExpToEnv :: ModExpBase NoInfo Name -> TypeM (TySet, Env, ModExpBase Info VName) checkOneModExpToEnv e = do- (MTy abs mod, e') <- checkOneModExp e+ (e_abs, MTy abs mod, e') <- checkOneModExp e case mod of- ModEnv env -> return (abs, env, e')+ ModEnv env -> pure (e_abs <> abs, env, e') ModFun {} -> unappliedFunctor $ srclocOf e withModParam ::@@ -418,7 +434,7 @@ (ModParamBase Info VName -> TySet -> Mod -> TypeM a) -> TypeM a withModParam (ModParam pname psig_e NoInfo loc) m = do- (MTy p_abs p_mod, psig_e') <- checkSigExp psig_e+ (_abs, MTy p_abs p_mod, psig_e') <- checkSigExp psig_e bindSpaced [(Term, pname)] $ do pname' <- checkName Term pname loc let in_body_env = mempty {envModTable = M.singleton pname' p_mod}@@ -439,27 +455,38 @@ ModExpBase NoInfo Name -> SrcLoc -> TypeM- ( Maybe (SigExp, Info (M.Map VName VName)),+ ( TySet,+ Maybe (SigExp, Info (M.Map VName VName)), ModExp, MTy ) checkModBody maybe_fsig_e body_e loc = do- (body_mty, body_e') <- checkOneModExp body_e+ (body_e_abs, body_mty, body_e') <- checkOneModExp body_e case maybe_fsig_e of Nothing ->- return (Nothing, body_e', body_mty)+ return+ ( mtyAbs body_mty <> body_e_abs,+ Nothing,+ body_e',+ body_mty+ ) Just fsig_e -> do- (fsig_mty, fsig_e') <- checkSigExp fsig_e+ (fsig_abs, fsig_mty, fsig_e') <- checkSigExp fsig_e fsig_subst <- badOnLeft $ matchMTys body_mty fsig_mty loc- return (Just (fsig_e', Info fsig_subst), body_e', fsig_mty)+ return+ ( fsig_abs <> body_e_abs,+ Just (fsig_e', Info fsig_subst),+ body_e',+ fsig_mty+ ) checkModBind :: ModBindBase NoInfo Name -> TypeM (TySet, Env, ModBindBase Info VName) checkModBind (ModBind name [] maybe_fsig_e e doc loc) = do- (maybe_fsig_e', e', mty) <- checkModBody (fst <$> maybe_fsig_e) e loc+ (e_abs, maybe_fsig_e', e', mty) <- checkModBody (fst <$> maybe_fsig_e) e loc bindSpaced [(Term, name)] $ do name' <- checkName Term name loc return- ( mtyAbs mty,+ ( e_abs, mempty { envModTable = M.singleton name' $ mtyMod mty, envNameMap = M.singleton (Term, name) $ qualName name'@@ -467,22 +494,23 @@ ModBind name' [] maybe_fsig_e' e' doc loc ) checkModBind (ModBind name (p : ps) maybe_fsig_e body_e doc loc) = do- (params', maybe_fsig_e', body_e', funsig) <-+ (abs, params', maybe_fsig_e', body_e', funsig) <- withModParam p $ \p' p_abs p_mod -> withModParams ps $ \params_stuff -> do let (ps', ps_abs, ps_mod) = unzip3 params_stuff- (maybe_fsig_e', body_e', mty) <- checkModBody (fst <$> maybe_fsig_e) body_e loc+ (abs, maybe_fsig_e', body_e', mty) <- checkModBody (fst <$> maybe_fsig_e) body_e loc let addParam (x, y) mty' = MTy mempty $ ModFun $ FunSig x y mty' return- ( p' : ps',+ ( abs,+ p' : ps', maybe_fsig_e', body_e', FunSig p_abs p_mod $ foldr addParam mty $ zip ps_abs ps_mod ) bindSpaced [(Term, name)] $ do name' <- checkName Term name loc- return- ( mempty,+ pure+ ( abs, mempty { envModTable = M.singleton name' $ ModFun funsig,@@ -559,16 +587,16 @@ TypeBind name' l tps' td' doc loc ) -entryPoint :: [Pattern] -> Maybe (TypeExp VName) -> StructType -> EntryPoint+entryPoint :: [Pat] -> Maybe (TypeExp VName) -> StructType -> EntryPoint entryPoint params orig_ret_te orig_ret = EntryPoint (map patternEntry params ++ more_params) rettype' where (more_params, rettype') = onRetType orig_ret_te orig_ret - patternEntry (PatternParens p _) =+ patternEntry (PatParens p _) = patternEntry p- patternEntry (PatternAscription _ tdecl _) =+ patternEntry (PatAscription _ tdecl _) = EntryType (unInfo (expandedType tdecl)) (Just (declaredType tdecl)) patternEntry p = EntryType (patternStructType p) Nothing@@ -659,11 +687,11 @@ nastyType' (Just te') _ | niceTypeExp te' = False nastyType' _ t' = nastyType t' -nastyParameter :: Pattern -> Bool+nastyParameter :: Pat -> Bool nastyParameter p = nastyType (patternType p) && not (ascripted p) where- ascripted (PatternAscription _ (TypeDecl te _) _) = niceTypeExp te- ascripted (PatternParens p' _) = ascripted p'+ ascripted (PatAscription _ (TypeDecl te _) _) = niceTypeExp te+ ascripted (PatParens p' _) = ascripted p' ascripted _ = False niceTypeExp :: TypeExp VName -> Bool@@ -677,8 +705,8 @@ (abs, modenv, struct') <- checkModBind struct return (abs, modenv, ModDec struct') checkOneDec (SigDec sig) = do- (sigenv, sig') <- checkSigBind sig- return (mempty, sigenv, SigDec sig')+ (abs, sigenv, sig') <- checkSigBind sig+ return (abs, sigenv, SigDec sig') checkOneDec (TypeDec tdec) = do (tenv, tdec') <- checkTypeBind tdec return (mempty, tenv, TypeDec tdec')
src/Language/Futhark/TypeChecker/Match.hs view
@@ -50,22 +50,22 @@ instance Pretty Match where ppr = pprMatch (-1) -patternToMatch :: Pattern -> Match+patternToMatch :: Pat -> Match patternToMatch (Id _ (Info t) _) = MatchWild $ toStruct t patternToMatch (Wildcard (Info t) _) = MatchWild $ toStruct t-patternToMatch (PatternParens p _) = patternToMatch p-patternToMatch (PatternAscription p _ _) = patternToMatch p-patternToMatch (PatternLit l (Info t) _) =+patternToMatch (PatParens p _) = patternToMatch p+patternToMatch (PatAscription p _ _) = patternToMatch p+patternToMatch (PatLit l (Info t) _) = MatchConstr (ConstrLit l) [] $ toStruct t-patternToMatch p@(TuplePattern ps _) =+patternToMatch p@(TuplePat ps _) = MatchConstr ConstrTuple (map patternToMatch ps) $ patternStructType p-patternToMatch p@(RecordPattern fs _) =+patternToMatch p@(RecordPat fs _) = MatchConstr (ConstrRecord fnames) (map patternToMatch ps) $ patternStructType p where (fnames, ps) = unzip $ sortFields $ M.fromList fs-patternToMatch (PatternConstr c (Info t) args _) =+patternToMatch (PatConstr c (Info t) args _) = MatchConstr (Constr c) (map patternToMatch args) $ toStruct t isConstr :: Match -> Maybe Name@@ -164,7 +164,7 @@ {-# NOINLINE unmatched #-} -- | Find the unmatched cases.-unmatched :: [Pattern] -> [Match]+unmatched :: [Pat] -> [Match] unmatched orig_ps = -- The algorithm may find duplicate example, which we filter away -- here.
src/Language/Futhark/TypeChecker/Modules.hs view
@@ -208,7 +208,7 @@ "Cannot refine a type having" <+> tpMsg ps <> " with a type having " <> tpMsg cur_ps <> "." | otherwise =- typeError loc mempty $ ppr tname <+> "is not an abstract type in the module type."+ typeError loc mempty $ pquote (ppr tname) <+> "is not an abstract type in the module type." where tpMsg [] = "no type parameters" tpMsg xs = "type parameters" <+> spread (map ppr xs)
src/Language/Futhark/TypeChecker/Monad.hs view
@@ -40,6 +40,7 @@ MTy (..), anySignedType, anyUnsignedType,+ anyIntType, anyFloatType, anyNumberType, anyPrimType,@@ -143,10 +144,7 @@ = TypeM ( ReaderT Context- ( StateT- TypeState- (Except (Warnings, TypeError))- )+ (StateT TypeState (Except (Warnings, TypeError))) a ) deriving@@ -236,7 +234,7 @@ lookupType :: SrcLoc -> QualName Name -> m (QualName VName, [TypeParam], StructType, Liftedness) lookupMod :: SrcLoc -> QualName Name -> m (QualName VName, Mod)- lookupVar :: SrcLoc -> QualName Name -> m (QualName VName, PatternType)+ lookupVar :: SrcLoc -> QualName Name -> m (QualName VName, PatType) checkNamedDim :: SrcLoc -> QualName Name -> m (QualName VName) checkNamedDim loc v = do@@ -469,7 +467,7 @@ where atTopLevel :: (Namespace, Name) -> Bool atTopLevel (Type, _) = True- atTopLevel (Term, v) = v `S.member` (type_names <> binop_names <> unop_names <> fun_names)+ atTopLevel (Term, v) = v `S.member` (type_names <> binop_names <> fun_names) where type_names = S.fromList $ map (nameFromString . pretty) anyPrimType binop_names =@@ -477,6 +475,5 @@ map (nameFromString . pretty) [minBound .. (maxBound :: BinOp)]- unop_names = S.fromList $ map nameFromString ["!"] fun_names = S.fromList $ map nameFromString ["shape"] atTopLevel _ = False
src/Language/Futhark/TypeChecker/Terms.hs view
@@ -158,7 +158,7 @@ | CheckingAscription StructType StructType | CheckingLetGeneralise Name | CheckingParams (Maybe Name)- | CheckingPattern UncheckedPattern InferredType+ | CheckingPat UncheckedPat InferredType | CheckingLoopBody StructType StructType | CheckingLoopInitial StructType StructType | CheckingRecordUpdate [Name] StructType StructType@@ -193,10 +193,10 @@ "Invalid use of parameters in" <+> pquote fname' <> "." where fname' = maybe "anonymous function" ppr fname- ppr (CheckingPattern pat NoneInferred) =+ ppr (CheckingPat pat NoneInferred) = "Invalid pattern" <+> pquote (ppr pat) <> "."- ppr (CheckingPattern pat (Ascribed t)) =- "Pattern" <+> pquote (ppr pat)+ ppr (CheckingPat pat (Ascribed t)) =+ "Pat" <+> pquote (ppr pat) <+> "cannot match value of type" </> indent 2 (ppr t) ppr (CheckingLoopBody expected actual) =@@ -233,7 +233,7 @@ data ValBinding = -- | Aliases in parameters indicate the lexical -- closure.- BoundV Locality [TypeParam] PatternType+ BoundV Locality [TypeParam] PatType | OverloadedF [PrimType] [Maybe PrimType] (Maybe PrimType) | EqualityF | WasConsumed SrcLoc@@ -287,14 +287,14 @@ -- | Get the type of an expression, with top level type variables -- substituted. Never call 'typeOf' directly (except in a few -- carefully inspected locations)!-expType :: Exp -> TermTypeM PatternType-expType = normPatternType . typeOf+expType :: Exp -> TermTypeM PatType+expType = normPatType . typeOf -- | Get the type of an expression, with all type variables -- substituted. Slower than 'expType', but sometimes necessary. -- Never call 'typeOf' directly (except in a few carefully inspected -- locations)!-expTypeFully :: Exp -> TermTypeM PatternType+expTypeFully :: Exp -> TermTypeM PatType expTypeFully = normTypeFully . typeOf -- Wrap a function name to give it a vacuous Eq instance for SizeSource.@@ -462,7 +462,7 @@ Just d -> return ( NamedDim $ qualName d,- Nothing+ Just d ) -- Any argument sizes created with 'extSize' inside the given action@@ -656,8 +656,8 @@ instantiateTypeScheme :: SrcLoc -> [TypeParam] ->- PatternType ->- TermTypeM ([VName], PatternType)+ PatType ->+ TermTypeM ([VName], PatType) instantiateTypeScheme loc tparams t = do let tnames = map typeParamName tparams (tparam_names, tparam_substs) <- unzip <$> mapM (instantiateTypeParam loc) tparams@@ -746,12 +746,12 @@ -- Mismatched dimensions are turned into fresh rigid type variables. -- Causes a 'TypeError' if they fail to match, and otherwise returns -- one of them.-unifyBranchTypes :: SrcLoc -> PatternType -> PatternType -> TermTypeM (PatternType, [VName])+unifyBranchTypes :: SrcLoc -> PatType -> PatType -> TermTypeM (PatType, [VName]) unifyBranchTypes loc t1 t2 = onFailure (CheckingBranches (toStruct t1) (toStruct t2)) $ unifyMostCommon (mkUsage loc "unification of branch results") t1 t2 -unifyBranches :: SrcLoc -> Exp -> Exp -> TermTypeM (PatternType, [VName])+unifyBranches :: SrcLoc -> Exp -> Exp -> TermTypeM (PatType, [VName]) unifyBranches loc e1 e2 = do e1_t <- expTypeFully e1 e2_t <- expTypeFully e2@@ -764,7 +764,7 @@ data InferredType = NoneInferred- | Ascribed PatternType+ | Ascribed PatType -- All this complexity is just so we can handle un-suffixed numeric -- literals in patterns.@@ -797,56 +797,56 @@ pure $ NamedDim $ qualName v' onDim d = pure d -checkPattern' ::+checkPat' :: [SizeBinder VName] ->- UncheckedPattern ->+ UncheckedPat -> InferredType ->- TermTypeM Pattern-checkPattern' sizes (PatternParens p loc) t =- PatternParens <$> checkPattern' sizes p t <*> pure loc-checkPattern' _ (Id name _ loc) _+ TermTypeM Pat+checkPat' sizes (PatParens p loc) t =+ PatParens <$> checkPat' sizes p t <*> pure loc+checkPat' _ (Id name _ loc) _ | name' `elem` doNotShadow = typeError loc mempty $ "The" <+> text name' <+> "operator may not be redefined." where name' = nameToString name-checkPattern' _ (Id name NoInfo loc) (Ascribed t) = do+checkPat' _ (Id name NoInfo loc) (Ascribed t) = do name' <- newID name return $ Id name' (Info t) loc-checkPattern' _ (Id name NoInfo loc) NoneInferred = do+checkPat' _ (Id name NoInfo loc) NoneInferred = do name' <- newID name t <- newTypeVar loc "t" return $ Id name' (Info t) loc-checkPattern' _ (Wildcard _ loc) (Ascribed t) =+checkPat' _ (Wildcard _ loc) (Ascribed t) = return $ Wildcard (Info $ t `setUniqueness` Nonunique) loc-checkPattern' _ (Wildcard NoInfo loc) NoneInferred = do+checkPat' _ (Wildcard NoInfo loc) NoneInferred = do t <- newTypeVar loc "t" return $ Wildcard (Info t) loc-checkPattern' sizes (TuplePattern ps loc) (Ascribed t)+checkPat' sizes (TuplePat ps loc) (Ascribed t) | Just ts <- isTupleRecord t, length ts == length ps =- TuplePattern- <$> zipWithM (checkPattern' sizes) ps (map Ascribed ts)+ TuplePat+ <$> zipWithM (checkPat' sizes) ps (map Ascribed ts) <*> pure loc-checkPattern' sizes p@(TuplePattern ps loc) (Ascribed t) = do+checkPat' sizes p@(TuplePat ps loc) (Ascribed t) = do ps_t <- replicateM (length ps) (newTypeVar loc "t") unify (mkUsage loc "matching a tuple pattern") (tupleRecord ps_t) $ toStruct t t' <- normTypeFully t- checkPattern' sizes p $ Ascribed t'-checkPattern' sizes (TuplePattern ps loc) NoneInferred =- TuplePattern <$> mapM (\p -> checkPattern' sizes p NoneInferred) ps <*> pure loc-checkPattern' _ (RecordPattern p_fs _) _+ checkPat' sizes p $ Ascribed t'+checkPat' sizes (TuplePat ps loc) NoneInferred =+ TuplePat <$> mapM (\p -> checkPat' sizes p NoneInferred) ps <*> pure loc+checkPat' _ (RecordPat p_fs _) _ | Just (f, fp) <- find (("_" `isPrefixOf`) . nameToString . fst) p_fs = typeError fp mempty $ "Underscore-prefixed fields are not allowed." </> "Did you mean" <> dquotes (text (drop 1 (nameToString f)) <> "=_") <> "?"-checkPattern' sizes (RecordPattern p_fs loc) (Ascribed (Scalar (Record t_fs)))+checkPat' sizes (RecordPat p_fs loc) (Ascribed (Scalar (Record t_fs))) | sort (map fst p_fs) == sort (M.keys t_fs) =- RecordPattern . M.toList <$> check <*> pure loc+ RecordPat . M.toList <$> check <*> pure loc where check =- traverse (uncurry (checkPattern' sizes)) $+ traverse (uncurry (checkPat' sizes)) $ M.intersectionWith (,) (M.fromList p_fs) (fmap Ascribed t_fs)-checkPattern' sizes p@(RecordPattern fields loc) (Ascribed t) = do+checkPat' sizes p@(RecordPat fields loc) (Ascribed t) = do fields' <- traverse (const $ newTypeVar loc "t") $ M.fromList fields when (sort (M.keys fields') /= sort (map fst fields)) $@@ -854,12 +854,12 @@ unify (mkUsage loc "matching a record pattern") (Scalar (Record fields')) $ toStruct t t' <- normTypeFully t- checkPattern' sizes p $ Ascribed t'-checkPattern' sizes (RecordPattern fs loc) NoneInferred =- RecordPattern . M.toList- <$> traverse (\p -> checkPattern' sizes p NoneInferred) (M.fromList fs)+ checkPat' sizes p $ Ascribed t'+checkPat' sizes (RecordPat fs loc) NoneInferred =+ RecordPat . M.toList+ <$> traverse (\p -> checkPat' sizes p NoneInferred) (M.fromList fs) <*> pure loc-checkPattern' sizes (PatternAscription p (TypeDecl t NoInfo) loc) maybe_outer_t = do+checkPat' sizes (PatAscription p (TypeDecl t NoInfo) loc) maybe_outer_t = do (t', st_nodims, _) <- checkTypeExp t (st, _) <- instantiateEmptyArrayDims loc "impl" Nonrigid st_nodims @@ -875,7 +875,7 @@ outer_t' <- normTypeFully outer_t case unifyTypesU unifyUniqueness st'' outer_t' of Just outer_t'' ->- PatternAscription <$> checkPattern' sizes p (Ascribed outer_t'')+ PatAscription <$> checkPat' sizes p (Ascribed outer_t'') <*> pure (TypeDecl t' (Info st)) <*> pure loc Nothing ->@@ -883,53 +883,53 @@ "Cannot match type" <+> pquote (ppr outer_t') <+> "with expected type" <+> pquote (ppr st'') <> "." NoneInferred ->- PatternAscription <$> checkPattern' sizes p (Ascribed st')+ PatAscription <$> checkPat' sizes p (Ascribed st') <*> pure (TypeDecl t' (Info st)) <*> pure loc where unifyUniqueness u1 u2 = if u2 `subuniqueOf` u1 then Just u1 else Nothing-checkPattern' _ (PatternLit l NoInfo loc) (Ascribed t) = do+checkPat' _ (PatLit l NoInfo loc) (Ascribed t) = do t' <- patLitMkType l loc unify (mkUsage loc "matching against literal") t' (toStruct t)- return $ PatternLit l (Info (fromStruct t')) loc-checkPattern' _ (PatternLit l NoInfo loc) NoneInferred = do+ return $ PatLit l (Info (fromStruct t')) loc+checkPat' _ (PatLit l NoInfo loc) NoneInferred = do t' <- patLitMkType l loc- return $ PatternLit l (Info (fromStruct t')) loc-checkPattern' sizes (PatternConstr n NoInfo ps loc) (Ascribed (Scalar (Sum cs)))+ return $ PatLit l (Info (fromStruct t')) loc+checkPat' sizes (PatConstr n NoInfo ps loc) (Ascribed (Scalar (Sum cs))) | Just ts <- M.lookup n cs = do- ps' <- zipWithM (checkPattern' sizes) ps $ map Ascribed ts- return $ PatternConstr n (Info (Scalar (Sum cs))) ps' loc-checkPattern' sizes (PatternConstr n NoInfo ps loc) (Ascribed t) = do+ ps' <- zipWithM (checkPat' sizes) ps $ map Ascribed ts+ return $ PatConstr n (Info (Scalar (Sum cs))) ps' loc+checkPat' sizes (PatConstr n NoInfo ps loc) (Ascribed t) = do t' <- newTypeVar loc "t"- ps' <- mapM (\p -> checkPattern' sizes p NoneInferred) ps+ ps' <- mapM (\p -> checkPat' sizes p NoneInferred) ps mustHaveConstr usage n t' (patternStructType <$> ps') unify usage t' (toStruct t) t'' <- normTypeFully t- return $ PatternConstr n (Info t'') ps' loc+ return $ PatConstr n (Info t'') ps' loc where usage = mkUsage loc "matching against constructor"-checkPattern' sizes (PatternConstr n NoInfo ps loc) NoneInferred = do- ps' <- mapM (\p -> checkPattern' sizes p NoneInferred) ps+checkPat' sizes (PatConstr n NoInfo ps loc) NoneInferred = do+ ps' <- mapM (\p -> checkPat' sizes p NoneInferred) ps t <- newTypeVar loc "t" mustHaveConstr usage n t (patternStructType <$> ps')- return $ PatternConstr n (Info $ fromStruct t) ps' loc+ return $ PatConstr n (Info $ fromStruct t) ps' loc where usage = mkUsage loc "matching against constructor" -patternNameMap :: Pattern -> NameMap-patternNameMap = M.fromList . map asTerm . S.toList . patternNames+patternNameMap :: Pat -> NameMap+patternNameMap = M.fromList . map asTerm . S.toList . patNames where asTerm v = ((Term, baseName v), qualName v) -checkPattern ::+checkPat :: [SizeBinder VName] ->- UncheckedPattern ->+ UncheckedPat -> InferredType ->- (Pattern -> TermTypeM a) ->+ (Pat -> TermTypeM a) -> TermTypeM a-checkPattern sizes p t m = do+checkPat sizes p t m = do checkForDuplicateNames [p]- p' <- onFailure (CheckingPattern p t) $ checkPattern' sizes p t+ p' <- onFailure (CheckingPat p t) $ checkPat' sizes p t let explicit = mustBeExplicitInType $ patternStructType p' @@ -1047,7 +1047,7 @@ bindingIdent :: IdentBase NoInfo Name ->- PatternType ->+ PatType -> (Ident -> TermTypeM a) -> TermTypeM a bindingIdent (Ident v NoInfo vloc) t m =@@ -1058,15 +1058,15 @@ bindingParams :: [UncheckedTypeParam] ->- [UncheckedPattern] ->- ([TypeParam] -> [Pattern] -> TermTypeM a) ->+ [UncheckedPat] ->+ ([TypeParam] -> [Pat] -> TermTypeM a) -> TermTypeM a bindingParams tps orig_ps m = do checkForDuplicateNames orig_ps checkTypeParams tps $ \tps' -> bindingTypeParams tps' $ do let descend ps' (p : ps) =- checkPattern [] p NoneInferred $ \p' ->- binding (S.toList $ patternIdents p') $ descend (p' : ps') ps+ checkPat [] p NoneInferred $ \p' ->+ binding (S.toList $ patIdents p') $ descend (p' : ps') ps descend ps' [] = do -- Perform an observation of every type parameter. This -- prevents unused-name warnings for otherwise unused@@ -1101,15 +1101,15 @@ check (SizeBinder v loc) = SizeBinder <$> checkName Term v loc <*> pure loc -bindingPattern ::+bindingPat :: [SizeBinder VName] ->- PatternBase NoInfo Name ->+ PatBase NoInfo Name -> InferredType ->- (Pattern -> TermTypeM a) ->+ (Pat -> TermTypeM a) -> TermTypeM a-bindingPattern sizes p t m = do+bindingPat sizes p t m = do checkForDuplicateNames [p]- checkPattern sizes p t $ \p' -> binding (S.toList $ patternIdents p') $ do+ checkPat sizes p t $ \p' -> binding (S.toList $ patIdents p') $ do -- Perform an observation of every declared dimension. This -- prevents unused-name warnings for otherwise unused dimensions. mapM_ observe $ patternDims p'@@ -1120,10 +1120,10 @@ size : _ -> typeError size mempty $ "Size" <+> ppr size <+> "unused in pattern." -patternDims :: Pattern -> [Ident]-patternDims (PatternParens p _) = patternDims p-patternDims (TuplePattern pats _) = concatMap patternDims pats-patternDims (PatternAscription p (TypeDecl _ (Info t)) _) =+patternDims :: Pat -> [Ident]+patternDims (PatParens p _) = patternDims p+patternDims (TuplePat pats _) = concatMap patternDims pats+patternDims (PatAscription p (TypeDecl _ (Info t)) _) = patternDims p <> mapMaybe (dimIdent (srclocOf p)) (nestedDims t) where dimIdent _ (AnyDim _) = Nothing@@ -1172,7 +1172,7 @@ adjustDims (DimFix {} : idxes') (_ : dims) = adjustDims idxes' dims- -- Pattern match some known slices to be non-existential.+ -- Pat match some known slices to be non-existential. adjustDims (DimSlice i j stride : idxes') (_ : dims) | refine_sizes, maybe True ((== Just 0) . isInt64) i,@@ -1205,7 +1205,7 @@ -- The closure of a lambda or local function are those variables that -- it references, and which local to the current top-level function.-lexicalClosure :: [Pattern] -> Occurences -> TermTypeM Aliasing+lexicalClosure :: [Pat] -> Occurences -> TermTypeM Aliasing lexicalClosure params closure = do vtable <- asks $ scopeVtable . termScope let isLocal v = case v `M.lookup` vtable of@@ -1214,9 +1214,9 @@ return $ S.map AliasBound $ S.filter isLocal $- allOccuring closure S.\\ mconcat (map patternNames params)+ allOccuring closure S.\\ mconcat (map patNames params) -noAliasesIfOverloaded :: PatternType -> TermTypeM PatternType+noAliasesIfOverloaded :: PatType -> TermTypeM PatType noAliasesIfOverloaded t@(Scalar (TypeVar _ u tn [])) = do subst <- fmap snd . M.lookup (typeLeaf tn) <$> getConstraints case subst of@@ -1258,8 +1258,8 @@ unscopeType :: SrcLoc -> M.Map VName Ident ->- PatternType ->- TermTypeM (PatternType, [VName])+ PatType ->+ TermTypeM (PatType, [VName]) unscopeType tloc unscoped t = do (t', m) <- runStateT (traverseDims onDim t) mempty return (t' `addAliases` S.map unAlias, M.elems m)@@ -1286,7 +1286,7 @@ -- When a function result is not immediately bound to a name, we need -- to invent a name for it so we can track it during aliasing -- (uniqueness-error54.fut, uniqueness-error55.fut).-addResultAliases :: NameReason -> PatternType -> TermTypeM PatternType+addResultAliases :: NameReason -> PatType -> TermTypeM PatType addResultAliases r (Scalar (Record fs)) = Scalar . Record <$> traverse (addResultAliases r) fs addResultAliases r (Scalar (Sum fs)) =@@ -1306,8 +1306,8 @@ -- function", for better error messages. checkApplyExp :: UncheckedExp -> TermTypeM (Exp, ApplyOp) checkApplyExp (AppExp (Apply e1 e2 _ loc) _) = do- (e1', (fname, i)) <- checkApplyExp e1 arg <- checkArg e2+ (e1', (fname, i)) <- checkApplyExp e1 t <- expType e1' (t1, rt, argext, exts) <- checkApply loc (fname, i) t arg rt' <- addResultAliases (NameAppRes fname loc) rt@@ -1545,6 +1545,9 @@ checkExp (Negate arg loc) = do arg' <- require "numeric negation" anyNumberType =<< checkExp arg return $ Negate arg' loc+checkExp (Not arg loc) = do+ arg' <- require "logical negation" (Bool : anyIntType) =<< checkExp arg+ return $ Not arg' loc checkExp e@(AppExp Apply {} _) = fst <$> checkApplyExp e checkExp (AppExp (LetPat sizes pat e body loc) _) = sequentially (checkExp e) $ \e' e_occs -> do@@ -1558,7 +1561,7 @@ _ -> return () incLevel . bindingSizes sizes $ \sizes' ->- bindingPattern sizes' pat (Ascribed t) $ \pat' -> do+ bindingPat sizes' pat (Ascribed t) $ \pat' -> do body' <- checkExp body (body_t, retext) <- unscopeType loc (sizesMap sizes' <> patternMap pat') =<< expTypeFully body'@@ -1930,7 +1933,7 @@ uboundexp' <- require "being the bound in a 'for' loop" anySignedType =<< checkExp uboundexp bound_t <- expTypeFully uboundexp' bindingIdent i bound_t $ \i' ->- noUnique . bindingPattern [] mergepat (Ascribed merge_t) $+ noUnique . bindingPat [] mergepat (Ascribed merge_t) $ \mergepat' -> onlySelfAliasing $ tapOccurences $ do loopbody' <- noSizeEscape $ checkExp loopbody@@ -1948,8 +1951,8 @@ case t of _ | Just t' <- peelArray 1 t ->- bindingPattern [] xpat (Ascribed t') $ \xpat' ->- noUnique . bindingPattern [] mergepat (Ascribed merge_t) $+ bindingPat [] xpat (Ascribed t') $ \xpat' ->+ noUnique . bindingPat [] mergepat (Ascribed merge_t) $ \mergepat' -> onlySelfAliasing . tapOccurences $ do loopbody' <- noSizeEscape $ checkExp loopbody (sparams, mergepat'') <- checkLoopReturnSize mergepat' loopbody'@@ -1964,7 +1967,7 @@ "Iteratee of a for-in loop must be an array, but expression has type" <+> ppr t While cond ->- noUnique . bindingPattern [] mergepat (Ascribed merge_t) $ \mergepat' ->+ noUnique . bindingPat [] mergepat (Ascribed merge_t) $ \mergepat' -> onlySelfAliasing . tapOccurences $ sequentially ( checkExp cond@@ -1982,17 +1985,17 @@ mergepat'' <- do loopbody_t <- expTypeFully loopbody'- convergePattern mergepat' (allConsumed bodyflow) loopbody_t $+ convergePat mergepat' (allConsumed bodyflow) loopbody_t $ mkUsage (srclocOf loopbody') "being (part of) the result of the loop body" let consumeMerge (Id _ (Info pt) ploc) mt | unique pt = consume ploc $ aliases mt- consumeMerge (TuplePattern pats _) t+ consumeMerge (TuplePat pats _) t | Just ts <- isTupleRecord t = zipWithM_ consumeMerge pats ts- consumeMerge (PatternParens pat _) t =+ consumeMerge (PatParens pat _) t = consumeMerge pat t- consumeMerge (PatternAscription pat _ _) t =+ consumeMerge (PatAscription pat _ _) t = consumeMerge pat t consumeMerge _ _ = return ()@@ -2017,11 +2020,11 @@ -- and matches what happens for function calls. Those arrays that -- really *cannot* be consumed will alias something unconsumable, -- and will be caught that way.- let bound_here = patternNames mergepat'' <> S.fromList sparams <> form_bound+ let bound_here = patNames mergepat'' <> S.fromList sparams <> form_bound form_bound = case form' of For v _ -> S.singleton $ identName v- ForIn forpat _ -> patternNames forpat+ ForIn forpat _ -> patNames forpat While {} -> mempty loopt' = second (`S.difference` S.map AliasBound bound_here) $@@ -2042,13 +2045,13 @@ | v `elem` to_hide = AnyDim Nothing onDim d = d - convergePattern pat body_cons body_t body_loc = do- let consumed_merge = patternNames pat `S.intersection` body_cons+ convergePat pat body_cons body_t body_loc = do+ let consumed_merge = patNames pat `S.intersection` body_cons uniquePat (Wildcard (Info t) wloc) = Wildcard (Info $ t `setUniqueness` Nonunique) wloc- uniquePat (PatternParens p ploc) =- PatternParens (uniquePat p) ploc+ uniquePat (PatParens p ploc) =+ PatParens (uniquePat p) ploc uniquePat (Id name (Info t) iloc) | name `S.member` consumed_merge = let t' = t `setUniqueness` Unique `setAliases` mempty@@ -2056,15 +2059,15 @@ | otherwise = let t' = t `setUniqueness` Nonunique in Id name (Info t') iloc- uniquePat (TuplePattern pats ploc) =- TuplePattern (map uniquePat pats) ploc- uniquePat (RecordPattern fs ploc) =- RecordPattern (map (fmap uniquePat) fs) ploc- uniquePat (PatternAscription p t ploc) =- PatternAscription p t ploc- uniquePat p@PatternLit {} = p- uniquePat (PatternConstr n t ps ploc) =- PatternConstr n t (map uniquePat ps) ploc+ uniquePat (TuplePat pats ploc) =+ TuplePat (map uniquePat pats) ploc+ uniquePat (RecordPat fs ploc) =+ RecordPat (map (fmap uniquePat) fs) ploc+ uniquePat (PatAscription p t ploc) =+ PatAscription p t ploc+ uniquePat p@PatLit {} = p+ uniquePat (PatConstr n t ps ploc) =+ PatConstr n t (map uniquePat ps) ploc -- Make the pattern unique where needed. pat' = uniquePat pat@@ -2118,21 +2121,21 @@ return $ Id pat_v (Info (combAliases pat_v_t t)) patloc checkMergeReturn (Wildcard (Info pat_v_t) patloc) t = return $ Wildcard (Info (combAliases pat_v_t t)) patloc- checkMergeReturn (PatternParens p _) t =+ checkMergeReturn (PatParens p _) t = checkMergeReturn p t- checkMergeReturn (PatternAscription p _ _) t =+ checkMergeReturn (PatAscription p _ _) t = checkMergeReturn p t- checkMergeReturn (RecordPattern pfs patloc) (Scalar (Record tfs)) =- RecordPattern . M.toList <$> sequence pfs' <*> pure patloc+ checkMergeReturn (RecordPat pfs patloc) (Scalar (Record tfs)) =+ RecordPat . M.toList <$> sequence pfs' <*> pure patloc where pfs' = M.intersectionWith checkMergeReturn (M.fromList pfs) tfs- checkMergeReturn (TuplePattern pats patloc) t+ checkMergeReturn (TuplePat pats patloc) t | Just ts <- isTupleRecord t =- TuplePattern+ TuplePat <$> zipWithM checkMergeReturn pats ts <*> pure patloc checkMergeReturn p _ =@@ -2144,7 +2147,7 @@ let body_cons' = body_cons <> S.map aliasVar pat_cons if body_cons' == body_cons && patternType pat'' == patternType pat then return pat'- else convergePattern pat'' body_cons' body_t body_loc+ else convergePat pat'' body_cons' body_t body_loc checkExp (Constr name es NoInfo loc) = do t <- newTypeVar loc "t" es' <- mapM checkExp es@@ -2166,9 +2169,9 @@ Attr info <$> checkExp e <*> pure loc checkCases ::- PatternType ->+ PatType -> NE.NonEmpty (CaseBase NoInfo Name) ->- TermTypeM (NE.NonEmpty (CaseBase Info VName), PatternType, [VName])+ TermTypeM (NE.NonEmpty (CaseBase Info VName), PatType, [VName]) checkCases mt rest_cs = case NE.uncons rest_cs of (c, Nothing) -> do@@ -2185,11 +2188,11 @@ return (NE.cons c' cs', t, retext) checkCase ::- PatternType ->+ PatType -> CaseBase NoInfo Name ->- TermTypeM (CaseBase Info VName, PatternType, [VName])+ TermTypeM (CaseBase Info VName, PatType, [VName]) checkCase mt (CasePat p e loc) =- bindingPattern [] p (Ascribed mt) $ \p' -> do+ bindingPat [] p (Ascribed mt) $ \p' -> do e' <- checkExp e (t, retext) <- unscopeType loc (patternMap p') =<< expTypeFully e' return (CasePat p' e' loc, t, retext)@@ -2203,23 +2206,23 @@ | Unmatched p deriving (Functor, Show) -instance Pretty (Unmatched (PatternBase Info VName)) where+instance Pretty (Unmatched (PatBase Info VName)) where ppr um = case um of (UnmatchedNum p nums) -> ppr' p <+> "where p is not one of" <+> ppr nums (UnmatchedBool p) -> ppr' p (UnmatchedConstr p) -> ppr' p (Unmatched p) -> ppr' p where- ppr' (PatternAscription p t _) = ppr p <> ":" <+> ppr t- ppr' (PatternParens p _) = parens $ ppr' p+ ppr' (PatAscription p t _) = ppr p <> ":" <+> ppr t+ ppr' (PatParens p _) = parens $ ppr' p ppr' (Id v _ _) = pprName v- ppr' (TuplePattern pats _) = parens $ commasep $ map ppr' pats- ppr' (RecordPattern fs _) = braces $ commasep $ map ppField fs+ ppr' (TuplePat pats _) = parens $ commasep $ map ppr' pats+ ppr' (RecordPat fs _) = braces $ commasep $ map ppField fs where ppField (name, t) = text (nameToString name) <> equals <> ppr' t ppr' Wildcard {} = "_"- ppr' (PatternLit e _ _) = ppr e- ppr' (PatternConstr n _ ps _) = "#" <> ppr n <+> sep (map ppr' ps)+ ppr' (PatLit e _ _) = ppr e+ ppr' (PatConstr n _ ps _) = "#" <> ppr n <+> sep (map ppr' ps) checkUnmatched :: Exp -> TermTypeM () checkUnmatched e = void $ checkUnmatched' e >> astMap tv e@@ -2240,7 +2243,7 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = pure,- mapOnPatternType = pure+ mapOnPatType = pure } checkIdent :: IdentBase NoInfo Name -> TermTypeM Ident@@ -2272,12 +2275,12 @@ occur $ m1flow `seqOccurences` m2flow return b -type Arg = (Exp, PatternType, Occurences, SrcLoc)+type Arg = (Exp, PatType, Occurences, SrcLoc) argExp :: Arg -> Exp argExp (e, _, _, _) = e -argType :: Arg -> PatternType+argType :: Arg -> PatType argType (_, t, _, _) = t checkArg :: UncheckedExp -> TermTypeM Arg@@ -2310,9 +2313,9 @@ checkApply :: SrcLoc -> ApplyOp ->- PatternType ->+ PatType -> Arg ->- TermTypeM (PatternType, PatternType, Maybe VName, [VName])+ TermTypeM (PatType, PatType, Maybe VName, [VName]) checkApply loc (fname, _)@@ -2375,7 +2378,7 @@ -- to infer that a function is consuming. unify (mkUsage loc "use as function") (toStruct tfun) $ Scalar $ Arrow mempty Unnamed (toStruct (argType arg) `setUniqueness` Nonunique) tv- tfun' <- normPatternType tfun+ tfun' <- normPatType tfun checkApply loc fname tfun' arg checkApply loc (fname, prev_applied) ftype (argexp, _, _, _) = do let fname' = maybe "expression" (pquote . ppr) fname@@ -2426,10 +2429,10 @@ -- an argument the given types to a function with the given return -- type, consuming the argument with the given diet. returnType ::- PatternType ->+ PatType -> Diet ->- PatternType ->- PatternType+ PatType ->+ PatType returnType (Array _ Unique et shape) _ _ = Array mempty Unique et shape returnType (Array als Nonunique et shape) d arg =@@ -2468,7 +2471,7 @@ maskAliases t FuncDiet {} = t maskAliases _ _ = error "Invalid arguments passed to maskAliases." -consumeArg :: SrcLoc -> PatternType -> Diet -> TermTypeM [Occurence]+consumeArg :: SrcLoc -> PatType -> Diet -> TermTypeM [Occurence] consumeArg loc (Scalar (Record ets)) (RecordDiet ds) = concat . M.elems <$> traverse (uncurry $ consumeArg loc) (M.intersectionWith (,) ets ds) consumeArg loc (Array _ Nonunique _ _) Consume =@@ -2637,9 +2640,11 @@ bitWidth ty = 8 * intByteSize ty :: Int inBoundsI x (Signed t) = x >= -2 ^ (bitWidth t - 1) && x < 2 ^ (bitWidth t - 1) inBoundsI x (Unsigned t) = x >= 0 && x < 2 ^ bitWidth t+ inBoundsI x (FloatType Float16) = not $ isInfinite (fromIntegral x :: Half) inBoundsI x (FloatType Float32) = not $ isInfinite (fromIntegral x :: Float) inBoundsI x (FloatType Float64) = not $ isInfinite (fromIntegral x :: Double) inBoundsI _ Bool = error "Inferred type of int literal is not a number"+ inBoundsF x Float16 = not $ isInfinite (realToFrac x :: Float) inBoundsF x Float32 = not $ isInfinite (realToFrac x :: Float) inBoundsF x Float64 = not $ isInfinite x warnBounds inBounds x ty loc =@@ -2657,14 +2662,14 @@ ( Name, Maybe UncheckedTypeExp, [UncheckedTypeParam],- [UncheckedPattern],+ [UncheckedPat], UncheckedExp, SrcLoc ) -> TypeM ( VName, [TypeParam],- [Pattern],+ [Pat], Maybe (TypeExp VName), StructType, [VName],@@ -2749,17 +2754,17 @@ typeError usage mempty $ "Size" <+> pquote (pprName v) <+> "is ambiguous.\n" fixOverloaded _ = return () -hiddenParamNames :: [Pattern] -> Names+hiddenParamNames :: [Pat] -> Names hiddenParamNames params = hidden where- param_all_names = mconcat $ map patternNames params+ param_all_names = mconcat $ map patNames params named (Named x, _) = Just x named (Unnamed, _) = Nothing param_names = S.fromList $ mapMaybe (named . patternParam) params hidden = param_all_names `S.difference` param_names -inferredReturnType :: SrcLoc -> [Pattern] -> PatternType -> TermTypeM StructType+inferredReturnType :: SrcLoc -> [Pat] -> PatType -> TermTypeM StructType inferredReturnType loc params t = -- The inferred type may refer to names that are bound by the -- parameter patterns, but which will not be visible in the type.@@ -2777,13 +2782,13 @@ ( Name, Maybe UncheckedTypeExp, [UncheckedTypeParam],- [UncheckedPattern],+ [UncheckedPat], UncheckedExp, SrcLoc ) -> TermTypeM ( [TypeParam],- [Pattern],+ [Pat], Maybe (TypeExp VName), StructType, [VName],@@ -2855,7 +2860,7 @@ forM_ params' $ \p -> let consumedNonunique p' = not (unique $ unInfo $ identType p') && (identName p' `S.member` names)- in case find consumedNonunique $ S.toList $ patternIdents p of+ in case find consumedNonunique $ S.toList $ patIdents p of Just p' -> returnAliased fname (baseName $ identName p') loc Nothing ->@@ -2883,7 +2888,7 @@ onTypeArg (TypeArgType t _) = onParam t typeDimNamesPos _ = mempty -checkGlobalAliases :: [Pattern] -> PatternType -> SrcLoc -> TermTypeM ()+checkGlobalAliases :: [Pat] -> PatType -> SrcLoc -> TermTypeM () checkGlobalAliases params body_t loc = do vtable <- asks $ scopeVtable . termScope let isLocal v = case v `M.lookup` vtable of@@ -2893,7 +2898,7 @@ filter (not . isLocal) $ S.toList $ boundArrayAliases body_t- `S.difference` foldMap patternNames params+ `S.difference` foldMap patNames params case als of v : _ | not $ null params ->@@ -2905,7 +2910,7 @@ _ -> return () -inferReturnUniqueness :: [Pattern] -> PatternType -> PatternType+inferReturnUniqueness :: [Pat] -> PatType -> PatType inferReturnUniqueness params t = let forbidden = aliasesMultipleTimes t uniques = uniqueParamNames params@@ -2920,7 +2925,7 @@ in delve t -- An alias inhibits uniqueness if it is used in disjoint values.-aliasesMultipleTimes :: PatternType -> Names+aliasesMultipleTimes :: PatType -> Names aliasesMultipleTimes = S.fromList . map fst . filter ((> 1) . snd) . M.toList . delve where delve (Scalar (Record fs)) =@@ -2928,13 +2933,13 @@ delve t = M.fromList $ zip (map aliasVar $ S.toList (aliases t)) $ repeat (1 :: Int) -uniqueParamNames :: [Pattern] -> Names+uniqueParamNames :: [Pat] -> Names uniqueParamNames = S.map identName . S.filter (unique . unInfo . identType)- . foldMap patternIdents+ . foldMap patIdents -boundArrayAliases :: PatternType -> S.Set VName+boundArrayAliases :: PatType -> S.Set VName boundArrayAliases (Array als _ _ _) = boundAliases als boundArrayAliases (Scalar Prim {}) = mempty boundArrayAliases (Scalar (Record fs)) = foldMap boundArrayAliases fs@@ -2966,10 +2971,10 @@ -- These restrictions apply to all functions (anonymous or otherwise). -- Top-level functions have further restrictions that are checked -- during let-generalisation.-verifyFunctionParams :: Maybe Name -> [Pattern] -> TermTypeM ()+verifyFunctionParams :: Maybe Name -> [Pat] -> TermTypeM () verifyFunctionParams fname params = onFailure (CheckingParams fname) $- verifyParams (foldMap patternNames params) =<< mapM updateTypes params+ verifyParams (foldMap patNames params) =<< mapM updateTypes params where verifyParams forbidden (p : ps) | d : _ <- S.toList $ patternDimNames p `S.intersection` forbidden =@@ -3065,9 +3070,9 @@ Name -> SrcLoc -> [TypeParam] ->- [Pattern] ->+ [Pat] -> StructType ->- TermTypeM ([TypeParam], [Pattern], StructType, [VName])+ TermTypeM ([TypeParam], [Pat], StructType, [VName]) letGeneralise defname defloc tparams params rettype = onFailure (CheckingLetGeneralise defname) $ do now_substs <- getConstraints@@ -3120,7 +3125,7 @@ return (tparams', params, rettype'', retext) checkFunBody ::- [Pattern] ->+ [Pat] -> UncheckedExp -> Maybe StructType -> SrcLoc ->@@ -3301,5 +3306,5 @@ mapOnName = pure, mapOnQualName = pure, mapOnStructType = normTypeFully,- mapOnPatternType = normTypeFully+ mapOnPatType = normTypeFully }
src/Language/Futhark/TypeChecker/Types.hs view
@@ -15,13 +15,11 @@ Subst (..), substFromAbbr, TypeSubs,- unionSubs, Substitutable (..), substTypesAny, ) where -import Control.Applicative import Control.Monad.Identity import Control.Monad.Reader import Control.Monad.State@@ -279,18 +277,18 @@ -- a description of all names used in the pattern group. checkForDuplicateNames :: MonadTypeChecker m =>- [UncheckedPattern] ->+ [UncheckedPat] -> m () checkForDuplicateNames = (`evalStateT` mempty) . mapM_ check where check (Id v _ loc) = seen v loc- check (PatternParens p _) = check p+ check (PatParens p _) = check p check Wildcard {} = return ()- check (TuplePattern ps _) = mapM_ check ps- check (RecordPattern fs _) = mapM_ (check . snd) fs- check (PatternAscription p _ _) = check p- check PatternLit {} = return ()- check (PatternConstr _ _ ps _) = mapM_ check ps+ check (TuplePat ps _) = mapM_ check ps+ check (RecordPat fs _) = mapM_ (check . snd) fs+ check (PatAscription p _ _) = check p+ check PatLit {} = return ()+ check (PatConstr _ _ ps _) = mapM_ check ps seen v loc = do already <- gets $ M.lookup v@@ -384,16 +382,13 @@ data Subst t = Subst [TypeParam] t | PrimSubst | SizeSubst (DimDecl VName) deriving (Show) +-- | Create a type substitution corresponding to a type binding. substFromAbbr :: TypeBinding -> Subst StructType substFromAbbr (TypeAbbr _ ps t) = Subst ps t -- | Substitutions to apply in a type. type TypeSubs = VName -> Maybe (Subst StructType) --- | Additively combine two non-intersecting substitutions.-unionSubs :: TypeSubs -> TypeSubs -> TypeSubs-unionSubs f g v = g v <|> f v- instance Functor Subst where fmap f (Subst ps t) = Subst ps $ f t fmap _ PrimSubst = PrimSubst@@ -418,7 +413,7 @@ instance Substitutable d => Substitutable (ShapeDecl d) where applySubst f = fmap $ applySubst f -instance Substitutable Pattern where+instance Substitutable Pat where applySubst f = runIdentity . astMap mapper where mapper =@@ -427,7 +422,7 @@ mapOnName = return, mapOnQualName = return, mapOnStructType = return . applySubst f,- mapOnPatternType = return . applySubst f+ mapOnPatType = return . applySubst f } applyType ::
src/Language/Futhark/TypeChecker/Unify.hs view
@@ -27,7 +27,7 @@ mustHaveField, mustBeOneOf, equalityType,- normPatternType,+ normPatType, normTypeFully, instantiateEmptyArrayDims, unify,@@ -312,14 +312,14 @@ normType t = return t -- | Replace any top-level type variable with its substitution.-normPatternType :: MonadUnify m => PatternType -> m PatternType-normPatternType t@(Scalar (TypeVar als u (TypeName [] v) [])) = do+normPatType :: MonadUnify m => PatType -> m PatType+normPatType t@(Scalar (TypeVar als u (TypeName [] v) [])) = do constraints <- getConstraints case snd <$> M.lookup v constraints of Just (Constraint t' _) ->- normPatternType $ t' `setUniqueness` u `setAliases` als+ normPatType $ t' `setUniqueness` u `setAliases` als _ -> return t-normPatternType t = return t+normPatType t = return t rigidConstraint :: Constraint -> Bool rigidConstraint ParamType {} = True@@ -1017,8 +1017,8 @@ Usage -> BreadCrumbs -> Name ->- PatternType ->- m PatternType+ PatType ->+ m PatType mustHaveFieldWith onDims usage bcs l t = do constraints <- getConstraints l_type <- newTypeVar (srclocOf usage) "t"@@ -1055,8 +1055,8 @@ MonadUnify m => Usage -> Name ->- PatternType ->- m PatternType+ PatType ->+ m PatType mustHaveField usage = mustHaveFieldWith (unifyDims usage) usage noBreadCrumbs -- | Replace dimension mismatches with AnyDim.@@ -1102,9 +1102,9 @@ unifyMostCommon :: MonadUnify m => Usage ->- PatternType ->- PatternType ->- m (PatternType, [VName])+ PatType ->+ PatType ->+ m (PatType, [VName]) unifyMostCommon usage t1 t2 = do -- We are ignoring the dimensions here, because any mismatches -- should be turned into fresh size variables.
src/futhark.hs view
@@ -21,6 +21,7 @@ import qualified Futhark.CLI.Literate as Literate import qualified Futhark.CLI.Misc as Misc import qualified Futhark.CLI.Multicore as Multicore+import qualified Futhark.CLI.MulticoreWASM as MulticoreWASM import qualified Futhark.CLI.OpenCL as OpenCL import qualified Futhark.CLI.Pkg as Pkg import qualified Futhark.CLI.PyOpenCL as PyOpenCL@@ -29,6 +30,7 @@ import qualified Futhark.CLI.REPL as REPL import qualified Futhark.CLI.Run as Run import qualified Futhark.CLI.Test as Test+import qualified Futhark.CLI.WASM as WASM import Futhark.Error import Futhark.Util (maxinum) import Futhark.Util.Options@@ -54,6 +56,8 @@ ("multicore", (Multicore.main, "Compile to multicore C.")), ("python", (Python.main, "Compile to sequential Python.")), ("pyopencl", (PyOpenCL.main, "Compile to Python calling PyOpenCL.")),+ ("wasm", (WASM.main, "Compile to WASM with sequential C")),+ ("wasm-multicore", (MulticoreWASM.main, "Compile to WASM with multicore C")), ("test", (Test.main, "Test Futhark programs.")), ("bench", (Bench.main, "Benchmark Futhark programs.")), ("dataset", (Dataset.main, "Generate random test data.")),
unittests/Futhark/IR/Mem/IxFun/Alg.hs view
@@ -8,6 +8,7 @@ rotate, reshape, slice,+ flatSlice, rebase, shape, index,@@ -19,8 +20,11 @@ import Futhark.IR.Syntax ( DimChange (..), DimIndex (..),+ FlatDimIndex (..),+ FlatSlice (..), ShapeChange,- Slice,+ Slice (..),+ flatSliceDims, sliceDims, unitSlice, )@@ -39,6 +43,7 @@ | Permute (IxFun num) Permutation | Rotate (IxFun num) (Indices num) | Index (IxFun num) (Slice num)+ | FlatIndex (IxFun num) (FlatSlice num) | Reshape (IxFun num) (ShapeChange num) | OffsetIndex (IxFun num) num | Rebase (IxFun num) (IxFun num)@@ -49,7 +54,8 @@ text "Direct" <> parens (commasep $ map ppr dims) ppr (Permute fun perm) = ppr fun <> ppr perm ppr (Rotate fun offsets) = ppr fun <> brackets (commasep $ map ((text "+" <>) . ppr) offsets)- ppr (Index fun is) = ppr fun <> brackets (commasep $ map ppr is)+ ppr (Index fun is) = ppr fun <> ppr is+ ppr (FlatIndex fun is) = ppr fun <> ppr is ppr (Reshape fun oldshape) = ppr fun <> text "->reshape" <> parens (commasep (map ppr oldshape))@@ -73,6 +79,9 @@ slice :: IxFun num -> Slice num -> IxFun num slice = Index +flatSlice :: IxFun num -> FlatSlice num -> IxFun num+flatSlice = FlatIndex+ rebase :: IxFun num -> IxFun num -> IxFun num rebase = Rebase @@ -91,6 +100,8 @@ shape ixfun shape (Index _ how) = sliceDims how+shape (FlatIndex ixfun how) =+ flatSliceDims how <> tail (shape ixfun) shape (Reshape _ dims) = map newDim dims shape (OffsetIndex ixfun _) =@@ -115,19 +126,23 @@ index fun $ zipWith mod (zipWith (+) is offsets) dims where dims = shape fun-index (Index fun js) is =+index (Index fun (Slice js)) is = index fun (adjust js is) where adjust (DimFix j : js') is' = j : adjust js' is' adjust (DimSlice j _ s : js') (i : is') = j + i * s : adjust js' is' adjust _ _ = []+index (FlatIndex fun (FlatSlice offset js)) is =+ index fun $ sum (offset : zipWith f is js) : drop (length js) is+ where+ f i (FlatDimIndex _ s) = i * s index (Reshape fun newshape) is = let new_indices = reshapeIndex (shape fun) (newDims newshape) is in index fun new_indices index (OffsetIndex fun i) is = case shape fun of d : ds ->- index (Index fun (DimSlice i (d - i) 1 : map (unitSlice 0) ds)) is+ index (Index fun (Slice (DimSlice i (d - i) 1 : map (unitSlice 0) ds))) is [] -> error "index: OffsetIndex: underlying index function has rank zero" index (Rebase new_base fun) is = let fun' = case fun of@@ -141,6 +156,8 @@ rotate (rebase new_base ixfun) offsets Index ixfun iis -> slice (rebase new_base ixfun) iis+ FlatIndex ixfun iis ->+ flatSlice (rebase new_base ixfun) iis Reshape ixfun new_shape -> reshape (rebase new_base ixfun) new_shape OffsetIndex ixfun s ->
unittests/Futhark/IR/Mem/IxFunTests.hs view
@@ -80,12 +80,13 @@ n :: Int n = 19 -slice3 :: [DimIndex Int]+slice3 :: Slice Int slice3 =- [ DimSlice 2 (n `P.div` 3) 3,- DimFix (n `P.div` 2),- DimSlice 1 (n `P.div` 2) 2- ]+ Slice+ [ DimSlice 2 (n `P.div` 3) 3,+ DimFix (n `P.div` 2),+ DimSlice 1 (n `P.div` 2) 2+ ] -- Actual tests. tests :: TestTree@@ -110,7 +111,15 @@ test_rebase1, test_rebase2, test_rebase3,- test_rebase4_5+ test_rebase4_5,+ test_flatSlice_iota,+ test_slice_flatSlice_iota,+ test_flatSlice_flatSlice_iota,+ test_flatSlice_slice_iota,+ test_flatSlice_rotate_iota,+ test_flatSlice_rotate_slice_iota,+ test_flatSlice_transpose_slice_iota,+ test_rotate_flatSlice_transpose_slice_iota ] singleton :: TestTree -> [TestTree]@@ -160,15 +169,17 @@ testCase "slice . rotate . permute . slice . iota 1" $ compareOps $ let slice2 =- [ DimSlice 0 n 1,- DimSlice 1 (n `P.div` 2) 2,- DimSlice 0 n 1- ]+ Slice+ [ DimSlice 0 n 1,+ DimSlice 1 (n `P.div` 2) 2,+ DimSlice 0 n 1+ ] slice13 =- [ DimSlice 2 (n `P.div` 3) 3,- DimSlice 0 (n `P.div` 2) 1,- DimSlice 1 (n `P.div` 2) 2- ]+ Slice+ [ DimSlice 2 (n `P.div` 3) 3,+ DimSlice 0 (n `P.div` 2) 1,+ DimSlice 1 (n `P.div` 2) 2+ ] ixfun = permute (slice (iota [n, n, n]) slice2) [2, 1, 0] ixfun' = slice (rotate ixfun [3, 1, 2]) slice13 in ixfun'@@ -179,15 +190,17 @@ testCase "slice . rotate . permute . slice . iota 2" $ compareOps $ let slice2 =- [ DimSlice 0 (n `P.div` 2) 1,- DimFix (n `P.div` 2),- DimSlice 0 (n `P.div` 3) 1- ]+ Slice+ [ DimSlice 0 (n `P.div` 2) 1,+ DimFix (n `P.div` 2),+ DimSlice 0 (n `P.div` 3) 1+ ] slice13 =- [ DimSlice 2 (n `P.div` 3) 3,- DimSlice 0 n 1,- DimSlice 1 (n `P.div` 2) 2- ]+ Slice+ [ DimSlice 2 (n `P.div` 3) 3,+ DimSlice 0 n 1,+ DimSlice 1 (n `P.div` 2) 2+ ] ixfun = permute (slice (iota [n, n, n]) slice13) [2, 1, 0] ixfun' = slice (rotate ixfun [3, 1, 2]) slice2 in ixfun'@@ -204,7 +217,11 @@ (n1, m1) = case IxFunLMAD.shape (fst ixfun') of [a, b] -> (a, b) _ -> error "expecting 2 dimensions at this point!"- negslice = [DimSlice 0 n1 1, DimSlice (m1 - 1) m1 (-1)]+ negslice =+ Slice+ [ DimSlice 0 n1 1,+ DimSlice (m1 - 1) m1 (-1)+ ] ixfun'' = rotate (slice ixfun' negslice) [1, 2] in ixfun'' @@ -215,13 +232,18 @@ compareOps $ -- contiguousness let slice33 =- [ DimFix (n `P.div` 2),- DimSlice (n - 1) (n `P.div` 3) (-1),- DimSlice 0 n 1- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n - 1) (n `P.div` 3) (-1),+ DimSlice 0 n 1+ ] ixfun = permute (slice (iota [n, n, n]) slice33) [1, 0] m = n `P.div` 3- slice1 = [DimSlice (n - 1) n (-1), DimSlice 2 (m - 2) 1]+ slice1 =+ Slice+ [ DimSlice (n - 1) n (-1),+ DimSlice 2 (m - 2) 1+ ] ixfun' = permute (rotate (slice ixfun slice1) [1, 2]) [1, 0] in ixfun' @@ -251,11 +273,12 @@ compareOps $ let newdims = [DimNew (n * n), DimCoercion n] slc =- [ DimFix (n `P.div` 2),- DimSlice (n -1) n (-1),- DimSlice 0 n 1,- DimSlice (n -1) n (-1)- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n -1) n (-1),+ DimSlice 0 n 1,+ DimSlice (n -1) n (-1)+ ] in reshape (slice (iota [n, n, n, n]) slc) newdims test_reshape_slice_iota3 :: [TestTree]@@ -266,11 +289,12 @@ compareOps $ let newdims = [DimNew (n * n), DimCoercion n] slc =- [ DimFix (n `P.div` 2),- DimSlice 0 n 1,- DimSlice 0 (n `P.div` 2) 1,- DimSlice 0 n 1- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice 0 n 1,+ DimSlice 0 (n `P.div` 2) 1,+ DimSlice 0 n 1+ ] in reshape (slice (iota [n, n, n, n]) slc) newdims test_complex1 :: [TestTree]@@ -285,14 +309,21 @@ DimCoercion ((n `P.div` 3) - 2) ] slice33 =- [ DimSlice (n -1) (n `P.div` 3) (-1),- DimSlice (n -1) n (-1),- DimSlice (n -1) n (-1),- DimSlice 0 n 1- ]+ Slice+ [ DimSlice (n -1) (n `P.div` 3) (-1),+ DimSlice (n -1) n (-1),+ DimSlice (n -1) n (-1),+ DimSlice 0 n 1+ ] ixfun = permute (slice (iota [n, n, n, n, n]) slice33) [3, 1, 2, 0] m = n `P.div` 3- slice1 = [DimSlice 0 n 1, DimSlice (n -1) n (-1), DimSlice (n -1) n (-1), DimSlice 1 (m -2) (-1)]+ slice1 =+ Slice+ [ DimSlice 0 n 1,+ DimSlice (n -1) n (-1),+ DimSlice (n -1) n (-1),+ DimSlice 1 (m -2) (-1)+ ] ixfun' = reshape (rotate (slice ixfun slice1) [1, 2, 3, 4]) newdims in ixfun' @@ -307,15 +338,22 @@ DimCoercion ((n `P.div` 3) - 2) ] slc2 =- [ DimFix (n `P.div` 2),- DimSlice (n -1) (n `P.div` 3) (-1),- DimSlice (n -1) n (-1),- DimSlice (n -1) n (-1),- DimSlice 0 n 1- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n -1) (n `P.div` 3) (-1),+ DimSlice (n -1) n (-1),+ DimSlice (n -1) n (-1),+ DimSlice 0 n 1+ ] ixfun = permute (slice (iota [n, n, n, n, n]) slc2) [3, 1, 2, 0] m = n `P.div` 3- slice1 = [DimSlice 0 n 1, DimSlice (n -1) n (-1), DimSlice (n -1) n (-1), DimSlice 1 (m -2) (-1)]+ slice1 =+ Slice+ [ DimSlice 0 n 1,+ DimSlice (n -1) n (-1),+ DimSlice (n -1) n (-1),+ DimSlice 1 (m -2) (-1)+ ] ixfun' = reshape (rotate (slice ixfun slice1) [1, 0, 0, 2]) newdims in ixfun' @@ -325,10 +363,11 @@ testCase "rebase 1" $ compareOps $ let slice_base =- [ DimFix (n `P.div` 2),- DimSlice 2 (n -2) 1,- DimSlice 3 (n -3) 1- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice 2 (n -2) 1,+ DimSlice 3 (n -3) 1+ ] ixfn_base = rotate (permute (slice (iota [n, n, n]) slice_base) [1, 0]) [2, 1] ixfn_orig = rotate (permute (iota [n -3, n -2]) [1, 0]) [1, 2] ixfn_rebase = rebase ixfn_base ixfn_orig@@ -340,14 +379,16 @@ testCase "rebase 2" $ compareOps $ let slice_base =- [ DimFix (n `P.div` 2),- DimSlice (n -1) (n -2) (-1),- DimSlice (n -1) (n -3) (-1)- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n -1) (n -2) (-1),+ DimSlice (n -1) (n -3) (-1)+ ] slice_orig =- [ DimSlice (n -4) (n -3) (-1),- DimSlice (n -3) (n -2) (-1)- ]+ Slice+ [ DimSlice (n -4) (n -3) (-1),+ DimSlice (n -3) (n -2) (-1)+ ] ixfn_base = rotate (permute (slice (iota [n, n, n]) slice_base) [1, 0]) [2, 1] ixfn_orig = rotate (permute (slice (iota [n -3, n -2]) slice_orig) [1, 0]) [1, 2] ixfn_rebase = rebase ixfn_base ixfn_orig@@ -361,14 +402,16 @@ let n2 = (n -2) `P.div` 3 n3 = (n -3) `P.div` 2 slice_base =- [ DimFix (n `P.div` 2),- DimSlice (n -1) n2 (-3),- DimSlice (n -1) n3 (-2)- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n -1) n2 (-3),+ DimSlice (n -1) n3 (-2)+ ] slice_orig =- [ DimSlice (n3 -1) n3 (-1),- DimSlice (n2 -1) n2 (-1)- ]+ Slice+ [ DimSlice (n3 -1) n3 (-1),+ DimSlice (n2 -1) n2 (-1)+ ] ixfn_base = rotate (permute (slice (iota [n, n, n]) slice_base) [1, 0]) [2, 1] ixfn_orig = rotate (permute (slice (iota [n3, n2]) slice_orig) [1, 0]) [1, 2] ixfn_rebase = rebase ixfn_base ixfn_orig@@ -379,17 +422,92 @@ let n2 = (n -2) `P.div` 3 n3 = (n -3) `P.div` 2 slice_base =- [ DimFix (n `P.div` 2),- DimSlice (n -1) n2 (-3),- DimSlice 3 n3 2- ]+ Slice+ [ DimFix (n `P.div` 2),+ DimSlice (n -1) n2 (-3),+ DimSlice 3 n3 2+ ] slice_orig =- [ DimSlice (n3 -1) n3 (-1),- DimSlice 0 n2 1- ]+ Slice+ [ DimSlice (n3 -1) n3 (-1),+ DimSlice 0 n2 1+ ] ixfn_base = rotate (permute (slice (iota [n, n, n]) slice_base) [1, 0]) [2, 1] ixfn_orig = rotate (permute (slice (iota [n3, n2]) slice_orig) [1, 0]) [1, 2] in [ testCase "rebase mixed monotonicities" $ compareOps $ rebase ixfn_base ixfn_orig ]++test_flatSlice_iota :: [TestTree]+test_flatSlice_iota =+ singleton $+ testCase "flatSlice . iota" $+ compareOps $+ flatSlice (iota [n * n * n * n]) $+ FlatSlice 2 [FlatDimIndex (n * 2) 4, FlatDimIndex n 3, FlatDimIndex 1 2]++test_slice_flatSlice_iota :: [TestTree]+test_slice_flatSlice_iota =+ singleton $+ testCase "slice . flatSlice . iota " $+ compareOps $+ slice (flatSlice (iota [2 + n * n * n]) flat_slice) $+ Slice [DimFix 2, DimSlice 0 n 1, DimFix 0]+ where+ flat_slice = FlatSlice 2 [FlatDimIndex (n * n) 1, FlatDimIndex n 1, FlatDimIndex 1 1]++test_flatSlice_flatSlice_iota :: [TestTree]+test_flatSlice_flatSlice_iota =+ singleton $+ testCase "flatSlice . flatSlice . iota " $+ compareOps $+ flatSlice (flatSlice (iota [10 * 10]) flat_slice_1) flat_slice_2+ where+ flat_slice_1 = FlatSlice 17 [FlatDimIndex 3 27, FlatDimIndex 3 10, FlatDimIndex 3 1]+ flat_slice_2 = FlatSlice 2 [FlatDimIndex 2 (-2)]++test_flatSlice_slice_iota :: [TestTree]+test_flatSlice_slice_iota =+ singleton $+ testCase "flatSlice . slice . iota " $+ compareOps $+ flatSlice (slice (iota [210, 100]) $ Slice [DimSlice 10 100 2, DimFix 10]) flat_slice_1+ where+ flat_slice_1 = FlatSlice 17 [FlatDimIndex 3 27, FlatDimIndex 3 10, FlatDimIndex 3 1]++test_flatSlice_rotate_iota :: [TestTree]+test_flatSlice_rotate_iota =+ singleton $+ testCase "flatSlice . rotate . iota " $+ compareOps $+ flatSlice (rotate (iota [10, 10]) [2, 5]) flat_slice_1+ where+ flat_slice_1 = FlatSlice 3 [FlatDimIndex 2 2, FlatDimIndex 2 1]++test_flatSlice_rotate_slice_iota :: [TestTree]+test_flatSlice_rotate_slice_iota =+ singleton $+ testCase "flatSlice . rotate . slice . iota " $+ compareOps $+ flatSlice (rotate (slice (iota [20, 20]) $ Slice [DimSlice 1 5 2, DimSlice 0 5 2]) [2, 3]) flat_slice_1+ where+ flat_slice_1 = FlatSlice 1 [FlatDimIndex 2 2]++test_flatSlice_transpose_slice_iota :: [TestTree]+test_flatSlice_transpose_slice_iota =+ singleton $+ testCase "flatSlice . transpose . slice . iota " $+ compareOps $+ flatSlice (permute (slice (iota [20, 20]) $ Slice [DimSlice 1 5 2, DimSlice 0 5 2]) [1, 0]) flat_slice_1+ where+ flat_slice_1 = FlatSlice 1 [FlatDimIndex 2 2]++test_rotate_flatSlice_transpose_slice_iota :: [TestTree]+test_rotate_flatSlice_transpose_slice_iota =+ singleton $+ testCase "flatSlice . transpose . slice . iota " $+ compareOps $+ rotate (flatSlice (permute (slice (iota [20, 20]) $ Slice [DimSlice 1 5 2, DimSlice 1 5 2]) [1, 0]) flat_slice_1) [2, 1]+ where+ flat_slice_1 = FlatSlice 1 [FlatDimIndex 2 2]
unittests/Futhark/IR/Mem/IxFunWrapper.hs view
@@ -7,13 +7,14 @@ rotate, reshape, slice,+ flatSlice, rebase, ) where import qualified Futhark.IR.Mem.IxFun as I import qualified Futhark.IR.Mem.IxFun.Alg as IA-import Futhark.IR.Syntax (ShapeChange, Slice)+import Futhark.IR.Syntax (FlatSlice, ShapeChange, Slice) import Futhark.Util.IntegralExp type Shape num = [num]@@ -57,6 +58,13 @@ Slice num -> IxFun num slice (l, a) x = (I.slice l x, IA.slice a x)++flatSlice ::+ (Eq num, IntegralExp num) =>+ IxFun num ->+ FlatSlice num ->+ IxFun num+flatSlice (l, a) x = (I.flatSlice l x, IA.flatSlice a x) rebase :: (Eq num, IntegralExp num) =>
unittests/Futhark/IR/PrimitiveTests.hs view
@@ -9,6 +9,7 @@ import Control.Applicative import Futhark.IR.Primitive+import Futhark.Util (convFloat) import Test.QuickCheck import Test.Tasty import Test.Tasty.HUnit@@ -44,10 +45,14 @@ Int64Value <$> arbitrary ] +instance Arbitrary Half where+ arbitrary = (convFloat :: Float -> Half) <$> arbitrary+ instance Arbitrary FloatValue where arbitrary = oneof- [ Float32Value <$> arbitrary,+ [ Float16Value <$> arbitrary,+ Float32Value <$> arbitrary, Float64Value <$> arbitrary ] @@ -65,6 +70,7 @@ arbitraryPrimValOfType (IntType Int16) = IntValue . Int16Value <$> arbitrary arbitraryPrimValOfType (IntType Int32) = IntValue . Int32Value <$> arbitrary arbitraryPrimValOfType (IntType Int64) = IntValue . Int64Value <$> arbitrary+arbitraryPrimValOfType (FloatType Float16) = FloatValue . Float16Value <$> arbitrary arbitraryPrimValOfType (FloatType Float32) = FloatValue . Float32Value <$> arbitrary arbitraryPrimValOfType (FloatType Float64) = FloatValue . Float32Value <$> arbitrary arbitraryPrimValOfType Bool = BoolValue <$> arbitrary
unittests/Futhark/Optimise/ReuseAllocations/GreedyColoringTests.hs view
@@ -5,8 +5,8 @@ import Control.Arrow ((***)) import Data.Function ((&))-import qualified Data.Map as Map-import qualified Data.Set as Set+import qualified Data.Map as M+import qualified Data.Set as S import qualified Futhark.Optimise.ReuseAllocations.GreedyColoring as GreedyColoring import Test.Tasty import Test.Tasty.HUnit@@ -23,10 +23,10 @@ assertEqual "Color simple 1-2-3 using two colors" ([(0, "local"), (1, "local")], [(1 :: Int, 0), (2, 1), (3, 0)])- $ (Map.toList *** Map.toList) $+ $ (M.toList *** M.toList) $ GreedyColoring.colorGraph- (Map.fromList [(1, "local"), (2, "local"), (3, "local")])- $ Set.fromList [(1, 2), (2, 3)]+ (M.fromList [(1, "local"), (2, "local"), (3, "local")])+ $ S.fromList [(1, 2), (2, 3)] allIntersect :: TestTree allIntersect =@@ -34,10 +34,10 @@ assertEqual "Color a graph where all values intersect" ([(0, "local"), (1, "local"), (2, "local")], [(1 :: Int, 2), (2, 1), (3, 0)])- $ (Map.toList *** Map.toList) $+ $ (M.toList *** M.toList) $ GreedyColoring.colorGraph- (Map.fromList [(1, "local"), (2, "local"), (3, "local")])- $ Set.fromList [(1, 2), (2, 3), (1, 3)]+ (M.fromList [(1, "local"), (2, "local"), (3, "local")])+ $ S.fromList [(1, 2), (2, 3), (1, 3)] emptyGraph :: TestTree emptyGraph =@@ -45,14 +45,14 @@ assertEqual "Color an empty graph" ([] :: [(Int, Char)], [] :: [(Int, Int)])- $ (Map.toList *** Map.toList) $ GreedyColoring.colorGraph Map.empty $ Set.fromList []+ $ (M.toList *** M.toList) $ GreedyColoring.colorGraph M.empty $ S.fromList [] noIntersections :: TestTree noIntersections = GreedyColoring.colorGraph- (Map.fromList [(1, "local"), (2, "local"), (3, "local")])- (Set.fromList [])- & Map.toList *** Map.toList+ (M.fromList [(1, "local"), (2, "local"), (3, "local")])+ (S.fromList [])+ & M.toList *** M.toList & assertEqual "Color nodes with no intersections" ([(0, "local")], [(1, 0), (2, 0), (3, 0)] :: [(Int, Int)])@@ -61,9 +61,9 @@ differentSpaces :: TestTree differentSpaces = GreedyColoring.colorGraph- (Map.fromList [(1, "a"), (2, "b"), (3, "c")])- (Set.fromList [])- & Map.toList *** Map.toList+ (M.fromList [(1, "a"), (2, "b"), (3, "c")])+ (S.fromList [])+ & M.toList *** M.toList & assertEqual "Color nodes with no intersections but in different spaces" ([(0, "c"), (1, "b"), (2, "a")], [(1, 2), (2, 1), (3, 0)] :: [(Int, Int)])