futhark 0.19.6 → 0.19.7
raw patch · 181 files changed
+13121/−13244 lines, 181 filesdep +futhark-datadep +futhark-serverPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: futhark-data, futhark-server
API changes (from Hackage documentation)
- Futhark.Analysis.HORep.MapNest: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.Analysis.HORep.MapNest.MapNest lore)
- Futhark.Analysis.HORep.MapNest: instance GHC.Classes.Eq (Futhark.Analysis.HORep.MapNest.Nesting lore)
- Futhark.Analysis.HORep.MapNest: instance GHC.Classes.Ord (Futhark.Analysis.HORep.MapNest.Nesting lore)
- Futhark.Analysis.HORep.MapNest: instance GHC.Show.Show (Futhark.Analysis.HORep.MapNest.Nesting lore)
- Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.Analysis.HORep.SOAC.SOAC lore)
- Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.Analysis.HORep.SOAC.SOAC lore)
- Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.Analysis.HORep.SOAC.SOAC lore)
- Futhark.Analysis.Rephrase: [rephraseBodyLore] :: Rephraser m from to -> BodyDec from -> m (BodyDec to)
- Futhark.Analysis.Rephrase: [rephraseExpLore] :: Rephraser m from to -> ExpDec from -> m (ExpDec to)
- Futhark.Analysis.Rephrase: [rephraseFParamLore] :: Rephraser m from to -> FParamInfo from -> m (FParamInfo to)
- Futhark.Analysis.Rephrase: [rephraseLParamLore] :: Rephraser m from to -> LParamInfo from -> m (LParamInfo to)
- Futhark.Analysis.Rephrase: [rephraseLetBoundLore] :: Rephraser m from to -> LetDec from -> m (LetDec to)
- Futhark.Analysis.SymbolTable: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Types.Typed (Futhark.Analysis.SymbolTable.Entry lore)
- Futhark.Analysis.SymbolTable: instance GHC.Base.Monoid (Futhark.Analysis.SymbolTable.SymbolTable lore)
- Futhark.Analysis.SymbolTable: instance GHC.Base.Semigroup (Futhark.Analysis.SymbolTable.SymbolTable lore)
- Futhark.Binder: instance (Futhark.IR.Prop.ASTLore lore, Futhark.MonadFreshNames.MonadFreshNames m, Futhark.Binder.BinderOps lore) => Futhark.Binder.Class.MonadBinder (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance (Futhark.IR.Prop.ASTLore lore, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.HasScope lore (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance (Futhark.IR.Prop.ASTLore lore, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.LocalScope lore (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance Control.Monad.Trans.Class.MonadTrans (Futhark.Binder.BinderT lore)
- Futhark.Binder: instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance Futhark.MonadFreshNames.MonadFreshNames m => Futhark.MonadFreshNames.MonadFreshNames (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance GHC.Base.Monad m => GHC.Base.Applicative (Futhark.Binder.BinderT lore m)
- Futhark.Binder: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.Binder.BinderT lore m)
- Futhark.CodeGen.ImpCode.Kernels: (.&&.) :: TPrimExp Bool v -> TPrimExp Bool v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.&.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: (.<.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.<<.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: (.<=.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.==.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.>.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.>=.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: (.>>.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: (.^.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: (.|.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: (.||.) :: TPrimExp Bool v -> TPrimExp Bool v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: AShr :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: Abs :: IntType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: Add :: IntType -> Overflow -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: And :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: ArrayValue :: VName -> Space -> PrimType -> Signedness -> [DimSize] -> ValueDesc
- Futhark.CodeGen.ImpCode.Kernels: ArrayValues :: [PrimValue] -> ArrayContents
- Futhark.CodeGen.ImpCode.Kernels: ArrayZeros :: Int -> ArrayContents
- Futhark.CodeGen.ImpCode.Kernels: Atomic :: Space -> AtomicOp -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicAdd :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicAnd :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicCmpXchg :: PrimType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicFAdd :: FloatType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicOr :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicSMax :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicSMin :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicUMax :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicUMin :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicXchg :: PrimType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: AtomicXor :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: BToI :: IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: Barrier :: Fence -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: BinOpExp :: BinOp -> PrimExp v -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: Bool :: PrimType
- Futhark.CodeGen.ImpCode.Kernels: BoolValue :: !Bool -> PrimValue
- Futhark.CodeGen.ImpCode.Kernels: CallKernel :: Kernel -> HostOp
- Futhark.CodeGen.ImpCode.Kernels: CmpEq :: PrimType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpLle :: CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpLlt :: CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpOpExp :: CmpOp -> PrimExp v -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: CmpSizeLe :: VName -> Name -> SizeClass -> Exp -> HostOp
- Futhark.CodeGen.ImpCode.Kernels: CmpSle :: IntType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpSlt :: IntType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpUle :: IntType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: CmpUlt :: IntType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: Commutative :: Commutativity
- Futhark.CodeGen.ImpCode.Kernels: Complement :: IntType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: ConstUse :: VName -> KernelConstExp -> KernelUse
- Futhark.CodeGen.ImpCode.Kernels: Constant :: PrimValue -> SubExp
- Futhark.CodeGen.ImpCode.Kernels: Constants :: [Param] -> Code a -> Constants a
- Futhark.CodeGen.ImpCode.Kernels: ConvOpExp :: ConvOp -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: Count :: e -> Count u e
- Futhark.CodeGen.ImpCode.Kernels: DefaultSpace :: Space
- Futhark.CodeGen.ImpCode.Kernels: Definitions :: Constants a -> Functions a -> Definitions a
- Futhark.CodeGen.ImpCode.Kernels: ErrorInt32 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Kernels: ErrorInt64 :: a -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Kernels: ErrorMsg :: [ErrorMsgPart a] -> ErrorMsg a
- Futhark.CodeGen.ImpCode.Kernels: ErrorString :: String -> ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Kernels: ErrorSync :: Fence -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: ExpArg :: Exp -> Arg
- Futhark.CodeGen.ImpCode.Kernels: FAbs :: FloatType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: FAdd :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FCmpLe :: FloatType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: FCmpLt :: FloatType -> CmpOp
- Futhark.CodeGen.ImpCode.Kernels: FDiv :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FMax :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FMin :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FMod :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FMul :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FPConv :: FloatType -> FloatType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: FPToSI :: FloatType -> IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: FPToUI :: FloatType -> IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: FPow :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FSignum :: FloatType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: FSub :: FloatType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: FenceGlobal :: Fence
- Futhark.CodeGen.ImpCode.Kernels: FenceLocal :: Fence
- Futhark.CodeGen.ImpCode.Kernels: Float32 :: FloatType
- Futhark.CodeGen.ImpCode.Kernels: Float32Value :: !Float -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: Float64 :: FloatType
- Futhark.CodeGen.ImpCode.Kernels: Float64Value :: !Double -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: FloatType :: FloatType -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: FloatValue :: !FloatValue -> PrimValue
- Futhark.CodeGen.ImpCode.Kernels: FunExp :: String -> [PrimExp v] -> PrimType -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: Function :: Maybe Name -> [Param] -> [Param] -> Code a -> [ExternalValue] -> [ExternalValue] -> FunctionT a
- Futhark.CodeGen.ImpCode.Kernels: Functions :: [(Name, Function a)] -> Functions a
- Futhark.CodeGen.ImpCode.Kernels: GetGlobalId :: VName -> Int -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetGlobalSize :: VName -> Int -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetGroupId :: VName -> Int -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetLocalId :: VName -> Int -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetLocalSize :: VName -> Int -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetLockstepWidth :: VName -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: GetSize :: VName -> Name -> SizeClass -> HostOp
- Futhark.CodeGen.ImpCode.Kernels: GetSizeMax :: VName -> SizeClass -> HostOp
- Futhark.CodeGen.ImpCode.Kernels: IToB :: IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: Index :: VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> ExpLeaf
- Futhark.CodeGen.ImpCode.Kernels: Int16 :: IntType
- Futhark.CodeGen.ImpCode.Kernels: Int16Value :: !Int16 -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: Int32 :: IntType
- Futhark.CodeGen.ImpCode.Kernels: Int32Value :: !Int32 -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: Int64 :: IntType
- Futhark.CodeGen.ImpCode.Kernels: Int64Value :: !Int64 -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: Int8 :: IntType
- Futhark.CodeGen.ImpCode.Kernels: Int8Value :: !Int8 -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: IntType :: IntType -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: IntValue :: !IntValue -> PrimValue
- Futhark.CodeGen.ImpCode.Kernels: Kernel :: Code KernelOp -> [KernelUse] -> [Exp] -> [Exp] -> Name -> Bool -> Kernel
- Futhark.CodeGen.ImpCode.Kernels: LShr :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: LeafExp :: v -> PrimType -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: LocalAlloc :: VName -> Count Bytes (TExp Int64) -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: LogAnd :: BinOp
- Futhark.CodeGen.ImpCode.Kernels: LogOr :: BinOp
- Futhark.CodeGen.ImpCode.Kernels: MemArg :: VName -> Arg
- Futhark.CodeGen.ImpCode.Kernels: MemFence :: Fence -> KernelOp
- Futhark.CodeGen.ImpCode.Kernels: MemParam :: VName -> Space -> Param
- Futhark.CodeGen.ImpCode.Kernels: MemoryUse :: VName -> KernelUse
- Futhark.CodeGen.ImpCode.Kernels: Mul :: IntType -> Overflow -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: Noncommutative :: Commutativity
- Futhark.CodeGen.ImpCode.Kernels: Nonunique :: Uniqueness
- Futhark.CodeGen.ImpCode.Kernels: Nonvolatile :: Volatility
- Futhark.CodeGen.ImpCode.Kernels: Not :: UnOp
- Futhark.CodeGen.ImpCode.Kernels: OpaqueValue :: String -> [ValueDesc] -> ExternalValue
- Futhark.CodeGen.ImpCode.Kernels: Or :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: OverflowUndef :: Overflow
- Futhark.CodeGen.ImpCode.Kernels: OverflowWrap :: Overflow
- Futhark.CodeGen.ImpCode.Kernels: Pow :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SDiv :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SDivUp :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SExt :: IntType -> IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: SIToFP :: IntType -> FloatType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: SMax :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SMin :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SMod :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SQuot :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SRem :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SSignum :: IntType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: Safe :: Safety
- Futhark.CodeGen.ImpCode.Kernels: ScalarParam :: VName -> PrimType -> Param
- Futhark.CodeGen.ImpCode.Kernels: ScalarSpace :: [SubExp] -> PrimType -> Space
- Futhark.CodeGen.ImpCode.Kernels: ScalarUse :: VName -> PrimType -> KernelUse
- Futhark.CodeGen.ImpCode.Kernels: ScalarValue :: PrimType -> Signedness -> VName -> ValueDesc
- Futhark.CodeGen.ImpCode.Kernels: ScalarVar :: VName -> ExpLeaf
- Futhark.CodeGen.ImpCode.Kernels: Shl :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: SizeConst :: Name -> KernelConst
- Futhark.CodeGen.ImpCode.Kernels: Space :: SpaceId -> Space
- Futhark.CodeGen.ImpCode.Kernels: Sub :: IntType -> Overflow -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: TPrimExp :: PrimExp v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: TransparentValue :: ValueDesc -> ExternalValue
- Futhark.CodeGen.ImpCode.Kernels: TypeDirect :: Signedness
- Futhark.CodeGen.ImpCode.Kernels: TypeUnsigned :: Signedness
- Futhark.CodeGen.ImpCode.Kernels: UDiv :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: UDivUp :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: UIToFP :: IntType -> FloatType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: UMax :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: UMin :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: UMod :: IntType -> Safety -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: USignum :: IntType -> UnOp
- Futhark.CodeGen.ImpCode.Kernels: UnOpExp :: UnOp -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: Unique :: Uniqueness
- Futhark.CodeGen.ImpCode.Kernels: Unit :: PrimType
- Futhark.CodeGen.ImpCode.Kernels: UnitValue :: PrimValue
- Futhark.CodeGen.ImpCode.Kernels: Unsafe :: Safety
- Futhark.CodeGen.ImpCode.Kernels: VName :: !Name -> !Int -> VName
- Futhark.CodeGen.ImpCode.Kernels: ValueExp :: PrimValue -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: Var :: VName -> SubExp
- Futhark.CodeGen.ImpCode.Kernels: Volatile :: Volatility
- Futhark.CodeGen.ImpCode.Kernels: Xor :: IntType -> BinOp
- Futhark.CodeGen.ImpCode.Kernels: ZExt :: IntType -> IntType -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: [constsDecl] :: Constants a -> [Param]
- Futhark.CodeGen.ImpCode.Kernels: [constsInit] :: Constants a -> Code a
- Futhark.CodeGen.ImpCode.Kernels: [defConsts] :: Definitions a -> Constants a
- Futhark.CodeGen.ImpCode.Kernels: [defFuns] :: Definitions a -> Functions a
- Futhark.CodeGen.ImpCode.Kernels: [kernelBody] :: Kernel -> Code KernelOp
- Futhark.CodeGen.ImpCode.Kernels: [kernelFailureTolerant] :: Kernel -> Bool
- Futhark.CodeGen.ImpCode.Kernels: [kernelGroupSize] :: Kernel -> [Exp]
- Futhark.CodeGen.ImpCode.Kernels: [kernelName] :: Kernel -> Name
- Futhark.CodeGen.ImpCode.Kernels: [kernelNumGroups] :: Kernel -> [Exp]
- Futhark.CodeGen.ImpCode.Kernels: [kernelUses] :: Kernel -> [KernelUse]
- Futhark.CodeGen.ImpCode.Kernels: [unCount] :: Count u e -> e
- Futhark.CodeGen.ImpCode.Kernels: [untyped] :: TPrimExp t v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: allBinOps :: [BinOp]
- Futhark.CodeGen.ImpCode.Kernels: allCmpOps :: [CmpOp]
- Futhark.CodeGen.ImpCode.Kernels: allConvOps :: [ConvOp]
- Futhark.CodeGen.ImpCode.Kernels: allFloatTypes :: [FloatType]
- Futhark.CodeGen.ImpCode.Kernels: allIntTypes :: [IntType]
- Futhark.CodeGen.ImpCode.Kernels: allPrimTypes :: [PrimType]
- Futhark.CodeGen.ImpCode.Kernels: allUnOps :: [UnOp]
- Futhark.CodeGen.ImpCode.Kernels: bNot :: TPrimExp Bool v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: baseName :: VName -> Name
- Futhark.CodeGen.ImpCode.Kernels: baseString :: VName -> String
- Futhark.CodeGen.ImpCode.Kernels: baseTag :: VName -> Int
- Futhark.CodeGen.ImpCode.Kernels: binOpType :: BinOp -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: blankPrimValue :: PrimType -> PrimValue
- Futhark.CodeGen.ImpCode.Kernels: boundByLambda :: Lambda lore -> [VName]
- Futhark.CodeGen.ImpCode.Kernels: boundByStm :: Stm lore -> Names
- Futhark.CodeGen.ImpCode.Kernels: boundByStms :: Stms lore -> Names
- Futhark.CodeGen.ImpCode.Kernels: boundInBody :: Body lore -> Names
- Futhark.CodeGen.ImpCode.Kernels: bytes :: a -> Count Bytes a
- Futhark.CodeGen.ImpCode.Kernels: calledFuncs :: Code a -> Set Name
- Futhark.CodeGen.ImpCode.Kernels: class NumExp t => FloatExp t
- Futhark.CodeGen.ImpCode.Kernels: class FreeIn dec => FreeDec dec
- Futhark.CodeGen.ImpCode.Kernels: class FreeIn a
- Futhark.CodeGen.ImpCode.Kernels: class NumExp t => IntExp t
- Futhark.CodeGen.ImpCode.Kernels: class Located a
- Futhark.CodeGen.ImpCode.Kernels: class NumExp t
- Futhark.CodeGen.ImpCode.Kernels: cmpOpType :: CmpOp -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: coerceIntPrimExp :: IntType -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: commutativeBinOp :: BinOp -> Bool
- Futhark.CodeGen.ImpCode.Kernels: constFoldPrimExp :: PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: convOpFun :: ConvOp -> String
- Futhark.CodeGen.ImpCode.Kernels: convOpType :: ConvOp -> (PrimType, PrimType)
- Futhark.CodeGen.ImpCode.Kernels: data Arg
- Futhark.CodeGen.ImpCode.Kernels: data ArrayContents
- Futhark.CodeGen.ImpCode.Kernels: data AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: data BinOp
- Futhark.CodeGen.ImpCode.Kernels: data Bytes
- Futhark.CodeGen.ImpCode.Kernels: data CmpOp
- Futhark.CodeGen.ImpCode.Kernels: data Commutativity
- Futhark.CodeGen.ImpCode.Kernels: data Constants a
- Futhark.CodeGen.ImpCode.Kernels: data ConvOp
- Futhark.CodeGen.ImpCode.Kernels: data Definitions a
- Futhark.CodeGen.ImpCode.Kernels: data Elements
- Futhark.CodeGen.ImpCode.Kernels: data ErrorMsgPart a
- Futhark.CodeGen.ImpCode.Kernels: data ExpLeaf
- Futhark.CodeGen.ImpCode.Kernels: data ExternalValue
- Futhark.CodeGen.ImpCode.Kernels: data FV
- Futhark.CodeGen.ImpCode.Kernels: data Fence
- Futhark.CodeGen.ImpCode.Kernels: data FloatType
- Futhark.CodeGen.ImpCode.Kernels: data FloatValue
- Futhark.CodeGen.ImpCode.Kernels: data FunctionT a
- Futhark.CodeGen.ImpCode.Kernels: data HostOp
- Futhark.CodeGen.ImpCode.Kernels: data Int16
- Futhark.CodeGen.ImpCode.Kernels: data Int32
- Futhark.CodeGen.ImpCode.Kernels: data Int64
- Futhark.CodeGen.ImpCode.Kernels: data Int8
- Futhark.CodeGen.ImpCode.Kernels: data IntType
- Futhark.CodeGen.ImpCode.Kernels: data IntValue
- Futhark.CodeGen.ImpCode.Kernels: data Kernel
- Futhark.CodeGen.ImpCode.Kernels: data KernelOp
- Futhark.CodeGen.ImpCode.Kernels: data KernelUse
- Futhark.CodeGen.ImpCode.Kernels: data Loc
- Futhark.CodeGen.ImpCode.Kernels: data Name
- Futhark.CodeGen.ImpCode.Kernels: data Names
- Futhark.CodeGen.ImpCode.Kernels: data Overflow
- Futhark.CodeGen.ImpCode.Kernels: data Param
- Futhark.CodeGen.ImpCode.Kernels: data PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: data PrimType
- Futhark.CodeGen.ImpCode.Kernels: data PrimValue
- Futhark.CodeGen.ImpCode.Kernels: data Safety
- Futhark.CodeGen.ImpCode.Kernels: data Signedness
- Futhark.CodeGen.ImpCode.Kernels: data Space
- Futhark.CodeGen.ImpCode.Kernels: data SrcLoc
- Futhark.CodeGen.ImpCode.Kernels: data SubExp
- Futhark.CodeGen.ImpCode.Kernels: data UnOp
- Futhark.CodeGen.ImpCode.Kernels: data Uniqueness
- Futhark.CodeGen.ImpCode.Kernels: data VName
- Futhark.CodeGen.ImpCode.Kernels: data ValueDesc
- Futhark.CodeGen.ImpCode.Kernels: data Volatility
- Futhark.CodeGen.ImpCode.Kernels: data Word16
- Futhark.CodeGen.ImpCode.Kernels: data Word32
- Futhark.CodeGen.ImpCode.Kernels: data Word64
- Futhark.CodeGen.ImpCode.Kernels: data Word8
- Futhark.CodeGen.ImpCode.Kernels: declaredIn :: Code a -> Names
- Futhark.CodeGen.ImpCode.Kernels: defaultEntryPoint :: Name
- Futhark.CodeGen.ImpCode.Kernels: doAbs :: IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doAdd :: IntValue -> IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue
- Futhark.CodeGen.ImpCode.Kernels: doCmpEq :: PrimValue -> PrimValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doCmpOp :: CmpOp -> PrimValue -> PrimValue -> Maybe Bool
- Futhark.CodeGen.ImpCode.Kernels: doCmpSle :: IntValue -> IntValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doCmpSlt :: IntValue -> IntValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doCmpUle :: IntValue -> IntValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doCmpUlt :: IntValue -> IntValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doComplement :: IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doConvOp :: ConvOp -> PrimValue -> Maybe PrimValue
- Futhark.CodeGen.ImpCode.Kernels: doFAbs :: FloatValue -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: doFCmpLe :: FloatValue -> FloatValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doFCmpLt :: FloatValue -> FloatValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: doFPConv :: FloatValue -> FloatType -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: doFPToSI :: FloatValue -> IntType -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doFPToUI :: FloatValue -> IntType -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doMul :: IntValue -> IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doPow :: IntValue -> IntValue -> Maybe IntValue
- Futhark.CodeGen.ImpCode.Kernels: doSDiv :: IntValue -> IntValue -> Maybe IntValue
- Futhark.CodeGen.ImpCode.Kernels: doSExt :: IntValue -> IntType -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doSIToFP :: IntValue -> FloatType -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: doSMod :: IntValue -> IntValue -> Maybe IntValue
- Futhark.CodeGen.ImpCode.Kernels: doSSignum :: IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doUIToFP :: IntValue -> FloatType -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: doUSignum :: IntValue -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: doUnOp :: UnOp -> PrimValue -> Maybe PrimValue
- Futhark.CodeGen.ImpCode.Kernels: doZExt :: IntValue -> IntType -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: elements :: a -> Count Elements a
- Futhark.CodeGen.ImpCode.Kernels: errorMsgArgTypes :: ErrorMsg a -> [PrimType]
- Futhark.CodeGen.ImpCode.Kernels: evalPrimExp :: (Pretty v, MonadFail m) => (v -> m PrimValue) -> PrimExp v -> m PrimValue
- Futhark.CodeGen.ImpCode.Kernels: fMax64 :: TPrimExp Double v -> TPrimExp Double v -> TPrimExp Double v
- Futhark.CodeGen.ImpCode.Kernels: fMin64 :: TPrimExp Double v -> TPrimExp Double v -> TPrimExp Double v
- Futhark.CodeGen.ImpCode.Kernels: false :: TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: flipConvOp :: ConvOp -> ConvOp
- Futhark.CodeGen.ImpCode.Kernels: floatByteSize :: Num a => FloatType -> a
- Futhark.CodeGen.ImpCode.Kernels: floatValue :: Real num => FloatType -> num -> FloatValue
- Futhark.CodeGen.ImpCode.Kernels: floatValueType :: FloatValue -> FloatType
- Futhark.CodeGen.ImpCode.Kernels: freeIn :: FreeIn a => a -> Names
- Futhark.CodeGen.ImpCode.Kernels: freeIn' :: FreeIn a => a -> FV
- Futhark.CodeGen.ImpCode.Kernels: freeInStmsAndRes :: (FreeIn (Op lore), FreeIn (LetDec lore), FreeIn (LParamInfo lore), FreeIn (FParamInfo lore), FreeDec (BodyDec lore), FreeIn (RetType lore), FreeIn (BranchType lore), FreeDec (ExpDec lore)) => Stms lore -> Result -> FV
- Futhark.CodeGen.ImpCode.Kernels: fromBoolExp :: NumExp t => TPrimExp Bool v -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: fromInteger' :: NumExp t => Integer -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: fromRational' :: FloatExp t => Rational -> TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: fvBind :: Names -> FV -> FV
- Futhark.CodeGen.ImpCode.Kernels: fvName :: VName -> FV
- Futhark.CodeGen.ImpCode.Kernels: fvNames :: Names -> FV
- Futhark.CodeGen.ImpCode.Kernels: index :: VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> Exp
- Futhark.CodeGen.ImpCode.Kernels: infix 4 .>=.
- Futhark.CodeGen.ImpCode.Kernels: infixr 2 .||.
- Futhark.CodeGen.ImpCode.Kernels: infixr 3 .&&.
- Futhark.CodeGen.ImpCode.Kernels: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.Kernels.AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.Kernels.HostOp
- Futhark.CodeGen.ImpCode.Kernels: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.Kernels.Kernel
- Futhark.CodeGen.ImpCode.Kernels: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.Kernels.KernelOp
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Classes.Eq Futhark.CodeGen.ImpCode.Kernels.KernelConst
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Classes.Eq Futhark.CodeGen.ImpCode.Kernels.KernelUse
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Classes.Ord Futhark.CodeGen.ImpCode.Kernels.KernelConst
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Classes.Ord Futhark.CodeGen.ImpCode.Kernels.KernelUse
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.AtomicOp
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.Fence
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.HostOp
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.Kernel
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.KernelConst
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.KernelOp
- Futhark.CodeGen.ImpCode.Kernels: instance GHC.Show.Show Futhark.CodeGen.ImpCode.Kernels.KernelUse
- Futhark.CodeGen.ImpCode.Kernels: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.Kernels.HostOp
- Futhark.CodeGen.ImpCode.Kernels: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.Kernels.Kernel
- Futhark.CodeGen.ImpCode.Kernels: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.Kernels.KernelConst
- Futhark.CodeGen.ImpCode.Kernels: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.Kernels.KernelOp
- Futhark.CodeGen.ImpCode.Kernels: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.Kernels.KernelUse
- Futhark.CodeGen.ImpCode.Kernels: intByteSize :: Num a => IntType -> a
- Futhark.CodeGen.ImpCode.Kernels: intToInt64 :: IntValue -> Int64
- Futhark.CodeGen.ImpCode.Kernels: intToWord64 :: IntValue -> Word64
- Futhark.CodeGen.ImpCode.Kernels: intValue :: Integral int => IntType -> int -> IntValue
- Futhark.CodeGen.ImpCode.Kernels: intValueType :: IntValue -> IntType
- Futhark.CodeGen.ImpCode.Kernels: isBool :: PrimExp v -> TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: isF32 :: PrimExp v -> TPrimExp Float v
- Futhark.CodeGen.ImpCode.Kernels: isF64 :: PrimExp v -> TPrimExp Double v
- Futhark.CodeGen.ImpCode.Kernels: isInt16 :: PrimExp v -> TPrimExp Int16 v
- Futhark.CodeGen.ImpCode.Kernels: isInt32 :: PrimExp v -> TPrimExp Int32 v
- Futhark.CodeGen.ImpCode.Kernels: isInt64 :: PrimExp v -> TPrimExp Int64 v
- Futhark.CodeGen.ImpCode.Kernels: isInt8 :: PrimExp v -> TPrimExp Int8 v
- Futhark.CodeGen.ImpCode.Kernels: leafExpTypes :: Ord a => PrimExp a -> Set (a, PrimType)
- Futhark.CodeGen.ImpCode.Kernels: lexicalMemoryUsage :: Function a -> Map VName Space
- Futhark.CodeGen.ImpCode.Kernels: locOf :: Located a => a -> Loc
- Futhark.CodeGen.ImpCode.Kernels: locOfList :: Located a => [a] -> Loc
- Futhark.CodeGen.ImpCode.Kernels: locStr :: Located a => a -> String
- Futhark.CodeGen.ImpCode.Kernels: locStrRel :: (Located a, Located b) => a -> b -> String
- Futhark.CodeGen.ImpCode.Kernels: mapNames :: (VName -> VName) -> Names -> Names
- Futhark.CodeGen.ImpCode.Kernels: nameFromString :: String -> Name
- Futhark.CodeGen.ImpCode.Kernels: nameFromText :: Text -> Name
- Futhark.CodeGen.ImpCode.Kernels: nameIn :: VName -> Names -> Bool
- Futhark.CodeGen.ImpCode.Kernels: nameToString :: Name -> String
- Futhark.CodeGen.ImpCode.Kernels: nameToText :: Name -> Text
- Futhark.CodeGen.ImpCode.Kernels: namesFromList :: [VName] -> Names
- Futhark.CodeGen.ImpCode.Kernels: namesIntMap :: Names -> IntMap VName
- Futhark.CodeGen.ImpCode.Kernels: namesIntersect :: Names -> Names -> Bool
- Futhark.CodeGen.ImpCode.Kernels: namesIntersection :: Names -> Names -> Names
- Futhark.CodeGen.ImpCode.Kernels: namesSubtract :: Names -> Names -> Names
- Futhark.CodeGen.ImpCode.Kernels: namesToList :: Names -> [VName]
- Futhark.CodeGen.ImpCode.Kernels: negativeIsh :: PrimValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: newtype Count u e
- Futhark.CodeGen.ImpCode.Kernels: newtype ErrorMsg a
- Futhark.CodeGen.ImpCode.Kernels: newtype Functions a
- Futhark.CodeGen.ImpCode.Kernels: newtype KernelConst
- Futhark.CodeGen.ImpCode.Kernels: newtype TPrimExp t v
- Futhark.CodeGen.ImpCode.Kernels: oneIsh :: PrimValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: oneIshInt :: IntValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: oneName :: VName -> Names
- Futhark.CodeGen.ImpCode.Kernels: paramName :: Param -> VName
- Futhark.CodeGen.ImpCode.Kernels: pattern Skip :: () => Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern Assert :: () => Exp -> ErrorMsg Exp -> (SrcLoc, [SrcLoc]) -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern Comment :: () => String -> Code a -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern If :: () => TExp Bool -> Code a -> Code a -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern Write :: () => VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> Exp -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern Call :: () => [VName] -> Name -> [Arg] -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pattern Op :: () => a -> Code a
- Futhark.CodeGen.ImpCode.Kernels: pquote :: Doc -> Doc
- Futhark.CodeGen.ImpCode.Kernels: precomputed :: FreeDec dec => dec -> FV -> FV
- Futhark.CodeGen.ImpCode.Kernels: pretty :: Pretty a => a -> String
- Futhark.CodeGen.ImpCode.Kernels: prettySigned :: Bool -> PrimType -> String
- Futhark.CodeGen.ImpCode.Kernels: prettyStacktrace :: Int -> [String] -> String
- Futhark.CodeGen.ImpCode.Kernels: primBitSize :: PrimType -> Int
- Futhark.CodeGen.ImpCode.Kernels: primByteSize :: Num a => PrimType -> a
- Futhark.CodeGen.ImpCode.Kernels: primExpSizeAtLeast :: Int -> PrimExp v -> Bool
- Futhark.CodeGen.ImpCode.Kernels: primExpType :: PrimExp v -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: primFuns :: Map String ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue)
- Futhark.CodeGen.ImpCode.Kernels: primValueType :: PrimValue -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: quote :: String -> String
- Futhark.CodeGen.ImpCode.Kernels: sExt :: IntType -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: sExt32 :: IntExp t => TPrimExp t v -> TPrimExp Int32 v
- Futhark.CodeGen.ImpCode.Kernels: sExt64 :: IntExp t => TPrimExp t v -> TPrimExp Int64 v
- Futhark.CodeGen.ImpCode.Kernels: sMax32 :: TPrimExp Int32 v -> TPrimExp Int32 v -> TPrimExp Int32 v
- Futhark.CodeGen.ImpCode.Kernels: sMax64 :: TPrimExp Int64 v -> TPrimExp Int64 v -> TPrimExp Int64 v
- Futhark.CodeGen.ImpCode.Kernels: sMin32 :: TPrimExp Int32 v -> TPrimExp Int32 v -> TPrimExp Int32 v
- Futhark.CodeGen.ImpCode.Kernels: sMin64 :: TPrimExp Int64 v -> TPrimExp Int64 v -> TPrimExp Int64 v
- Futhark.CodeGen.ImpCode.Kernels: srclocOf :: Located a => a -> SrcLoc
- Futhark.CodeGen.ImpCode.Kernels: true :: TPrimExp Bool v
- Futhark.CodeGen.ImpCode.Kernels: type Code = Code HostOp
- Futhark.CodeGen.ImpCode.Kernels: type DimSize = SubExp
- Futhark.CodeGen.ImpCode.Kernels: type Exp = PrimExp ExpLeaf
- Futhark.CodeGen.ImpCode.Kernels: type Function = Function HostOp
- Futhark.CodeGen.ImpCode.Kernels: type KernelCode = Code KernelOp
- Futhark.CodeGen.ImpCode.Kernels: type KernelConstExp = PrimExp KernelConst
- Futhark.CodeGen.ImpCode.Kernels: type MemSize = SubExp
- Futhark.CodeGen.ImpCode.Kernels: type Program = Definitions HostOp
- Futhark.CodeGen.ImpCode.Kernels: type SpaceId = String
- Futhark.CodeGen.ImpCode.Kernels: type TExp t = TPrimExp t ExpLeaf
- Futhark.CodeGen.ImpCode.Kernels: unOpType :: UnOp -> PrimType
- Futhark.CodeGen.ImpCode.Kernels: valueIntegral :: Integral int => IntValue -> int
- Futhark.CodeGen.ImpCode.Kernels: var :: VName -> PrimType -> Exp
- Futhark.CodeGen.ImpCode.Kernels: vi32 :: VName -> TExp Int32
- Futhark.CodeGen.ImpCode.Kernels: vi64 :: VName -> TExp Int64
- Futhark.CodeGen.ImpCode.Kernels: withElemType :: Count Elements (TExp Int64) -> PrimType -> Count Bytes (TExp Int64)
- Futhark.CodeGen.ImpCode.Kernels: zExt :: IntType -> PrimExp v -> PrimExp v
- Futhark.CodeGen.ImpCode.Kernels: zExt32 :: IntExp t => TPrimExp t v -> TPrimExp Int32 v
- Futhark.CodeGen.ImpCode.Kernels: zExt64 :: IntExp t => TPrimExp t v -> TPrimExp Int64 v
- Futhark.CodeGen.ImpCode.Kernels: zeroIsh :: PrimValue -> Bool
- Futhark.CodeGen.ImpCode.Kernels: zeroIshInt :: IntValue -> Bool
- Futhark.CodeGen.ImpCode.Multicore: Commutative :: Commutativity
- Futhark.CodeGen.ImpCode.Multicore: Noncommutative :: Commutativity
- Futhark.CodeGen.ImpCode.Multicore: data Commutativity
- Futhark.CodeGen.ImpCode.OpenCL: Commutative :: Commutativity
- Futhark.CodeGen.ImpCode.OpenCL: Noncommutative :: Commutativity
- Futhark.CodeGen.ImpCode.OpenCL: data Commutativity
- Futhark.CodeGen.ImpCode.Sequential: Commutative :: Commutativity
- Futhark.CodeGen.ImpCode.Sequential: Noncommutative :: Commutativity
- Futhark.CodeGen.ImpCode.Sequential: data Commutativity
- Futhark.CodeGen.ImpGen: instance Control.Monad.Reader.Class.MonadReader (Futhark.CodeGen.ImpGen.Env lore r op) (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance Control.Monad.State.Class.MonadState (Futhark.CodeGen.ImpGen.ImpState lore r op) (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.CodeGen.ImpGen.VarEntry lore)
- Futhark.CodeGen.ImpGen: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.SOACS.SOACS (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance GHC.Base.Applicative (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance GHC.Base.Functor (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen: instance GHC.Base.Monad (Futhark.CodeGen.ImpGen.ImpM lore r op)
- Futhark.CodeGen.ImpGen.Kernels: compileProgCUDA :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, Program)
- Futhark.CodeGen.ImpGen.Kernels: compileProgOpenCL :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, Program)
- Futhark.CodeGen.ImpGen.Kernels: data Warnings
- Futhark.CodeGen.ImpGen.Kernels.Base: AtomicCAS :: DoAtomicUpdate lore r -> AtomicUpdate lore r
- Futhark.CodeGen.ImpGen.Kernels.Base: AtomicLocking :: (Locking -> DoAtomicUpdate lore r) -> AtomicUpdate lore r
- Futhark.CodeGen.ImpGen.Kernels.Base: AtomicPrim :: DoAtomicUpdate lore r -> AtomicUpdate lore r
- Futhark.CodeGen.ImpGen.Kernels.Base: CUDA :: Target
- Futhark.CodeGen.ImpGen.Kernels.Base: HostEnv :: AtomicBinOp -> Target -> Map VName Locks -> HostEnv
- Futhark.CodeGen.ImpGen.Kernels.Base: KernelConstants :: TExp Int32 -> TExp Int32 -> TExp Int32 -> VName -> VName -> VName -> TExp Int64 -> TExp Int64 -> TExp Int32 -> TExp Int32 -> TExp Bool -> Map [SubExp] [TExp Int32] -> KernelConstants
- Futhark.CodeGen.ImpGen.Kernels.Base: KernelEnv :: AtomicBinOp -> KernelConstants -> Map VName Locks -> KernelEnv
- Futhark.CodeGen.ImpGen.Kernels.Base: Locking :: VName -> TExp Int32 -> TExp Int32 -> TExp Int32 -> ([TExp Int64] -> [TExp Int64]) -> Locking
- Futhark.CodeGen.ImpGen.Kernels.Base: Locks :: VName -> Int -> Locks
- Futhark.CodeGen.ImpGen.Kernels.Base: OpenCL :: Target
- Futhark.CodeGen.ImpGen.Kernels.Base: [hostAtomics] :: HostEnv -> AtomicBinOp
- Futhark.CodeGen.ImpGen.Kernels.Base: [hostLocks] :: HostEnv -> Map VName Locks
- Futhark.CodeGen.ImpGen.Kernels.Base: [hostTarget] :: HostEnv -> Target
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelAtomics] :: KernelEnv -> AtomicBinOp
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelConstants] :: KernelEnv -> KernelConstants
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelGlobalThreadIdVar] :: KernelConstants -> VName
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelGlobalThreadId] :: KernelConstants -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelGroupIdVar] :: KernelConstants -> VName
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelGroupId] :: KernelConstants -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelGroupSize] :: KernelConstants -> TExp Int64
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelLocalIdMap] :: KernelConstants -> Map [SubExp] [TExp Int32]
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelLocalThreadIdVar] :: KernelConstants -> VName
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelLocalThreadId] :: KernelConstants -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelLocks] :: KernelEnv -> Map VName Locks
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelNumGroups] :: KernelConstants -> TExp Int64
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelNumThreads] :: KernelConstants -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelThreadActive] :: KernelConstants -> TExp Bool
- Futhark.CodeGen.ImpGen.Kernels.Base: [kernelWaveSize] :: KernelConstants -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [lockingArray] :: Locking -> VName
- Futhark.CodeGen.ImpGen.Kernels.Base: [lockingIsUnlocked] :: Locking -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [lockingMapping] :: Locking -> [TExp Int64] -> [TExp Int64]
- Futhark.CodeGen.ImpGen.Kernels.Base: [lockingToLock] :: Locking -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [lockingToUnlock] :: Locking -> TExp Int32
- Futhark.CodeGen.ImpGen.Kernels.Base: [locksArray] :: Locks -> VName
- Futhark.CodeGen.ImpGen.Kernels.Base: [locksCount] :: Locks -> Int
- Futhark.CodeGen.ImpGen.Kernels.Base: atomicUpdateLocking :: AtomicBinOp -> Lambda KernelsMem -> AtomicUpdate KernelsMem KernelEnv
- Futhark.CodeGen.ImpGen.Kernels.Base: compileGroupResult :: SegSpace -> PatElem KernelsMem -> KernelResult -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: compileThreadResult :: SegSpace -> PatElem KernelsMem -> KernelResult -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: computeThreadChunkSize :: SplitOrdering -> TExp Int64 -> Count Elements (TExp Int64) -> Count Elements (TExp Int64) -> TV Int64 -> ImpM lore r op ()
- Futhark.CodeGen.ImpGen.Kernels.Base: data AtomicUpdate lore r
- Futhark.CodeGen.ImpGen.Kernels.Base: data HostEnv
- Futhark.CodeGen.ImpGen.Kernels.Base: data KernelConstants
- Futhark.CodeGen.ImpGen.Kernels.Base: data KernelEnv
- Futhark.CodeGen.ImpGen.Kernels.Base: data Locking
- Futhark.CodeGen.ImpGen.Kernels.Base: data Locks
- Futhark.CodeGen.ImpGen.Kernels.Base: data Target
- Futhark.CodeGen.ImpGen.Kernels.Base: groupCoverSpace :: [TExp Int64] -> ([TExp Int64] -> InKernelGen ()) -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: groupLoop :: TExp Int64 -> (TExp Int64 -> InKernelGen ()) -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: groupReduce :: TExp Int32 -> Lambda KernelsMem -> [VName] -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: groupScan :: Maybe (TExp Int32 -> TExp Int32 -> TExp Bool) -> TExp Int64 -> TExp Int64 -> Lambda KernelsMem -> [VName] -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: isActive :: [(VName, SubExp)] -> TExp Bool
- Futhark.CodeGen.ImpGen.Kernels.Base: kernelLoop :: IntExp t => TExp t -> TExp t -> TExp t -> (TExp t -> InKernelGen ()) -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: keyWithEntryPoint :: Maybe Name -> Name -> Name
- Futhark.CodeGen.ImpGen.Kernels.Base: precomputeSegOpIDs :: Stms KernelsMem -> InKernelGen a -> InKernelGen a
- Futhark.CodeGen.ImpGen.Kernels.Base: sCopy :: CopyCompiler KernelsMem HostEnv HostOp
- Futhark.CodeGen.ImpGen.Kernels.Base: sIota :: VName -> TExp Int64 -> Exp -> Exp -> IntType -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: sKernelGroup :: String -> Count NumGroups (TExp Int64) -> Count GroupSize (TExp Int64) -> VName -> InKernelGen () -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: sKernelThread :: String -> Count NumGroups (TExp Int64) -> Count GroupSize (TExp Int64) -> VName -> InKernelGen () -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: sReplicate :: VName -> SubExp -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.Base: type AtomicBinOp = BinOp -> Maybe (VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp)
- Futhark.CodeGen.ImpGen.Kernels.Base: type CallKernelGen = ImpM KernelsMem HostEnv HostOp
- Futhark.CodeGen.ImpGen.Kernels.Base: type DoAtomicUpdate lore r = Space -> [VName] -> [TExp Int64] -> ImpM lore r KernelOp ()
- Futhark.CodeGen.ImpGen.Kernels.Base: type InKernelGen = ImpM KernelsMem KernelEnv KernelOp
- Futhark.CodeGen.ImpGen.Kernels.Base: virtualiseGroups :: SegVirt -> TExp Int32 -> (TExp Int32 -> InKernelGen ()) -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegHist: compileSegHist :: Pattern KernelsMem -> Count NumGroups SubExp -> Count GroupSize SubExp -> SegSpace -> [HistOp KernelsMem] -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegHist: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.Kernels.SegHist.Passage
- Futhark.CodeGen.ImpGen.Kernels.SegHist: instance GHC.Classes.Ord Futhark.CodeGen.ImpGen.Kernels.SegHist.Passage
- Futhark.CodeGen.ImpGen.Kernels.SegMap: compileSegMap :: Pattern KernelsMem -> SegLevel -> SegSpace -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegRed: compileSegRed :: Pattern KernelsMem -> SegLevel -> SegSpace -> [SegBinOp KernelsMem] -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegRed: compileSegRed' :: Pattern KernelsMem -> SegLevel -> SegSpace -> [SegBinOp KernelsMem] -> DoSegBody -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegRed: type DoSegBody = ([(SubExp, [TExp Int64])] -> InKernelGen ()) -> InKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegScan: compileSegScan :: Pattern KernelsMem -> SegLevel -> SegSpace -> [SegBinOp KernelsMem] -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegScan.SinglePass: compileSegScan :: Pattern KernelsMem -> SegLevel -> SegSpace -> SegBinOp KernelsMem -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.SegScan.TwoPass: compileSegScan :: Pattern KernelsMem -> SegLevel -> SegSpace -> [SegBinOp KernelsMem] -> KernelBody KernelsMem -> CallKernelGen ()
- Futhark.CodeGen.ImpGen.Kernels.ToOpenCL: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.Kernels.ToOpenCL.OpsMode
- Futhark.CodeGen.ImpGen.Kernels.ToOpenCL: kernelsToCUDA :: Program -> Program
- Futhark.CodeGen.ImpGen.Kernels.ToOpenCL: kernelsToOpenCL :: Program -> Program
- Futhark.CodeGen.ImpGen.Kernels.Transpose: TransposeLowHeight :: TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: TransposeLowWidth :: TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: TransposeNormal :: TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: TransposeSmall :: TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: data TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.Kernels.Transpose.TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: instance GHC.Classes.Ord Futhark.CodeGen.ImpGen.Kernels.Transpose.TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: instance GHC.Show.Show Futhark.CodeGen.ImpGen.Kernels.Transpose.TransposeType
- Futhark.CodeGen.ImpGen.Kernels.Transpose: mapTransposeKernel :: String -> Integer -> TransposeArgs -> PrimType -> TransposeType -> Kernel
- Futhark.CodeGen.ImpGen.Kernels.Transpose: type TransposeArgs = (VName, TExp Int32, VName, TExp Int32, TExp Int32, TExp Int32, TExp Int32, TExp Int32, TExp Int32, VName)
- Futhark.IR.Aliases: instance (Futhark.Binder.Class.Bindable lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.Binder.Class.Bindable (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Aliases: instance (Futhark.IR.Decorations.Decorations lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Decorations.Decorations (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTLore (Futhark.IR.Aliases.Aliases lore), Futhark.Binder.Class.Bindable (Futhark.IR.Aliases.Aliases lore)) => Futhark.Binder.BinderOps (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Pretty.PrettyLore (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.ASTLore (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Aliases.Aliased (Futhark.IR.Aliases.Aliases lore)
- Futhark.IR.Decorations: -- | Extensible operation.
- Futhark.IR.Decorations: class (Show (LetDec l), Show (ExpDec l), Show (BodyDec l), Show (FParamInfo l), Show (LParamInfo l), Show (RetType l), Show (BranchType l), Show (Op l), Eq (LetDec l), Eq (ExpDec l), Eq (BodyDec l), Eq (FParamInfo l), Eq (LParamInfo l), Eq (RetType l), Eq (BranchType l), Eq (Op l), Ord (LetDec l), Ord (ExpDec l), Ord (BodyDec l), Ord (FParamInfo l), Ord (LParamInfo l), Ord (RetType l), Ord (BranchType l), Ord (Op l), IsRetType (RetType l), IsBodyType (BranchType l), Typed (FParamInfo l), Typed (LParamInfo l), Typed (LetDec l), DeclTyped (FParamInfo l)) => Decorations l where {
- Futhark.IR.Decorations: type BodyDec l = ();
- Futhark.IR.Decorations: type BranchType l = ExtType;
- Futhark.IR.Decorations: type ExpDec l = ();
- Futhark.IR.Decorations: type FParamInfo l = DeclType;
- Futhark.IR.Decorations: type LParamInfo l = Type;
- Futhark.IR.Decorations: type LetDec l = Type;
- Futhark.IR.Decorations: type Op l = ();
- Futhark.IR.Decorations: type RetType l = DeclExtType;
- Futhark.IR.Decorations: type family Op l :: Type;
- Futhark.IR.Decorations: }
- Futhark.IR.Kernels: Disorder :: StreamOrd
- Futhark.IR.Kernels: Hist :: SubExp -> [HistOp lore] -> Lambda lore -> [VName] -> SOAC lore
- Futhark.IR.Kernels: InOrder :: StreamOrd
- Futhark.IR.Kernels: Parallel :: StreamOrd -> Commutativity -> Lambda lore -> StreamForm lore
- Futhark.IR.Kernels: Reduce :: Commutativity -> Lambda lore -> [SubExp] -> Reduce lore
- Futhark.IR.Kernels: SOACMapper :: (SubExp -> m SubExp) -> (Lambda flore -> m (Lambda tlore)) -> (VName -> m VName) -> SOACMapper flore tlore m
- Futhark.IR.Kernels: Scan :: Lambda lore -> [SubExp] -> Scan lore
- Futhark.IR.Kernels: Scatter :: SubExp -> Lambda lore -> [VName] -> [(Shape, Int, VName)] -> SOAC lore
- Futhark.IR.Kernels: Screma :: SubExp -> [VName] -> ScremaForm lore -> SOAC lore
- Futhark.IR.Kernels: ScremaForm :: [Scan lore] -> [Reduce lore] -> Lambda lore -> ScremaForm lore
- Futhark.IR.Kernels: Sequential :: StreamForm lore
- Futhark.IR.Kernels: Stream :: SubExp -> [VName] -> StreamForm lore -> [SubExp] -> Lambda lore -> SOAC lore
- Futhark.IR.Kernels: [mapOnSOACLambda] :: SOACMapper flore tlore m -> Lambda flore -> m (Lambda tlore)
- Futhark.IR.Kernels: [mapOnSOACSubExp] :: SOACMapper flore tlore m -> SubExp -> m SubExp
- Futhark.IR.Kernels: [mapOnSOACVName] :: SOACMapper flore tlore m -> VName -> m VName
- Futhark.IR.Kernels: [redComm] :: Reduce lore -> Commutativity
- Futhark.IR.Kernels: [redLambda] :: Reduce lore -> Lambda lore
- Futhark.IR.Kernels: [redNeutral] :: Reduce lore -> [SubExp]
- Futhark.IR.Kernels: [scanLambda] :: Scan lore -> Lambda lore
- Futhark.IR.Kernels: [scanNeutral] :: Scan lore -> [SubExp]
- Futhark.IR.Kernels: data Kernels
- Futhark.IR.Kernels: data Reduce lore
- Futhark.IR.Kernels: data SOAC lore
- Futhark.IR.Kernels: data SOACMapper flore tlore m
- Futhark.IR.Kernels: data Scan lore
- Futhark.IR.Kernels: data ScremaForm lore
- Futhark.IR.Kernels: data StreamForm lore
- Futhark.IR.Kernels: data StreamOrd
- Futhark.IR.Kernels: groupScatterResults :: [(Shape, Int, array)] -> [a] -> [(Shape, array, [([a], a)])]
- Futhark.IR.Kernels: groupScatterResults' :: [(Shape, Int, array)] -> [a] -> [([a], a)]
- Futhark.IR.Kernels: identitySOACMapper :: Monad m => SOACMapper lore lore m
- Futhark.IR.Kernels: instance Futhark.Binder.BinderOps Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.Binder.Class.Bindable Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.IR.Decorations.Decorations Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.IR.Prop.ASTLore Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.IR.SegOp.HasSegOp Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.TypeCheck.Checkable Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: instance Futhark.TypeCheck.CheckableOp Futhark.IR.Kernels.Kernels
- Futhark.IR.Kernels: isIdentityLambda :: Lambda lore -> Bool
- Futhark.IR.Kernels: isMapSOAC :: ScremaForm lore -> Maybe (Lambda lore)
- Futhark.IR.Kernels: isRedomapSOAC :: ScremaForm lore -> Maybe ([Reduce lore], Lambda lore)
- Futhark.IR.Kernels: isReduceSOAC :: ScremaForm lore -> Maybe [Reduce lore]
- Futhark.IR.Kernels: isScanSOAC :: ScremaForm lore -> Maybe [Scan lore]
- Futhark.IR.Kernels: isScanomapSOAC :: ScremaForm lore -> Maybe ([Scan lore], Lambda lore)
- Futhark.IR.Kernels: mapSOAC :: Lambda lore -> ScremaForm lore
- Futhark.IR.Kernels: mapSOACM :: (Applicative m, Monad m) => SOACMapper flore tlore m -> SOAC flore -> m (SOAC tlore)
- Futhark.IR.Kernels: mkIdentityLambda :: (Bindable lore, MonadFreshNames m) => [Type] -> m (Lambda lore)
- Futhark.IR.Kernels: nilFn :: Bindable lore => Lambda lore
- Futhark.IR.Kernels: ppHist :: (PrettyLore lore, Pretty inp) => SubExp -> [HistOp lore] -> Lambda lore -> [inp] -> Doc
- Futhark.IR.Kernels: ppScrema :: (PrettyLore lore, Pretty inp) => SubExp -> [inp] -> ScremaForm lore -> Doc
- Futhark.IR.Kernels: redResults :: [Reduce lore] -> Int
- Futhark.IR.Kernels: redomapSOAC :: [Reduce lore] -> Lambda lore -> ScremaForm lore
- Futhark.IR.Kernels: reduceSOAC :: (Bindable lore, MonadFreshNames m) => [Reduce lore] -> m (ScremaForm lore)
- Futhark.IR.Kernels: scanResults :: [Scan lore] -> Int
- Futhark.IR.Kernels: scanSOAC :: (Bindable lore, MonadFreshNames m) => [Scan lore] -> m (ScremaForm lore)
- Futhark.IR.Kernels: scanomapSOAC :: [Scan lore] -> Lambda lore -> ScremaForm lore
- Futhark.IR.Kernels: scremaType :: SubExp -> ScremaForm lore -> [Type]
- Futhark.IR.Kernels: singleReduce :: Bindable lore => [Reduce lore] -> Reduce lore
- Futhark.IR.Kernels: singleScan :: Bindable lore => [Scan lore] -> Scan lore
- Futhark.IR.Kernels: soacType :: SOAC lore -> [Type]
- Futhark.IR.Kernels: splitScatterResults :: [(Shape, Int, array)] -> [a] -> ([a], [a])
- Futhark.IR.Kernels: typeCheckSOAC :: Checkable lore => SOAC (Aliases lore) -> TypeM lore ()
- Futhark.IR.Kernels.Kernel: CalcNumGroups :: SubExp -> Name -> SubExp -> SizeOp
- Futhark.IR.Kernels.Kernel: CmpSizeLe :: Name -> SizeClass -> SubExp -> SizeOp
- Futhark.IR.Kernels.Kernel: GetSize :: Name -> SizeClass -> SizeOp
- Futhark.IR.Kernels.Kernel: GetSizeMax :: SizeClass -> SizeOp
- Futhark.IR.Kernels.Kernel: OtherOp :: op -> HostOp lore op
- Futhark.IR.Kernels.Kernel: SegGroup :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
- Futhark.IR.Kernels.Kernel: SegOp :: SegOp SegLevel lore -> HostOp lore op
- Futhark.IR.Kernels.Kernel: SegThread :: Count NumGroups SubExp -> Count GroupSize SubExp -> SegVirt -> SegLevel
- Futhark.IR.Kernels.Kernel: SizeOp :: SizeOp -> HostOp lore op
- Futhark.IR.Kernels.Kernel: SplitSpace :: SplitOrdering -> SubExp -> SubExp -> SubExp -> SizeOp
- Futhark.IR.Kernels.Kernel: [segGroupSize] :: SegLevel -> Count GroupSize SubExp
- Futhark.IR.Kernels.Kernel: [segNumGroups] :: SegLevel -> Count NumGroups SubExp
- Futhark.IR.Kernels.Kernel: [segVirt] :: SegLevel -> SegVirt
- Futhark.IR.Kernels.Kernel: data HostOp lore op
- Futhark.IR.Kernels.Kernel: data SegLevel
- Futhark.IR.Kernels.Kernel: data SizeOp
- Futhark.IR.Kernels.Kernel: instance (Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Decorations.Op lore), Futhark.Analysis.Metrics.OpMetrics op) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Eq op) => GHC.Classes.Eq (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Ord op) => GHC.Classes.Ord (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Decorations.Decorations lore, GHC.Show.Show op) => GHC.Show.Show (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Pretty.PrettyLore lore, Text.PrettyPrint.Mainland.Class.Pretty op) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Analysis.SymbolTable.IndexOp op) => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.IsOp op) => Futhark.IR.Prop.IsOp (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Names.FreeIn op) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Transform.Rename.Rename op) => Futhark.Transform.Rename.Rename (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Transform.Substitute.Substitute op) => Futhark.Transform.Substitute.Substitute (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.Aliases.Aliased lore, Futhark.IR.Prop.Aliases.AliasedOp op, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore), Futhark.IR.Prop.Aliases.CanBeAliased op, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance (Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore), Futhark.Optimise.Simplify.Lore.CanBeWise op, Futhark.IR.Prop.ASTLore lore) => Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance Futhark.Analysis.Metrics.OpMetrics Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.Aliases.AliasedOp Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.IsOp Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.Names.FreeIn Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.TypeOf.TypedOp Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.IR.Prop.TypeOf.TypedOp op => Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.IR.Kernels.Kernel: instance Futhark.Optimise.Simplify.Engine.Simplifiable Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance Futhark.Transform.Rename.Rename Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance Futhark.Transform.Rename.Rename Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Futhark.Transform.Substitute.Substitute Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance Futhark.Transform.Substitute.Substitute Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance GHC.Classes.Eq Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance GHC.Classes.Eq Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance GHC.Classes.Ord Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance GHC.Classes.Ord Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance GHC.Show.Show Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance GHC.Show.Show Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Kernels.Kernel.SegLevel
- Futhark.IR.Kernels.Kernel: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Kernels.Kernel.SizeOp
- Futhark.IR.Kernels.Kernel: typeCheckHostOp :: Checkable lore => (SegLevel -> OpWithAliases (Op lore) -> TypeM lore ()) -> Maybe SegLevel -> (op -> TypeM lore ()) -> HostOp (Aliases lore) op -> TypeM lore ()
- Futhark.IR.Kernels.Simplify: data Kernels
- Futhark.IR.Kernels.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.Kernels.Kernels)
- Futhark.IR.Kernels.Simplify: instance Futhark.IR.SOACS.Simplify.HasSOAC (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.Kernels.Kernels)
- Futhark.IR.Kernels.Simplify: instance Futhark.IR.SegOp.HasSegOp (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.Kernels.Kernels)
- Futhark.IR.Kernels.Simplify: simplifyKernelOp :: (SimplifiableLore lore, BodyDec lore ~ ()) => SimplifyOp lore op -> HostOp lore op -> SimpleM lore (HostOp (Wise lore) (OpWithWisdom op), Stms (Wise lore))
- Futhark.IR.Kernels.Simplify: simplifyKernels :: Prog Kernels -> PassM (Prog Kernels)
- Futhark.IR.Kernels.Simplify: simplifyLambda :: (HasScope Kernels m, MonadFreshNames m) => Lambda Kernels -> m (Lambda Kernels)
- Futhark.IR.Kernels.Sizes: Count :: e -> Count u e
- Futhark.IR.Kernels.Sizes: SizeBespoke :: Name -> Int64 -> SizeClass
- Futhark.IR.Kernels.Sizes: SizeGroup :: SizeClass
- Futhark.IR.Kernels.Sizes: SizeLocalMemory :: SizeClass
- Futhark.IR.Kernels.Sizes: SizeNumGroups :: SizeClass
- Futhark.IR.Kernels.Sizes: SizeRegTile :: SizeClass
- Futhark.IR.Kernels.Sizes: SizeThreshold :: KernelPath -> Maybe Int64 -> SizeClass
- Futhark.IR.Kernels.Sizes: SizeTile :: SizeClass
- Futhark.IR.Kernels.Sizes: [unCount] :: Count u e -> e
- Futhark.IR.Kernels.Sizes: data GroupSize
- Futhark.IR.Kernels.Sizes: data NumGroups
- Futhark.IR.Kernels.Sizes: data NumThreads
- Futhark.IR.Kernels.Sizes: data SizeClass
- Futhark.IR.Kernels.Sizes: instance Data.Foldable.Foldable (Futhark.IR.Kernels.Sizes.Count u)
- Futhark.IR.Kernels.Sizes: instance Data.Traversable.Traversable (Futhark.IR.Kernels.Sizes.Count u)
- Futhark.IR.Kernels.Sizes: instance Futhark.IR.Prop.Names.FreeIn e => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance Futhark.Transform.Substitute.Substitute e => Futhark.Transform.Substitute.Substitute (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance Futhark.Util.IntegralExp.IntegralExp e => Futhark.Util.IntegralExp.IntegralExp (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance GHC.Base.Functor (Futhark.IR.Kernels.Sizes.Count u)
- Futhark.IR.Kernels.Sizes: instance GHC.Classes.Eq Futhark.IR.Kernels.Sizes.SizeClass
- Futhark.IR.Kernels.Sizes: instance GHC.Classes.Eq e => GHC.Classes.Eq (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance GHC.Classes.Ord Futhark.IR.Kernels.Sizes.SizeClass
- Futhark.IR.Kernels.Sizes: instance GHC.Classes.Ord e => GHC.Classes.Ord (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance GHC.Num.Num e => GHC.Num.Num (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance GHC.Show.Show Futhark.IR.Kernels.Sizes.SizeClass
- Futhark.IR.Kernels.Sizes: instance GHC.Show.Show e => GHC.Show.Show (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Kernels.Sizes.SizeClass
- Futhark.IR.Kernels.Sizes: instance Text.PrettyPrint.Mainland.Class.Pretty e => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Kernels.Sizes.Count u e)
- Futhark.IR.Kernels.Sizes: newtype Count u e
- Futhark.IR.Kernels.Sizes: sizeDefault :: SizeClass -> Maybe Int64
- Futhark.IR.Kernels.Sizes: type KernelPath = [(Name, Bool)]
- Futhark.IR.KernelsMem: data KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.KernelsMem.KernelsMem)
- Futhark.IR.KernelsMem: instance Futhark.Binder.BinderOps Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.IR.Decorations.Decorations Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.IR.Mem.OpReturns Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.IR.Prop.ASTLore Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.TypeCheck.Checkable Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: instance Futhark.TypeCheck.CheckableOp Futhark.IR.KernelsMem.KernelsMem
- Futhark.IR.KernelsMem: simpleKernelsMem :: SimpleOps KernelsMem
- Futhark.IR.KernelsMem: simplifyProg :: Prog KernelsMem -> PassM (Prog KernelsMem)
- Futhark.IR.KernelsMem: simplifyStms :: (HasScope KernelsMem m, MonadFreshNames m) => Stms KernelsMem -> m (SymbolTable (Wise KernelsMem), Stms KernelsMem)
- Futhark.IR.MC: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.MC.MC)
- Futhark.IR.MC: instance Futhark.IR.Decorations.Decorations Futhark.IR.MC.MC
- Futhark.IR.MC: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.MC.MC
- Futhark.IR.MC: instance Futhark.IR.Prop.ASTLore Futhark.IR.MC.MC
- Futhark.IR.MC: instance Futhark.IR.SegOp.HasSegOp (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.MC.MC)
- Futhark.IR.MC.Op: instance (Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Decorations.Op lore), Futhark.Analysis.Metrics.OpMetrics op) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Eq op) => GHC.Classes.Eq (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Ord op) => GHC.Classes.Ord (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Decorations.Decorations lore, GHC.Show.Show op) => GHC.Show.Show (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Pretty.PrettyLore lore, Text.PrettyPrint.Mainland.Class.Pretty op) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Analysis.SymbolTable.IndexOp op) => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.IsOp op) => Futhark.IR.Prop.IsOp (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Names.FreeIn op) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Transform.Rename.Rename op) => Futhark.Transform.Rename.Rename (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Transform.Substitute.Substitute op) => Futhark.Transform.Substitute.Substitute (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.Aliases.Aliased lore, Futhark.IR.Prop.Aliases.AliasedOp op, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore), Futhark.IR.Prop.Aliases.CanBeAliased op, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance (Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore), Futhark.Optimise.Simplify.Lore.CanBeWise op, Futhark.IR.Prop.ASTLore lore) => Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MC.Op: instance Futhark.IR.Prop.TypeOf.TypedOp op => Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.IR.MCMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.MCMem.MCMem)
- Futhark.IR.MCMem: instance Futhark.IR.Decorations.Decorations Futhark.IR.MCMem.MCMem
- Futhark.IR.MCMem: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.MCMem.MCMem
- Futhark.IR.MCMem: instance Futhark.IR.Prop.ASTLore Futhark.IR.MCMem.MCMem
- Futhark.IR.Mem: instance Futhark.Optimise.Simplify.Lore.CanBeWise inner => Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Mem.MemOp inner)
- Futhark.IR.Parse: parseKernels :: FilePath -> Text -> Either Text (Prog Kernels)
- Futhark.IR.Parse: parseKernelsMem :: FilePath -> Text -> Either Text (Prog KernelsMem)
- Futhark.IR.Pretty: class (Decorations lore, Pretty (RetType lore), Pretty (BranchType lore), Pretty (FParamInfo lore), Pretty (LParamInfo lore), Pretty (LetDec lore), Pretty (Op lore)) => PrettyLore lore
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Body lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Exp lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Lambda lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Prog lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Stm lore)
- Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Stms lore)
- Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Language.Futhark.Core.Commutativity
- Futhark.IR.Pretty: ppExpLore :: PrettyLore lore => ExpDec lore -> Exp lore -> Maybe Doc
- Futhark.IR.Prop: class (Decorations lore, PrettyLore lore, Renameable lore, Substitutable lore, FreeDec (ExpDec lore), FreeIn (LetDec lore), FreeDec (BodyDec lore), FreeIn (FParamInfo lore), FreeIn (LParamInfo lore), FreeIn (RetType lore), FreeIn (BranchType lore), IsOp (Op lore)) => ASTLore lore
- Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.ExpDec lore), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.BodyDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.FParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LetDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.RetType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.BranchType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Body lore)
- Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.ExpDec lore), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.BodyDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.FParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LetDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.RetType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.BranchType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Exp lore)
- Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.ExpDec lore), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.BodyDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.FParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LetDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.RetType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.BranchType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.ExpDec lore), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.BodyDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.FParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LetDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.RetType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.BranchType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Lambda lore)
- Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.ExpDec lore), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Decorations.BodyDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.FParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LetDec lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.RetType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.BranchType lore), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stm lore)
- Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.LoopForm lore)
- Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stm lore) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stms lore)
- Futhark.IR.Prop.Patterns: setPatElemLore :: PatElemT oldattr -> newattr -> PatElemT newattr
- Futhark.IR.Prop.Scope: instance (Futhark.IR.Prop.Scope.HasScope lore m, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.HasScope lore (Futhark.IR.Prop.Scope.ExtendedScope lore m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.HasScope lore (Control.Monad.Trans.Reader.ReaderT (Futhark.IR.Prop.Scope.Scope lore) m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.LocalScope lore (Control.Monad.Trans.Reader.ReaderT (Futhark.IR.Prop.Scope.Scope lore) m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.HasScope lore (Control.Monad.Trans.RWS.Lazy.RWST (Futhark.IR.Prop.Scope.Scope lore) w s m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.HasScope lore (Control.Monad.Trans.RWS.Strict.RWST (Futhark.IR.Prop.Scope.Scope lore) w s m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.LocalScope lore (Control.Monad.Trans.RWS.Lazy.RWST (Futhark.IR.Prop.Scope.Scope lore) w s m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Decorations.Decorations lore) => Futhark.IR.Prop.Scope.LocalScope lore (Control.Monad.Trans.RWS.Strict.RWST (Futhark.IR.Prop.Scope.Scope lore) w s m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Monad m, Futhark.IR.Prop.Scope.HasScope lore m) => Futhark.IR.Prop.Scope.HasScope lore (Control.Monad.Trans.Except.ExceptT e m)
- Futhark.IR.Prop.Scope: instance (GHC.Base.Monad m, Futhark.IR.Prop.Scope.LocalScope lore m) => Futhark.IR.Prop.Scope.LocalScope lore (Control.Monad.Trans.Except.ExceptT e m)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Decorations.Decorations lore => Futhark.IR.Prop.Types.Typed (Futhark.IR.Prop.Scope.NameInfo lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Prop.Scope.NameInfo lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Futhark.IR.Syntax.Lambda lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Futhark.IR.Syntax.LoopForm lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Futhark.IR.Syntax.Stm lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Futhark.IR.Syntax.Stms lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore (Language.Futhark.Core.VName, Futhark.IR.Prop.Scope.NameInfo lore)
- Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped lore a => Futhark.IR.Prop.Scope.Scoped lore [a]
- Futhark.IR.Prop.Scope: instance GHC.Base.Applicative m => GHC.Base.Applicative (Futhark.IR.Prop.Scope.ExtendedScope lore m)
- Futhark.IR.Prop.Scope: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.IR.Prop.Scope.ExtendedScope lore m)
- Futhark.IR.Prop.Scope: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Futhark.IR.Prop.Scope.Scope lore) (Futhark.IR.Prop.Scope.ExtendedScope lore m)
- Futhark.IR.Prop.Scope: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.IR.Prop.Scope.ExtendedScope lore m)
- Futhark.IR.Prop.TypeOf: instance Futhark.IR.Decorations.Decorations lore => Futhark.IR.Prop.Scope.HasScope lore (Futhark.IR.Prop.TypeOf.FeelBad lore)
- Futhark.IR.Prop.TypeOf: instance GHC.Base.Applicative (Futhark.IR.Prop.TypeOf.FeelBad lore)
- Futhark.IR.Prop.TypeOf: instance GHC.Base.Functor (Futhark.IR.Prop.TypeOf.FeelBad lore)
- Futhark.IR.SOACS: class (Show (LetDec l), Show (ExpDec l), Show (BodyDec l), Show (FParamInfo l), Show (LParamInfo l), Show (RetType l), Show (BranchType l), Show (Op l), Eq (LetDec l), Eq (ExpDec l), Eq (BodyDec l), Eq (FParamInfo l), Eq (LParamInfo l), Eq (RetType l), Eq (BranchType l), Eq (Op l), Ord (LetDec l), Ord (ExpDec l), Ord (BodyDec l), Ord (FParamInfo l), Ord (LParamInfo l), Ord (RetType l), Ord (BranchType l), Ord (Op l), IsRetType (RetType l), IsBodyType (BranchType l), Typed (FParamInfo l), Typed (LParamInfo l), Typed (LetDec l), DeclTyped (FParamInfo l)) => Decorations l where {
- Futhark.IR.SOACS: instance Futhark.IR.Decorations.Decorations Futhark.IR.SOACS.SOACS
- Futhark.IR.SOACS: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.SOACS.SOACS
- Futhark.IR.SOACS: instance Futhark.IR.Prop.ASTLore Futhark.IR.SOACS.SOACS
- Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.ASTLore (Futhark.IR.Aliases.Aliases lore), Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.Aliased lore) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Decorations.Op lore) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.HistOp lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.Reduce lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.Scan lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.ScremaForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.StreamForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.HistOp lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.Reduce lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.Scan lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.ScremaForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.StreamForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.HistOp lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.Reduce lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.Scan lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.ScremaForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SOACS.SOAC.StreamForm lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.Reduce lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.Scan lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.IsOp (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTLore lore => Futhark.Transform.Rename.Rename (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTLore lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.SOACS.SOAC.SOAC lore)
- Futhark.IR.SOACS.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.SOACS.SOACS)
- Futhark.IR.SOACS.Simplify: instance Futhark.IR.SOACS.Simplify.HasSOAC (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.SOACS.SOACS)
- Futhark.IR.SegOp: [kernelBodyLore] :: KernelBody lore -> BodyDec lore
- Futhark.IR.SegOp: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Eq lvl) => GHC.Classes.Eq (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Decorations.Decorations lore, GHC.Classes.Ord lvl) => GHC.Classes.Ord (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Decorations.Decorations lore, GHC.Show.Show lvl) => GHC.Show.Show (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Pretty.PrettyLore lore, Text.PrettyPrint.Mainland.Class.Pretty lvl) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.IsOp (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.Transform.Rename.Rename (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.ASTLore (Futhark.IR.Aliases.Aliases lore), Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore), Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.Aliased lore, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Decorations.LParamInfo lore), Futhark.IR.Prop.Names.FreeIn lvl) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Transform.Substitute.Substitute lvl) => Futhark.Transform.Substitute.Substitute (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance (Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore), Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Decorations.Op lore) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SegOp.HistOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.SegOp.SegBinOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SegOp.HistOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.SegOp.SegBinOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SegOp.HistOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.SegOp.SegBinOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Pretty.PrettyLore lore => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.SegBinOp lore)
- Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTLore lore => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTLore lore => Futhark.Transform.Rename.Rename (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTLore lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.SegOp.KernelBody lore)
- Futhark.IR.SegOp: instance Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.IR.Seq: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.Seq.Seq)
- Futhark.IR.Seq: instance Futhark.IR.Decorations.Decorations Futhark.IR.Seq.Seq
- Futhark.IR.Seq: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.Seq.Seq
- Futhark.IR.Seq: instance Futhark.IR.Prop.ASTLore Futhark.IR.Seq.Seq
- Futhark.IR.SeqMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Lore.Wise Futhark.IR.SeqMem.SeqMem)
- Futhark.IR.SeqMem: instance Futhark.IR.Decorations.Decorations Futhark.IR.SeqMem.SeqMem
- Futhark.IR.SeqMem: instance Futhark.IR.Pretty.PrettyLore Futhark.IR.SeqMem.SeqMem
- Futhark.IR.SeqMem: instance Futhark.IR.Prop.ASTLore Futhark.IR.SeqMem.SeqMem
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.BodyT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.ExpT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.LambdaT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.LoopForm lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.Prog lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Eq (Futhark.IR.Syntax.Stm lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.BodyT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.ExpT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.LambdaT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.LoopForm lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.Prog lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Classes.Ord (Futhark.IR.Syntax.Stm lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.BodyT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.ExpT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.FunDef lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.LambdaT lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.LoopForm lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.Prog lore)
- Futhark.IR.Syntax: instance Futhark.IR.Decorations.Decorations lore => GHC.Show.Show (Futhark.IR.Syntax.Stm lore)
- Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.Aliased lore, Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Decorations.Op lore)) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.Aliased lore, Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Decorations.Op lore), Futhark.Optimise.CSE.CSEInOp op) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.Aliased lore, Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Decorations.Op lore), Futhark.Optimise.CSE.CSEInOp op) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTLore lore, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Decorations.Op lore), Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Prop.Aliases.OpWithAliases (Futhark.IR.Decorations.Op lore))) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.SOACS.SOAC.SOAC (Futhark.IR.Aliases.Aliases lore))
- Futhark.Optimise.DoubleBuffer: doubleBufferKernels :: Pass KernelsMem KernelsMem
- Futhark.Optimise.DoubleBuffer: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.DoubleBuffer.Env lore) (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Scope.HasScope lore (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Scope.LocalScope lore (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance GHC.Base.Applicative (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance GHC.Base.Functor (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.DoubleBuffer: instance GHC.Base.Monad (Futhark.Optimise.DoubleBuffer.DoubleBufferM lore)
- Futhark.Optimise.InPlaceLowering: inPlaceLoweringKernels :: Pass Kernels Kernels
- Futhark.Optimise.InPlaceLowering: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.InPlaceLowering.TopDown lore) (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance Control.Monad.State.Class.MonadState Futhark.FreshNames.VNameSource (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance Control.Monad.Writer.Class.MonadWriter (Futhark.Optimise.InPlaceLowering.BottomUp lore) (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance Futhark.Optimise.InPlaceLowering.Constraints lore => Futhark.IR.Prop.Scope.HasScope (Futhark.IR.Aliases.Aliases lore) (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance GHC.Base.Applicative (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance GHC.Base.Functor (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance GHC.Base.Monad (Futhark.Optimise.InPlaceLowering.ForwardingM lore)
- Futhark.Optimise.InPlaceLowering: instance GHC.Base.Monoid (Futhark.Optimise.InPlaceLowering.BottomUp lore)
- Futhark.Optimise.InPlaceLowering: instance GHC.Base.Semigroup (Futhark.Optimise.InPlaceLowering.BottomUp lore)
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdateKernels :: MonadFreshNames m => LowerUpdate Kernels m
- Futhark.Optimise.Simplify: type SimplifiableLore lore = (ASTLore lore, Simplifiable (LetDec lore), Simplifiable (FParamInfo lore), Simplifiable (LParamInfo lore), Simplifiable (RetType lore), Simplifiable (BranchType lore), CanBeWise (Op lore), IndexOp (OpWithWisdom (Op lore)), BinderOps (Wise lore), IsOp (Op lore))
- Futhark.Optimise.Simplify.Engine: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.Simplify.Engine.SimpleOps lore, Futhark.Optimise.Simplify.Engine.Env lore) (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- 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 lore)
- Futhark.Optimise.Simplify.Engine: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.SimplifiableLore lore => Futhark.IR.Prop.Scope.HasScope (Futhark.Optimise.Simplify.Lore.Wise lore) (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.SimplifiableLore lore => Futhark.IR.Prop.Scope.LocalScope (Futhark.Optimise.Simplify.Lore.Wise lore) (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: instance GHC.Base.Applicative (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: instance GHC.Base.Functor (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: instance GHC.Base.Monad (Futhark.Optimise.Simplify.Engine.SimpleM lore)
- Futhark.Optimise.Simplify.Engine: type SimplifiableLore lore = (ASTLore lore, Simplifiable (LetDec lore), Simplifiable (FParamInfo lore), Simplifiable (LParamInfo lore), Simplifiable (RetType lore), Simplifiable (BranchType lore), CanBeWise (Op lore), IndexOp (OpWithWisdom (Op lore)), BinderOps (Wise lore), IsOp (Op lore))
- Futhark.Optimise.Simplify.Lore: VarWisdom :: VarAliases -> VarWisdom
- Futhark.Optimise.Simplify.Lore: [varWisdomAliases] :: VarWisdom -> VarAliases
- Futhark.Optimise.Simplify.Lore: addScopeWisdom :: Scope lore -> Scope (Wise lore)
- Futhark.Optimise.Simplify.Lore: addWisdomToPattern :: (ASTLore lore, CanBeWise (Op lore)) => Pattern lore -> Exp (Wise lore) -> Pattern (Wise lore)
- Futhark.Optimise.Simplify.Lore: class (AliasedOp (OpWithWisdom op), IsOp (OpWithWisdom op)) => CanBeWise op where {
- Futhark.Optimise.Simplify.Lore: data ExpWisdom
- Futhark.Optimise.Simplify.Lore: data Wise lore
- Futhark.Optimise.Simplify.Lore: instance (Futhark.Binder.Class.Bindable lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.Binder.Class.Bindable (Futhark.Optimise.Simplify.Lore.Wise lore)
- Futhark.Optimise.Simplify.Lore: instance (Futhark.IR.Decorations.Decorations lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Decorations.Decorations (Futhark.Optimise.Simplify.Lore.Wise lore)
- Futhark.Optimise.Simplify.Lore: instance (Futhark.IR.Pretty.PrettyLore lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Pretty.PrettyLore (Futhark.Optimise.Simplify.Lore.Wise lore)
- Futhark.Optimise.Simplify.Lore: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.ASTLore (Futhark.Optimise.Simplify.Lore.Wise lore)
- Futhark.Optimise.Simplify.Lore: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Optimise.Simplify.Lore.CanBeWise (Futhark.IR.Decorations.Op lore)) => Futhark.IR.Prop.Aliases.Aliased (Futhark.Optimise.Simplify.Lore.Wise lore)
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Aliases.AliasesOf (Futhark.Optimise.Simplify.Lore.VarWisdom, dec)
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Names.FreeDec Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Names.FreeDec Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Optimise.Simplify.Lore.CanBeWise ()
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Show.Show Futhark.Optimise.Simplify.Lore.BodyWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Show.Show Futhark.Optimise.Simplify.Lore.ExpWisdom
- Futhark.Optimise.Simplify.Lore: instance GHC.Show.Show Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Optimise.Simplify.Lore.VarWisdom
- Futhark.Optimise.Simplify.Lore: mkWiseBody :: (ASTLore lore, CanBeWise (Op lore)) => BodyDec lore -> Stms (Wise lore) -> Result -> Body (Wise lore)
- Futhark.Optimise.Simplify.Lore: mkWiseExpDec :: (ASTLore lore, CanBeWise (Op lore)) => Pattern (Wise lore) -> ExpDec lore -> Exp (Wise lore) -> ExpDec (Wise lore)
- Futhark.Optimise.Simplify.Lore: mkWiseLetStm :: (ASTLore lore, CanBeWise (Op lore)) => Pattern lore -> StmAux (ExpDec lore) -> Exp (Wise lore) -> Stm (Wise lore)
- Futhark.Optimise.Simplify.Lore: newtype VarWisdom
- Futhark.Optimise.Simplify.Lore: removeBodyWisdom :: CanBeWise (Op lore) => Body (Wise lore) -> Body lore
- Futhark.Optimise.Simplify.Lore: removeExpWisdom :: CanBeWise (Op lore) => Exp (Wise lore) -> Exp lore
- Futhark.Optimise.Simplify.Lore: removeFunDefWisdom :: CanBeWise (Op lore) => FunDef (Wise lore) -> FunDef lore
- Futhark.Optimise.Simplify.Lore: removeLambdaWisdom :: CanBeWise (Op lore) => Lambda (Wise lore) -> Lambda lore
- Futhark.Optimise.Simplify.Lore: removeOpWisdom :: CanBeWise op => OpWithWisdom op -> op
- Futhark.Optimise.Simplify.Lore: removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a
- Futhark.Optimise.Simplify.Lore: removeScopeWisdom :: Scope (Wise lore) -> Scope lore
- Futhark.Optimise.Simplify.Lore: removeStmWisdom :: CanBeWise (Op lore) => Stm (Wise lore) -> Stm lore
- Futhark.Optimise.Simplify.Lore: type family OpWithWisdom op :: Type;
- Futhark.Optimise.Simplify.Lore: }
- Futhark.Optimise.Simplify.Rule: instance (Futhark.IR.Prop.ASTLore lore, Futhark.Binder.BinderOps lore) => Futhark.Binder.Class.MonadBinder (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Scope.HasScope lore (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance Futhark.IR.Prop.ASTLore lore => Futhark.IR.Prop.Scope.LocalScope lore (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Applicative (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Functor (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monad (Futhark.Optimise.Simplify.Rule.RuleM lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monoid (Futhark.Optimise.Simplify.Rule.RuleBook lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monoid (Futhark.Optimise.Simplify.Rule.Rules lore a)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Semigroup (Futhark.Optimise.Simplify.Rule.RuleBook lore)
- Futhark.Optimise.Simplify.Rule: instance GHC.Base.Semigroup (Futhark.Optimise.Simplify.Rule.Rules lore a)
- Futhark.Optimise.Sink: sinkKernels :: Pass Kernels Kernels
- Futhark.Optimise.Unstream: unstreamKernels :: Pass Kernels Kernels
- Futhark.Pass.ExpandAllocations: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.KernelsMem.KernelsMem Futhark.Pass.ExpandAllocations.OffsetM
- Futhark.Pass.ExpandAllocations: instance Futhark.IR.Prop.Scope.LocalScope Futhark.IR.KernelsMem.KernelsMem Futhark.Pass.ExpandAllocations.OffsetM
- Futhark.Pass.ExplicitAllocations: instance (Futhark.Pass.ExplicitAllocations.Allocable fromlore tolore, Futhark.Pass.ExplicitAllocations.Allocator tolore (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)) => Futhark.Binder.Class.MonadBinder (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance Control.Monad.Reader.Class.MonadReader (Futhark.Pass.ExplicitAllocations.AllocEnv fromlore tolore) (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance Control.Monad.Writer.Class.MonadWriter [Futhark.Pass.ExplicitAllocations.AllocStm] (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Decorations.Decorations lore => Futhark.IR.Prop.Scope.HasScope lore (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Decorations.Decorations lore => Futhark.IR.Prop.Scope.LocalScope lore (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Mem.Mem lore => Futhark.Pass.ExplicitAllocations.Allocator lore (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Prop.ASTLore tolore => Futhark.IR.Prop.Scope.HasScope tolore (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Prop.ASTLore tolore => Futhark.IR.Prop.Scope.LocalScope tolore (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance Futhark.Pass.ExplicitAllocations.Allocable fromlore tolore => Futhark.Pass.ExplicitAllocations.Allocator tolore (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Applicative (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Applicative (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Functor (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Functor (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Monad (Futhark.Pass.ExplicitAllocations.AllocM fromlore tolore)
- Futhark.Pass.ExplicitAllocations: instance GHC.Base.Monad (Futhark.Pass.ExplicitAllocations.PatAllocM lore)
- Futhark.Pass.ExplicitAllocations.Kernels: explicitAllocations :: Pass Kernels KernelsMem
- Futhark.Pass.ExplicitAllocations.Kernels: explicitAllocationsInStms :: (MonadFreshNames m, HasScope KernelsMem m) => Stms Kernels -> m (Stms KernelsMem)
- Futhark.Pass.ExplicitAllocations.Kernels: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.Kernels.Kernel.HostOp lore op)
- Futhark.Pass.ExplicitAllocations.MC: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.MC.Op.MCOp lore op)
- Futhark.Pass.ExplicitAllocations.SegOp: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.SegOp.SegOp lvl lore)
- Futhark.Pass.ExtractKernels: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.Kernels.Kernels Futhark.Pass.ExtractKernels.DistribM
- Futhark.Pass.ExtractKernels: instance Futhark.IR.Prop.Scope.LocalScope Futhark.IR.Kernels.Kernels Futhark.Pass.ExtractKernels.DistribM
- Futhark.Pass.ExtractKernels.BlockedKernel: type DistLore lore = (Bindable lore, HasSegOp lore, BinderOps lore, LetDec lore ~ Type, ExpDec lore ~ (), BodyDec lore ~ (), CanBeAliased (Op lore))
- Futhark.Pass.ExtractKernels.DistributeNests: instance (GHC.Base.Monad m, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Scope.HasScope lore (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance (GHC.Base.Monad m, Futhark.IR.Prop.ASTLore lore) => Futhark.IR.Prop.Scope.LocalScope lore (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance Futhark.MonadFreshNames.MonadFreshNames m => Futhark.MonadFreshNames.MonadFreshNames (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Applicative m => GHC.Base.Applicative (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Futhark.Pass.ExtractKernels.DistributeNests.DistEnv lore m) (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Control.Monad.Writer.Class.MonadWriter (Futhark.Pass.ExtractKernels.DistributeNests.DistRes lore) (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Futhark.Util.Log.MonadLogger (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore m)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monoid (Futhark.Pass.ExtractKernels.DistributeNests.DistRes lore)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monoid (Futhark.Pass.ExtractKernels.DistributeNests.PostStms lore)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Semigroup (Futhark.Pass.ExtractKernels.DistributeNests.DistRes lore)
- Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Semigroup (Futhark.Pass.ExtractKernels.DistributeNests.PostStms lore)
- Futhark.Pass.ExtractKernels.ToKernels: getSize :: (MonadBinder m, Op (Lore m) ~ HostOp (Lore m) inner) => String -> SizeClass -> m SubExp
- Futhark.Pass.ExtractKernels.ToKernels: injectSOACS :: (Monad m, SameScope from to, ExpDec from ~ ExpDec to, BodyDec from ~ BodyDec to, RetType from ~ RetType to, BranchType from ~ BranchType to, Op from ~ SOAC from) => (SOAC to -> Op to) -> Rephraser m from to
- Futhark.Pass.ExtractKernels.ToKernels: scopeForKernels :: Scope SOACS -> Scope Kernels
- Futhark.Pass.ExtractKernels.ToKernels: scopeForSOACs :: Scope Kernels -> Scope SOACS
- Futhark.Pass.ExtractKernels.ToKernels: segThread :: (MonadBinder m, Op (Lore m) ~ HostOp (Lore m) inner) => String -> m SegLevel
- Futhark.Pass.ExtractKernels.ToKernels: soacsLambdaToKernels :: Lambda SOACS -> Lambda Kernels
- Futhark.Pass.ExtractKernels.ToKernels: soacsStmToKernels :: Stm SOACS -> Stm Kernels
- Futhark.Pass.Simplify: simplifyKernels :: Pass Kernels Kernels
- Futhark.Pass.Simplify: simplifyKernelsMem :: Pass KernelsMem KernelsMem
- Futhark.Server: CmdFailure :: [Text] -> [Text] -> CmdFailure
- Futhark.Server: [failureLog] :: CmdFailure -> [Text]
- Futhark.Server: [failureMsg] :: CmdFailure -> [Text]
- Futhark.Server: cmdCall :: Server -> EntryName -> [VarName] -> [VarName] -> IO (Either CmdFailure [Text])
- Futhark.Server: cmdClear :: Server -> IO (Maybe CmdFailure)
- Futhark.Server: cmdEither :: (MonadError Text m, MonadIO m) => IO (Either CmdFailure a) -> m a
- Futhark.Server: cmdFree :: Server -> [VarName] -> IO (Maybe CmdFailure)
- Futhark.Server: cmdInputs :: Server -> EntryName -> IO (Either CmdFailure [TypeName])
- Futhark.Server: cmdMaybe :: (MonadError Text m, MonadIO m) => IO (Maybe CmdFailure) -> m ()
- Futhark.Server: cmdOutputs :: Server -> EntryName -> IO (Either CmdFailure [TypeName])
- Futhark.Server: cmdRename :: Server -> VarName -> VarName -> IO (Maybe CmdFailure)
- Futhark.Server: cmdReport :: Server -> IO (Either CmdFailure [Text])
- Futhark.Server: cmdRestore :: Server -> FilePath -> [(VarName, TypeName)] -> IO (Maybe CmdFailure)
- Futhark.Server: cmdStore :: Server -> FilePath -> [VarName] -> IO (Maybe CmdFailure)
- Futhark.Server: data CmdFailure
- Futhark.Server: data Server
- Futhark.Server: instance GHC.Classes.Eq Futhark.Server.CmdFailure
- Futhark.Server: instance GHC.Classes.Ord Futhark.Server.CmdFailure
- Futhark.Server: instance GHC.Show.Show Futhark.Server.CmdFailure
- Futhark.Server: type EntryName = Text
- Futhark.Server: type TypeName = Text
- Futhark.Server: type VarName = Text
- Futhark.Server: withServer :: FilePath -> [FilePath] -> (Server -> IO a) -> IO a
- Futhark.Test.Values: BoolValue :: Vector Int -> Vector Bool -> Value
- Futhark.Test.Values: Float32Value :: Vector Int -> Vector Float -> Value
- Futhark.Test.Values: Float64Value :: Vector Int -> Vector Double -> Value
- Futhark.Test.Values: Int16Value :: Vector Int -> Vector Int16 -> Value
- Futhark.Test.Values: Int32Value :: Vector Int -> Vector Int32 -> Value
- Futhark.Test.Values: Int64Value :: Vector Int -> Vector Int64 -> Value
- Futhark.Test.Values: Int8Value :: Vector Int -> Vector Int8 -> Value
- Futhark.Test.Values: ValueType :: [Int] -> PrimType -> ValueType
- Futhark.Test.Values: Word16Value :: Vector Int -> Vector Word16 -> Value
- Futhark.Test.Values: Word32Value :: Vector Int -> Vector Word32 -> Value
- Futhark.Test.Values: Word64Value :: Vector Int -> Vector Word64 -> Value
- Futhark.Test.Values: Word8Value :: Vector Int -> Vector Word8 -> Value
- Futhark.Test.Values: class GetValue t
- Futhark.Test.Values: class PutValue t
- Futhark.Test.Values: compareValues :: [Value] -> [Value] -> [Mismatch]
- Futhark.Test.Values: data Mismatch
- Futhark.Test.Values: data Value
- Futhark.Test.Values: data ValueType
- Futhark.Test.Values: getValue :: GetValue t => Value -> Maybe t
- Futhark.Test.Values: instance Data.Binary.Class.Binary Futhark.Test.Values.Value
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Int.Int16
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Int.Int32
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Int.Int64
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Int.Int8
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Types.Bool
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Word.Word16
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Word.Word32
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Word.Word64
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue GHC.Word.Word8
- Futhark.Test.Values: instance Futhark.Test.Values.GetValue t => Futhark.Test.Values.GetValue [t]
- Futhark.Test.Values: instance Futhark.Test.Values.PutValue Data.ByteString.Internal.ByteString
- Futhark.Test.Values: instance Futhark.Test.Values.PutValue Data.Text.Internal.Text
- Futhark.Test.Values: instance Futhark.Test.Values.PutValue GHC.Word.Word8
- Futhark.Test.Values: instance Futhark.Test.Values.PutValue Language.Futhark.Syntax.PrimValue
- Futhark.Test.Values: instance Futhark.Test.Values.PutValue [Futhark.Test.Values.Value]
- Futhark.Test.Values: instance GHC.Classes.Eq Futhark.Test.Values.ValueType
- Futhark.Test.Values: instance GHC.Classes.Ord Futhark.Test.Values.ValueType
- Futhark.Test.Values: instance GHC.Show.Show Futhark.Test.Values.Mismatch
- Futhark.Test.Values: instance GHC.Show.Show Futhark.Test.Values.Value
- Futhark.Test.Values: instance GHC.Show.Show Futhark.Test.Values.ValueType
- Futhark.Test.Values: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Test.Values.Value
- Futhark.Test.Values: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Test.Values.ValueType
- Futhark.Test.Values: prettyValueTypeNoDims :: ValueType -> Text
- Futhark.Test.Values: putValue :: PutValue t => t -> Maybe Value
- Futhark.Test.Values: readValues :: ByteString -> Maybe [Value]
- Futhark.Test.Values: type Vector = Vector
- Futhark.Test.Values: valueElems :: Value -> [Value]
- Futhark.Test.Values: valueShape :: Value -> [Int]
- Futhark.Test.Values: valueType :: Value -> ValueType
- Futhark.Test.Values.Parser: parsePrimType :: Parser PrimType
- Futhark.Test.Values.Parser: parsePrimValue :: Parser PrimValue
- Futhark.Test.Values.Parser: parseType :: Parser ValueType
- Futhark.Test.Values.Parser: parseValue :: Parser () -> Parser Value
- Futhark.Transform.FirstOrderTransform: type FirstOrderLore lore = (Bindable lore, BinderOps lore, LetDec SOACS ~ LetDec lore, LParamInfo SOACS ~ LParamInfo lore, CanBeAliased (Op lore))
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable lore => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Body lore)
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable lore => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Exp lore)
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable lore => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.FunDef lore)
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable lore => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Lambda lore)
- Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable lore => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Stm lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.Prop.Scope.NameInfo lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Body lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Exp lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Lambda lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable lore => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stm lore)
- Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stm lore) => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stms lore)
- Futhark.TypeCheck: checkBodyLore :: (Checkable lore, BodyDec lore ~ ()) => BodyDec lore -> TypeM lore ()
- Futhark.TypeCheck: checkExpLore :: (Checkable lore, ExpDec lore ~ ()) => ExpDec lore -> TypeM lore ()
- Futhark.TypeCheck: checkFParamLore :: (Checkable lore, FParamInfo lore ~ DeclType) => VName -> FParamInfo lore -> TypeM lore ()
- Futhark.TypeCheck: checkLParamLore :: (Checkable lore, LParamInfo lore ~ Type) => VName -> LParamInfo lore -> TypeM lore ()
- Futhark.TypeCheck: checkLetBoundLore :: (Checkable lore, LetDec lore ~ Type) => VName -> LetDec lore -> TypeM lore ()
- Futhark.TypeCheck: instance Control.Monad.Reader.Class.MonadReader (Futhark.TypeCheck.Env lore) (Futhark.TypeCheck.TypeM lore)
- Futhark.TypeCheck: instance Control.Monad.State.Class.MonadState Futhark.TypeCheck.TState (Futhark.TypeCheck.TypeM lore)
- Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable lore => Futhark.IR.Prop.Scope.HasScope (Futhark.IR.Aliases.Aliases lore) (Futhark.TypeCheck.TypeM lore)
- Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable lore => GHC.Show.Show (Futhark.TypeCheck.ErrorCase lore)
- Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable lore => GHC.Show.Show (Futhark.TypeCheck.TypeError lore)
- Futhark.TypeCheck: instance GHC.Base.Applicative (Futhark.TypeCheck.TypeM lore)
- Futhark.TypeCheck: instance GHC.Base.Functor (Futhark.TypeCheck.TypeM lore)
- Futhark.TypeCheck: instance GHC.Base.Monad (Futhark.TypeCheck.TypeM lore)
- Language.Futhark.Core: Commutative :: Commutativity
- Language.Futhark.Core: Noncommutative :: Commutativity
- Language.Futhark.Core: data Commutativity
- Language.Futhark.Core: instance GHC.Base.Monoid Language.Futhark.Core.Commutativity
- Language.Futhark.Core: instance GHC.Base.Semigroup Language.Futhark.Core.Commutativity
- Language.Futhark.Core: instance GHC.Classes.Eq Language.Futhark.Core.Commutativity
- Language.Futhark.Core: instance GHC.Classes.Ord Language.Futhark.Core.Commutativity
- Language.Futhark.Core: instance GHC.Show.Show Language.Futhark.Core.Commutativity
- Language.Futhark.Core: pretty :: Pretty a => a -> String
+ Futhark.Analysis.HORep.MapNest: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.Analysis.HORep.MapNest.MapNest rep)
+ Futhark.Analysis.HORep.MapNest: instance GHC.Classes.Eq (Futhark.Analysis.HORep.MapNest.Nesting rep)
+ Futhark.Analysis.HORep.MapNest: instance GHC.Classes.Ord (Futhark.Analysis.HORep.MapNest.Nesting rep)
+ Futhark.Analysis.HORep.MapNest: instance GHC.Show.Show (Futhark.Analysis.HORep.MapNest.Nesting rep)
+ Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.Analysis.HORep.SOAC.SOAC rep)
+ Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.Analysis.HORep.SOAC.SOAC rep)
+ Futhark.Analysis.HORep.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.Analysis.HORep.SOAC.SOAC rep)
+ Futhark.Analysis.Interference: analyseGPU :: LocalScope GPUMem m => LastUseMap -> Stms GPUMem -> m (Graph VName)
+ Futhark.Analysis.Interference: type Graph a = Set (a, a)
+ Futhark.Analysis.LastUse: analyseProg :: Prog GPUMem -> (LastUseMap, Used)
+ Futhark.Analysis.LastUse: type LastUseMap = Map VName Names
+ Futhark.Analysis.Rephrase: [rephraseBodyDec] :: Rephraser m from to -> BodyDec from -> m (BodyDec to)
+ Futhark.Analysis.Rephrase: [rephraseExpDec] :: Rephraser m from to -> ExpDec from -> m (ExpDec to)
+ Futhark.Analysis.Rephrase: [rephraseFParamDec] :: Rephraser m from to -> FParamInfo from -> m (FParamInfo to)
+ Futhark.Analysis.Rephrase: [rephraseLParamDec] :: Rephraser m from to -> LParamInfo from -> m (LParamInfo to)
+ Futhark.Analysis.Rephrase: [rephraseLetBoundDec] :: Rephraser m from to -> LetDec from -> m (LetDec to)
+ Futhark.Analysis.SymbolTable: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Types.Typed (Futhark.Analysis.SymbolTable.Entry rep)
+ Futhark.Analysis.SymbolTable: instance GHC.Base.Monoid (Futhark.Analysis.SymbolTable.SymbolTable rep)
+ Futhark.Analysis.SymbolTable: instance GHC.Base.Semigroup (Futhark.Analysis.SymbolTable.SymbolTable rep)
+ 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.CodeGen.Backends.GenericC: instance GHC.Classes.Eq Futhark.CodeGen.Backends.GenericC.Publicness
+ Futhark.CodeGen.Backends.GenericC: instance GHC.Classes.Ord Futhark.CodeGen.Backends.GenericC.Publicness
+ Futhark.CodeGen.Backends.GenericC: instance GHC.Show.Show Futhark.CodeGen.Backends.GenericC.Publicness
+ Futhark.CodeGen.ImpCode: instance GHC.Classes.Ord Futhark.CodeGen.ImpCode.Signedness
+ Futhark.CodeGen.ImpCode: pretty :: Pretty a => a -> String
+ Futhark.CodeGen.ImpCode.GPU: (.&&.) :: TPrimExp Bool v -> TPrimExp Bool v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.&.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: (.<.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.<<.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: (.<=.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.==.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.>.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.>=.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: (.>>.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: (.^.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: (.|.) :: TPrimExp t v -> TPrimExp t v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: (.||.) :: TPrimExp Bool v -> TPrimExp Bool v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: AShr :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: Abs :: IntType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: Add :: IntType -> Overflow -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: And :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: ArrayValue :: VName -> Space -> PrimType -> Signedness -> [DimSize] -> ValueDesc
+ Futhark.CodeGen.ImpCode.GPU: ArrayValues :: [PrimValue] -> ArrayContents
+ Futhark.CodeGen.ImpCode.GPU: ArrayZeros :: Int -> ArrayContents
+ Futhark.CodeGen.ImpCode.GPU: Atomic :: Space -> AtomicOp -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicAdd :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicAnd :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicCmpXchg :: PrimType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicFAdd :: FloatType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicOr :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicSMax :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicSMin :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicUMax :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicUMin :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicXchg :: PrimType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: AtomicXor :: IntType -> VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: BToI :: IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: Barrier :: Fence -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: BinOpExp :: BinOp -> PrimExp v -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: Bool :: PrimType
+ Futhark.CodeGen.ImpCode.GPU: BoolValue :: !Bool -> PrimValue
+ Futhark.CodeGen.ImpCode.GPU: CallKernel :: Kernel -> HostOp
+ Futhark.CodeGen.ImpCode.GPU: CmpEq :: PrimType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpLle :: CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpLlt :: CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpOpExp :: CmpOp -> PrimExp v -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: CmpSizeLe :: VName -> Name -> SizeClass -> Exp -> HostOp
+ Futhark.CodeGen.ImpCode.GPU: CmpSle :: IntType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpSlt :: IntType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpUle :: IntType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: CmpUlt :: IntType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: Complement :: IntType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: ConstUse :: VName -> KernelConstExp -> KernelUse
+ Futhark.CodeGen.ImpCode.GPU: Constant :: PrimValue -> SubExp
+ Futhark.CodeGen.ImpCode.GPU: Constants :: [Param] -> Code a -> Constants a
+ Futhark.CodeGen.ImpCode.GPU: ConvOpExp :: ConvOp -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: Count :: e -> Count u e
+ Futhark.CodeGen.ImpCode.GPU: DefaultSpace :: Space
+ Futhark.CodeGen.ImpCode.GPU: Definitions :: Constants a -> Functions a -> Definitions a
+ Futhark.CodeGen.ImpCode.GPU: ErrorInt32 :: a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.GPU: ErrorInt64 :: a -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.GPU: ErrorMsg :: [ErrorMsgPart a] -> ErrorMsg a
+ Futhark.CodeGen.ImpCode.GPU: ErrorString :: String -> ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.GPU: ErrorSync :: Fence -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: ExpArg :: Exp -> Arg
+ Futhark.CodeGen.ImpCode.GPU: FAbs :: FloatType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: FAdd :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FCmpLe :: FloatType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: FCmpLt :: FloatType -> CmpOp
+ Futhark.CodeGen.ImpCode.GPU: FDiv :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FMax :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FMin :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FMod :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FMul :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FPConv :: FloatType -> FloatType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: FPToSI :: FloatType -> IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: FPToUI :: FloatType -> IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: FPow :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FSignum :: FloatType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: FSub :: FloatType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: FenceGlobal :: Fence
+ Futhark.CodeGen.ImpCode.GPU: FenceLocal :: Fence
+ Futhark.CodeGen.ImpCode.GPU: Float32 :: FloatType
+ Futhark.CodeGen.ImpCode.GPU: Float32Value :: !Float -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: Float64 :: FloatType
+ Futhark.CodeGen.ImpCode.GPU: Float64Value :: !Double -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: FloatType :: FloatType -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: FloatValue :: !FloatValue -> PrimValue
+ Futhark.CodeGen.ImpCode.GPU: FunExp :: String -> [PrimExp v] -> PrimType -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: Function :: Maybe Name -> [Param] -> [Param] -> Code a -> [ExternalValue] -> [ExternalValue] -> FunctionT a
+ Futhark.CodeGen.ImpCode.GPU: Functions :: [(Name, Function a)] -> Functions a
+ Futhark.CodeGen.ImpCode.GPU: GetGlobalId :: VName -> Int -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetGlobalSize :: VName -> Int -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetGroupId :: VName -> Int -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetLocalId :: VName -> Int -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetLocalSize :: VName -> Int -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetLockstepWidth :: VName -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: GetSize :: VName -> Name -> SizeClass -> HostOp
+ Futhark.CodeGen.ImpCode.GPU: GetSizeMax :: VName -> SizeClass -> HostOp
+ Futhark.CodeGen.ImpCode.GPU: IToB :: IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: Index :: VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> ExpLeaf
+ Futhark.CodeGen.ImpCode.GPU: Int16 :: IntType
+ Futhark.CodeGen.ImpCode.GPU: Int16Value :: !Int16 -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: Int32 :: IntType
+ Futhark.CodeGen.ImpCode.GPU: Int32Value :: !Int32 -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: Int64 :: IntType
+ Futhark.CodeGen.ImpCode.GPU: Int64Value :: !Int64 -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: Int8 :: IntType
+ Futhark.CodeGen.ImpCode.GPU: Int8Value :: !Int8 -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: IntType :: IntType -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: IntValue :: !IntValue -> PrimValue
+ Futhark.CodeGen.ImpCode.GPU: Kernel :: Code KernelOp -> [KernelUse] -> [Exp] -> [Exp] -> Name -> Bool -> Kernel
+ Futhark.CodeGen.ImpCode.GPU: LShr :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: LeafExp :: v -> PrimType -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: LocalAlloc :: VName -> Count Bytes (TExp Int64) -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: LogAnd :: BinOp
+ Futhark.CodeGen.ImpCode.GPU: LogOr :: BinOp
+ Futhark.CodeGen.ImpCode.GPU: MemArg :: VName -> Arg
+ Futhark.CodeGen.ImpCode.GPU: MemFence :: Fence -> KernelOp
+ Futhark.CodeGen.ImpCode.GPU: MemParam :: VName -> Space -> Param
+ Futhark.CodeGen.ImpCode.GPU: MemoryUse :: VName -> KernelUse
+ Futhark.CodeGen.ImpCode.GPU: Mul :: IntType -> Overflow -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: Nonunique :: Uniqueness
+ Futhark.CodeGen.ImpCode.GPU: Nonvolatile :: Volatility
+ Futhark.CodeGen.ImpCode.GPU: Not :: UnOp
+ Futhark.CodeGen.ImpCode.GPU: OpaqueValue :: Uniqueness -> String -> [ValueDesc] -> ExternalValue
+ Futhark.CodeGen.ImpCode.GPU: Or :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: OverflowUndef :: Overflow
+ Futhark.CodeGen.ImpCode.GPU: OverflowWrap :: Overflow
+ Futhark.CodeGen.ImpCode.GPU: Pow :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SDiv :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SDivUp :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SExt :: IntType -> IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: SIToFP :: IntType -> FloatType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: SMax :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SMin :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SMod :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SQuot :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SRem :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SSignum :: IntType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: Safe :: Safety
+ Futhark.CodeGen.ImpCode.GPU: ScalarParam :: VName -> PrimType -> Param
+ Futhark.CodeGen.ImpCode.GPU: ScalarSpace :: [SubExp] -> PrimType -> Space
+ Futhark.CodeGen.ImpCode.GPU: ScalarUse :: VName -> PrimType -> KernelUse
+ Futhark.CodeGen.ImpCode.GPU: ScalarValue :: PrimType -> Signedness -> VName -> ValueDesc
+ Futhark.CodeGen.ImpCode.GPU: ScalarVar :: VName -> ExpLeaf
+ Futhark.CodeGen.ImpCode.GPU: Shl :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: SizeConst :: Name -> KernelConst
+ Futhark.CodeGen.ImpCode.GPU: Space :: SpaceId -> Space
+ Futhark.CodeGen.ImpCode.GPU: Sub :: IntType -> Overflow -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: TPrimExp :: PrimExp v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: TransparentValue :: Uniqueness -> ValueDesc -> ExternalValue
+ Futhark.CodeGen.ImpCode.GPU: TypeDirect :: Signedness
+ Futhark.CodeGen.ImpCode.GPU: TypeUnsigned :: Signedness
+ Futhark.CodeGen.ImpCode.GPU: UDiv :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: UDivUp :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: UIToFP :: IntType -> FloatType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: UMax :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: UMin :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: UMod :: IntType -> Safety -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: USignum :: IntType -> UnOp
+ Futhark.CodeGen.ImpCode.GPU: UnOpExp :: UnOp -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: Unique :: Uniqueness
+ Futhark.CodeGen.ImpCode.GPU: Unit :: PrimType
+ Futhark.CodeGen.ImpCode.GPU: UnitValue :: PrimValue
+ Futhark.CodeGen.ImpCode.GPU: Unsafe :: Safety
+ Futhark.CodeGen.ImpCode.GPU: VName :: !Name -> !Int -> VName
+ Futhark.CodeGen.ImpCode.GPU: ValueExp :: PrimValue -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: Var :: VName -> SubExp
+ Futhark.CodeGen.ImpCode.GPU: Volatile :: Volatility
+ Futhark.CodeGen.ImpCode.GPU: Xor :: IntType -> BinOp
+ Futhark.CodeGen.ImpCode.GPU: ZExt :: IntType -> IntType -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: [constsDecl] :: Constants a -> [Param]
+ Futhark.CodeGen.ImpCode.GPU: [constsInit] :: Constants a -> Code a
+ Futhark.CodeGen.ImpCode.GPU: [defConsts] :: Definitions a -> Constants a
+ Futhark.CodeGen.ImpCode.GPU: [defFuns] :: Definitions a -> Functions a
+ Futhark.CodeGen.ImpCode.GPU: [kernelBody] :: Kernel -> Code KernelOp
+ Futhark.CodeGen.ImpCode.GPU: [kernelFailureTolerant] :: Kernel -> Bool
+ Futhark.CodeGen.ImpCode.GPU: [kernelGroupSize] :: Kernel -> [Exp]
+ Futhark.CodeGen.ImpCode.GPU: [kernelName] :: Kernel -> Name
+ Futhark.CodeGen.ImpCode.GPU: [kernelNumGroups] :: Kernel -> [Exp]
+ Futhark.CodeGen.ImpCode.GPU: [kernelUses] :: Kernel -> [KernelUse]
+ Futhark.CodeGen.ImpCode.GPU: [unCount] :: Count u e -> e
+ Futhark.CodeGen.ImpCode.GPU: [untyped] :: TPrimExp t v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: allBinOps :: [BinOp]
+ Futhark.CodeGen.ImpCode.GPU: allCmpOps :: [CmpOp]
+ Futhark.CodeGen.ImpCode.GPU: allConvOps :: [ConvOp]
+ Futhark.CodeGen.ImpCode.GPU: allFloatTypes :: [FloatType]
+ Futhark.CodeGen.ImpCode.GPU: allIntTypes :: [IntType]
+ Futhark.CodeGen.ImpCode.GPU: allPrimTypes :: [PrimType]
+ Futhark.CodeGen.ImpCode.GPU: allUnOps :: [UnOp]
+ Futhark.CodeGen.ImpCode.GPU: bNot :: TPrimExp Bool v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: baseName :: VName -> Name
+ Futhark.CodeGen.ImpCode.GPU: baseString :: VName -> String
+ Futhark.CodeGen.ImpCode.GPU: baseTag :: VName -> Int
+ Futhark.CodeGen.ImpCode.GPU: binOpType :: BinOp -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: blankPrimValue :: PrimType -> PrimValue
+ Futhark.CodeGen.ImpCode.GPU: boundByLambda :: Lambda rep -> [VName]
+ Futhark.CodeGen.ImpCode.GPU: boundByStm :: Stm rep -> Names
+ Futhark.CodeGen.ImpCode.GPU: boundByStms :: Stms rep -> Names
+ Futhark.CodeGen.ImpCode.GPU: boundInBody :: Body rep -> Names
+ Futhark.CodeGen.ImpCode.GPU: bytes :: a -> Count Bytes a
+ Futhark.CodeGen.ImpCode.GPU: calledFuncs :: Code a -> Set Name
+ Futhark.CodeGen.ImpCode.GPU: class NumExp t => FloatExp t
+ Futhark.CodeGen.ImpCode.GPU: class FreeIn dec => FreeDec dec
+ Futhark.CodeGen.ImpCode.GPU: class FreeIn a
+ Futhark.CodeGen.ImpCode.GPU: class NumExp t => IntExp t
+ Futhark.CodeGen.ImpCode.GPU: class Located a
+ Futhark.CodeGen.ImpCode.GPU: class NumExp t
+ Futhark.CodeGen.ImpCode.GPU: cmpOpType :: CmpOp -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: coerceIntPrimExp :: IntType -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: commutativeBinOp :: BinOp -> Bool
+ Futhark.CodeGen.ImpCode.GPU: constFoldPrimExp :: PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: convOpFun :: ConvOp -> String
+ Futhark.CodeGen.ImpCode.GPU: convOpType :: ConvOp -> (PrimType, PrimType)
+ Futhark.CodeGen.ImpCode.GPU: data Arg
+ Futhark.CodeGen.ImpCode.GPU: data ArrayContents
+ Futhark.CodeGen.ImpCode.GPU: data AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: data BinOp
+ Futhark.CodeGen.ImpCode.GPU: data Bytes
+ Futhark.CodeGen.ImpCode.GPU: data CmpOp
+ Futhark.CodeGen.ImpCode.GPU: data Constants a
+ Futhark.CodeGen.ImpCode.GPU: data ConvOp
+ Futhark.CodeGen.ImpCode.GPU: data Definitions a
+ Futhark.CodeGen.ImpCode.GPU: data Elements
+ Futhark.CodeGen.ImpCode.GPU: data ErrorMsgPart a
+ Futhark.CodeGen.ImpCode.GPU: data ExpLeaf
+ Futhark.CodeGen.ImpCode.GPU: data ExternalValue
+ Futhark.CodeGen.ImpCode.GPU: data FV
+ Futhark.CodeGen.ImpCode.GPU: data Fence
+ Futhark.CodeGen.ImpCode.GPU: data FloatType
+ Futhark.CodeGen.ImpCode.GPU: data FloatValue
+ Futhark.CodeGen.ImpCode.GPU: data FunctionT a
+ Futhark.CodeGen.ImpCode.GPU: data HostOp
+ Futhark.CodeGen.ImpCode.GPU: data Int16
+ Futhark.CodeGen.ImpCode.GPU: data Int32
+ Futhark.CodeGen.ImpCode.GPU: data Int64
+ Futhark.CodeGen.ImpCode.GPU: data Int8
+ Futhark.CodeGen.ImpCode.GPU: data IntType
+ Futhark.CodeGen.ImpCode.GPU: data IntValue
+ Futhark.CodeGen.ImpCode.GPU: data Kernel
+ Futhark.CodeGen.ImpCode.GPU: data KernelOp
+ Futhark.CodeGen.ImpCode.GPU: data KernelUse
+ Futhark.CodeGen.ImpCode.GPU: data Loc
+ Futhark.CodeGen.ImpCode.GPU: data Name
+ Futhark.CodeGen.ImpCode.GPU: data Names
+ Futhark.CodeGen.ImpCode.GPU: data Overflow
+ Futhark.CodeGen.ImpCode.GPU: data Param
+ Futhark.CodeGen.ImpCode.GPU: data PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: data PrimType
+ Futhark.CodeGen.ImpCode.GPU: data PrimValue
+ Futhark.CodeGen.ImpCode.GPU: data Safety
+ Futhark.CodeGen.ImpCode.GPU: data Signedness
+ Futhark.CodeGen.ImpCode.GPU: data Space
+ Futhark.CodeGen.ImpCode.GPU: data SrcLoc
+ Futhark.CodeGen.ImpCode.GPU: data SubExp
+ Futhark.CodeGen.ImpCode.GPU: data UnOp
+ Futhark.CodeGen.ImpCode.GPU: data Uniqueness
+ Futhark.CodeGen.ImpCode.GPU: data VName
+ Futhark.CodeGen.ImpCode.GPU: data ValueDesc
+ Futhark.CodeGen.ImpCode.GPU: data Volatility
+ Futhark.CodeGen.ImpCode.GPU: data Word16
+ Futhark.CodeGen.ImpCode.GPU: data Word32
+ Futhark.CodeGen.ImpCode.GPU: data Word64
+ Futhark.CodeGen.ImpCode.GPU: data Word8
+ Futhark.CodeGen.ImpCode.GPU: declaredIn :: Code a -> Names
+ Futhark.CodeGen.ImpCode.GPU: defaultEntryPoint :: Name
+ Futhark.CodeGen.ImpCode.GPU: doAbs :: IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doAdd :: IntValue -> IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue
+ Futhark.CodeGen.ImpCode.GPU: doCmpEq :: PrimValue -> PrimValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doCmpOp :: CmpOp -> PrimValue -> PrimValue -> Maybe Bool
+ Futhark.CodeGen.ImpCode.GPU: doCmpSle :: IntValue -> IntValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doCmpSlt :: IntValue -> IntValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doCmpUle :: IntValue -> IntValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doCmpUlt :: IntValue -> IntValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doComplement :: IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doConvOp :: ConvOp -> PrimValue -> Maybe PrimValue
+ Futhark.CodeGen.ImpCode.GPU: doFAbs :: FloatValue -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: doFCmpLe :: FloatValue -> FloatValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doFCmpLt :: FloatValue -> FloatValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: doFPConv :: FloatValue -> FloatType -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: doFPToSI :: FloatValue -> IntType -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doFPToUI :: FloatValue -> IntType -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doMul :: IntValue -> IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doPow :: IntValue -> IntValue -> Maybe IntValue
+ Futhark.CodeGen.ImpCode.GPU: doSDiv :: IntValue -> IntValue -> Maybe IntValue
+ Futhark.CodeGen.ImpCode.GPU: doSExt :: IntValue -> IntType -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doSIToFP :: IntValue -> FloatType -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: doSMod :: IntValue -> IntValue -> Maybe IntValue
+ Futhark.CodeGen.ImpCode.GPU: doSSignum :: IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doUIToFP :: IntValue -> FloatType -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: doUSignum :: IntValue -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: doUnOp :: UnOp -> PrimValue -> Maybe PrimValue
+ Futhark.CodeGen.ImpCode.GPU: doZExt :: IntValue -> IntType -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: elements :: a -> Count Elements a
+ Futhark.CodeGen.ImpCode.GPU: errorMsgArgTypes :: ErrorMsg a -> [PrimType]
+ Futhark.CodeGen.ImpCode.GPU: evalPrimExp :: (Pretty v, MonadFail m) => (v -> m PrimValue) -> PrimExp v -> m PrimValue
+ Futhark.CodeGen.ImpCode.GPU: fMax64 :: TPrimExp Double v -> TPrimExp Double v -> TPrimExp Double v
+ Futhark.CodeGen.ImpCode.GPU: fMin64 :: TPrimExp Double v -> TPrimExp Double v -> TPrimExp Double v
+ Futhark.CodeGen.ImpCode.GPU: false :: TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: flipConvOp :: ConvOp -> ConvOp
+ Futhark.CodeGen.ImpCode.GPU: floatByteSize :: Num a => FloatType -> a
+ Futhark.CodeGen.ImpCode.GPU: floatValue :: Real num => FloatType -> num -> FloatValue
+ Futhark.CodeGen.ImpCode.GPU: floatValueType :: FloatValue -> FloatType
+ Futhark.CodeGen.ImpCode.GPU: freeIn :: FreeIn a => a -> Names
+ Futhark.CodeGen.ImpCode.GPU: freeIn' :: FreeIn a => a -> FV
+ Futhark.CodeGen.ImpCode.GPU: freeInStmsAndRes :: (FreeIn (Op rep), FreeIn (LetDec rep), FreeIn (LParamInfo rep), FreeIn (FParamInfo rep), FreeDec (BodyDec rep), FreeIn (RetType rep), FreeIn (BranchType rep), FreeDec (ExpDec rep)) => Stms rep -> Result -> FV
+ Futhark.CodeGen.ImpCode.GPU: fromBoolExp :: NumExp t => TPrimExp Bool v -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: fromInteger' :: NumExp t => Integer -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: fromRational' :: FloatExp t => Rational -> TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: fvBind :: Names -> FV -> FV
+ Futhark.CodeGen.ImpCode.GPU: fvName :: VName -> FV
+ Futhark.CodeGen.ImpCode.GPU: fvNames :: Names -> FV
+ Futhark.CodeGen.ImpCode.GPU: index :: VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> Exp
+ Futhark.CodeGen.ImpCode.GPU: infix 4 .>=.
+ Futhark.CodeGen.ImpCode.GPU: infixr 2 .||.
+ Futhark.CodeGen.ImpCode.GPU: infixr 3 .&&.
+ Futhark.CodeGen.ImpCode.GPU: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.GPU.AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.GPU.HostOp
+ Futhark.CodeGen.ImpCode.GPU: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.GPU.Kernel
+ Futhark.CodeGen.ImpCode.GPU: instance Futhark.IR.Prop.Names.FreeIn Futhark.CodeGen.ImpCode.GPU.KernelOp
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Classes.Eq Futhark.CodeGen.ImpCode.GPU.KernelConst
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Classes.Eq Futhark.CodeGen.ImpCode.GPU.KernelUse
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Classes.Ord Futhark.CodeGen.ImpCode.GPU.KernelConst
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Classes.Ord Futhark.CodeGen.ImpCode.GPU.KernelUse
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.AtomicOp
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.Fence
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.HostOp
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.Kernel
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.KernelConst
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.KernelOp
+ Futhark.CodeGen.ImpCode.GPU: instance GHC.Show.Show Futhark.CodeGen.ImpCode.GPU.KernelUse
+ Futhark.CodeGen.ImpCode.GPU: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.GPU.HostOp
+ Futhark.CodeGen.ImpCode.GPU: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.GPU.Kernel
+ Futhark.CodeGen.ImpCode.GPU: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.GPU.KernelConst
+ Futhark.CodeGen.ImpCode.GPU: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.GPU.KernelOp
+ Futhark.CodeGen.ImpCode.GPU: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.CodeGen.ImpCode.GPU.KernelUse
+ Futhark.CodeGen.ImpCode.GPU: intByteSize :: Num a => IntType -> a
+ Futhark.CodeGen.ImpCode.GPU: intToInt64 :: IntValue -> Int64
+ Futhark.CodeGen.ImpCode.GPU: intToWord64 :: IntValue -> Word64
+ Futhark.CodeGen.ImpCode.GPU: intValue :: Integral int => IntType -> int -> IntValue
+ Futhark.CodeGen.ImpCode.GPU: intValueType :: IntValue -> IntType
+ Futhark.CodeGen.ImpCode.GPU: isBool :: PrimExp v -> TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: isF32 :: PrimExp v -> TPrimExp Float v
+ Futhark.CodeGen.ImpCode.GPU: isF64 :: PrimExp v -> TPrimExp Double v
+ Futhark.CodeGen.ImpCode.GPU: isInt16 :: PrimExp v -> TPrimExp Int16 v
+ Futhark.CodeGen.ImpCode.GPU: isInt32 :: PrimExp v -> TPrimExp Int32 v
+ Futhark.CodeGen.ImpCode.GPU: isInt64 :: PrimExp v -> TPrimExp Int64 v
+ Futhark.CodeGen.ImpCode.GPU: isInt8 :: PrimExp v -> TPrimExp Int8 v
+ Futhark.CodeGen.ImpCode.GPU: leafExpTypes :: Ord a => PrimExp a -> Set (a, PrimType)
+ Futhark.CodeGen.ImpCode.GPU: lexicalMemoryUsage :: Function a -> Map VName Space
+ Futhark.CodeGen.ImpCode.GPU: locOf :: Located a => a -> Loc
+ Futhark.CodeGen.ImpCode.GPU: locOfList :: Located a => [a] -> Loc
+ Futhark.CodeGen.ImpCode.GPU: locStr :: Located a => a -> String
+ Futhark.CodeGen.ImpCode.GPU: locStrRel :: (Located a, Located b) => a -> b -> String
+ Futhark.CodeGen.ImpCode.GPU: mapNames :: (VName -> VName) -> Names -> Names
+ Futhark.CodeGen.ImpCode.GPU: nameFromString :: String -> Name
+ Futhark.CodeGen.ImpCode.GPU: nameFromText :: Text -> Name
+ Futhark.CodeGen.ImpCode.GPU: nameIn :: VName -> Names -> Bool
+ Futhark.CodeGen.ImpCode.GPU: nameToString :: Name -> String
+ Futhark.CodeGen.ImpCode.GPU: nameToText :: Name -> Text
+ Futhark.CodeGen.ImpCode.GPU: namesFromList :: [VName] -> Names
+ Futhark.CodeGen.ImpCode.GPU: namesIntMap :: Names -> IntMap VName
+ Futhark.CodeGen.ImpCode.GPU: namesIntersect :: Names -> Names -> Bool
+ Futhark.CodeGen.ImpCode.GPU: namesIntersection :: Names -> Names -> Names
+ Futhark.CodeGen.ImpCode.GPU: namesSubtract :: Names -> Names -> Names
+ Futhark.CodeGen.ImpCode.GPU: namesToList :: Names -> [VName]
+ Futhark.CodeGen.ImpCode.GPU: negativeIsh :: PrimValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: newtype Count u e
+ Futhark.CodeGen.ImpCode.GPU: newtype ErrorMsg a
+ Futhark.CodeGen.ImpCode.GPU: newtype Functions a
+ Futhark.CodeGen.ImpCode.GPU: newtype KernelConst
+ Futhark.CodeGen.ImpCode.GPU: newtype TPrimExp t v
+ Futhark.CodeGen.ImpCode.GPU: oneIsh :: PrimValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: oneIshInt :: IntValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: oneName :: VName -> Names
+ Futhark.CodeGen.ImpCode.GPU: paramName :: Param -> VName
+ Futhark.CodeGen.ImpCode.GPU: pattern Skip :: () => Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern Assert :: () => Exp -> ErrorMsg Exp -> (SrcLoc, [SrcLoc]) -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern Comment :: () => String -> Code a -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern If :: () => TExp Bool -> Code a -> Code a -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern Write :: () => VName -> Count Elements (TExp Int64) -> PrimType -> Space -> Volatility -> Exp -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern Call :: () => [VName] -> Name -> [Arg] -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pattern Op :: () => a -> Code a
+ Futhark.CodeGen.ImpCode.GPU: pquote :: Doc -> Doc
+ Futhark.CodeGen.ImpCode.GPU: precomputed :: FreeDec dec => dec -> FV -> FV
+ Futhark.CodeGen.ImpCode.GPU: pretty :: Pretty a => a -> String
+ Futhark.CodeGen.ImpCode.GPU: prettySigned :: Bool -> PrimType -> String
+ Futhark.CodeGen.ImpCode.GPU: prettyStacktrace :: Int -> [String] -> String
+ Futhark.CodeGen.ImpCode.GPU: primBitSize :: PrimType -> Int
+ Futhark.CodeGen.ImpCode.GPU: primByteSize :: Num a => PrimType -> a
+ Futhark.CodeGen.ImpCode.GPU: primExpSizeAtLeast :: Int -> PrimExp v -> Bool
+ Futhark.CodeGen.ImpCode.GPU: primExpType :: PrimExp v -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: primFuns :: Map String ([PrimType], PrimType, [PrimValue] -> Maybe PrimValue)
+ Futhark.CodeGen.ImpCode.GPU: primValueType :: PrimValue -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: quote :: String -> String
+ Futhark.CodeGen.ImpCode.GPU: sExt :: IntType -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: sExt32 :: IntExp t => TPrimExp t v -> TPrimExp Int32 v
+ Futhark.CodeGen.ImpCode.GPU: sExt64 :: IntExp t => TPrimExp t v -> TPrimExp Int64 v
+ Futhark.CodeGen.ImpCode.GPU: sMax32 :: TPrimExp Int32 v -> TPrimExp Int32 v -> TPrimExp Int32 v
+ Futhark.CodeGen.ImpCode.GPU: sMax64 :: TPrimExp Int64 v -> TPrimExp Int64 v -> TPrimExp Int64 v
+ Futhark.CodeGen.ImpCode.GPU: sMin32 :: TPrimExp Int32 v -> TPrimExp Int32 v -> TPrimExp Int32 v
+ Futhark.CodeGen.ImpCode.GPU: sMin64 :: TPrimExp Int64 v -> TPrimExp Int64 v -> TPrimExp Int64 v
+ Futhark.CodeGen.ImpCode.GPU: srclocOf :: Located a => a -> SrcLoc
+ Futhark.CodeGen.ImpCode.GPU: true :: TPrimExp Bool v
+ Futhark.CodeGen.ImpCode.GPU: type Code = Code HostOp
+ Futhark.CodeGen.ImpCode.GPU: type DimSize = SubExp
+ Futhark.CodeGen.ImpCode.GPU: type Exp = PrimExp ExpLeaf
+ Futhark.CodeGen.ImpCode.GPU: type Function = Function HostOp
+ Futhark.CodeGen.ImpCode.GPU: type KernelCode = Code KernelOp
+ Futhark.CodeGen.ImpCode.GPU: type KernelConstExp = PrimExp KernelConst
+ Futhark.CodeGen.ImpCode.GPU: type MemSize = SubExp
+ Futhark.CodeGen.ImpCode.GPU: type Program = Definitions HostOp
+ Futhark.CodeGen.ImpCode.GPU: type SpaceId = String
+ Futhark.CodeGen.ImpCode.GPU: type TExp t = TPrimExp t ExpLeaf
+ Futhark.CodeGen.ImpCode.GPU: unOpType :: UnOp -> PrimType
+ Futhark.CodeGen.ImpCode.GPU: valueIntegral :: Integral int => IntValue -> int
+ Futhark.CodeGen.ImpCode.GPU: var :: VName -> PrimType -> Exp
+ Futhark.CodeGen.ImpCode.GPU: vi32 :: VName -> TExp Int32
+ Futhark.CodeGen.ImpCode.GPU: vi64 :: VName -> TExp Int64
+ Futhark.CodeGen.ImpCode.GPU: withElemType :: Count Elements (TExp Int64) -> PrimType -> Count Bytes (TExp Int64)
+ Futhark.CodeGen.ImpCode.GPU: zExt :: IntType -> PrimExp v -> PrimExp v
+ Futhark.CodeGen.ImpCode.GPU: zExt32 :: IntExp t => TPrimExp t v -> TPrimExp Int32 v
+ Futhark.CodeGen.ImpCode.GPU: zExt64 :: IntExp t => TPrimExp t v -> TPrimExp Int64 v
+ Futhark.CodeGen.ImpCode.GPU: zeroIsh :: PrimValue -> Bool
+ Futhark.CodeGen.ImpCode.GPU: zeroIshInt :: IntValue -> Bool
+ Futhark.CodeGen.ImpGen: instance Control.Monad.Reader.Class.MonadReader (Futhark.CodeGen.ImpGen.Env rep r op) (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance Control.Monad.State.Class.MonadState (Futhark.CodeGen.ImpGen.ImpState rep r op) (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.SOACS.SOACS (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.CodeGen.ImpGen.VarEntry rep)
+ Futhark.CodeGen.ImpGen: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance GHC.Base.Applicative (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance GHC.Base.Functor (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen: instance GHC.Base.Monad (Futhark.CodeGen.ImpGen.ImpM rep r op)
+ Futhark.CodeGen.ImpGen.GPU: compileProgCUDA :: MonadFreshNames m => Prog GPUMem -> m (Warnings, Program)
+ Futhark.CodeGen.ImpGen.GPU: compileProgOpenCL :: MonadFreshNames m => Prog GPUMem -> m (Warnings, Program)
+ Futhark.CodeGen.ImpGen.GPU: data Warnings
+ Futhark.CodeGen.ImpGen.GPU.Base: AtomicCAS :: DoAtomicUpdate rep r -> AtomicUpdate rep r
+ Futhark.CodeGen.ImpGen.GPU.Base: AtomicLocking :: (Locking -> DoAtomicUpdate rep r) -> AtomicUpdate rep r
+ Futhark.CodeGen.ImpGen.GPU.Base: AtomicPrim :: DoAtomicUpdate rep r -> AtomicUpdate rep r
+ Futhark.CodeGen.ImpGen.GPU.Base: CUDA :: Target
+ Futhark.CodeGen.ImpGen.GPU.Base: HostEnv :: AtomicBinOp -> Target -> Map VName Locks -> HostEnv
+ Futhark.CodeGen.ImpGen.GPU.Base: KernelConstants :: TExp Int32 -> TExp Int32 -> TExp Int32 -> VName -> VName -> VName -> TExp Int64 -> TExp Int64 -> TExp Int32 -> TExp Int32 -> TExp Bool -> Map [SubExp] [TExp Int32] -> KernelConstants
+ Futhark.CodeGen.ImpGen.GPU.Base: KernelEnv :: AtomicBinOp -> KernelConstants -> Map VName Locks -> KernelEnv
+ Futhark.CodeGen.ImpGen.GPU.Base: Locking :: VName -> TExp Int32 -> TExp Int32 -> TExp Int32 -> ([TExp Int64] -> [TExp Int64]) -> Locking
+ Futhark.CodeGen.ImpGen.GPU.Base: Locks :: VName -> Int -> Locks
+ Futhark.CodeGen.ImpGen.GPU.Base: OpenCL :: Target
+ Futhark.CodeGen.ImpGen.GPU.Base: [hostAtomics] :: HostEnv -> AtomicBinOp
+ Futhark.CodeGen.ImpGen.GPU.Base: [hostLocks] :: HostEnv -> Map VName Locks
+ Futhark.CodeGen.ImpGen.GPU.Base: [hostTarget] :: HostEnv -> Target
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelAtomics] :: KernelEnv -> AtomicBinOp
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelConstants] :: KernelEnv -> KernelConstants
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelGlobalThreadIdVar] :: KernelConstants -> VName
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelGlobalThreadId] :: KernelConstants -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelGroupIdVar] :: KernelConstants -> VName
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelGroupId] :: KernelConstants -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelGroupSize] :: KernelConstants -> TExp Int64
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelLocalIdMap] :: KernelConstants -> Map [SubExp] [TExp Int32]
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelLocalThreadIdVar] :: KernelConstants -> VName
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelLocalThreadId] :: KernelConstants -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelLocks] :: KernelEnv -> Map VName Locks
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelNumGroups] :: KernelConstants -> TExp Int64
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelNumThreads] :: KernelConstants -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelThreadActive] :: KernelConstants -> TExp Bool
+ Futhark.CodeGen.ImpGen.GPU.Base: [kernelWaveSize] :: KernelConstants -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [lockingArray] :: Locking -> VName
+ Futhark.CodeGen.ImpGen.GPU.Base: [lockingIsUnlocked] :: Locking -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [lockingMapping] :: Locking -> [TExp Int64] -> [TExp Int64]
+ Futhark.CodeGen.ImpGen.GPU.Base: [lockingToLock] :: Locking -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [lockingToUnlock] :: Locking -> TExp Int32
+ Futhark.CodeGen.ImpGen.GPU.Base: [locksArray] :: Locks -> VName
+ Futhark.CodeGen.ImpGen.GPU.Base: [locksCount] :: Locks -> Int
+ Futhark.CodeGen.ImpGen.GPU.Base: atomicUpdateLocking :: AtomicBinOp -> Lambda GPUMem -> AtomicUpdate GPUMem KernelEnv
+ Futhark.CodeGen.ImpGen.GPU.Base: compileGroupResult :: SegSpace -> PatElem GPUMem -> KernelResult -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: compileThreadResult :: SegSpace -> PatElem GPUMem -> KernelResult -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: computeThreadChunkSize :: SplitOrdering -> TExp Int64 -> Count Elements (TExp Int64) -> Count Elements (TExp Int64) -> TV Int64 -> ImpM rep r op ()
+ Futhark.CodeGen.ImpGen.GPU.Base: data AtomicUpdate rep r
+ Futhark.CodeGen.ImpGen.GPU.Base: data HostEnv
+ Futhark.CodeGen.ImpGen.GPU.Base: data KernelConstants
+ Futhark.CodeGen.ImpGen.GPU.Base: data KernelEnv
+ Futhark.CodeGen.ImpGen.GPU.Base: data Locking
+ Futhark.CodeGen.ImpGen.GPU.Base: data Locks
+ Futhark.CodeGen.ImpGen.GPU.Base: data Target
+ Futhark.CodeGen.ImpGen.GPU.Base: groupCoverSpace :: [TExp Int64] -> ([TExp Int64] -> InKernelGen ()) -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: groupLoop :: TExp Int64 -> (TExp Int64 -> InKernelGen ()) -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: groupReduce :: TExp Int32 -> Lambda GPUMem -> [VName] -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: groupScan :: Maybe (TExp Int32 -> TExp Int32 -> TExp Bool) -> TExp Int64 -> TExp Int64 -> Lambda GPUMem -> [VName] -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: isActive :: [(VName, SubExp)] -> TExp Bool
+ Futhark.CodeGen.ImpGen.GPU.Base: kernelLoop :: IntExp t => TExp t -> TExp t -> TExp t -> (TExp t -> InKernelGen ()) -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: keyWithEntryPoint :: Maybe Name -> Name -> Name
+ Futhark.CodeGen.ImpGen.GPU.Base: precomputeSegOpIDs :: Stms GPUMem -> InKernelGen a -> InKernelGen a
+ Futhark.CodeGen.ImpGen.GPU.Base: sCopy :: CopyCompiler GPUMem HostEnv HostOp
+ Futhark.CodeGen.ImpGen.GPU.Base: sIota :: VName -> TExp Int64 -> Exp -> Exp -> IntType -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: sKernelGroup :: String -> Count NumGroups (TExp Int64) -> Count GroupSize (TExp Int64) -> VName -> InKernelGen () -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: sKernelThread :: String -> Count NumGroups (TExp Int64) -> Count GroupSize (TExp Int64) -> VName -> InKernelGen () -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: sReplicate :: VName -> SubExp -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.Base: type AtomicBinOp = BinOp -> Maybe (VName -> VName -> Count Elements (TExp Int64) -> Exp -> AtomicOp)
+ Futhark.CodeGen.ImpGen.GPU.Base: type CallKernelGen = ImpM GPUMem HostEnv HostOp
+ Futhark.CodeGen.ImpGen.GPU.Base: type DoAtomicUpdate rep r = Space -> [VName] -> [TExp Int64] -> ImpM rep r KernelOp ()
+ Futhark.CodeGen.ImpGen.GPU.Base: type InKernelGen = ImpM GPUMem KernelEnv KernelOp
+ Futhark.CodeGen.ImpGen.GPU.Base: virtualiseGroups :: SegVirt -> TExp Int32 -> (TExp Int32 -> InKernelGen ()) -> InKernelGen ()
+ 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: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.GPU.SegHist.Passage
+ Futhark.CodeGen.ImpGen.GPU.SegHist: instance GHC.Classes.Ord Futhark.CodeGen.ImpGen.GPU.SegHist.Passage
+ Futhark.CodeGen.ImpGen.GPU.SegMap: compileSegMap :: Pattern 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' :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> DoSegBody -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegRed: type DoSegBody = ([(SubExp, [TExp Int64])] -> InKernelGen ()) -> InKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.SegScan: compileSegScan :: Pattern 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.TwoPass: compileSegScan :: Pattern GPUMem -> SegLevel -> SegSpace -> [SegBinOp GPUMem] -> KernelBody GPUMem -> CallKernelGen ()
+ Futhark.CodeGen.ImpGen.GPU.ToOpenCL: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.GPU.ToOpenCL.OpsMode
+ Futhark.CodeGen.ImpGen.GPU.ToOpenCL: kernelsToCUDA :: Program -> Program
+ Futhark.CodeGen.ImpGen.GPU.ToOpenCL: kernelsToOpenCL :: Program -> Program
+ Futhark.CodeGen.ImpGen.GPU.Transpose: TransposeLowHeight :: TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: TransposeLowWidth :: TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: TransposeNormal :: TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: TransposeSmall :: TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: data TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: instance GHC.Classes.Eq Futhark.CodeGen.ImpGen.GPU.Transpose.TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: instance GHC.Classes.Ord Futhark.CodeGen.ImpGen.GPU.Transpose.TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: instance GHC.Show.Show Futhark.CodeGen.ImpGen.GPU.Transpose.TransposeType
+ Futhark.CodeGen.ImpGen.GPU.Transpose: mapTransposeKernel :: String -> Integer -> TransposeArgs -> PrimType -> TransposeType -> Kernel
+ Futhark.CodeGen.ImpGen.GPU.Transpose: type TransposeArgs = (VName, TExp Int32, VName, TExp Int32, TExp Int32, TExp Int32, TExp Int32, TExp Int32, TExp Int32, VName)
+ 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: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.IR.Pretty.PrettyRep (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.ASTRep (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.Aliases: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Aliases.Aliased (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.Aliases: instance (Futhark.IR.Rep.RepTypes rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.IR.Rep.RepTypes (Futhark.IR.Aliases.Aliases rep)
+ Futhark.IR.GPU: Disorder :: StreamOrd
+ Futhark.IR.GPU: Hist :: SubExp -> [HistOp rep] -> Lambda rep -> [VName] -> SOAC rep
+ Futhark.IR.GPU: InOrder :: StreamOrd
+ Futhark.IR.GPU: Parallel :: StreamOrd -> Commutativity -> Lambda rep -> StreamForm rep
+ Futhark.IR.GPU: Reduce :: Commutativity -> Lambda rep -> [SubExp] -> Reduce rep
+ Futhark.IR.GPU: SOACMapper :: (SubExp -> m SubExp) -> (Lambda frep -> m (Lambda trep)) -> (VName -> m VName) -> SOACMapper frep trep m
+ Futhark.IR.GPU: Scan :: Lambda rep -> [SubExp] -> Scan rep
+ Futhark.IR.GPU: Scatter :: SubExp -> Lambda rep -> [VName] -> [(Shape, Int, VName)] -> SOAC rep
+ Futhark.IR.GPU: Screma :: SubExp -> [VName] -> ScremaForm rep -> SOAC rep
+ Futhark.IR.GPU: ScremaForm :: [Scan rep] -> [Reduce rep] -> Lambda rep -> ScremaForm rep
+ Futhark.IR.GPU: Sequential :: StreamForm rep
+ Futhark.IR.GPU: Stream :: SubExp -> [VName] -> StreamForm rep -> [SubExp] -> Lambda rep -> SOAC rep
+ Futhark.IR.GPU: [mapOnSOACLambda] :: SOACMapper frep trep m -> Lambda frep -> m (Lambda trep)
+ Futhark.IR.GPU: [mapOnSOACSubExp] :: SOACMapper frep trep m -> SubExp -> m SubExp
+ Futhark.IR.GPU: [mapOnSOACVName] :: SOACMapper frep trep m -> VName -> m VName
+ Futhark.IR.GPU: [redComm] :: Reduce rep -> Commutativity
+ Futhark.IR.GPU: [redLambda] :: Reduce rep -> Lambda rep
+ Futhark.IR.GPU: [redNeutral] :: Reduce rep -> [SubExp]
+ Futhark.IR.GPU: [scanLambda] :: Scan rep -> Lambda rep
+ Futhark.IR.GPU: [scanNeutral] :: Scan rep -> [SubExp]
+ Futhark.IR.GPU: data GPU
+ Futhark.IR.GPU: data Reduce rep
+ Futhark.IR.GPU: data SOAC rep
+ Futhark.IR.GPU: data SOACMapper frep trep m
+ Futhark.IR.GPU: data Scan rep
+ Futhark.IR.GPU: data ScremaForm rep
+ Futhark.IR.GPU: data StreamForm rep
+ Futhark.IR.GPU: data StreamOrd
+ Futhark.IR.GPU: groupScatterResults :: [(Shape, Int, array)] -> [a] -> [(Shape, array, [([a], a)])]
+ Futhark.IR.GPU: groupScatterResults' :: [(Shape, Int, array)] -> [a] -> [([a], a)]
+ Futhark.IR.GPU: identitySOACMapper :: Monad m => SOACMapper rep rep m
+ 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: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.IR.Prop.ASTRep Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.IR.Rep.RepTypes Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.IR.SegOp.HasSegOp Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.TypeCheck.Checkable Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: instance Futhark.TypeCheck.CheckableOp Futhark.IR.GPU.GPU
+ Futhark.IR.GPU: isIdentityLambda :: Lambda rep -> Bool
+ Futhark.IR.GPU: isMapSOAC :: ScremaForm rep -> Maybe (Lambda rep)
+ Futhark.IR.GPU: isRedomapSOAC :: ScremaForm rep -> Maybe ([Reduce rep], Lambda rep)
+ Futhark.IR.GPU: isReduceSOAC :: ScremaForm rep -> Maybe [Reduce rep]
+ Futhark.IR.GPU: isScanSOAC :: ScremaForm rep -> Maybe [Scan rep]
+ Futhark.IR.GPU: isScanomapSOAC :: ScremaForm rep -> Maybe ([Scan rep], Lambda rep)
+ Futhark.IR.GPU: mapSOAC :: Lambda rep -> ScremaForm rep
+ Futhark.IR.GPU: mapSOACM :: (Applicative m, Monad m) => SOACMapper frep trep m -> SOAC frep -> m (SOAC trep)
+ Futhark.IR.GPU: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
+ Futhark.IR.GPU: nilFn :: Bindable rep => Lambda rep
+ Futhark.IR.GPU: ppHist :: (PrettyRep rep, Pretty inp) => SubExp -> [HistOp rep] -> Lambda rep -> [inp] -> Doc
+ Futhark.IR.GPU: ppScrema :: (PrettyRep rep, Pretty inp) => SubExp -> [inp] -> ScremaForm rep -> Doc
+ Futhark.IR.GPU: redResults :: [Reduce rep] -> Int
+ Futhark.IR.GPU: redomapSOAC :: [Reduce rep] -> Lambda rep -> ScremaForm rep
+ Futhark.IR.GPU: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
+ Futhark.IR.GPU: scanResults :: [Scan rep] -> Int
+ Futhark.IR.GPU: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
+ Futhark.IR.GPU: scanomapSOAC :: [Scan rep] -> Lambda rep -> ScremaForm rep
+ Futhark.IR.GPU: scremaType :: SubExp -> ScremaForm rep -> [Type]
+ Futhark.IR.GPU: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
+ Futhark.IR.GPU: singleScan :: Bindable rep => [Scan rep] -> Scan rep
+ Futhark.IR.GPU: soacType :: SOAC rep -> [Type]
+ Futhark.IR.GPU: splitScatterResults :: [(Shape, Int, array)] -> [a] -> ([a], [a])
+ Futhark.IR.GPU: typeCheckSOAC :: Checkable rep => SOAC (Aliases rep) -> TypeM rep ()
+ 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: data GPU
+ Futhark.IR.GPU.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPU.GPU)
+ Futhark.IR.GPU.Simplify: instance Futhark.IR.SOACS.Simplify.HasSOAC (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPU.GPU)
+ Futhark.IR.GPU.Simplify: instance Futhark.IR.SegOp.HasSegOp (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.GPU.GPU)
+ Futhark.IR.GPU.Simplify: simplifyGPU :: Prog GPU -> PassM (Prog GPU)
+ Futhark.IR.GPU.Simplify: simplifyKernelOp :: (SimplifiableRep rep, BodyDec rep ~ ()) => SimplifyOp rep op -> HostOp rep op -> SimpleM rep (HostOp (Wise rep) (OpWithWisdom op), Stms (Wise rep))
+ Futhark.IR.GPU.Simplify: simplifyLambda :: (HasScope GPU m, MonadFreshNames m) => Lambda GPU -> m (Lambda GPU)
+ Futhark.IR.GPU.Sizes: Count :: e -> Count u e
+ Futhark.IR.GPU.Sizes: SizeBespoke :: Name -> Int64 -> SizeClass
+ Futhark.IR.GPU.Sizes: SizeGroup :: SizeClass
+ Futhark.IR.GPU.Sizes: SizeLocalMemory :: SizeClass
+ Futhark.IR.GPU.Sizes: SizeNumGroups :: SizeClass
+ Futhark.IR.GPU.Sizes: SizeRegTile :: SizeClass
+ Futhark.IR.GPU.Sizes: SizeThreshold :: KernelPath -> Maybe Int64 -> SizeClass
+ Futhark.IR.GPU.Sizes: SizeTile :: SizeClass
+ Futhark.IR.GPU.Sizes: [unCount] :: Count u e -> e
+ Futhark.IR.GPU.Sizes: data GroupSize
+ Futhark.IR.GPU.Sizes: data NumGroups
+ Futhark.IR.GPU.Sizes: data NumThreads
+ Futhark.IR.GPU.Sizes: data SizeClass
+ Futhark.IR.GPU.Sizes: instance Data.Foldable.Foldable (Futhark.IR.GPU.Sizes.Count u)
+ Futhark.IR.GPU.Sizes: instance Data.Traversable.Traversable (Futhark.IR.GPU.Sizes.Count u)
+ Futhark.IR.GPU.Sizes: instance Futhark.IR.Prop.Names.FreeIn e => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance Futhark.Transform.Substitute.Substitute e => Futhark.Transform.Substitute.Substitute (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance Futhark.Util.IntegralExp.IntegralExp e => Futhark.Util.IntegralExp.IntegralExp (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance GHC.Base.Functor (Futhark.IR.GPU.Sizes.Count u)
+ Futhark.IR.GPU.Sizes: instance GHC.Classes.Eq Futhark.IR.GPU.Sizes.SizeClass
+ Futhark.IR.GPU.Sizes: instance GHC.Classes.Eq e => GHC.Classes.Eq (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance GHC.Classes.Ord Futhark.IR.GPU.Sizes.SizeClass
+ Futhark.IR.GPU.Sizes: instance GHC.Classes.Ord e => GHC.Classes.Ord (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance GHC.Num.Num e => GHC.Num.Num (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance GHC.Show.Show Futhark.IR.GPU.Sizes.SizeClass
+ Futhark.IR.GPU.Sizes: instance GHC.Show.Show e => GHC.Show.Show (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.GPU.Sizes.SizeClass
+ Futhark.IR.GPU.Sizes: instance Text.PrettyPrint.Mainland.Class.Pretty e => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.GPU.Sizes.Count u e)
+ Futhark.IR.GPU.Sizes: newtype Count u e
+ Futhark.IR.GPU.Sizes: sizeDefault :: SizeClass -> Maybe Int64
+ Futhark.IR.GPU.Sizes: type KernelPath = [(Name, Bool)]
+ Futhark.IR.GPUMem: data GPUMem
+ 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.GPUMem: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: instance Futhark.IR.Prop.ASTRep Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: instance Futhark.IR.Rep.RepTypes Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: instance Futhark.TypeCheck.Checkable Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: instance Futhark.TypeCheck.CheckableOp Futhark.IR.GPUMem.GPUMem
+ Futhark.IR.GPUMem: simpleGPUMem :: SimpleOps GPUMem
+ Futhark.IR.GPUMem: simplifyProg :: Prog GPUMem -> PassM (Prog GPUMem)
+ Futhark.IR.GPUMem: simplifyStms :: (HasScope GPUMem m, MonadFreshNames m) => Stms GPUMem -> m (SymbolTable (Wise GPUMem), Stms GPUMem)
+ Futhark.IR.MC: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MC.MC)
+ Futhark.IR.MC: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.MC.MC
+ Futhark.IR.MC: instance Futhark.IR.Prop.ASTRep Futhark.IR.MC.MC
+ Futhark.IR.MC: instance Futhark.IR.Rep.RepTypes Futhark.IR.MC.MC
+ Futhark.IR.MC: instance Futhark.IR.SegOp.HasSegOp (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MC.MC)
+ Futhark.IR.MC.Op: instance (Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Rep.Op rep), Futhark.Analysis.Metrics.OpMetrics op) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Pretty.PrettyRep rep, Text.PrettyPrint.Mainland.Class.Pretty op) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Analysis.SymbolTable.IndexOp op) => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.IsOp op) => Futhark.IR.Prop.IsOp (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Names.FreeIn op) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Rename.Rename op) => Futhark.Transform.Rename.Rename (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Substitute.Substitute op) => Futhark.Transform.Substitute.Substitute (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.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.MC.Op.MCOp rep op)
+ Futhark.IR.MC.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.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Eq op) => GHC.Classes.Eq (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Ord op) => GHC.Classes.Ord (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance (Futhark.IR.Rep.RepTypes rep, GHC.Show.Show op) => GHC.Show.Show (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MC.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.MC.Op.MCOp rep op)
+ Futhark.IR.MC.Op: instance Futhark.IR.Prop.TypeOf.TypedOp op => Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.IR.MCMem: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.MCMem.MCMem)
+ Futhark.IR.MCMem: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.MCMem.MCMem
+ Futhark.IR.MCMem: instance Futhark.IR.Prop.ASTRep Futhark.IR.MCMem.MCMem
+ Futhark.IR.MCMem: instance Futhark.IR.Rep.RepTypes Futhark.IR.MCMem.MCMem
+ Futhark.IR.Mem: instance Futhark.Optimise.Simplify.Rep.CanBeWise inner => Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Mem.MemOp inner)
+ Futhark.IR.Parse: parseGPU :: FilePath -> Text -> Either Text (Prog GPU)
+ Futhark.IR.Parse: parseGPUMem :: FilePath -> Text -> Either Text (Prog GPUMem)
+ Futhark.IR.Pretty: class (RepTypes rep, Pretty (RetType rep), Pretty (BranchType rep), Pretty (FParamInfo rep), Pretty (LParamInfo rep), Pretty (LetDec rep), Pretty (Op rep)) => PrettyRep rep
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Body rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Exp rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Lambda rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Prog rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Pretty: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.Syntax.Stms rep)
+ Futhark.IR.Pretty: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.IR.Syntax.Core.Commutativity
+ Futhark.IR.Pretty: ppExpDec :: PrettyRep rep => ExpDec rep -> Exp rep -> Maybe Doc
+ Futhark.IR.Prop: class (RepTypes rep, PrettyRep rep, Renameable rep, Substitutable rep, FreeDec (ExpDec rep), FreeIn (LetDec rep), FreeDec (BodyDec rep), FreeIn (FParamInfo rep), FreeIn (LParamInfo rep), FreeIn (RetType rep), FreeIn (BranchType rep), IsOp (Op rep)) => ASTRep rep
+ Futhark.IR.Prop: lamIsBinOp :: ASTRep rep => Lambda rep -> Maybe [(BinOp, PrimType, VName, VName)]
+ Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.ExpDec rep), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.BodyDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.FParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LetDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.RetType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.BranchType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Body rep)
+ Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.ExpDec rep), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.BodyDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.FParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LetDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.RetType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.BranchType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Exp rep)
+ Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.ExpDec rep), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.BodyDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.FParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LetDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.RetType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.BranchType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.ExpDec rep), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.BodyDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.FParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LetDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.RetType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.BranchType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Lambda rep)
+ Futhark.IR.Prop.Names: instance (Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.ExpDec rep), Futhark.IR.Prop.Names.FreeDec (Futhark.IR.Rep.BodyDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.FParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LetDec rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.RetType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.BranchType rep), Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.LoopForm rep)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stm rep) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.Stms rep)
+ Futhark.IR.Prop.Patterns: setPatElemDec :: PatElemT oldattr -> newattr -> PatElemT newattr
+ Futhark.IR.Prop.Scope: instance (Futhark.IR.Prop.Scope.HasScope rep m, GHC.Base.Monad m) => Futhark.IR.Prop.Scope.HasScope rep (Futhark.IR.Prop.Scope.ExtendedScope rep m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.HasScope rep (Control.Monad.Trans.Reader.ReaderT (Futhark.IR.Prop.Scope.Scope rep) m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.LocalScope rep (Control.Monad.Trans.Reader.ReaderT (Futhark.IR.Prop.Scope.Scope rep) m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.HasScope rep (Control.Monad.Trans.RWS.Lazy.RWST (Futhark.IR.Prop.Scope.Scope rep) w s m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.HasScope rep (Control.Monad.Trans.RWS.Strict.RWST (Futhark.IR.Prop.Scope.Scope rep) w s m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.LocalScope rep (Control.Monad.Trans.RWS.Lazy.RWST (Futhark.IR.Prop.Scope.Scope rep) w s m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Applicative m, GHC.Base.Monad m, GHC.Base.Monoid w, Futhark.IR.Rep.RepTypes rep) => Futhark.IR.Prop.Scope.LocalScope rep (Control.Monad.Trans.RWS.Strict.RWST (Futhark.IR.Prop.Scope.Scope rep) w s m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Monad m, Futhark.IR.Prop.Scope.HasScope rep m) => Futhark.IR.Prop.Scope.HasScope rep (Control.Monad.Trans.Except.ExceptT e m)
+ Futhark.IR.Prop.Scope: instance (GHC.Base.Monad m, Futhark.IR.Prop.Scope.LocalScope rep m) => Futhark.IR.Prop.Scope.LocalScope rep (Control.Monad.Trans.Except.ExceptT e m)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Futhark.IR.Syntax.Lambda rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Futhark.IR.Syntax.LoopForm rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Futhark.IR.Syntax.Stms rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep (Language.Futhark.Core.VName, Futhark.IR.Prop.Scope.NameInfo rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Prop.Scope.Scoped rep a => Futhark.IR.Prop.Scope.Scoped rep [a]
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Rep.RepTypes rep => Futhark.IR.Prop.Types.Typed (Futhark.IR.Prop.Scope.NameInfo rep)
+ Futhark.IR.Prop.Scope: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Prop.Scope.NameInfo rep)
+ Futhark.IR.Prop.Scope: instance GHC.Base.Applicative m => GHC.Base.Applicative (Futhark.IR.Prop.Scope.ExtendedScope rep m)
+ Futhark.IR.Prop.Scope: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.IR.Prop.Scope.ExtendedScope rep m)
+ Futhark.IR.Prop.Scope: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Futhark.IR.Prop.Scope.Scope rep) (Futhark.IR.Prop.Scope.ExtendedScope rep m)
+ Futhark.IR.Prop.Scope: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.IR.Prop.Scope.ExtendedScope rep m)
+ Futhark.IR.Prop.TypeOf: instance Futhark.IR.Rep.RepTypes rep => Futhark.IR.Prop.Scope.HasScope rep (Futhark.IR.Prop.TypeOf.FeelBad rep)
+ Futhark.IR.Prop.TypeOf: instance GHC.Base.Applicative (Futhark.IR.Prop.TypeOf.FeelBad rep)
+ Futhark.IR.Prop.TypeOf: instance GHC.Base.Functor (Futhark.IR.Prop.TypeOf.FeelBad rep)
+ Futhark.IR.Rep: -- | Extensible operation.
+ Futhark.IR.Rep: class (Show (LetDec l), Show (ExpDec l), Show (BodyDec l), Show (FParamInfo l), Show (LParamInfo l), Show (RetType l), Show (BranchType l), Show (Op l), Eq (LetDec l), Eq (ExpDec l), Eq (BodyDec l), Eq (FParamInfo l), Eq (LParamInfo l), Eq (RetType l), Eq (BranchType l), Eq (Op l), Ord (LetDec l), Ord (ExpDec l), Ord (BodyDec l), Ord (FParamInfo l), Ord (LParamInfo l), Ord (RetType l), Ord (BranchType l), Ord (Op l), IsRetType (RetType l), IsBodyType (BranchType l), Typed (FParamInfo l), Typed (LParamInfo l), Typed (LetDec l), DeclTyped (FParamInfo l)) => RepTypes l where {
+ Futhark.IR.Rep: type BodyDec l = ();
+ Futhark.IR.Rep: type BranchType l = ExtType;
+ Futhark.IR.Rep: type ExpDec l = ();
+ Futhark.IR.Rep: type FParamInfo l = DeclType;
+ Futhark.IR.Rep: type LParamInfo l = Type;
+ Futhark.IR.Rep: type LetDec l = Type;
+ Futhark.IR.Rep: type Op l = ();
+ Futhark.IR.Rep: type RetType l = DeclExtType;
+ Futhark.IR.Rep: type family Op l :: Type;
+ Futhark.IR.Rep: }
+ Futhark.IR.SOACS: class (Show (LetDec l), Show (ExpDec l), Show (BodyDec l), Show (FParamInfo l), Show (LParamInfo l), Show (RetType l), Show (BranchType l), Show (Op l), Eq (LetDec l), Eq (ExpDec l), Eq (BodyDec l), Eq (FParamInfo l), Eq (LParamInfo l), Eq (RetType l), Eq (BranchType l), Eq (Op l), Ord (LetDec l), Ord (ExpDec l), Ord (BodyDec l), Ord (FParamInfo l), Ord (LParamInfo l), Ord (RetType l), Ord (BranchType l), Ord (Op l), IsRetType (RetType l), IsBodyType (BranchType l), Typed (FParamInfo l), Typed (LParamInfo l), Typed (LetDec l), DeclTyped (FParamInfo l)) => RepTypes l where {
+ Futhark.IR.SOACS: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.SOACS.SOACS
+ Futhark.IR.SOACS: instance Futhark.IR.Prop.ASTRep Futhark.IR.SOACS.SOACS
+ Futhark.IR.SOACS: instance Futhark.IR.Rep.RepTypes Futhark.IR.SOACS.SOACS
+ Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.ASTRep (Futhark.IR.Aliases.Aliases rep), Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.Aliased rep) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Rep.Op rep) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.Reduce rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SOACS.SOAC.Scan rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.IsOp (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTRep rep => Futhark.Transform.Rename.Rename (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.ASTRep rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.HistOp rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.Reduce rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.Scan rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.ScremaForm rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SOACS.SOAC.StreamForm rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.HistOp rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.Reduce rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.Scan rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.ScremaForm rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SOACS.SOAC.StreamForm rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.HistOp rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.Reduce rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.SOAC rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.Scan rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.ScremaForm rep)
+ Futhark.IR.SOACS.SOAC: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SOACS.SOAC.StreamForm rep)
+ Futhark.IR.SOACS.Simplify: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SOACS.SOACS)
+ Futhark.IR.SOACS.Simplify: instance Futhark.IR.SOACS.Simplify.HasSOAC (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.SOACS.SOACS)
+ Futhark.IR.SegOp: [kernelBodyDec] :: KernelBody rep -> BodyDec rep
+ Futhark.IR.SegOp: instance (Futhark.IR.Pretty.PrettyRep rep, Text.PrettyPrint.Mainland.Class.Pretty lvl) => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.IsOp (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.Transform.Rename.Rename (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.ASTRep (Futhark.IR.Aliases.Aliases rep), Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep), Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.Aliased rep, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.IR.Prop.Aliases.AliasedOp (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Rep.LParamInfo rep), Futhark.IR.Prop.Names.FreeIn lvl) => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Transform.Substitute.Substitute lvl) => Futhark.Transform.Substitute.Substitute (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Eq lvl) => GHC.Classes.Eq (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Rep.RepTypes rep, GHC.Classes.Ord lvl) => GHC.Classes.Ord (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.IR.Rep.RepTypes rep, GHC.Show.Show lvl) => GHC.Show.Show (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance (Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep), Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.ASTConstraints lvl) => Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.Rep.Op rep) => Futhark.Analysis.Metrics.OpMetrics (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Pretty.PrettyRep rep => Text.PrettyPrint.Mainland.Class.Pretty (Futhark.IR.SegOp.SegBinOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTRep rep => Futhark.Analysis.SymbolTable.IndexOp (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTRep rep => Futhark.Transform.Rename.Rename (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Prop.ASTRep rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Prop.TypeOf.TypedOp (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SegOp.HistOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.SegOp.SegBinOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SegOp.HistOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.SegOp.SegBinOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SegOp.HistOp rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SegOp.KernelBody rep)
+ Futhark.IR.SegOp: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.SegOp.SegBinOp rep)
+ Futhark.IR.SegOp: segBody :: SegOp lvl rep -> KernelBody rep
+ Futhark.IR.Seq: instance Futhark.Binder.BinderOps (Futhark.Optimise.Simplify.Rep.Wise Futhark.IR.Seq.Seq)
+ Futhark.IR.Seq: instance Futhark.IR.Pretty.PrettyRep Futhark.IR.Seq.Seq
+ Futhark.IR.Seq: instance Futhark.IR.Prop.ASTRep Futhark.IR.Seq.Seq
+ Futhark.IR.Seq: instance Futhark.IR.Rep.RepTypes 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.IR.Pretty.PrettyRep Futhark.IR.SeqMem.SeqMem
+ Futhark.IR.SeqMem: instance Futhark.IR.Prop.ASTRep Futhark.IR.SeqMem.SeqMem
+ Futhark.IR.SeqMem: instance Futhark.IR.Rep.RepTypes Futhark.IR.SeqMem.SeqMem
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.BodyT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.ExpT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.LambdaT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.LoopForm rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.Prog rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Eq (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.BodyT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.ExpT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.LambdaT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.LoopForm rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.Prog rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Classes.Ord (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.BodyT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.ExpT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.FunDef rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.LambdaT rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.LoopForm rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.Prog rep)
+ Futhark.IR.Syntax: instance Futhark.IR.Rep.RepTypes rep => GHC.Show.Show (Futhark.IR.Syntax.Stm rep)
+ Futhark.IR.Syntax: pretty :: Pretty a => a -> String
+ Futhark.IR.Syntax.Core: Commutative :: Commutativity
+ Futhark.IR.Syntax.Core: Noncommutative :: Commutativity
+ Futhark.IR.Syntax.Core: data Commutativity
+ Futhark.IR.Syntax.Core: instance GHC.Base.Monoid Futhark.IR.Syntax.Core.Commutativity
+ Futhark.IR.Syntax.Core: instance GHC.Base.Semigroup Futhark.IR.Syntax.Core.Commutativity
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Eq Futhark.IR.Syntax.Core.Commutativity
+ Futhark.IR.Syntax.Core: instance GHC.Classes.Ord Futhark.IR.Syntax.Core.Commutativity
+ Futhark.IR.Syntax.Core: instance GHC.Show.Show Futhark.IR.Syntax.Core.Commutativity
+ 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 (Futhark.IR.SegOp.SegOp lvl rep)
+ 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.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.MC.Op.MCOp rep op)
+ Futhark.Optimise.CSE: instance (Futhark.IR.Prop.ASTRep rep, Futhark.IR.Prop.Aliases.CanBeAliased (Futhark.IR.Rep.Op rep), Futhark.Optimise.CSE.CSEInOp (Futhark.IR.Prop.Aliases.OpWithAliases (Futhark.IR.Rep.Op rep))) => Futhark.Optimise.CSE.CSEInOp (Futhark.IR.SOACS.SOAC.SOAC (Futhark.IR.Aliases.Aliases rep))
+ Futhark.Optimise.DoubleBuffer: doubleBufferGPU :: Pass GPUMem GPUMem
+ Futhark.Optimise.DoubleBuffer: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.DoubleBuffer.Env rep) (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance GHC.Base.Applicative (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance GHC.Base.Functor (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.DoubleBuffer: instance GHC.Base.Monad (Futhark.Optimise.DoubleBuffer.DoubleBufferM rep)
+ Futhark.Optimise.InPlaceLowering: inPlaceLoweringGPU :: Pass GPU GPU
+ Futhark.Optimise.InPlaceLowering: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.InPlaceLowering.TopDown rep) (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance Control.Monad.State.Class.MonadState Futhark.FreshNames.VNameSource (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance Control.Monad.Writer.Class.MonadWriter (Futhark.Optimise.InPlaceLowering.BottomUp rep) (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance Futhark.Optimise.InPlaceLowering.Constraints rep => Futhark.IR.Prop.Scope.HasScope (Futhark.IR.Aliases.Aliases rep) (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance GHC.Base.Applicative (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance GHC.Base.Functor (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance GHC.Base.Monad (Futhark.Optimise.InPlaceLowering.ForwardingM rep)
+ Futhark.Optimise.InPlaceLowering: instance GHC.Base.Monoid (Futhark.Optimise.InPlaceLowering.BottomUp rep)
+ Futhark.Optimise.InPlaceLowering: instance GHC.Base.Semigroup (Futhark.Optimise.InPlaceLowering.BottomUp rep)
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdateGPU :: MonadFreshNames m => LowerUpdate GPU m
+ Futhark.Optimise.ReuseAllocations: optimise :: Pass GPUMem GPUMem
+ Futhark.Optimise.ReuseAllocations.GreedyColoring: colorGraph :: (Ord a, Ord space) => Map a space -> Graph a -> (Map Int space, Coloring a)
+ Futhark.Optimise.ReuseAllocations.GreedyColoring: type Coloring a = Map a Int
+ 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.Engine: instance Control.Monad.Reader.Class.MonadReader (Futhark.Optimise.Simplify.Engine.SimpleOps rep, Futhark.Optimise.Simplify.Engine.Env rep) (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ 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.MonadFreshNames.MonadFreshNames (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.SimplifiableRep rep => Futhark.IR.Prop.Scope.HasScope (Futhark.Optimise.Simplify.Rep.Wise rep) (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance Futhark.Optimise.Simplify.Engine.SimplifiableRep rep => Futhark.IR.Prop.Scope.LocalScope (Futhark.Optimise.Simplify.Rep.Wise rep) (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance GHC.Base.Applicative (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance GHC.Base.Functor (Futhark.Optimise.Simplify.Engine.SimpleM rep)
+ Futhark.Optimise.Simplify.Engine: instance GHC.Base.Monad (Futhark.Optimise.Simplify.Engine.SimpleM 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.Rep: VarWisdom :: VarAliases -> VarWisdom
+ Futhark.Optimise.Simplify.Rep: [varWisdomAliases] :: VarWisdom -> VarAliases
+ Futhark.Optimise.Simplify.Rep: addScopeWisdom :: Scope rep -> Scope (Wise rep)
+ Futhark.Optimise.Simplify.Rep: addWisdomToPattern :: (ASTRep rep, CanBeWise (Op rep)) => Pattern rep -> Exp (Wise rep) -> Pattern (Wise rep)
+ Futhark.Optimise.Simplify.Rep: class (AliasedOp (OpWithWisdom op), IsOp (OpWithWisdom op)) => CanBeWise op where {
+ Futhark.Optimise.Simplify.Rep: data ExpWisdom
+ Futhark.Optimise.Simplify.Rep: data 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: instance (Futhark.IR.Pretty.PrettyRep rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.IR.Pretty.PrettyRep (Futhark.Optimise.Simplify.Rep.Wise rep)
+ Futhark.Optimise.Simplify.Rep: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.ASTRep (Futhark.Optimise.Simplify.Rep.Wise rep)
+ Futhark.Optimise.Simplify.Rep: instance (Futhark.IR.Prop.ASTRep rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.IR.Prop.Aliases.Aliased (Futhark.Optimise.Simplify.Rep.Wise rep)
+ Futhark.Optimise.Simplify.Rep: instance (Futhark.IR.Rep.RepTypes rep, Futhark.Optimise.Simplify.Rep.CanBeWise (Futhark.IR.Rep.Op rep)) => Futhark.IR.Rep.RepTypes (Futhark.Optimise.Simplify.Rep.Wise rep)
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Aliases.AliasesOf (Futhark.Optimise.Simplify.Rep.VarWisdom, dec)
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Names.FreeDec Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Names.FreeDec Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.IR.Prop.Names.FreeIn Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Optimise.Simplify.Rep.CanBeWise ()
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Rename.Rename Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance Futhark.Transform.Substitute.Substitute Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Eq Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Classes.Ord Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Show.Show Futhark.Optimise.Simplify.Rep.BodyWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Show.Show Futhark.Optimise.Simplify.Rep.ExpWisdom
+ Futhark.Optimise.Simplify.Rep: instance GHC.Show.Show Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Optimise.Simplify.Rep.VarWisdom
+ Futhark.Optimise.Simplify.Rep: mkWiseBody :: (ASTRep rep, CanBeWise (Op rep)) => BodyDec rep -> Stms (Wise rep) -> Result -> Body (Wise 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: mkWiseLetStm :: (ASTRep rep, CanBeWise (Op rep)) => Pattern rep -> StmAux (ExpDec rep) -> Exp (Wise rep) -> Stm (Wise rep)
+ Futhark.Optimise.Simplify.Rep: newtype VarWisdom
+ Futhark.Optimise.Simplify.Rep: removeBodyWisdom :: CanBeWise (Op rep) => Body (Wise rep) -> Body rep
+ Futhark.Optimise.Simplify.Rep: removeExpWisdom :: CanBeWise (Op rep) => Exp (Wise rep) -> Exp rep
+ Futhark.Optimise.Simplify.Rep: removeFunDefWisdom :: CanBeWise (Op rep) => FunDef (Wise rep) -> FunDef rep
+ Futhark.Optimise.Simplify.Rep: removeLambdaWisdom :: CanBeWise (Op rep) => Lambda (Wise rep) -> Lambda rep
+ Futhark.Optimise.Simplify.Rep: removeOpWisdom :: CanBeWise op => OpWithWisdom op -> op
+ Futhark.Optimise.Simplify.Rep: removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a
+ Futhark.Optimise.Simplify.Rep: removeScopeWisdom :: Scope (Wise rep) -> Scope rep
+ Futhark.Optimise.Simplify.Rep: removeStmWisdom :: CanBeWise (Op rep) => Stm (Wise rep) -> Stm rep
+ Futhark.Optimise.Simplify.Rep: type family OpWithWisdom op :: Type;
+ Futhark.Optimise.Simplify.Rep: }
+ 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.Optimise.Simplify.Rule: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance Futhark.IR.Prop.ASTRep rep => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance Futhark.MonadFreshNames.MonadFreshNames (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Applicative (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Functor (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monad (Futhark.Optimise.Simplify.Rule.RuleM rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monoid (Futhark.Optimise.Simplify.Rule.RuleBook rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Monoid (Futhark.Optimise.Simplify.Rule.Rules rep a)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Semigroup (Futhark.Optimise.Simplify.Rule.RuleBook rep)
+ Futhark.Optimise.Simplify.Rule: instance GHC.Base.Semigroup (Futhark.Optimise.Simplify.Rule.Rules rep a)
+ Futhark.Optimise.Sink: sinkGPU :: Pass GPU GPU
+ Futhark.Optimise.TileLoops.Shared: segMap1D :: String -> SegLevel -> ResultManifest -> (VName -> Binder GPU [SubExp]) -> Binder GPU [VName]
+ Futhark.Optimise.Unstream: unstreamGPU :: Pass GPU GPU
+ Futhark.Pass.ExpandAllocations: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.GPUMem.GPUMem Futhark.Pass.ExpandAllocations.OffsetM
+ Futhark.Pass.ExpandAllocations: instance Futhark.IR.Prop.Scope.LocalScope Futhark.IR.GPUMem.GPUMem Futhark.Pass.ExpandAllocations.OffsetM
+ 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.Reader.Class.MonadReader (Futhark.Pass.ExplicitAllocations.AllocEnv fromrep torep) (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.Prop.ASTRep torep => Futhark.IR.Prop.Scope.HasScope torep (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
+ Futhark.Pass.ExplicitAllocations: instance Futhark.IR.Prop.ASTRep torep => Futhark.IR.Prop.Scope.LocalScope torep (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
+ 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.AllocM fromrep torep)
+ 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.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.AllocM fromrep torep)
+ Futhark.Pass.ExplicitAllocations: instance GHC.Base.Functor (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
+ Futhark.Pass.ExplicitAllocations: instance GHC.Base.Monad (Futhark.Pass.ExplicitAllocations.AllocM fromrep torep)
+ Futhark.Pass.ExplicitAllocations: instance GHC.Base.Monad (Futhark.Pass.ExplicitAllocations.PatAllocM rep)
+ Futhark.Pass.ExplicitAllocations.GPU: explicitAllocations :: Pass GPU GPUMem
+ Futhark.Pass.ExplicitAllocations.GPU: explicitAllocationsInStms :: (MonadFreshNames m, HasScope GPUMem m) => Stms GPU -> m (Stms GPUMem)
+ Futhark.Pass.ExplicitAllocations.GPU: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.GPU.Kernel.HostOp rep op)
+ Futhark.Pass.ExplicitAllocations.MC: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.MC.Op.MCOp rep op)
+ Futhark.Pass.ExplicitAllocations.SegOp: instance Futhark.Pass.ExplicitAllocations.SizeSubst (Futhark.IR.SegOp.SegOp lvl rep)
+ Futhark.Pass.ExtractKernels: instance Futhark.IR.Prop.Scope.HasScope Futhark.IR.GPU.GPU Futhark.Pass.ExtractKernels.DistribM
+ Futhark.Pass.ExtractKernels: instance Futhark.IR.Prop.Scope.LocalScope Futhark.IR.GPU.GPU Futhark.Pass.ExtractKernels.DistribM
+ 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.DistributeNests: instance (GHC.Base.Monad m, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Scope.HasScope rep (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance (GHC.Base.Monad m, Futhark.IR.Prop.ASTRep rep) => Futhark.IR.Prop.Scope.LocalScope rep (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance Futhark.MonadFreshNames.MonadFreshNames m => Futhark.MonadFreshNames.MonadFreshNames (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Applicative m => GHC.Base.Applicative (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Functor m => GHC.Base.Functor (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Futhark.Pass.ExtractKernels.DistributeNests.DistEnv rep m) (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Control.Monad.Writer.Class.MonadWriter (Futhark.Pass.ExtractKernels.DistributeNests.DistRes rep) (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => Futhark.Util.Log.MonadLogger (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monad m => GHC.Base.Monad (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT rep m)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monoid (Futhark.Pass.ExtractKernels.DistributeNests.DistRes rep)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Monoid (Futhark.Pass.ExtractKernels.DistributeNests.PostStms rep)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Semigroup (Futhark.Pass.ExtractKernels.DistributeNests.DistRes rep)
+ Futhark.Pass.ExtractKernels.DistributeNests: instance GHC.Base.Semigroup (Futhark.Pass.ExtractKernels.DistributeNests.PostStms rep)
+ Futhark.Pass.ExtractKernels.ToGPU: getSize :: (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SizeClass -> m SubExp
+ Futhark.Pass.ExtractKernels.ToGPU: injectSOACS :: (Monad m, SameScope from to, ExpDec from ~ ExpDec to, BodyDec from ~ BodyDec to, RetType from ~ RetType to, BranchType from ~ BranchType to, Op from ~ SOAC from) => (SOAC to -> Op to) -> Rephraser m from to
+ Futhark.Pass.ExtractKernels.ToGPU: scopeForGPU :: Scope SOACS -> Scope GPU
+ Futhark.Pass.ExtractKernels.ToGPU: scopeForSOACs :: Scope GPU -> Scope SOACS
+ Futhark.Pass.ExtractKernels.ToGPU: segThread :: (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> m SegLevel
+ Futhark.Pass.ExtractKernels.ToGPU: soacsLambdaToGPU :: Lambda SOACS -> Lambda GPU
+ Futhark.Pass.ExtractKernels.ToGPU: soacsStmToGPU :: Stm SOACS -> Stm GPU
+ Futhark.Pass.Simplify: simplifyGPU :: Pass GPU GPU
+ Futhark.Pass.Simplify: simplifyGPUMem :: Pass GPUMem GPUMem
+ Futhark.Test: futharkServerCfg :: FilePath -> [String] -> ServerCfg
+ Futhark.Test: valueText :: Value -> Text
+ Futhark.Test.Values: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Data.Value
+ Futhark.Test.Values: instance Text.PrettyPrint.Mainland.Class.Pretty Futhark.Data.ValueType
+ Futhark.Transform.FirstOrderTransform: type FirstOrderRep rep = (Bindable rep, BinderOps rep, LetDec SOACS ~ LetDec rep, LParamInfo SOACS ~ LParamInfo rep, CanBeAliased (Op rep))
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable rep => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Body rep)
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable rep => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Exp rep)
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable rep => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.FunDef rep)
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable rep => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Lambda rep)
+ Futhark.Transform.Rename: instance Futhark.Transform.Rename.Renameable rep => Futhark.Transform.Rename.Rename (Futhark.IR.Syntax.Stm rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.Prop.Scope.NameInfo rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Body rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Exp rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Lambda rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitutable rep => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stm rep)
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stm rep) => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.Stms rep)
+ Futhark.TypeCheck: checkBodyDec :: (Checkable rep, BodyDec rep ~ ()) => BodyDec rep -> TypeM rep ()
+ Futhark.TypeCheck: checkExpDec :: (Checkable rep, ExpDec rep ~ ()) => ExpDec rep -> TypeM rep ()
+ Futhark.TypeCheck: checkFParamDec :: (Checkable rep, FParamInfo rep ~ DeclType) => VName -> FParamInfo rep -> TypeM rep ()
+ Futhark.TypeCheck: checkLParamDec :: (Checkable rep, LParamInfo rep ~ Type) => VName -> LParamInfo rep -> TypeM rep ()
+ Futhark.TypeCheck: checkLetBoundDec :: (Checkable rep, LetDec rep ~ Type) => VName -> LetDec rep -> TypeM rep ()
+ Futhark.TypeCheck: instance Control.Monad.Reader.Class.MonadReader (Futhark.TypeCheck.Env rep) (Futhark.TypeCheck.TypeM rep)
+ Futhark.TypeCheck: instance Control.Monad.State.Class.MonadState Futhark.TypeCheck.TState (Futhark.TypeCheck.TypeM rep)
+ Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable rep => Futhark.IR.Prop.Scope.HasScope (Futhark.IR.Aliases.Aliases rep) (Futhark.TypeCheck.TypeM rep)
+ Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable rep => GHC.Show.Show (Futhark.TypeCheck.ErrorCase rep)
+ Futhark.TypeCheck: instance Futhark.TypeCheck.Checkable rep => GHC.Show.Show (Futhark.TypeCheck.TypeError rep)
+ Futhark.TypeCheck: instance GHC.Base.Applicative (Futhark.TypeCheck.TypeM rep)
+ Futhark.TypeCheck: instance GHC.Base.Functor (Futhark.TypeCheck.TypeM rep)
+ Futhark.TypeCheck: instance GHC.Base.Monad (Futhark.TypeCheck.TypeM rep)
+ Futhark.Util: invertMap :: (Ord v, Ord k) => Map k v -> Map v (Set k)
+ Language.Futhark.Syntax: pretty :: Pretty a => a -> String
- Futhark.Actions: compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem
+ Futhark.Actions: compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem
- Futhark.Actions: compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem
+ Futhark.Actions: compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem
- Futhark.Actions: compilePyOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem
+ Futhark.Actions: compilePyOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem
- Futhark.Actions: kernelImpCodeGenAction :: Action KernelsMem
+ Futhark.Actions: kernelImpCodeGenAction :: Action GPUMem
- Futhark.Actions: metricsAction :: OpMetrics (Op lore) => Action lore
+ Futhark.Actions: metricsAction :: OpMetrics (Op rep) => Action rep
- Futhark.Actions: printAction :: ASTLore lore => Action lore
+ Futhark.Actions: printAction :: ASTRep rep => Action rep
- Futhark.Actions: printAliasesAction :: (ASTLore lore, CanBeAliased (Op lore)) => Action lore
+ Futhark.Actions: printAliasesAction :: (ASTRep rep, CanBeAliased (Op rep)) => Action rep
- Futhark.Analysis.Alias: aliasAnalysis :: (ASTLore lore, CanBeAliased (Op lore)) => Prog lore -> Prog (Aliases lore)
+ Futhark.Analysis.Alias: aliasAnalysis :: (ASTRep rep, CanBeAliased (Op rep)) => Prog rep -> Prog (Aliases rep)
- Futhark.Analysis.Alias: analyseBody :: (ASTLore lore, CanBeAliased (Op lore)) => AliasTable -> Body lore -> Body (Aliases lore)
+ Futhark.Analysis.Alias: analyseBody :: (ASTRep rep, CanBeAliased (Op rep)) => AliasTable -> Body rep -> Body (Aliases rep)
- Futhark.Analysis.Alias: analyseExp :: (ASTLore lore, CanBeAliased (Op lore)) => AliasTable -> Exp lore -> Exp (Aliases lore)
+ Futhark.Analysis.Alias: analyseExp :: (ASTRep rep, CanBeAliased (Op rep)) => AliasTable -> Exp rep -> Exp (Aliases rep)
- Futhark.Analysis.Alias: analyseFun :: (ASTLore lore, CanBeAliased (Op lore)) => FunDef lore -> FunDef (Aliases lore)
+ Futhark.Analysis.Alias: analyseFun :: (ASTRep rep, CanBeAliased (Op rep)) => FunDef rep -> FunDef (Aliases rep)
- Futhark.Analysis.Alias: analyseLambda :: (ASTLore lore, CanBeAliased (Op lore)) => AliasTable -> Lambda lore -> Lambda (Aliases lore)
+ Futhark.Analysis.Alias: analyseLambda :: (ASTRep rep, CanBeAliased (Op rep)) => AliasTable -> Lambda rep -> Lambda (Aliases rep)
- Futhark.Analysis.Alias: analyseStms :: (ASTLore lore, CanBeAliased (Op lore)) => AliasTable -> Stms lore -> (Stms (Aliases lore), AliasesAndConsumed)
+ Futhark.Analysis.Alias: analyseStms :: (ASTRep rep, CanBeAliased (Op rep)) => AliasTable -> Stms rep -> (Stms (Aliases rep), AliasesAndConsumed)
- Futhark.Analysis.DataDependencies: dataDependencies :: ASTLore lore => Body lore -> Dependencies
+ Futhark.Analysis.DataDependencies: dataDependencies :: ASTRep rep => Body rep -> Dependencies
- Futhark.Analysis.HORep.MapNest: MapNest :: SubExp -> Lambda lore -> [Nesting lore] -> [Input] -> MapNest lore
+ Futhark.Analysis.HORep.MapNest: MapNest :: SubExp -> Lambda rep -> [Nesting rep] -> [Input] -> MapNest rep
- Futhark.Analysis.HORep.MapNest: Nesting :: [VName] -> [VName] -> [Type] -> SubExp -> Nesting lore
+ Futhark.Analysis.HORep.MapNest: Nesting :: [VName] -> [VName] -> [Type] -> SubExp -> Nesting rep
- Futhark.Analysis.HORep.MapNest: [nestingParamNames] :: Nesting lore -> [VName]
+ Futhark.Analysis.HORep.MapNest: [nestingParamNames] :: Nesting rep -> [VName]
- Futhark.Analysis.HORep.MapNest: [nestingResult] :: Nesting lore -> [VName]
+ Futhark.Analysis.HORep.MapNest: [nestingResult] :: Nesting rep -> [VName]
- Futhark.Analysis.HORep.MapNest: [nestingReturnType] :: Nesting lore -> [Type]
+ Futhark.Analysis.HORep.MapNest: [nestingReturnType] :: Nesting rep -> [Type]
- Futhark.Analysis.HORep.MapNest: [nestingWidth] :: Nesting lore -> SubExp
+ Futhark.Analysis.HORep.MapNest: [nestingWidth] :: Nesting rep -> SubExp
- Futhark.Analysis.HORep.MapNest: data MapNest lore
+ Futhark.Analysis.HORep.MapNest: data MapNest rep
- Futhark.Analysis.HORep.MapNest: data Nesting lore
+ Futhark.Analysis.HORep.MapNest: data Nesting rep
- Futhark.Analysis.HORep.MapNest: fromSOAC :: (Bindable lore, MonadFreshNames m, LocalScope lore m, Op lore ~ SOAC lore) => SOAC lore -> m (Maybe (MapNest lore))
+ 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: inputs :: MapNest lore -> [Input]
+ Futhark.Analysis.HORep.MapNest: inputs :: MapNest rep -> [Input]
- Futhark.Analysis.HORep.MapNest: params :: MapNest lore -> [VName]
+ Futhark.Analysis.HORep.MapNest: params :: MapNest rep -> [VName]
- Futhark.Analysis.HORep.MapNest: setInputs :: [Input] -> MapNest lore -> MapNest lore
+ Futhark.Analysis.HORep.MapNest: setInputs :: [Input] -> MapNest rep -> MapNest rep
- Futhark.Analysis.HORep.MapNest: toSOAC :: (MonadFreshNames m, HasScope lore m, Bindable lore, BinderOps lore, Op lore ~ SOAC lore) => MapNest lore -> m (SOAC lore)
+ 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: typeOf :: MapNest lore -> [Type]
+ Futhark.Analysis.HORep.MapNest: typeOf :: MapNest rep -> [Type]
- Futhark.Analysis.HORep.SOAC: Hist :: SubExp -> [HistOp lore] -> Lambda lore -> [Input] -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: Hist :: SubExp -> [HistOp rep] -> Lambda rep -> [Input] -> SOAC rep
- Futhark.Analysis.HORep.SOAC: Scatter :: SubExp -> Lambda lore -> [Input] -> [(Shape, Int, VName)] -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: Scatter :: SubExp -> Lambda rep -> [Input] -> [(Shape, Int, VName)] -> SOAC rep
- Futhark.Analysis.HORep.SOAC: Screma :: SubExp -> ScremaForm lore -> [Input] -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: Screma :: SubExp -> ScremaForm rep -> [Input] -> SOAC rep
- Futhark.Analysis.HORep.SOAC: ScremaForm :: [Scan lore] -> [Reduce lore] -> Lambda lore -> ScremaForm lore
+ Futhark.Analysis.HORep.SOAC: ScremaForm :: [Scan rep] -> [Reduce rep] -> Lambda rep -> ScremaForm rep
- Futhark.Analysis.HORep.SOAC: Stream :: SubExp -> StreamForm lore -> Lambda lore -> [SubExp] -> [Input] -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: Stream :: SubExp -> StreamForm rep -> Lambda rep -> [SubExp] -> [Input] -> SOAC rep
- Futhark.Analysis.HORep.SOAC: data SOAC lore
+ Futhark.Analysis.HORep.SOAC: data SOAC rep
- Futhark.Analysis.HORep.SOAC: data ScremaForm lore
+ Futhark.Analysis.HORep.SOAC: data ScremaForm rep
- Futhark.Analysis.HORep.SOAC: fromExp :: (Op lore ~ SOAC lore, HasScope lore m) => Exp lore -> m (Either NotSOAC (SOAC lore))
+ Futhark.Analysis.HORep.SOAC: fromExp :: (Op rep ~ SOAC rep, HasScope rep m) => Exp rep -> m (Either NotSOAC (SOAC rep))
- Futhark.Analysis.HORep.SOAC: inputs :: SOAC lore -> [Input]
+ Futhark.Analysis.HORep.SOAC: inputs :: SOAC rep -> [Input]
- Futhark.Analysis.HORep.SOAC: lambda :: SOAC lore -> Lambda lore
+ Futhark.Analysis.HORep.SOAC: lambda :: SOAC rep -> Lambda rep
- Futhark.Analysis.HORep.SOAC: setInputs :: [Input] -> SOAC lore -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: setInputs :: [Input] -> SOAC rep -> SOAC rep
- Futhark.Analysis.HORep.SOAC: setLambda :: Lambda lore -> SOAC lore -> SOAC lore
+ Futhark.Analysis.HORep.SOAC: setLambda :: Lambda rep -> SOAC rep -> SOAC rep
- Futhark.Analysis.HORep.SOAC: soacToStream :: (MonadFreshNames m, Bindable lore, Op lore ~ SOAC lore) => SOAC lore -> m (SOAC lore, [Ident])
+ Futhark.Analysis.HORep.SOAC: soacToStream :: (MonadFreshNames m, Bindable rep, Op rep ~ SOAC rep) => SOAC rep -> m (SOAC rep, [Ident])
- Futhark.Analysis.HORep.SOAC: toExp :: (MonadBinder m, Op (Lore m) ~ SOAC (Lore m)) => SOAC (Lore m) -> m (Exp (Lore m))
+ Futhark.Analysis.HORep.SOAC: toExp :: (MonadBinder m, Op (Rep m) ~ SOAC (Rep m)) => SOAC (Rep m) -> m (Exp (Rep m))
- Futhark.Analysis.HORep.SOAC: toSOAC :: MonadBinder m => SOAC (Lore m) -> m (SOAC (Lore m))
+ Futhark.Analysis.HORep.SOAC: toSOAC :: MonadBinder m => SOAC (Rep m) -> m (SOAC (Rep m))
- Futhark.Analysis.HORep.SOAC: transformFromExp :: Certificates -> Exp lore -> Maybe (VName, ArrayTransform)
+ Futhark.Analysis.HORep.SOAC: transformFromExp :: Certificates -> Exp rep -> Maybe (VName, ArrayTransform)
- Futhark.Analysis.HORep.SOAC: typeOf :: SOAC lore -> [Type]
+ Futhark.Analysis.HORep.SOAC: typeOf :: SOAC rep -> [Type]
- Futhark.Analysis.HORep.SOAC: width :: SOAC lore -> SubExp
+ Futhark.Analysis.HORep.SOAC: width :: SOAC rep -> SubExp
- Futhark.Analysis.Metrics: lambdaMetrics :: OpMetrics (Op lore) => Lambda lore -> MetricsM ()
+ Futhark.Analysis.Metrics: lambdaMetrics :: OpMetrics (Op rep) => Lambda rep -> MetricsM ()
- Futhark.Analysis.Metrics: progMetrics :: OpMetrics (Op lore) => Prog lore -> AstMetrics
+ Futhark.Analysis.Metrics: progMetrics :: OpMetrics (Op rep) => Prog rep -> AstMetrics
- Futhark.Analysis.Metrics: stmMetrics :: OpMetrics (Op lore) => Stm lore -> MetricsM ()
+ Futhark.Analysis.Metrics: stmMetrics :: OpMetrics (Op rep) => Stm rep -> MetricsM ()
- Futhark.Analysis.PrimExp.Convert: primExpFromExp :: (MonadFail m, Decorations lore) => (VName -> m (PrimExp v)) -> Exp lore -> m (PrimExp v)
+ Futhark.Analysis.PrimExp.Convert: primExpFromExp :: (MonadFail m, RepTypes rep) => (VName -> m (PrimExp v)) -> Exp rep -> m (PrimExp v)
- Futhark.Analysis.PrimExp.Simplify: simplifyExtPrimExp :: SimplifiableLore lore => PrimExp (Ext VName) -> SimpleM lore (PrimExp (Ext VName))
+ Futhark.Analysis.PrimExp.Simplify: simplifyExtPrimExp :: SimplifiableRep rep => PrimExp (Ext VName) -> SimpleM rep (PrimExp (Ext VName))
- Futhark.Analysis.PrimExp.Simplify: simplifyPrimExp :: SimplifiableLore lore => PrimExp VName -> SimpleM lore (PrimExp VName)
+ Futhark.Analysis.PrimExp.Simplify: simplifyPrimExp :: SimplifiableRep rep => PrimExp VName -> SimpleM rep (PrimExp VName)
- Futhark.Analysis.SymbolTable: available :: VName -> SymbolTable lore -> Bool
+ Futhark.Analysis.SymbolTable: available :: VName -> SymbolTable rep -> Bool
- Futhark.Analysis.SymbolTable: consume :: VName -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: consume :: VName -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: data Entry lore
+ Futhark.Analysis.SymbolTable: data Entry rep
- Futhark.Analysis.SymbolTable: data SymbolTable lore
+ Futhark.Analysis.SymbolTable: data SymbolTable rep
- Futhark.Analysis.SymbolTable: deepen :: SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: deepen :: SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: elem :: VName -> SymbolTable lore -> Bool
+ Futhark.Analysis.SymbolTable: elem :: VName -> SymbolTable rep -> Bool
- Futhark.Analysis.SymbolTable: empty :: SymbolTable lore
+ Futhark.Analysis.SymbolTable: empty :: SymbolTable rep
- Futhark.Analysis.SymbolTable: entryDepth :: Entry lore -> Int
+ Futhark.Analysis.SymbolTable: entryDepth :: Entry rep -> Int
- Futhark.Analysis.SymbolTable: entryFParam :: Entry lore -> Maybe (FParamInfo lore)
+ Futhark.Analysis.SymbolTable: entryFParam :: Entry rep -> Maybe (FParamInfo rep)
- Futhark.Analysis.SymbolTable: entryIsSize :: Entry lore -> Bool
+ Futhark.Analysis.SymbolTable: entryIsSize :: Entry rep -> Bool
- Futhark.Analysis.SymbolTable: entryLetBoundDec :: Entry lore -> Maybe (LetDec lore)
+ Futhark.Analysis.SymbolTable: entryLetBoundDec :: Entry rep -> Maybe (LetDec rep)
- Futhark.Analysis.SymbolTable: entryStm :: Entry lore -> Maybe (Stm lore)
+ Futhark.Analysis.SymbolTable: entryStm :: Entry rep -> Maybe (Stm rep)
- Futhark.Analysis.SymbolTable: fromScope :: ASTLore lore => Scope lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: fromScope :: ASTRep rep => Scope rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: hideCertified :: Names -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: hideCertified :: Names -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: index :: ASTLore lore => VName -> [SubExp] -> SymbolTable lore -> Maybe Indexed
+ Futhark.Analysis.SymbolTable: index :: ASTRep rep => VName -> [SubExp] -> SymbolTable rep -> Maybe Indexed
- Futhark.Analysis.SymbolTable: index' :: VName -> [TPrimExp Int64 VName] -> SymbolTable lore -> Maybe Indexed
+ Futhark.Analysis.SymbolTable: index' :: VName -> [TPrimExp Int64 VName] -> SymbolTable rep -> Maybe Indexed
- Futhark.Analysis.SymbolTable: indexOp :: (IndexOp op, ASTLore lore, IndexOp (Op lore)) => SymbolTable lore -> Int -> op -> [TPrimExp Int64 VName] -> Maybe Indexed
+ Futhark.Analysis.SymbolTable: indexOp :: (IndexOp op, ASTRep rep, IndexOp (Op rep)) => SymbolTable rep -> Int -> op -> [TPrimExp Int64 VName] -> Maybe Indexed
- Futhark.Analysis.SymbolTable: insertFParams :: ASTLore lore => [FParam lore] -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertFParams :: ASTRep rep => [FParam rep] -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: insertLParam :: ASTLore lore => LParam lore -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertLParam :: ASTRep rep => LParam rep -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: insertLoopMerge :: ASTLore lore => [(FParam lore, SubExp, SubExp)] -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertLoopMerge :: ASTRep rep => [(FParam rep, SubExp, SubExp)] -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: insertLoopVar :: ASTLore lore => VName -> IntType -> SubExp -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertLoopVar :: ASTRep rep => VName -> IntType -> SubExp -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: insertStm :: (ASTLore lore, IndexOp (Op lore), Aliased lore) => Stm lore -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertStm :: (ASTRep rep, IndexOp (Op rep), Aliased rep) => Stm rep -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: insertStms :: (ASTLore lore, IndexOp (Op lore), Aliased lore) => Stms lore -> SymbolTable lore -> SymbolTable lore
+ Futhark.Analysis.SymbolTable: insertStms :: (ASTRep rep, IndexOp (Op rep), Aliased rep) => Stms rep -> SymbolTable rep -> SymbolTable rep
- Futhark.Analysis.SymbolTable: lookup :: VName -> SymbolTable lore -> Maybe (Entry lore)
+ Futhark.Analysis.SymbolTable: lookup :: VName -> SymbolTable rep -> Maybe (Entry rep)
- Futhark.Analysis.SymbolTable: lookupAliases :: VName -> SymbolTable lore -> Names
+ Futhark.Analysis.SymbolTable: lookupAliases :: VName -> SymbolTable rep -> Names
- Futhark.Analysis.SymbolTable: lookupBasicOp :: VName -> SymbolTable lore -> Maybe (BasicOp, Certificates)
+ Futhark.Analysis.SymbolTable: lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certificates)
- Futhark.Analysis.SymbolTable: lookupExp :: VName -> SymbolTable lore -> Maybe (Exp lore, Certificates)
+ Futhark.Analysis.SymbolTable: lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certificates)
- Futhark.Analysis.SymbolTable: lookupLoopParam :: VName -> SymbolTable lore -> Maybe (SubExp, SubExp)
+ Futhark.Analysis.SymbolTable: lookupLoopParam :: VName -> SymbolTable rep -> Maybe (SubExp, SubExp)
- Futhark.Analysis.SymbolTable: lookupLoopVar :: VName -> SymbolTable lore -> Maybe SubExp
+ Futhark.Analysis.SymbolTable: lookupLoopVar :: VName -> SymbolTable rep -> Maybe SubExp
- Futhark.Analysis.SymbolTable: lookupStm :: VName -> SymbolTable lore -> Maybe (Stm lore)
+ Futhark.Analysis.SymbolTable: lookupStm :: VName -> SymbolTable rep -> Maybe (Stm rep)
- Futhark.Analysis.SymbolTable: lookupSubExp :: VName -> SymbolTable lore -> Maybe (SubExp, Certificates)
+ Futhark.Analysis.SymbolTable: lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certificates)
- Futhark.Analysis.SymbolTable: lookupType :: ASTLore lore => VName -> SymbolTable lore -> Maybe Type
+ Futhark.Analysis.SymbolTable: lookupType :: ASTRep rep => VName -> SymbolTable rep -> Maybe Type
- Futhark.Analysis.SymbolTable: toScope :: SymbolTable lore -> Scope lore
+ Futhark.Analysis.SymbolTable: toScope :: SymbolTable rep -> Scope rep
- Futhark.Analysis.UsageTable: usageInStm :: (ASTLore lore, Aliased lore) => Stm lore -> UsageTable
+ Futhark.Analysis.UsageTable: usageInStm :: (ASTRep rep, Aliased rep) => Stm rep -> UsageTable
- Futhark.Binder: class ASTLore lore => BinderOps lore
+ Futhark.Binder: class ASTRep rep => BinderOps rep
- Futhark.Binder: data BinderT lore m a
+ Futhark.Binder: data BinderT rep m a
- Futhark.Binder: mkBodyB :: (BinderOps lore, MonadBinder m, Bindable lore) => Stms lore -> Result -> m (Body lore)
+ Futhark.Binder: mkBodyB :: (BinderOps rep, MonadBinder m, Bindable rep) => Stms rep -> Result -> m (Body rep)
- Futhark.Binder: mkExpDecB :: (BinderOps lore, MonadBinder m, Bindable lore) => Pattern lore -> Exp lore -> m (ExpDec lore)
+ Futhark.Binder: mkExpDecB :: (BinderOps rep, MonadBinder m, Bindable rep) => Pattern rep -> Exp rep -> m (ExpDec rep)
- Futhark.Binder: mkLetNamesB :: (BinderOps lore, MonadBinder m, Lore m ~ lore, Bindable lore) => [VName] -> Exp lore -> m (Stm lore)
+ Futhark.Binder: mkLetNamesB :: (BinderOps rep, MonadBinder m, Rep m ~ rep, Bindable rep) => [VName] -> Exp rep -> m (Stm rep)
- Futhark.Binder: runBinder :: (MonadFreshNames m, HasScope somelore m, SameScope somelore lore) => Binder lore a -> m (a, Stms lore)
+ Futhark.Binder: runBinder :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep a -> m (a, Stms rep)
- Futhark.Binder: runBinderT :: MonadFreshNames m => BinderT lore m a -> Scope lore -> m (a, Stms lore)
+ Futhark.Binder: runBinderT :: MonadFreshNames m => BinderT rep m a -> Scope rep -> m (a, Stms rep)
- Futhark.Binder: runBinderT' :: (MonadFreshNames m, HasScope somelore m, SameScope somelore lore) => BinderT lore m a -> m (a, Stms lore)
+ 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 somelore m, SameScope somelore lore) => BinderT lore m a -> m (Stms lore)
+ Futhark.Binder: runBinderT'_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => BinderT rep m a -> m (Stms rep)
- Futhark.Binder: runBinderT_ :: MonadFreshNames m => BinderT lore m () -> Scope lore -> m (Stms lore)
+ Futhark.Binder: runBinderT_ :: MonadFreshNames m => BinderT rep m () -> Scope rep -> m (Stms rep)
- Futhark.Binder: runBinder_ :: (MonadFreshNames m, HasScope somelore m, SameScope somelore lore) => Binder lore a -> m (Stms lore)
+ Futhark.Binder: runBinder_ :: (MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep a -> m (Stms rep)
- Futhark.Binder: runBodyBinder :: (Bindable lore, MonadFreshNames m, HasScope somelore m, SameScope somelore lore) => Binder lore (Body lore) -> m (Body lore)
+ Futhark.Binder: runBodyBinder :: (Bindable rep, MonadFreshNames m, HasScope somerep m, SameScope somerep rep) => Binder rep (Body rep) -> m (Body rep)
- Futhark.Binder: type Binder lore = BinderT lore (State VNameSource)
+ Futhark.Binder: type Binder rep = BinderT rep (State VNameSource)
- Futhark.Binder.Class: addStm :: MonadBinder m => Stm (Lore m) -> m ()
+ Futhark.Binder.Class: addStm :: MonadBinder m => Stm (Rep m) -> m ()
- Futhark.Binder.Class: addStms :: MonadBinder m => Stms (Lore m) -> m ()
+ Futhark.Binder.Class: addStms :: MonadBinder m => Stms (Rep m) -> m ()
- Futhark.Binder.Class: auxing :: MonadBinder m => StmAux anylore -> m a -> m a
+ Futhark.Binder.Class: auxing :: MonadBinder m => StmAux anyrep -> m a -> m a
- Futhark.Binder.Class: bodyBind :: MonadBinder m => Body (Lore m) -> m [SubExp]
+ Futhark.Binder.Class: bodyBind :: MonadBinder m => Body (Rep m) -> m [SubExp]
- Futhark.Binder.Class: class (ASTLore lore, FParamInfo lore ~ DeclType, LParamInfo lore ~ Type, RetType lore ~ DeclExtType, BranchType lore ~ ExtType, SetType (LetDec lore)) => Bindable lore
+ 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 (ASTLore (Lore m), MonadFreshNames m, Applicative m, Monad m, LocalScope (Lore m) m) => MonadBinder m where {
+ 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 (Lore m))
+ Futhark.Binder.Class: collectStms :: MonadBinder m => m a -> m (a, Stms (Rep m))
- Futhark.Binder.Class: collectStms_ :: MonadBinder m => m a -> m (Stms (Lore m))
+ Futhark.Binder.Class: collectStms_ :: MonadBinder m => m a -> m (Stms (Rep m))
- Futhark.Binder.Class: insertStm :: Bindable lore => Stm lore -> Body lore -> Body lore
+ Futhark.Binder.Class: insertStm :: Bindable rep => Stm rep -> Body rep -> Body rep
- Futhark.Binder.Class: insertStms :: Bindable lore => Stms lore -> Body lore -> Body lore
+ Futhark.Binder.Class: insertStms :: Bindable rep => Stms rep -> Body rep -> Body rep
- Futhark.Binder.Class: letBind :: MonadBinder m => Pattern (Lore m) -> Exp (Lore m) -> m ()
+ Futhark.Binder.Class: letBind :: MonadBinder m => Pattern (Rep m) -> Exp (Rep m) -> m ()
- Futhark.Binder.Class: letBindNames :: MonadBinder m => [VName] -> Exp (Lore m) -> m ()
+ Futhark.Binder.Class: letBindNames :: MonadBinder m => [VName] -> Exp (Rep m) -> m ()
- Futhark.Binder.Class: mkBody :: Bindable lore => Stms lore -> Result -> Body lore
+ Futhark.Binder.Class: mkBody :: Bindable rep => Stms rep -> Result -> Body rep
- Futhark.Binder.Class: mkBodyM :: MonadBinder m => Stms (Lore m) -> Result -> m (Body (Lore m))
+ Futhark.Binder.Class: mkBodyM :: MonadBinder m => Stms (Rep m) -> Result -> m (Body (Rep m))
- Futhark.Binder.Class: mkExpDec :: Bindable lore => Pattern lore -> Exp lore -> ExpDec lore
+ Futhark.Binder.Class: mkExpDec :: Bindable rep => Pattern rep -> Exp rep -> ExpDec rep
- Futhark.Binder.Class: mkExpDecM :: MonadBinder m => Pattern (Lore m) -> Exp (Lore m) -> m (ExpDec (Lore m))
+ Futhark.Binder.Class: mkExpDecM :: MonadBinder m => Pattern (Rep m) -> Exp (Rep m) -> m (ExpDec (Rep m))
- Futhark.Binder.Class: mkExpPat :: Bindable lore => [Ident] -> [Ident] -> Exp lore -> Pattern lore
+ Futhark.Binder.Class: mkExpPat :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Pattern rep
- Futhark.Binder.Class: mkLet :: Bindable lore => [Ident] -> [Ident] -> Exp lore -> Stm lore
+ Futhark.Binder.Class: mkLet :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Stm rep
- Futhark.Binder.Class: mkLet' :: Bindable lore => [Ident] -> [Ident] -> StmAux a -> Exp lore -> Stm lore
+ Futhark.Binder.Class: mkLet' :: Bindable rep => [Ident] -> [Ident] -> StmAux a -> Exp rep -> Stm rep
- Futhark.Binder.Class: mkLetNames :: (Bindable lore, MonadFreshNames m, HasScope lore m) => [VName] -> Exp lore -> m (Stm lore)
+ 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 (Lore m) -> m (Stm (Lore m))
+ Futhark.Binder.Class: mkLetNamesM :: MonadBinder m => [VName] -> Exp (Rep m) -> m (Stm (Rep m))
- Futhark.Binder.Class: type family Lore m :: Type;
+ Futhark.Binder.Class: type family Rep m :: Type;
- Futhark.CodeGen.Backends.CCUDA: compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, CParts)
+ Futhark.CodeGen.Backends.CCUDA: compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, CParts)
- Futhark.CodeGen.Backends.COpenCL: compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, CParts)
+ Futhark.CodeGen.Backends.COpenCL: compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, CParts)
- Futhark.CodeGen.Backends.PyOpenCL: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog KernelsMem -> m (Warnings, String)
+ Futhark.CodeGen.Backends.PyOpenCL: compileProg :: MonadFreshNames m => CompilerMode -> String -> Prog GPUMem -> m (Warnings, String)
- Futhark.CodeGen.ImpCode: OpaqueValue :: String -> [ValueDesc] -> ExternalValue
+ Futhark.CodeGen.ImpCode: OpaqueValue :: Uniqueness -> String -> [ValueDesc] -> ExternalValue
- Futhark.CodeGen.ImpCode: TransparentValue :: ValueDesc -> ExternalValue
+ Futhark.CodeGen.ImpCode: TransparentValue :: Uniqueness -> ValueDesc -> ExternalValue
- Futhark.CodeGen.ImpCode.Multicore: OpaqueValue :: String -> [ValueDesc] -> ExternalValue
+ Futhark.CodeGen.ImpCode.Multicore: OpaqueValue :: Uniqueness -> String -> [ValueDesc] -> ExternalValue
- Futhark.CodeGen.ImpCode.Multicore: TransparentValue :: ValueDesc -> ExternalValue
+ Futhark.CodeGen.ImpCode.Multicore: TransparentValue :: Uniqueness -> ValueDesc -> ExternalValue
- Futhark.CodeGen.ImpCode.Multicore: boundByLambda :: Lambda lore -> [VName]
+ Futhark.CodeGen.ImpCode.Multicore: boundByLambda :: Lambda rep -> [VName]
- Futhark.CodeGen.ImpCode.Multicore: boundByStm :: Stm lore -> Names
+ Futhark.CodeGen.ImpCode.Multicore: boundByStm :: Stm rep -> Names
- Futhark.CodeGen.ImpCode.Multicore: boundByStms :: Stms lore -> Names
+ Futhark.CodeGen.ImpCode.Multicore: boundByStms :: Stms rep -> Names
- Futhark.CodeGen.ImpCode.Multicore: boundInBody :: Body lore -> Names
+ Futhark.CodeGen.ImpCode.Multicore: boundInBody :: Body rep -> Names
- Futhark.CodeGen.ImpCode.Multicore: freeInStmsAndRes :: (FreeIn (Op lore), FreeIn (LetDec lore), FreeIn (LParamInfo lore), FreeIn (FParamInfo lore), FreeDec (BodyDec lore), FreeIn (RetType lore), FreeIn (BranchType lore), FreeDec (ExpDec lore)) => Stms lore -> Result -> FV
+ Futhark.CodeGen.ImpCode.Multicore: freeInStmsAndRes :: (FreeIn (Op rep), FreeIn (LetDec rep), FreeIn (LParamInfo rep), FreeIn (FParamInfo rep), FreeDec (BodyDec rep), FreeIn (RetType rep), FreeIn (BranchType rep), FreeDec (ExpDec rep)) => Stms rep -> Result -> FV
- Futhark.CodeGen.ImpCode.OpenCL: OpaqueValue :: String -> [ValueDesc] -> ExternalValue
+ Futhark.CodeGen.ImpCode.OpenCL: OpaqueValue :: Uniqueness -> String -> [ValueDesc] -> ExternalValue
- Futhark.CodeGen.ImpCode.OpenCL: TransparentValue :: ValueDesc -> ExternalValue
+ Futhark.CodeGen.ImpCode.OpenCL: TransparentValue :: Uniqueness -> ValueDesc -> ExternalValue
- Futhark.CodeGen.ImpCode.OpenCL: boundByLambda :: Lambda lore -> [VName]
+ Futhark.CodeGen.ImpCode.OpenCL: boundByLambda :: Lambda rep -> [VName]
- Futhark.CodeGen.ImpCode.OpenCL: boundByStm :: Stm lore -> Names
+ Futhark.CodeGen.ImpCode.OpenCL: boundByStm :: Stm rep -> Names
- Futhark.CodeGen.ImpCode.OpenCL: boundByStms :: Stms lore -> Names
+ Futhark.CodeGen.ImpCode.OpenCL: boundByStms :: Stms rep -> Names
- Futhark.CodeGen.ImpCode.OpenCL: boundInBody :: Body lore -> Names
+ Futhark.CodeGen.ImpCode.OpenCL: boundInBody :: Body rep -> Names
- Futhark.CodeGen.ImpCode.OpenCL: freeInStmsAndRes :: (FreeIn (Op lore), FreeIn (LetDec lore), FreeIn (LParamInfo lore), FreeIn (FParamInfo lore), FreeDec (BodyDec lore), FreeIn (RetType lore), FreeIn (BranchType lore), FreeDec (ExpDec lore)) => Stms lore -> Result -> FV
+ Futhark.CodeGen.ImpCode.OpenCL: freeInStmsAndRes :: (FreeIn (Op rep), FreeIn (LetDec rep), FreeIn (LParamInfo rep), FreeIn (FParamInfo rep), FreeDec (BodyDec rep), FreeIn (RetType rep), FreeIn (BranchType rep), FreeDec (ExpDec rep)) => Stms rep -> Result -> FV
- Futhark.CodeGen.ImpCode.Sequential: OpaqueValue :: String -> [ValueDesc] -> ExternalValue
+ Futhark.CodeGen.ImpCode.Sequential: OpaqueValue :: Uniqueness -> String -> [ValueDesc] -> ExternalValue
- Futhark.CodeGen.ImpCode.Sequential: TransparentValue :: ValueDesc -> ExternalValue
+ Futhark.CodeGen.ImpCode.Sequential: TransparentValue :: Uniqueness -> ValueDesc -> ExternalValue
- Futhark.CodeGen.ImpCode.Sequential: boundByLambda :: Lambda lore -> [VName]
+ Futhark.CodeGen.ImpCode.Sequential: boundByLambda :: Lambda rep -> [VName]
- Futhark.CodeGen.ImpCode.Sequential: boundByStm :: Stm lore -> Names
+ Futhark.CodeGen.ImpCode.Sequential: boundByStm :: Stm rep -> Names
- Futhark.CodeGen.ImpCode.Sequential: boundByStms :: Stms lore -> Names
+ Futhark.CodeGen.ImpCode.Sequential: boundByStms :: Stms rep -> Names
- Futhark.CodeGen.ImpCode.Sequential: boundInBody :: Body lore -> Names
+ Futhark.CodeGen.ImpCode.Sequential: boundInBody :: Body rep -> Names
- Futhark.CodeGen.ImpCode.Sequential: freeInStmsAndRes :: (FreeIn (Op lore), FreeIn (LetDec lore), FreeIn (LParamInfo lore), FreeIn (FParamInfo lore), FreeDec (BodyDec lore), FreeIn (RetType lore), FreeIn (BranchType lore), FreeDec (ExpDec lore)) => Stms lore -> Result -> FV
+ Futhark.CodeGen.ImpCode.Sequential: freeInStmsAndRes :: (FreeIn (Op rep), FreeIn (LetDec rep), FreeIn (LParamInfo rep), FreeIn (FParamInfo rep), FreeDec (BodyDec rep), FreeIn (RetType rep), FreeIn (BranchType rep), FreeDec (ExpDec rep)) => Stms rep -> Result -> FV
- Futhark.CodeGen.ImpGen: (<--) :: TV t -> TExp t -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: (<--) :: TV t -> TExp t -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: (<~~) :: VName -> Exp -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: (<~~) :: VName -> Exp -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: AccVar :: Maybe (Exp lore) -> (VName, Shape, [Type]) -> VarEntry lore
+ Futhark.CodeGen.ImpGen: AccVar :: Maybe (Exp rep) -> (VName, Shape, [Type]) -> VarEntry rep
- Futhark.CodeGen.ImpGen: ArrayVar :: Maybe (Exp lore) -> ArrayEntry -> VarEntry lore
+ Futhark.CodeGen.ImpGen: ArrayVar :: Maybe (Exp rep) -> ArrayEntry -> VarEntry rep
- Futhark.CodeGen.ImpGen: MemVar :: Maybe (Exp lore) -> MemEntry -> VarEntry lore
+ Futhark.CodeGen.ImpGen: MemVar :: Maybe (Exp rep) -> MemEntry -> VarEntry rep
- Futhark.CodeGen.ImpGen: Operations :: ExpCompiler lore r op -> OpCompiler lore r op -> StmsCompiler lore r op -> CopyCompiler lore r op -> Map Space (AllocCompiler lore r op) -> Operations lore r op
+ Futhark.CodeGen.ImpGen: Operations :: ExpCompiler rep r op -> OpCompiler rep r op -> StmsCompiler rep r op -> CopyCompiler rep r op -> Map Space (AllocCompiler rep r op) -> Operations rep r op
- Futhark.CodeGen.ImpGen: ScalarVar :: Maybe (Exp lore) -> ScalarEntry -> VarEntry lore
+ Futhark.CodeGen.ImpGen: ScalarVar :: Maybe (Exp rep) -> ScalarEntry -> VarEntry rep
- Futhark.CodeGen.ImpGen: [opsAllocCompilers] :: Operations lore r op -> Map Space (AllocCompiler lore r op)
+ Futhark.CodeGen.ImpGen: [opsAllocCompilers] :: Operations rep r op -> Map Space (AllocCompiler rep r op)
- Futhark.CodeGen.ImpGen: [opsCopyCompiler] :: Operations lore r op -> CopyCompiler lore r op
+ Futhark.CodeGen.ImpGen: [opsCopyCompiler] :: Operations rep r op -> CopyCompiler rep r op
- Futhark.CodeGen.ImpGen: [opsExpCompiler] :: Operations lore r op -> ExpCompiler lore r op
+ Futhark.CodeGen.ImpGen: [opsExpCompiler] :: Operations rep r op -> ExpCompiler rep r op
- Futhark.CodeGen.ImpGen: [opsOpCompiler] :: Operations lore r op -> OpCompiler lore r op
+ Futhark.CodeGen.ImpGen: [opsOpCompiler] :: Operations rep r op -> OpCompiler rep r op
- Futhark.CodeGen.ImpGen: [opsStmsCompiler] :: Operations lore r op -> StmsCompiler lore r op
+ Futhark.CodeGen.ImpGen: [opsStmsCompiler] :: Operations rep r op -> StmsCompiler rep r op
- Futhark.CodeGen.ImpGen: askEnv :: ImpM lore r op r
+ Futhark.CodeGen.ImpGen: askEnv :: ImpM rep r op r
- Futhark.CodeGen.ImpGen: askFunction :: ImpM lore r op (Maybe Name)
+ Futhark.CodeGen.ImpGen: askFunction :: ImpM rep r op (Maybe Name)
- Futhark.CodeGen.ImpGen: collect :: ImpM lore r op () -> ImpM lore r op (Code op)
+ Futhark.CodeGen.ImpGen: collect :: ImpM rep r op () -> ImpM rep r op (Code op)
- Futhark.CodeGen.ImpGen: collect' :: ImpM lore r op a -> ImpM lore r op (a, Code op)
+ Futhark.CodeGen.ImpGen: collect' :: ImpM rep r op a -> ImpM rep r op (a, Code op)
- Futhark.CodeGen.ImpGen: comment :: String -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: comment :: String -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileAlloc :: Mem lore => Pattern lore -> SubExp -> Space -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileAlloc :: Mem rep => Pattern rep -> SubExp -> Space -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileBody :: Mem lore => Pattern lore -> Body lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileBody :: Mem rep => Pattern rep -> Body rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileBody' :: [Param dec] -> Body lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileBody' :: [Param dec] -> Body rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileExp :: Pattern lore -> Exp lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileExp :: Pattern rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileLoopBody :: Typed dec => [Param dec] -> Body lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileLoopBody :: Typed dec => [Param dec] -> Body rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: compileProg :: (Mem lore, FreeIn op, MonadFreshNames m) => r -> Operations lore r op -> Space -> Prog lore -> m (Warnings, Definitions 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: compileStms :: Names -> Stms lore -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: compileStms :: Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: copy :: CopyCompiler lore r op
+ Futhark.CodeGen.ImpGen: copy :: CopyCompiler rep r op
- Futhark.CodeGen.ImpGen: copyDWIM :: VName -> [DimIndex (TExp Int64)] -> SubExp -> [DimIndex (TExp Int64)] -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: copyDWIM :: VName -> [DimIndex (TExp Int64)] -> SubExp -> [DimIndex (TExp Int64)] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: copyDWIMFix :: VName -> [TExp Int64] -> SubExp -> [TExp Int64] -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: copyDWIMFix :: VName -> [TExp Int64] -> SubExp -> [TExp Int64] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: copyElementWise :: CopyCompiler lore r op
+ Futhark.CodeGen.ImpGen: copyElementWise :: CopyCompiler rep r op
- Futhark.CodeGen.ImpGen: dArray :: VName -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dArray :: VName -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dFParams :: Mem lore => [FParam lore] -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dFParams :: Mem rep => [FParam rep] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dIndexSpace :: [(VName, TExp Int64)] -> TExp Int64 -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dIndexSpace :: [(VName, TExp Int64)] -> TExp Int64 -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dLParams :: Mem lore => [LParam lore] -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dLParams :: Mem rep => [LParam rep] -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dPrim :: String -> PrimType -> ImpM lore r op (TV t)
+ Futhark.CodeGen.ImpGen: dPrim :: String -> PrimType -> ImpM rep r op (TV t)
- Futhark.CodeGen.ImpGen: dPrimV :: String -> TExp t -> ImpM lore r op (TV t)
+ Futhark.CodeGen.ImpGen: dPrimV :: String -> TExp t -> ImpM rep r op (TV t)
- Futhark.CodeGen.ImpGen: dPrimVE :: String -> TExp t -> ImpM lore r op (TExp t)
+ Futhark.CodeGen.ImpGen: dPrimVE :: String -> TExp t -> ImpM rep r op (TExp t)
- Futhark.CodeGen.ImpGen: dPrimV_ :: VName -> TExp t -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dPrimV_ :: VName -> TExp t -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dPrimVol :: String -> PrimType -> TExp t -> ImpM lore r op (TV t)
+ Futhark.CodeGen.ImpGen: dPrimVol :: String -> PrimType -> TExp t -> ImpM rep r op (TV t)
- Futhark.CodeGen.ImpGen: dPrim_ :: VName -> PrimType -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dPrim_ :: VName -> PrimType -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: dScope :: Mem lore => Maybe (Exp lore) -> Scope lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: dScope :: Mem rep => Maybe (Exp rep) -> Scope rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: data ImpM lore r op a
+ Futhark.CodeGen.ImpGen: data ImpM rep r op a
- Futhark.CodeGen.ImpGen: data Operations lore r op
+ Futhark.CodeGen.ImpGen: data Operations rep r op
- Futhark.CodeGen.ImpGen: data VarEntry lore
+ Futhark.CodeGen.ImpGen: data VarEntry rep
- Futhark.CodeGen.ImpGen: defCompileExp :: Mem lore => Pattern lore -> Exp lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: defCompileExp :: Mem rep => Pattern rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: defCompileStms :: (Mem lore, FreeIn op) => Names -> Stms lore -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: defCompileStms :: (Mem rep, FreeIn op) => Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: defaultOperations :: (Mem lore, FreeIn op) => OpCompiler lore r op -> Operations lore r op
+ Futhark.CodeGen.ImpGen: defaultOperations :: (Mem rep, FreeIn op) => OpCompiler rep r op -> Operations rep r op
- Futhark.CodeGen.ImpGen: emit :: Code op -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: emit :: Code op -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: emitFunction :: Name -> Function op -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: emitFunction :: Name -> Function op -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: everythingVolatile :: ImpM lore r op a -> ImpM lore r op a
+ Futhark.CodeGen.ImpGen: everythingVolatile :: ImpM rep r op a -> ImpM rep r op a
- Futhark.CodeGen.ImpGen: fullyIndexArray :: VName -> [TExp Int64] -> ImpM lore r op (VName, Space, Count Elements (TExp Int64))
+ Futhark.CodeGen.ImpGen: fullyIndexArray :: VName -> [TExp Int64] -> ImpM rep r op (VName, Space, Count Elements (TExp Int64))
- Futhark.CodeGen.ImpGen: fullyIndexArray' :: MemLocation -> [TExp Int64] -> ImpM lore r op (VName, Space, Count Elements (TExp Int64))
+ Futhark.CodeGen.ImpGen: fullyIndexArray' :: MemLocation -> [TExp Int64] -> ImpM rep r op (VName, Space, Count Elements (TExp Int64))
- Futhark.CodeGen.ImpGen: function :: Name -> [Param] -> [Param] -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: function :: Name -> [Param] -> [Param] -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: getVTable :: ImpM lore r op (VTable lore)
+ Futhark.CodeGen.ImpGen: getVTable :: ImpM rep r op (VTable rep)
- Futhark.CodeGen.ImpGen: hasFunction :: Name -> ImpM lore r op Bool
+ Futhark.CodeGen.ImpGen: hasFunction :: Name -> ImpM rep r op Bool
- Futhark.CodeGen.ImpGen: localDefaultSpace :: Space -> ImpM lore r op a -> ImpM lore r op a
+ Futhark.CodeGen.ImpGen: localDefaultSpace :: Space -> ImpM rep r op a -> ImpM rep r op a
- Futhark.CodeGen.ImpGen: localEnv :: (r -> r) -> ImpM lore r op a -> ImpM lore r op a
+ Futhark.CodeGen.ImpGen: localEnv :: (r -> r) -> ImpM rep r op a -> ImpM rep r op a
- Futhark.CodeGen.ImpGen: localOps :: Operations lore r op -> ImpM lore r op a -> ImpM lore r op a
+ Futhark.CodeGen.ImpGen: localOps :: Operations rep r op -> ImpM rep r op a -> ImpM rep r op a
- Futhark.CodeGen.ImpGen: localVTable :: (VTable lore -> VTable lore) -> ImpM lore r op a -> ImpM lore r op a
+ Futhark.CodeGen.ImpGen: localVTable :: (VTable rep -> VTable rep) -> ImpM rep r op a -> ImpM rep r op a
- Futhark.CodeGen.ImpGen: lookupAcc :: VName -> [TExp Int64] -> ImpM lore r op (VName, Space, [VName], [TExp Int64], Maybe (Lambda lore))
+ Futhark.CodeGen.ImpGen: lookupAcc :: VName -> [TExp Int64] -> ImpM rep r op (VName, Space, [VName], [TExp Int64], Maybe (Lambda rep))
- Futhark.CodeGen.ImpGen: lookupArray :: VName -> ImpM lore r op ArrayEntry
+ Futhark.CodeGen.ImpGen: lookupArray :: VName -> ImpM rep r op ArrayEntry
- Futhark.CodeGen.ImpGen: lookupMemory :: VName -> ImpM lore r op MemEntry
+ Futhark.CodeGen.ImpGen: lookupMemory :: VName -> ImpM rep r op MemEntry
- Futhark.CodeGen.ImpGen: lookupVar :: VName -> ImpM lore r op (VarEntry lore)
+ Futhark.CodeGen.ImpGen: lookupVar :: VName -> ImpM rep r op (VarEntry rep)
- Futhark.CodeGen.ImpGen: nameForFun :: String -> ImpM lore r op Name
+ Futhark.CodeGen.ImpGen: nameForFun :: String -> ImpM rep r op Name
- Futhark.CodeGen.ImpGen: newVNameForFun :: String -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: newVNameForFun :: String -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sAlloc :: String -> Count Bytes (TExp Int64) -> Space -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sAlloc :: String -> Count Bytes (TExp Int64) -> Space -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sAllocArray :: String -> PrimType -> ShapeBase SubExp -> Space -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sAllocArray :: String -> PrimType -> ShapeBase SubExp -> Space -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sAllocArrayPerm :: String -> PrimType -> ShapeBase SubExp -> Space -> [Int] -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sAllocArrayPerm :: String -> PrimType -> ShapeBase SubExp -> Space -> [Int] -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sAlloc_ :: VName -> Count Bytes (TExp Int64) -> Space -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sAlloc_ :: VName -> Count Bytes (TExp Int64) -> Space -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sArray :: String -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sArray :: String -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sArrayInMem :: String -> PrimType -> ShapeBase SubExp -> VName -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sArrayInMem :: String -> PrimType -> ShapeBase SubExp -> VName -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sComment :: String -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sComment :: String -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sDeclareMem :: String -> Space -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sDeclareMem :: String -> Space -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sFor :: String -> TExp t -> (TExp t -> ImpM lore r op ()) -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sFor :: String -> TExp t -> (TExp t -> ImpM rep r op ()) -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sIf :: TExp Bool -> ImpM lore r op () -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sIf :: TExp Bool -> ImpM rep r op () -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sLoopNest :: Shape -> ([TExp Int64] -> ImpM lore r op ()) -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sLoopNest :: Shape -> ([TExp Int64] -> ImpM rep r op ()) -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sOp :: op -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sOp :: op -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sStaticArray :: String -> Space -> PrimType -> ArrayContents -> ImpM lore r op VName
+ Futhark.CodeGen.ImpGen: sStaticArray :: String -> Space -> PrimType -> ArrayContents -> ImpM rep r op VName
- Futhark.CodeGen.ImpGen: sUnless :: TExp Bool -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sUnless :: TExp Bool -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sUpdate :: VName -> Slice (TExp Int64) -> SubExp -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sUpdate :: VName -> Slice (TExp Int64) -> SubExp -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sWhen :: TExp Bool -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sWhen :: TExp Bool -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sWhile :: TExp Bool -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sWhile :: TExp Bool -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: sWrite :: VName -> [TExp Int64] -> Exp -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: sWrite :: VName -> [TExp Int64] -> Exp -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: subImpM :: r' -> Operations lore r' op' -> ImpM lore r' op' a -> ImpM lore r op (a, Code op')
+ Futhark.CodeGen.ImpGen: subImpM :: r' -> Operations rep r' op' -> ImpM rep r' op' a -> ImpM rep r op (a, Code op')
- Futhark.CodeGen.ImpGen: subImpM_ :: r' -> Operations lore r' op' -> ImpM lore r' op' a -> ImpM lore r op (Code op')
+ Futhark.CodeGen.ImpGen: subImpM_ :: r' -> Operations rep r' op' -> ImpM rep r' op' a -> ImpM rep r op (Code op')
- Futhark.CodeGen.ImpGen: toExp :: ToExp a => a -> ImpM lore r op Exp
+ Futhark.CodeGen.ImpGen: toExp :: ToExp a => a -> ImpM rep r op Exp
- Futhark.CodeGen.ImpGen: type AllocCompiler lore r op = VName -> Count Bytes (TExp Int64) -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: type AllocCompiler rep r op = VName -> Count Bytes (TExp Int64) -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type CopyCompiler lore r op = PrimType -> MemLocation -> Slice (TExp Int64) -> MemLocation -> Slice (TExp Int64) -> ImpM lore r op ()
+ 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 ExpCompiler lore r op = Pattern lore -> Exp lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: type ExpCompiler rep r op = Pattern rep -> Exp rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type OpCompiler lore r op = Pattern lore -> Op lore -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: type OpCompiler rep r op = Pattern rep -> Op rep -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type StmsCompiler lore r op = Names -> Stms lore -> ImpM lore r op () -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: type StmsCompiler rep r op = Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen: type VTable lore = Map VName (VarEntry lore)
+ Futhark.CodeGen.ImpGen: type VTable rep = Map VName (VarEntry rep)
- Futhark.CodeGen.ImpGen: warn :: Located loc => loc -> [loc] -> String -> ImpM lore r op ()
+ Futhark.CodeGen.ImpGen: warn :: Located loc => loc -> [loc] -> String -> ImpM rep r op ()
- Futhark.CodeGen.ImpGen.CUDA: compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, Program)
+ Futhark.CodeGen.ImpGen.CUDA: compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, Program)
- Futhark.CodeGen.ImpGen.Multicore.Base: AtomicCAS :: DoAtomicUpdate lore r -> AtomicUpdate lore r
+ Futhark.CodeGen.ImpGen.Multicore.Base: AtomicCAS :: DoAtomicUpdate rep r -> AtomicUpdate rep r
- Futhark.CodeGen.ImpGen.Multicore.Base: AtomicLocking :: (Locking -> DoAtomicUpdate lore r) -> AtomicUpdate lore r
+ Futhark.CodeGen.ImpGen.Multicore.Base: AtomicLocking :: (Locking -> DoAtomicUpdate rep r) -> AtomicUpdate rep r
- Futhark.CodeGen.ImpGen.Multicore.Base: AtomicPrim :: DoAtomicUpdate lore r -> AtomicUpdate lore r
+ Futhark.CodeGen.ImpGen.Multicore.Base: AtomicPrim :: DoAtomicUpdate rep r -> AtomicUpdate rep r
- Futhark.CodeGen.ImpGen.Multicore.Base: data AtomicUpdate lore r
+ Futhark.CodeGen.ImpGen.Multicore.Base: data AtomicUpdate rep r
- Futhark.CodeGen.ImpGen.Multicore.Base: decideScheduling' :: SegOp () lore -> Code -> Scheduling
+ Futhark.CodeGen.ImpGen.Multicore.Base: decideScheduling' :: SegOp () rep -> Code -> Scheduling
- Futhark.CodeGen.ImpGen.OpenCL: compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, Program)
+ Futhark.CodeGen.ImpGen.OpenCL: compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, Program)
- Futhark.Compiler: runCompilerOnProgram :: FutharkConfig -> Pipeline SOACS lore -> Action lore -> FilePath -> IO ()
+ Futhark.Compiler: runCompilerOnProgram :: FutharkConfig -> Pipeline SOACS rep -> Action rep -> FilePath -> IO ()
- Futhark.Compiler: runPipelineOnProgram :: FutharkConfig -> Pipeline SOACS tolore -> FilePath -> FutharkM (Prog tolore)
+ Futhark.Compiler: runPipelineOnProgram :: FutharkConfig -> Pipeline SOACS torep -> FilePath -> FutharkM (Prog torep)
- Futhark.Compiler.CLI: compilerMain :: cfg -> [CompilerOption cfg] -> String -> String -> Pipeline SOACS lore -> (FutharkConfig -> cfg -> CompilerMode -> FilePath -> Prog lore -> FutharkM ()) -> String -> [String] -> IO ()
+ Futhark.Compiler.CLI: compilerMain :: cfg -> [CompilerOption cfg] -> String -> String -> Pipeline SOACS rep -> (FutharkConfig -> cfg -> CompilerMode -> FilePath -> Prog rep -> FutharkM ()) -> String -> [String] -> IO ()
- Futhark.Construct: binOpLambda :: (MonadBinder m, Bindable (Lore m)) => BinOp -> PrimType -> m (Lambda (Lore m))
+ Futhark.Construct: binOpLambda :: (MonadBinder m, Bindable (Rep m)) => BinOp -> PrimType -> m (Lambda (Rep m))
- Futhark.Construct: buildBody :: MonadBinder m => m (Result, a) -> m (Body (Lore m), a)
+ Futhark.Construct: buildBody :: MonadBinder m => m (Result, a) -> m (Body (Rep m), a)
- Futhark.Construct: buildBody_ :: MonadBinder m => m Result -> m (Body (Lore m))
+ Futhark.Construct: buildBody_ :: MonadBinder m => m Result -> m (Body (Rep m))
- Futhark.Construct: cmpOpLambda :: (MonadBinder m, Bindable (Lore m)) => CmpOp -> m (Lambda (Lore m))
+ Futhark.Construct: cmpOpLambda :: (MonadBinder m, Bindable (Rep m)) => CmpOp -> m (Lambda (Rep m))
- Futhark.Construct: eAll :: MonadBinder m => [SubExp] -> m (Exp (Lore m))
+ Futhark.Construct: eAll :: MonadBinder m => [SubExp] -> m (Exp (Rep m))
- Futhark.Construct: eBinOp :: MonadBinder m => BinOp -> m (Exp (Lore m)) -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eBinOp :: MonadBinder m => BinOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eBlank :: MonadBinder m => Type -> m (Exp (Lore m))
+ Futhark.Construct: eBlank :: MonadBinder m => Type -> m (Exp (Rep m))
- Futhark.Construct: eBody :: MonadBinder m => [m (Exp (Lore m))] -> m (Body (Lore m))
+ Futhark.Construct: eBody :: MonadBinder m => [m (Exp (Rep m))] -> m (Body (Rep m))
- Futhark.Construct: eCmpOp :: MonadBinder m => CmpOp -> m (Exp (Lore m)) -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eCmpOp :: MonadBinder m => CmpOp -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eConvOp :: MonadBinder m => ConvOp -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eConvOp :: MonadBinder m => ConvOp -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eCopy :: MonadBinder m => m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eCopy :: MonadBinder m => m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eIf :: (MonadBinder m, BranchType (Lore m) ~ ExtType) => m (Exp (Lore m)) -> m (Body (Lore m)) -> m (Body (Lore m)) -> m (Exp (Lore 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' :: (MonadBinder m, BranchType (Lore m) ~ ExtType) => m (Exp (Lore m)) -> m (Body (Lore m)) -> m (Body (Lore m)) -> IfSort -> m (Exp (Lore 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: eLambda :: MonadBinder m => Lambda (Lore m) -> [m (Exp (Lore m))] -> m [SubExp]
+ Futhark.Construct: eLambda :: MonadBinder m => Lambda (Rep m) -> [m (Exp (Rep m))] -> m [SubExp]
- Futhark.Construct: eOutOfBounds :: MonadBinder m => VName -> [m (Exp (Lore m))] -> m (Exp (Lore m))
+ Futhark.Construct: eOutOfBounds :: MonadBinder m => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m))
- Futhark.Construct: eRoundToMultipleOf :: MonadBinder m => IntType -> m (Exp (Lore m)) -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eRoundToMultipleOf :: MonadBinder m => IntType -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSignum :: MonadBinder m => m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eSignum :: MonadBinder m => m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSliceArray :: MonadBinder m => Int -> VName -> m (Exp (Lore m)) -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eSliceArray :: MonadBinder m => Int -> VName -> m (Exp (Rep m)) -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: eSubExp :: MonadBinder m => SubExp -> m (Exp (Lore m))
+ Futhark.Construct: eSubExp :: MonadBinder m => SubExp -> m (Exp (Rep m))
- Futhark.Construct: eWriteArray :: (MonadBinder m, BranchType (Lore m) ~ ExtType) => VName -> [m (Exp (Lore m))] -> m (Exp (Lore m)) -> m (Exp (Lore m))
+ Futhark.Construct: eWriteArray :: (MonadBinder m, BranchType (Rep m) ~ ExtType) => VName -> [m (Exp (Rep m))] -> m (Exp (Rep m)) -> m (Exp (Rep m))
- Futhark.Construct: foldBinOp :: MonadBinder m => BinOp -> SubExp -> [SubExp] -> m (Exp (Lore m))
+ Futhark.Construct: foldBinOp :: MonadBinder m => BinOp -> SubExp -> [SubExp] -> m (Exp (Rep m))
- Futhark.Construct: insertStmsM :: MonadBinder m => m (Body (Lore m)) -> m (Body (Lore m))
+ Futhark.Construct: insertStmsM :: MonadBinder m => m (Body (Rep m)) -> m (Body (Rep m))
- Futhark.Construct: letExp :: MonadBinder m => String -> Exp (Lore m) -> m VName
+ Futhark.Construct: letExp :: MonadBinder m => String -> Exp (Rep m) -> m VName
- Futhark.Construct: letInPlace :: MonadBinder m => String -> VName -> Slice SubExp -> Exp (Lore m) -> m VName
+ Futhark.Construct: letInPlace :: MonadBinder m => String -> VName -> Slice SubExp -> Exp (Rep m) -> m VName
- Futhark.Construct: letSubExp :: MonadBinder m => String -> Exp (Lore m) -> m SubExp
+ Futhark.Construct: letSubExp :: MonadBinder m => String -> Exp (Rep m) -> m SubExp
- Futhark.Construct: letSubExps :: MonadBinder m => String -> [Exp (Lore m)] -> m [SubExp]
+ Futhark.Construct: letSubExps :: MonadBinder m => String -> [Exp (Rep m)] -> m [SubExp]
- Futhark.Construct: letTupExp :: MonadBinder m => String -> Exp (Lore m) -> m [VName]
+ Futhark.Construct: letTupExp :: MonadBinder m => String -> Exp (Rep m) -> m [VName]
- Futhark.Construct: letTupExp' :: MonadBinder m => String -> Exp (Lore m) -> m [SubExp]
+ Futhark.Construct: letTupExp' :: MonadBinder m => String -> Exp (Rep m) -> m [SubExp]
- Futhark.Construct: mapResult :: Bindable lore => (Result -> Body lore) -> Body lore -> Body lore
+ Futhark.Construct: mapResult :: Bindable rep => (Result -> Body rep) -> Body rep -> Body rep
- Futhark.Construct: mkLambda :: MonadBinder m => [LParam (Lore m)] -> m Result -> m (Lambda (Lore m))
+ Futhark.Construct: mkLambda :: MonadBinder m => [LParam (Rep m)] -> m Result -> m (Lambda (Rep m))
- Futhark.Construct: resultBody :: Bindable lore => [SubExp] -> Body lore
+ Futhark.Construct: resultBody :: Bindable rep => [SubExp] -> Body rep
- Futhark.Construct: resultBodyM :: MonadBinder m => [SubExp] -> m (Body (Lore m))
+ Futhark.Construct: resultBodyM :: MonadBinder m => [SubExp] -> m (Body (Rep m))
- Futhark.Construct: simpleMkLetNames :: (ExpDec lore ~ (), LetDec lore ~ Type, MonadFreshNames m, TypedOp (Op lore), HasScope lore m) => [VName] -> Exp lore -> m (Stm lore)
+ Futhark.Construct: simpleMkLetNames :: (ExpDec rep ~ (), LetDec rep ~ Type, MonadFreshNames m, TypedOp (Op rep), HasScope rep m) => [VName] -> Exp rep -> m (Stm rep)
- Futhark.Construct: toExp :: (ToExp a, MonadBinder m) => a -> m (Exp (Lore m))
+ Futhark.Construct: toExp :: (ToExp a, MonadBinder m) => a -> m (Exp (Rep m))
- Futhark.IR.Aliases: addAliasesToPattern :: (ASTLore lore, CanBeAliased (Op lore), Typed dec) => PatternT dec -> Exp (Aliases lore) -> PatternT (VarAliases, dec)
+ Futhark.IR.Aliases: addAliasesToPattern :: (ASTRep rep, CanBeAliased (Op rep), Typed dec) => PatternT dec -> Exp (Aliases rep) -> PatternT (VarAliases, dec)
- Futhark.IR.Aliases: data Aliases lore
+ Futhark.IR.Aliases: data Aliases rep
- Futhark.IR.Aliases: mkAliasedBody :: (ASTLore lore, CanBeAliased (Op lore)) => BodyDec lore -> Stms (Aliases lore) -> Result -> Body (Aliases lore)
+ Futhark.IR.Aliases: mkAliasedBody :: (ASTRep rep, CanBeAliased (Op rep)) => BodyDec rep -> Stms (Aliases rep) -> Result -> Body (Aliases rep)
- Futhark.IR.Aliases: mkAliasedLetStm :: (ASTLore lore, CanBeAliased (Op lore)) => Pattern lore -> StmAux (ExpDec lore) -> Exp (Aliases lore) -> Stm (Aliases lore)
+ Futhark.IR.Aliases: mkAliasedLetStm :: (ASTRep rep, CanBeAliased (Op rep)) => Pattern rep -> StmAux (ExpDec rep) -> Exp (Aliases rep) -> Stm (Aliases rep)
- Futhark.IR.Aliases: mkBodyAliases :: Aliased lore => Stms lore -> Result -> BodyAliasing
+ Futhark.IR.Aliases: mkBodyAliases :: Aliased rep => Stms rep -> Result -> BodyAliasing
- Futhark.IR.Aliases: mkPatternAliases :: (Aliased lore, Typed dec) => PatternT dec -> Exp lore -> ([PatElemT (VarAliases, dec)], [PatElemT (VarAliases, dec)])
+ Futhark.IR.Aliases: mkPatternAliases :: (Aliased rep, Typed dec) => PatternT dec -> Exp rep -> ([PatElemT (VarAliases, dec)], [PatElemT (VarAliases, dec)])
- Futhark.IR.Aliases: mkStmsAliases :: Aliased lore => Stms lore -> [SubExp] -> ([Names], Names)
+ Futhark.IR.Aliases: mkStmsAliases :: Aliased rep => Stms rep -> [SubExp] -> ([Names], Names)
- Futhark.IR.Aliases: removeExpAliases :: CanBeAliased (Op lore) => Exp (Aliases lore) -> Exp lore
+ Futhark.IR.Aliases: removeExpAliases :: CanBeAliased (Op rep) => Exp (Aliases rep) -> Exp rep
- Futhark.IR.Aliases: removeFunDefAliases :: CanBeAliased (Op lore) => FunDef (Aliases lore) -> FunDef lore
+ Futhark.IR.Aliases: removeFunDefAliases :: CanBeAliased (Op rep) => FunDef (Aliases rep) -> FunDef rep
- Futhark.IR.Aliases: removeLambdaAliases :: CanBeAliased (Op lore) => Lambda (Aliases lore) -> Lambda lore
+ Futhark.IR.Aliases: removeLambdaAliases :: CanBeAliased (Op rep) => Lambda (Aliases rep) -> Lambda rep
- Futhark.IR.Aliases: removeProgAliases :: CanBeAliased (Op lore) => Prog (Aliases lore) -> Prog lore
+ Futhark.IR.Aliases: removeProgAliases :: CanBeAliased (Op rep) => Prog (Aliases rep) -> Prog rep
- Futhark.IR.Aliases: removeScopeAliases :: Scope (Aliases lore) -> Scope lore
+ Futhark.IR.Aliases: removeScopeAliases :: Scope (Aliases rep) -> Scope rep
- Futhark.IR.Aliases: removeStmAliases :: CanBeAliased (Op lore) => Stm (Aliases lore) -> Stm lore
+ Futhark.IR.Aliases: removeStmAliases :: CanBeAliased (Op rep) => Stm (Aliases rep) -> Stm rep
- Futhark.IR.Aliases: trackAliases :: Aliased lore => AliasesAndConsumed -> Stm lore -> AliasesAndConsumed
+ Futhark.IR.Aliases: trackAliases :: Aliased rep => AliasesAndConsumed -> Stm rep -> AliasesAndConsumed
- Futhark.IR.MC: Hist :: SubExp -> [HistOp lore] -> Lambda lore -> [VName] -> SOAC lore
+ Futhark.IR.MC: Hist :: SubExp -> [HistOp rep] -> Lambda rep -> [VName] -> SOAC rep
- Futhark.IR.MC: Parallel :: StreamOrd -> Commutativity -> Lambda lore -> StreamForm lore
+ Futhark.IR.MC: Parallel :: StreamOrd -> Commutativity -> Lambda rep -> StreamForm rep
- Futhark.IR.MC: Reduce :: Commutativity -> Lambda lore -> [SubExp] -> Reduce lore
+ Futhark.IR.MC: Reduce :: Commutativity -> Lambda rep -> [SubExp] -> Reduce rep
- Futhark.IR.MC: SOACMapper :: (SubExp -> m SubExp) -> (Lambda flore -> m (Lambda tlore)) -> (VName -> m VName) -> SOACMapper flore tlore m
+ Futhark.IR.MC: SOACMapper :: (SubExp -> m SubExp) -> (Lambda frep -> m (Lambda trep)) -> (VName -> m VName) -> SOACMapper frep trep m
- Futhark.IR.MC: Scan :: Lambda lore -> [SubExp] -> Scan lore
+ Futhark.IR.MC: Scan :: Lambda rep -> [SubExp] -> Scan rep
- Futhark.IR.MC: Scatter :: SubExp -> Lambda lore -> [VName] -> [(Shape, Int, VName)] -> SOAC lore
+ Futhark.IR.MC: Scatter :: SubExp -> Lambda rep -> [VName] -> [(Shape, Int, VName)] -> SOAC rep
- Futhark.IR.MC: Screma :: SubExp -> [VName] -> ScremaForm lore -> SOAC lore
+ Futhark.IR.MC: Screma :: SubExp -> [VName] -> ScremaForm rep -> SOAC rep
- Futhark.IR.MC: ScremaForm :: [Scan lore] -> [Reduce lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.MC: ScremaForm :: [Scan rep] -> [Reduce rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.MC: Sequential :: StreamForm lore
+ Futhark.IR.MC: Sequential :: StreamForm rep
- Futhark.IR.MC: Stream :: SubExp -> [VName] -> StreamForm lore -> [SubExp] -> Lambda lore -> SOAC lore
+ Futhark.IR.MC: Stream :: SubExp -> [VName] -> StreamForm rep -> [SubExp] -> Lambda rep -> SOAC rep
- Futhark.IR.MC: [mapOnSOACLambda] :: SOACMapper flore tlore m -> Lambda flore -> m (Lambda tlore)
+ Futhark.IR.MC: [mapOnSOACLambda] :: SOACMapper frep trep m -> Lambda frep -> m (Lambda trep)
- Futhark.IR.MC: [mapOnSOACSubExp] :: SOACMapper flore tlore m -> SubExp -> m SubExp
+ Futhark.IR.MC: [mapOnSOACSubExp] :: SOACMapper frep trep m -> SubExp -> m SubExp
- Futhark.IR.MC: [mapOnSOACVName] :: SOACMapper flore tlore m -> VName -> m VName
+ Futhark.IR.MC: [mapOnSOACVName] :: SOACMapper frep trep m -> VName -> m VName
- Futhark.IR.MC: [redComm] :: Reduce lore -> Commutativity
+ Futhark.IR.MC: [redComm] :: Reduce rep -> Commutativity
- Futhark.IR.MC: [redLambda] :: Reduce lore -> Lambda lore
+ Futhark.IR.MC: [redLambda] :: Reduce rep -> Lambda rep
- Futhark.IR.MC: [redNeutral] :: Reduce lore -> [SubExp]
+ Futhark.IR.MC: [redNeutral] :: Reduce rep -> [SubExp]
- Futhark.IR.MC: [scanLambda] :: Scan lore -> Lambda lore
+ Futhark.IR.MC: [scanLambda] :: Scan rep -> Lambda rep
- Futhark.IR.MC: [scanNeutral] :: Scan lore -> [SubExp]
+ Futhark.IR.MC: [scanNeutral] :: Scan rep -> [SubExp]
- Futhark.IR.MC: data Reduce lore
+ Futhark.IR.MC: data Reduce rep
- Futhark.IR.MC: data SOAC lore
+ Futhark.IR.MC: data SOAC rep
- Futhark.IR.MC: data SOACMapper flore tlore m
+ Futhark.IR.MC: data SOACMapper frep trep m
- Futhark.IR.MC: data Scan lore
+ Futhark.IR.MC: data Scan rep
- Futhark.IR.MC: data ScremaForm lore
+ Futhark.IR.MC: data ScremaForm rep
- Futhark.IR.MC: data StreamForm lore
+ Futhark.IR.MC: data StreamForm rep
- Futhark.IR.MC: identitySOACMapper :: Monad m => SOACMapper lore lore m
+ Futhark.IR.MC: identitySOACMapper :: Monad m => SOACMapper rep rep m
- Futhark.IR.MC: isIdentityLambda :: Lambda lore -> Bool
+ Futhark.IR.MC: isIdentityLambda :: Lambda rep -> Bool
- Futhark.IR.MC: isMapSOAC :: ScremaForm lore -> Maybe (Lambda lore)
+ Futhark.IR.MC: isMapSOAC :: ScremaForm rep -> Maybe (Lambda rep)
- Futhark.IR.MC: isRedomapSOAC :: ScremaForm lore -> Maybe ([Reduce lore], Lambda lore)
+ Futhark.IR.MC: isRedomapSOAC :: ScremaForm rep -> Maybe ([Reduce rep], Lambda rep)
- Futhark.IR.MC: isReduceSOAC :: ScremaForm lore -> Maybe [Reduce lore]
+ Futhark.IR.MC: isReduceSOAC :: ScremaForm rep -> Maybe [Reduce rep]
- Futhark.IR.MC: isScanSOAC :: ScremaForm lore -> Maybe [Scan lore]
+ Futhark.IR.MC: isScanSOAC :: ScremaForm rep -> Maybe [Scan rep]
- Futhark.IR.MC: isScanomapSOAC :: ScremaForm lore -> Maybe ([Scan lore], Lambda lore)
+ Futhark.IR.MC: isScanomapSOAC :: ScremaForm rep -> Maybe ([Scan rep], Lambda rep)
- Futhark.IR.MC: mapSOAC :: Lambda lore -> ScremaForm lore
+ Futhark.IR.MC: mapSOAC :: Lambda rep -> ScremaForm rep
- Futhark.IR.MC: mapSOACM :: (Applicative m, Monad m) => SOACMapper flore tlore m -> SOAC flore -> m (SOAC tlore)
+ Futhark.IR.MC: mapSOACM :: (Applicative m, Monad m) => SOACMapper frep trep m -> SOAC frep -> m (SOAC trep)
- Futhark.IR.MC: mkIdentityLambda :: (Bindable lore, MonadFreshNames m) => [Type] -> m (Lambda lore)
+ Futhark.IR.MC: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
- Futhark.IR.MC: nilFn :: Bindable lore => Lambda lore
+ Futhark.IR.MC: nilFn :: Bindable rep => Lambda rep
- Futhark.IR.MC: ppHist :: (PrettyLore lore, Pretty inp) => SubExp -> [HistOp lore] -> Lambda lore -> [inp] -> Doc
+ Futhark.IR.MC: ppHist :: (PrettyRep rep, Pretty inp) => SubExp -> [HistOp rep] -> Lambda rep -> [inp] -> Doc
- Futhark.IR.MC: ppScrema :: (PrettyLore lore, Pretty inp) => SubExp -> [inp] -> ScremaForm lore -> Doc
+ Futhark.IR.MC: ppScrema :: (PrettyRep rep, Pretty inp) => SubExp -> [inp] -> ScremaForm rep -> Doc
- Futhark.IR.MC: redResults :: [Reduce lore] -> Int
+ Futhark.IR.MC: redResults :: [Reduce rep] -> Int
- Futhark.IR.MC: redomapSOAC :: [Reduce lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.MC: redomapSOAC :: [Reduce rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.MC: reduceSOAC :: (Bindable lore, MonadFreshNames m) => [Reduce lore] -> m (ScremaForm lore)
+ Futhark.IR.MC: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
- Futhark.IR.MC: scanResults :: [Scan lore] -> Int
+ Futhark.IR.MC: scanResults :: [Scan rep] -> Int
- Futhark.IR.MC: scanSOAC :: (Bindable lore, MonadFreshNames m) => [Scan lore] -> m (ScremaForm lore)
+ Futhark.IR.MC: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
- Futhark.IR.MC: scanomapSOAC :: [Scan lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.MC: scanomapSOAC :: [Scan rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.MC: scremaType :: SubExp -> ScremaForm lore -> [Type]
+ Futhark.IR.MC: scremaType :: SubExp -> ScremaForm rep -> [Type]
- Futhark.IR.MC: singleReduce :: Bindable lore => [Reduce lore] -> Reduce lore
+ Futhark.IR.MC: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
- Futhark.IR.MC: singleScan :: Bindable lore => [Scan lore] -> Scan lore
+ Futhark.IR.MC: singleScan :: Bindable rep => [Scan rep] -> Scan rep
- Futhark.IR.MC: soacType :: SOAC lore -> [Type]
+ Futhark.IR.MC: soacType :: SOAC rep -> [Type]
- Futhark.IR.MC: typeCheckSOAC :: Checkable lore => SOAC (Aliases lore) -> TypeM lore ()
+ Futhark.IR.MC: typeCheckSOAC :: Checkable rep => SOAC (Aliases rep) -> TypeM rep ()
- Futhark.IR.MC.Op: OtherOp :: op -> MCOp lore op
+ Futhark.IR.MC.Op: OtherOp :: op -> MCOp rep op
- Futhark.IR.MC.Op: ParOp :: Maybe (SegOp () lore) -> SegOp () lore -> MCOp lore op
+ Futhark.IR.MC.Op: ParOp :: Maybe (SegOp () rep) -> SegOp () rep -> MCOp rep op
- Futhark.IR.MC.Op: data MCOp lore op
+ Futhark.IR.MC.Op: data MCOp rep op
- Futhark.IR.MC.Op: simplifyMCOp :: (SimplifiableLore lore, BodyDec lore ~ ()) => SimplifyOp lore op -> MCOp lore op -> SimpleM lore (MCOp (Wise lore) (OpWithWisdom op), Stms (Wise lore))
+ Futhark.IR.MC.Op: simplifyMCOp :: (SimplifiableRep rep, BodyDec rep ~ ()) => SimplifyOp rep op -> MCOp rep op -> SimpleM rep (MCOp (Wise rep) (OpWithWisdom op), Stms (Wise rep))
- Futhark.IR.MC.Op: typeCheckMCOp :: Checkable lore => (op -> TypeM lore ()) -> MCOp (Aliases lore) op -> TypeM lore ()
+ Futhark.IR.MC.Op: typeCheckMCOp :: Checkable rep => (op -> TypeM rep ()) -> MCOp (Aliases rep) op -> TypeM rep ()
- Futhark.IR.Mem: checkMemInfo :: Checkable lore => VName -> MemInfo SubExp u MemBind -> TypeM lore ()
+ Futhark.IR.Mem: checkMemInfo :: Checkable rep => VName -> MemInfo SubExp u MemBind -> TypeM rep ()
- Futhark.IR.Mem: class TypedOp (Op lore) => OpReturns lore
+ Futhark.IR.Mem: class TypedOp (Op rep) => OpReturns rep
- Futhark.IR.Mem: expReturns :: (Monad m, LocalScope lore m, Mem lore) => Exp lore -> m [ExpReturns]
+ Futhark.IR.Mem: expReturns :: (Monad m, LocalScope rep m, Mem rep) => Exp rep -> m [ExpReturns]
- Futhark.IR.Mem: lookupArraySummary :: (Mem lore, HasScope lore m, Monad m) => VName -> m (VName, IxFun (TPrimExp Int64 VName))
+ Futhark.IR.Mem: lookupArraySummary :: (Mem rep, HasScope rep m, Monad m) => VName -> m (VName, IxFun (TPrimExp Int64 VName))
- Futhark.IR.Mem: lookupMemInfo :: (HasScope lore m, Mem lore) => VName -> m (MemInfo SubExp NoUniqueness MemBind)
+ Futhark.IR.Mem: lookupMemInfo :: (HasScope rep m, Mem rep) => VName -> m (MemInfo SubExp NoUniqueness MemBind)
- Futhark.IR.Mem: matchBranchReturnType :: (Mem lore, Checkable lore) => [BodyReturns] -> Body (Aliases lore) -> TypeM lore ()
+ Futhark.IR.Mem: matchBranchReturnType :: (Mem rep, Checkable rep) => [BodyReturns] -> Body (Aliases rep) -> TypeM rep ()
- Futhark.IR.Mem: matchFunctionReturnType :: (Mem lore, Checkable lore) => [FunReturns] -> Result -> TypeM lore ()
+ Futhark.IR.Mem: matchFunctionReturnType :: (Mem rep, Checkable rep) => [FunReturns] -> Result -> TypeM rep ()
- Futhark.IR.Mem: matchLoopResultMem :: (Mem lore, Checkable lore) => [FParam (Aliases lore)] -> [FParam (Aliases lore)] -> [SubExp] -> TypeM lore ()
+ Futhark.IR.Mem: matchLoopResultMem :: (Mem rep, Checkable rep) => [FParam (Aliases rep)] -> [FParam (Aliases rep)] -> [SubExp] -> TypeM rep ()
- Futhark.IR.Mem: matchPatternToExp :: (Mem lore, Checkable lore) => Pattern (Aliases lore) -> Exp (Aliases lore) -> TypeM lore ()
+ Futhark.IR.Mem: matchPatternToExp :: (Mem rep, Checkable rep) => Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
- Futhark.IR.Mem: opReturns :: (OpReturns lore, Monad m, HasScope lore m) => Op lore -> m [ExpReturns]
+ Futhark.IR.Mem: opReturns :: (OpReturns rep, Monad m, HasScope rep m) => Op rep -> m [ExpReturns]
- Futhark.IR.Mem: subExpMemInfo :: (HasScope lore m, Monad m, Mem lore) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind)
+ Futhark.IR.Mem: subExpMemInfo :: (HasScope rep m, Monad m, Mem rep) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind)
- Futhark.IR.Mem: type Mem lore = (AllocOp (Op lore), FParamInfo lore ~ FParamMem, LParamInfo lore ~ LParamMem, LetDec lore ~ LetDecMem, RetType lore ~ RetTypeMem, BranchType lore ~ BranchTypeMem, ASTLore lore, Decorations lore, OpReturns lore)
+ 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: varReturns :: (HasScope lore m, Monad m, Mem lore) => VName -> m ExpReturns
+ Futhark.IR.Mem: varReturns :: (HasScope rep m, Monad m, Mem rep) => VName -> m ExpReturns
- Futhark.IR.Mem.Simplify: simpleGeneric :: (SimplifyMemory lore, Op lore ~ MemOp inner) => (OpWithWisdom inner -> UsageTable) -> SimplifyOp lore inner -> SimpleOps lore
+ Futhark.IR.Mem.Simplify: simpleGeneric :: (SimplifyMemory rep, Op rep ~ MemOp inner) => (OpWithWisdom inner -> UsageTable) -> SimplifyOp rep inner -> SimpleOps rep
- Futhark.IR.Mem.Simplify: simplifyProgGeneric :: (SimplifyMemory lore, Op lore ~ MemOp inner) => SimpleOps lore -> Prog lore -> PassM (Prog lore)
+ Futhark.IR.Mem.Simplify: simplifyProgGeneric :: (SimplifyMemory rep, Op rep ~ MemOp inner) => SimpleOps rep -> Prog rep -> PassM (Prog rep)
- Futhark.IR.Mem.Simplify: simplifyStmsGeneric :: (HasScope lore m, MonadFreshNames m, SimplifyMemory lore, Op lore ~ MemOp inner) => SimpleOps lore -> Stms lore -> m (SymbolTable (Wise lore), Stms lore)
+ 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: type SimplifyMemory lore = (SimplifiableLore lore, ExpDec lore ~ (), BodyDec lore ~ (), AllocOp (Op (Wise lore)), CanBeWise (Op lore), BinderOps (Wise lore), Mem lore)
+ 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.Prop: asBasicOp :: Exp lore -> Maybe BasicOp
+ Futhark.IR.Prop: asBasicOp :: Exp rep -> Maybe BasicOp
- Futhark.IR.Prop: certify :: Certificates -> Stm lore -> Stm lore
+ Futhark.IR.Prop: certify :: Certificates -> Stm rep -> Stm rep
- Futhark.IR.Prop: commutativeLambda :: Lambda lore -> Bool
+ Futhark.IR.Prop: commutativeLambda :: Lambda rep -> Bool
- Futhark.IR.Prop: expTypesFromPattern :: (ASTLore lore, HasScope lore m, Monad m) => Pattern lore -> m [BranchType lore]
+ Futhark.IR.Prop: expTypesFromPattern :: (ASTRep rep, HasScope rep m, Monad m) => Pattern rep -> m [BranchType rep]
- Futhark.IR.Prop: safeExp :: IsOp (Op lore) => Exp lore -> Bool
+ Futhark.IR.Prop: safeExp :: IsOp (Op rep) => Exp rep -> Bool
- Futhark.IR.Prop: stmCerts :: Stm lore -> Certificates
+ Futhark.IR.Prop: stmCerts :: Stm rep -> Certificates
- Futhark.IR.Prop.Aliases: bodyAliases :: Aliased lore => Body lore -> [Names]
+ Futhark.IR.Prop.Aliases: bodyAliases :: Aliased rep => Body rep -> [Names]
- Futhark.IR.Prop.Aliases: class (Decorations lore, AliasedOp (Op lore), AliasesOf (LetDec lore)) => Aliased lore
+ Futhark.IR.Prop.Aliases: class (RepTypes rep, AliasedOp (Op rep), AliasesOf (LetDec rep)) => Aliased rep
- Futhark.IR.Prop.Aliases: consumedByLambda :: Aliased lore => Lambda lore -> Names
+ Futhark.IR.Prop.Aliases: consumedByLambda :: Aliased rep => Lambda rep -> Names
- Futhark.IR.Prop.Aliases: consumedInBody :: Aliased lore => Body lore -> Names
+ Futhark.IR.Prop.Aliases: consumedInBody :: Aliased rep => Body rep -> Names
- Futhark.IR.Prop.Aliases: consumedInExp :: Aliased lore => Exp lore -> Names
+ Futhark.IR.Prop.Aliases: consumedInExp :: Aliased rep => Exp rep -> Names
- Futhark.IR.Prop.Aliases: consumedInStm :: Aliased lore => Stm lore -> Names
+ Futhark.IR.Prop.Aliases: consumedInStm :: Aliased rep => Stm rep -> Names
- Futhark.IR.Prop.Aliases: expAliases :: Aliased lore => Exp lore -> [Names]
+ Futhark.IR.Prop.Aliases: expAliases :: Aliased rep => Exp rep -> [Names]
- Futhark.IR.Prop.Aliases: lookupAliases :: AliasesOf (LetDec lore) => VName -> Scope lore -> Names
+ Futhark.IR.Prop.Aliases: lookupAliases :: AliasesOf (LetDec rep) => VName -> Scope rep -> Names
- Futhark.IR.Prop.Names: boundByLambda :: Lambda lore -> [VName]
+ Futhark.IR.Prop.Names: boundByLambda :: Lambda rep -> [VName]
- Futhark.IR.Prop.Names: boundByStm :: Stm lore -> Names
+ Futhark.IR.Prop.Names: boundByStm :: Stm rep -> Names
- Futhark.IR.Prop.Names: boundByStms :: Stms lore -> Names
+ Futhark.IR.Prop.Names: boundByStms :: Stms rep -> Names
- Futhark.IR.Prop.Names: boundInBody :: Body lore -> Names
+ Futhark.IR.Prop.Names: boundInBody :: Body rep -> Names
- Futhark.IR.Prop.Names: freeInStmsAndRes :: (FreeIn (Op lore), FreeIn (LetDec lore), FreeIn (LParamInfo lore), FreeIn (FParamInfo lore), FreeDec (BodyDec lore), FreeIn (RetType lore), FreeIn (BranchType lore), FreeDec (ExpDec lore)) => Stms lore -> Result -> FV
+ Futhark.IR.Prop.Names: freeInStmsAndRes :: (FreeIn (Op rep), FreeIn (LetDec rep), FreeIn (LParamInfo rep), FreeIn (FParamInfo rep), FreeDec (BodyDec rep), FreeIn (RetType rep), FreeIn (BranchType rep), FreeDec (ExpDec rep)) => Stms rep -> Result -> FV
- Futhark.IR.Prop.Reshape: shapeCoerce :: [SubExp] -> VName -> Exp lore
+ Futhark.IR.Prop.Reshape: shapeCoerce :: [SubExp] -> VName -> Exp rep
- Futhark.IR.Prop.Scope: FParamName :: FParamInfo lore -> NameInfo lore
+ Futhark.IR.Prop.Scope: FParamName :: FParamInfo rep -> NameInfo rep
- Futhark.IR.Prop.Scope: IndexName :: IntType -> NameInfo lore
+ Futhark.IR.Prop.Scope: IndexName :: IntType -> NameInfo rep
- Futhark.IR.Prop.Scope: LParamName :: LParamInfo lore -> NameInfo lore
+ Futhark.IR.Prop.Scope: LParamName :: LParamInfo rep -> NameInfo rep
- Futhark.IR.Prop.Scope: LetName :: LetDec lore -> NameInfo lore
+ Futhark.IR.Prop.Scope: LetName :: LetDec rep -> NameInfo rep
- Futhark.IR.Prop.Scope: askScope :: HasScope lore m => m (Scope lore)
+ Futhark.IR.Prop.Scope: askScope :: HasScope rep m => m (Scope rep)
- Futhark.IR.Prop.Scope: asksScope :: HasScope lore m => (Scope lore -> a) -> m a
+ Futhark.IR.Prop.Scope: asksScope :: HasScope rep m => (Scope rep -> a) -> m a
- Futhark.IR.Prop.Scope: castScope :: SameScope fromlore tolore => Scope fromlore -> Scope tolore
+ Futhark.IR.Prop.Scope: castScope :: SameScope fromrep torep => Scope fromrep -> Scope torep
- Futhark.IR.Prop.Scope: class (Applicative m, Decorations lore) => HasScope lore m | m -> lore
+ Futhark.IR.Prop.Scope: class (Applicative m, RepTypes rep) => HasScope rep m | m -> rep
- Futhark.IR.Prop.Scope: class (HasScope lore m, Monad m) => LocalScope lore m
+ Futhark.IR.Prop.Scope: class (HasScope rep m, Monad m) => LocalScope rep m
- Futhark.IR.Prop.Scope: class Scoped lore a | a -> lore
+ Futhark.IR.Prop.Scope: class Scoped rep a | a -> rep
- Futhark.IR.Prop.Scope: data ExtendedScope lore m a
+ Futhark.IR.Prop.Scope: data ExtendedScope rep m a
- Futhark.IR.Prop.Scope: data NameInfo lore
+ Futhark.IR.Prop.Scope: data NameInfo rep
- Futhark.IR.Prop.Scope: extendedScope :: ExtendedScope lore m a -> Scope lore -> m a
+ Futhark.IR.Prop.Scope: extendedScope :: ExtendedScope rep m a -> Scope rep -> m a
- Futhark.IR.Prop.Scope: inScopeOf :: (Scoped lore a, LocalScope lore m) => a -> m b -> m b
+ Futhark.IR.Prop.Scope: inScopeOf :: (Scoped rep a, LocalScope rep m) => a -> m b -> m b
- Futhark.IR.Prop.Scope: localScope :: LocalScope lore m => Scope lore -> m a -> m a
+ Futhark.IR.Prop.Scope: localScope :: LocalScope rep m => Scope rep -> m a -> m a
- Futhark.IR.Prop.Scope: lookupInfo :: HasScope lore m => VName -> m (NameInfo lore)
+ Futhark.IR.Prop.Scope: lookupInfo :: HasScope rep m => VName -> m (NameInfo rep)
- Futhark.IR.Prop.Scope: lookupType :: HasScope lore m => VName -> m Type
+ Futhark.IR.Prop.Scope: lookupType :: HasScope rep m => VName -> m Type
- Futhark.IR.Prop.Scope: scopeOf :: Scoped lore a => a -> Scope lore
+ Futhark.IR.Prop.Scope: scopeOf :: Scoped rep a => a -> Scope rep
- Futhark.IR.Prop.Scope: scopeOfFParams :: FParamInfo lore ~ dec => [Param dec] -> Scope lore
+ Futhark.IR.Prop.Scope: scopeOfFParams :: FParamInfo rep ~ dec => [Param dec] -> Scope rep
- Futhark.IR.Prop.Scope: scopeOfLParams :: LParamInfo lore ~ dec => [Param dec] -> Scope lore
+ Futhark.IR.Prop.Scope: scopeOfLParams :: LParamInfo rep ~ dec => [Param dec] -> Scope rep
- Futhark.IR.Prop.Scope: scopeOfPatElem :: LetDec lore ~ dec => PatElemT dec -> Scope lore
+ Futhark.IR.Prop.Scope: scopeOfPatElem :: LetDec rep ~ dec => PatElemT dec -> Scope rep
- Futhark.IR.Prop.Scope: scopeOfPattern :: LetDec lore ~ dec => PatternT dec -> Scope lore
+ Futhark.IR.Prop.Scope: scopeOfPattern :: LetDec rep ~ dec => PatternT dec -> Scope rep
- Futhark.IR.Prop.Scope: type SameScope lore1 lore2 = (LetDec lore1 ~ LetDec lore2, FParamInfo lore1 ~ FParamInfo lore2, LParamInfo lore1 ~ LParamInfo lore2)
+ Futhark.IR.Prop.Scope: type SameScope rep1 rep2 = (LetDec rep1 ~ LetDec rep2, FParamInfo rep1 ~ FParamInfo rep2, LParamInfo rep1 ~ LParamInfo rep2)
- Futhark.IR.Prop.Scope: type Scope lore = Map VName (NameInfo lore)
+ Futhark.IR.Prop.Scope: type Scope rep = Map VName (NameInfo rep)
- Futhark.IR.Prop.TypeOf: expExtType :: (HasScope lore m, TypedOp (Op lore)) => Exp lore -> m [ExtType]
+ Futhark.IR.Prop.TypeOf: expExtType :: (HasScope rep m, TypedOp (Op rep)) => Exp rep -> m [ExtType]
- Futhark.IR.Prop.TypeOf: expExtTypeSize :: (Decorations lore, TypedOp (Op lore)) => Exp lore -> Int
+ Futhark.IR.Prop.TypeOf: expExtTypeSize :: (RepTypes rep, TypedOp (Op rep)) => Exp rep -> Int
- Futhark.IR.Prop.TypeOf: mapType :: SubExp -> Lambda lore -> [Type]
+ Futhark.IR.Prop.TypeOf: mapType :: SubExp -> Lambda rep -> [Type]
- Futhark.IR.Prop.TypeOf: primOpType :: HasScope lore m => BasicOp -> m [Type]
+ Futhark.IR.Prop.TypeOf: primOpType :: HasScope rep m => BasicOp -> m [Type]
- Futhark.IR.SOACS: Apply :: Name -> [(SubExp, Diet)] -> [RetType lore] -> (Safety, SrcLoc, [SrcLoc]) -> ExpT lore
+ Futhark.IR.SOACS: Apply :: Name -> [(SubExp, Diet)] -> [RetType rep] -> (Safety, SrcLoc, [SrcLoc]) -> ExpT rep
- Futhark.IR.SOACS: BasicOp :: BasicOp -> ExpT lore
+ Futhark.IR.SOACS: BasicOp :: BasicOp -> ExpT rep
- Futhark.IR.SOACS: Body :: BodyDec lore -> Stms lore -> Result -> BodyT lore
+ Futhark.IR.SOACS: Body :: BodyDec rep -> Stms rep -> Result -> BodyT rep
- Futhark.IR.SOACS: DoLoop :: [(FParam lore, SubExp)] -> [(FParam lore, SubExp)] -> LoopForm lore -> BodyT lore -> ExpT lore
+ Futhark.IR.SOACS: DoLoop :: [(FParam rep, SubExp)] -> [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
- Futhark.IR.SOACS: ForLoop :: VName -> IntType -> SubExp -> [(LParam lore, VName)] -> LoopForm lore
+ Futhark.IR.SOACS: ForLoop :: VName -> IntType -> SubExp -> [(LParam rep, VName)] -> LoopForm rep
- Futhark.IR.SOACS: FunDef :: Maybe EntryPoint -> Attrs -> Name -> [RetType lore] -> [FParam lore] -> BodyT lore -> FunDef lore
+ Futhark.IR.SOACS: FunDef :: Maybe EntryPoint -> Attrs -> Name -> [RetType rep] -> [FParam rep] -> BodyT rep -> FunDef rep
- Futhark.IR.SOACS: If :: SubExp -> BodyT lore -> BodyT lore -> IfDec (BranchType lore) -> ExpT lore
+ Futhark.IR.SOACS: If :: SubExp -> BodyT rep -> BodyT rep -> IfDec (BranchType rep) -> ExpT rep
- Futhark.IR.SOACS: Lambda :: [LParam lore] -> BodyT lore -> [Type] -> LambdaT lore
+ Futhark.IR.SOACS: Lambda :: [LParam rep] -> BodyT rep -> [Type] -> LambdaT rep
- Futhark.IR.SOACS: Op :: Op lore -> ExpT lore
+ Futhark.IR.SOACS: Op :: Op rep -> ExpT rep
- Futhark.IR.SOACS: Prog :: Stms lore -> [FunDef lore] -> Prog lore
+ Futhark.IR.SOACS: Prog :: Stms rep -> [FunDef rep] -> Prog rep
- Futhark.IR.SOACS: TypeDirect :: EntryPointType
+ Futhark.IR.SOACS: TypeDirect :: Uniqueness -> EntryPointType
- Futhark.IR.SOACS: TypeOpaque :: String -> Int -> EntryPointType
+ Futhark.IR.SOACS: TypeOpaque :: Uniqueness -> String -> Int -> EntryPointType
- Futhark.IR.SOACS: TypeUnsigned :: EntryPointType
+ Futhark.IR.SOACS: TypeUnsigned :: Uniqueness -> EntryPointType
- Futhark.IR.SOACS: WhileLoop :: VName -> LoopForm lore
+ Futhark.IR.SOACS: WhileLoop :: VName -> LoopForm rep
- Futhark.IR.SOACS: WithAcc :: [(Shape, [VName], Maybe (Lambda lore, [SubExp]))] -> Lambda lore -> ExpT lore
+ Futhark.IR.SOACS: WithAcc :: [(Shape, [VName], Maybe (Lambda rep, [SubExp]))] -> Lambda rep -> ExpT rep
- Futhark.IR.SOACS: [funDefAttrs] :: FunDef lore -> Attrs
+ Futhark.IR.SOACS: [funDefAttrs] :: FunDef rep -> Attrs
- Futhark.IR.SOACS: [funDefBody] :: FunDef lore -> BodyT lore
+ Futhark.IR.SOACS: [funDefBody] :: FunDef rep -> BodyT rep
- Futhark.IR.SOACS: [funDefEntryPoint] :: FunDef lore -> Maybe EntryPoint
+ Futhark.IR.SOACS: [funDefEntryPoint] :: FunDef rep -> Maybe EntryPoint
- Futhark.IR.SOACS: [funDefName] :: FunDef lore -> Name
+ Futhark.IR.SOACS: [funDefName] :: FunDef rep -> Name
- Futhark.IR.SOACS: [funDefParams] :: FunDef lore -> [FParam lore]
+ Futhark.IR.SOACS: [funDefParams] :: FunDef rep -> [FParam rep]
- Futhark.IR.SOACS: [funDefRetType] :: FunDef lore -> [RetType lore]
+ Futhark.IR.SOACS: [funDefRetType] :: FunDef rep -> [RetType rep]
- Futhark.IR.SOACS: [progConsts] :: Prog lore -> Stms lore
+ Futhark.IR.SOACS: [progConsts] :: Prog rep -> Stms rep
- Futhark.IR.SOACS: [progFuns] :: Prog lore -> [FunDef lore]
+ Futhark.IR.SOACS: [progFuns] :: Prog rep -> [FunDef rep]
- Futhark.IR.SOACS: data BodyT lore
+ Futhark.IR.SOACS: data BodyT rep
- Futhark.IR.SOACS: data ExpT lore
+ Futhark.IR.SOACS: data ExpT rep
- Futhark.IR.SOACS: data FunDef lore
+ Futhark.IR.SOACS: data FunDef rep
- Futhark.IR.SOACS: data LambdaT lore
+ Futhark.IR.SOACS: data LambdaT rep
- Futhark.IR.SOACS: data LoopForm lore
+ Futhark.IR.SOACS: data LoopForm rep
- Futhark.IR.SOACS: data Prog lore
+ Futhark.IR.SOACS: data Prog rep
- Futhark.IR.SOACS: oneStm :: Stm lore -> Stms lore
+ Futhark.IR.SOACS: oneStm :: Stm rep -> Stms rep
- Futhark.IR.SOACS: pattern Let :: () => Pattern lore -> StmAux (ExpDec lore) -> Exp lore -> Stm lore
+ Futhark.IR.SOACS: pattern Let :: () => Pattern rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
- Futhark.IR.SOACS: stmAux :: Stm lore -> StmAux (ExpDec lore)
+ Futhark.IR.SOACS: stmAux :: Stm rep -> StmAux (ExpDec rep)
- Futhark.IR.SOACS: stmExp :: Stm lore -> Exp lore
+ Futhark.IR.SOACS: stmExp :: Stm rep -> Exp rep
- Futhark.IR.SOACS: stmPattern :: Stm lore -> Pattern lore
+ Futhark.IR.SOACS: stmPattern :: Stm rep -> Pattern rep
- Futhark.IR.SOACS: stmsFromList :: [Stm lore] -> Stms lore
+ Futhark.IR.SOACS: stmsFromList :: [Stm rep] -> Stms rep
- Futhark.IR.SOACS: stmsHead :: Stms lore -> Maybe (Stm lore, Stms lore)
+ Futhark.IR.SOACS: stmsHead :: Stms rep -> Maybe (Stm rep, Stms rep)
- Futhark.IR.SOACS: stmsToList :: Stms lore -> [Stm lore]
+ Futhark.IR.SOACS: stmsToList :: Stms rep -> [Stm rep]
- Futhark.IR.SOACS: type Stms lore = Seq (Stm lore)
+ Futhark.IR.SOACS: type Stms rep = Seq (Stm rep)
- Futhark.IR.SOACS.SOAC: Hist :: SubExp -> [HistOp lore] -> Lambda lore -> [VName] -> SOAC lore
+ Futhark.IR.SOACS.SOAC: Hist :: SubExp -> [HistOp rep] -> Lambda rep -> [VName] -> SOAC rep
- Futhark.IR.SOACS.SOAC: HistOp :: SubExp -> SubExp -> [VName] -> [SubExp] -> Lambda lore -> HistOp lore
+ Futhark.IR.SOACS.SOAC: HistOp :: SubExp -> SubExp -> [VName] -> [SubExp] -> Lambda rep -> HistOp rep
- Futhark.IR.SOACS.SOAC: Parallel :: StreamOrd -> Commutativity -> Lambda lore -> StreamForm lore
+ Futhark.IR.SOACS.SOAC: Parallel :: StreamOrd -> Commutativity -> Lambda rep -> StreamForm rep
- Futhark.IR.SOACS.SOAC: Reduce :: Commutativity -> Lambda lore -> [SubExp] -> Reduce lore
+ Futhark.IR.SOACS.SOAC: Reduce :: Commutativity -> Lambda rep -> [SubExp] -> Reduce rep
- Futhark.IR.SOACS.SOAC: SOACMapper :: (SubExp -> m SubExp) -> (Lambda flore -> m (Lambda tlore)) -> (VName -> m VName) -> SOACMapper flore tlore m
+ Futhark.IR.SOACS.SOAC: SOACMapper :: (SubExp -> m SubExp) -> (Lambda frep -> m (Lambda trep)) -> (VName -> m VName) -> SOACMapper frep trep m
- Futhark.IR.SOACS.SOAC: Scan :: Lambda lore -> [SubExp] -> Scan lore
+ Futhark.IR.SOACS.SOAC: Scan :: Lambda rep -> [SubExp] -> Scan rep
- Futhark.IR.SOACS.SOAC: Scatter :: SubExp -> Lambda lore -> [VName] -> [(Shape, Int, VName)] -> SOAC lore
+ Futhark.IR.SOACS.SOAC: Scatter :: SubExp -> Lambda rep -> [VName] -> [(Shape, Int, VName)] -> SOAC rep
- Futhark.IR.SOACS.SOAC: Screma :: SubExp -> [VName] -> ScremaForm lore -> SOAC lore
+ Futhark.IR.SOACS.SOAC: Screma :: SubExp -> [VName] -> ScremaForm rep -> SOAC rep
- Futhark.IR.SOACS.SOAC: ScremaForm :: [Scan lore] -> [Reduce lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.SOACS.SOAC: ScremaForm :: [Scan rep] -> [Reduce rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.SOACS.SOAC: Sequential :: StreamForm lore
+ Futhark.IR.SOACS.SOAC: Sequential :: StreamForm rep
- Futhark.IR.SOACS.SOAC: Stream :: SubExp -> [VName] -> StreamForm lore -> [SubExp] -> Lambda lore -> SOAC lore
+ Futhark.IR.SOACS.SOAC: Stream :: SubExp -> [VName] -> StreamForm rep -> [SubExp] -> Lambda rep -> SOAC rep
- Futhark.IR.SOACS.SOAC: [histDest] :: HistOp lore -> [VName]
+ Futhark.IR.SOACS.SOAC: [histDest] :: HistOp rep -> [VName]
- Futhark.IR.SOACS.SOAC: [histNeutral] :: HistOp lore -> [SubExp]
+ Futhark.IR.SOACS.SOAC: [histNeutral] :: HistOp rep -> [SubExp]
- Futhark.IR.SOACS.SOAC: [histOp] :: HistOp lore -> Lambda lore
+ Futhark.IR.SOACS.SOAC: [histOp] :: HistOp rep -> Lambda rep
- Futhark.IR.SOACS.SOAC: [histRaceFactor] :: HistOp lore -> SubExp
+ Futhark.IR.SOACS.SOAC: [histRaceFactor] :: HistOp rep -> SubExp
- Futhark.IR.SOACS.SOAC: [histWidth] :: HistOp lore -> SubExp
+ Futhark.IR.SOACS.SOAC: [histWidth] :: HistOp rep -> SubExp
- Futhark.IR.SOACS.SOAC: [mapOnSOACLambda] :: SOACMapper flore tlore m -> Lambda flore -> m (Lambda tlore)
+ Futhark.IR.SOACS.SOAC: [mapOnSOACLambda] :: SOACMapper frep trep m -> Lambda frep -> m (Lambda trep)
- Futhark.IR.SOACS.SOAC: [mapOnSOACSubExp] :: SOACMapper flore tlore m -> SubExp -> m SubExp
+ Futhark.IR.SOACS.SOAC: [mapOnSOACSubExp] :: SOACMapper frep trep m -> SubExp -> m SubExp
- Futhark.IR.SOACS.SOAC: [mapOnSOACVName] :: SOACMapper flore tlore m -> VName -> m VName
+ Futhark.IR.SOACS.SOAC: [mapOnSOACVName] :: SOACMapper frep trep m -> VName -> m VName
- Futhark.IR.SOACS.SOAC: [redComm] :: Reduce lore -> Commutativity
+ Futhark.IR.SOACS.SOAC: [redComm] :: Reduce rep -> Commutativity
- Futhark.IR.SOACS.SOAC: [redLambda] :: Reduce lore -> Lambda lore
+ Futhark.IR.SOACS.SOAC: [redLambda] :: Reduce rep -> Lambda rep
- Futhark.IR.SOACS.SOAC: [redNeutral] :: Reduce lore -> [SubExp]
+ Futhark.IR.SOACS.SOAC: [redNeutral] :: Reduce rep -> [SubExp]
- Futhark.IR.SOACS.SOAC: [scanLambda] :: Scan lore -> Lambda lore
+ Futhark.IR.SOACS.SOAC: [scanLambda] :: Scan rep -> Lambda rep
- Futhark.IR.SOACS.SOAC: [scanNeutral] :: Scan lore -> [SubExp]
+ Futhark.IR.SOACS.SOAC: [scanNeutral] :: Scan rep -> [SubExp]
- Futhark.IR.SOACS.SOAC: data HistOp lore
+ Futhark.IR.SOACS.SOAC: data HistOp rep
- Futhark.IR.SOACS.SOAC: data Reduce lore
+ Futhark.IR.SOACS.SOAC: data Reduce rep
- Futhark.IR.SOACS.SOAC: data SOAC lore
+ Futhark.IR.SOACS.SOAC: data SOAC rep
- Futhark.IR.SOACS.SOAC: data SOACMapper flore tlore m
+ Futhark.IR.SOACS.SOAC: data SOACMapper frep trep m
- Futhark.IR.SOACS.SOAC: data Scan lore
+ Futhark.IR.SOACS.SOAC: data Scan rep
- Futhark.IR.SOACS.SOAC: data ScremaForm lore
+ Futhark.IR.SOACS.SOAC: data ScremaForm rep
- Futhark.IR.SOACS.SOAC: data StreamForm lore
+ Futhark.IR.SOACS.SOAC: data StreamForm rep
- Futhark.IR.SOACS.SOAC: identitySOACMapper :: Monad m => SOACMapper lore lore m
+ Futhark.IR.SOACS.SOAC: identitySOACMapper :: Monad m => SOACMapper rep rep m
- Futhark.IR.SOACS.SOAC: isIdentityLambda :: Lambda lore -> Bool
+ Futhark.IR.SOACS.SOAC: isIdentityLambda :: Lambda rep -> Bool
- Futhark.IR.SOACS.SOAC: isMapSOAC :: ScremaForm lore -> Maybe (Lambda lore)
+ Futhark.IR.SOACS.SOAC: isMapSOAC :: ScremaForm rep -> Maybe (Lambda rep)
- Futhark.IR.SOACS.SOAC: isRedomapSOAC :: ScremaForm lore -> Maybe ([Reduce lore], Lambda lore)
+ Futhark.IR.SOACS.SOAC: isRedomapSOAC :: ScremaForm rep -> Maybe ([Reduce rep], Lambda rep)
- Futhark.IR.SOACS.SOAC: isReduceSOAC :: ScremaForm lore -> Maybe [Reduce lore]
+ Futhark.IR.SOACS.SOAC: isReduceSOAC :: ScremaForm rep -> Maybe [Reduce rep]
- Futhark.IR.SOACS.SOAC: isScanSOAC :: ScremaForm lore -> Maybe [Scan lore]
+ Futhark.IR.SOACS.SOAC: isScanSOAC :: ScremaForm rep -> Maybe [Scan rep]
- Futhark.IR.SOACS.SOAC: isScanomapSOAC :: ScremaForm lore -> Maybe ([Scan lore], Lambda lore)
+ Futhark.IR.SOACS.SOAC: isScanomapSOAC :: ScremaForm rep -> Maybe ([Scan rep], Lambda rep)
- Futhark.IR.SOACS.SOAC: mapSOAC :: Lambda lore -> ScremaForm lore
+ Futhark.IR.SOACS.SOAC: mapSOAC :: Lambda rep -> ScremaForm rep
- Futhark.IR.SOACS.SOAC: mapSOACM :: (Applicative m, Monad m) => SOACMapper flore tlore m -> SOAC flore -> m (SOAC tlore)
+ Futhark.IR.SOACS.SOAC: mapSOACM :: (Applicative m, Monad m) => SOACMapper frep trep m -> SOAC frep -> m (SOAC trep)
- Futhark.IR.SOACS.SOAC: mkIdentityLambda :: (Bindable lore, MonadFreshNames m) => [Type] -> m (Lambda lore)
+ Futhark.IR.SOACS.SOAC: mkIdentityLambda :: (Bindable rep, MonadFreshNames m) => [Type] -> m (Lambda rep)
- Futhark.IR.SOACS.SOAC: nilFn :: Bindable lore => Lambda lore
+ Futhark.IR.SOACS.SOAC: nilFn :: Bindable rep => Lambda rep
- Futhark.IR.SOACS.SOAC: ppHist :: (PrettyLore lore, Pretty inp) => SubExp -> [HistOp lore] -> Lambda lore -> [inp] -> Doc
+ Futhark.IR.SOACS.SOAC: ppHist :: (PrettyRep rep, Pretty inp) => SubExp -> [HistOp rep] -> Lambda rep -> [inp] -> Doc
- Futhark.IR.SOACS.SOAC: ppScrema :: (PrettyLore lore, Pretty inp) => SubExp -> [inp] -> ScremaForm lore -> Doc
+ Futhark.IR.SOACS.SOAC: ppScrema :: (PrettyRep rep, Pretty inp) => SubExp -> [inp] -> ScremaForm rep -> Doc
- Futhark.IR.SOACS.SOAC: redResults :: [Reduce lore] -> Int
+ Futhark.IR.SOACS.SOAC: redResults :: [Reduce rep] -> Int
- Futhark.IR.SOACS.SOAC: redomapSOAC :: [Reduce lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.SOACS.SOAC: redomapSOAC :: [Reduce rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.SOACS.SOAC: reduceSOAC :: (Bindable lore, MonadFreshNames m) => [Reduce lore] -> m (ScremaForm lore)
+ Futhark.IR.SOACS.SOAC: reduceSOAC :: (Bindable rep, MonadFreshNames m) => [Reduce rep] -> m (ScremaForm rep)
- Futhark.IR.SOACS.SOAC: scanResults :: [Scan lore] -> Int
+ Futhark.IR.SOACS.SOAC: scanResults :: [Scan rep] -> Int
- Futhark.IR.SOACS.SOAC: scanSOAC :: (Bindable lore, MonadFreshNames m) => [Scan lore] -> m (ScremaForm lore)
+ Futhark.IR.SOACS.SOAC: scanSOAC :: (Bindable rep, MonadFreshNames m) => [Scan rep] -> m (ScremaForm rep)
- Futhark.IR.SOACS.SOAC: scanomapSOAC :: [Scan lore] -> Lambda lore -> ScremaForm lore
+ Futhark.IR.SOACS.SOAC: scanomapSOAC :: [Scan rep] -> Lambda rep -> ScremaForm rep
- Futhark.IR.SOACS.SOAC: scremaType :: SubExp -> ScremaForm lore -> [Type]
+ Futhark.IR.SOACS.SOAC: scremaType :: SubExp -> ScremaForm rep -> [Type]
- Futhark.IR.SOACS.SOAC: singleReduce :: Bindable lore => [Reduce lore] -> Reduce lore
+ Futhark.IR.SOACS.SOAC: singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep
- Futhark.IR.SOACS.SOAC: singleScan :: Bindable lore => [Scan lore] -> Scan lore
+ Futhark.IR.SOACS.SOAC: singleScan :: Bindable rep => [Scan rep] -> Scan rep
- Futhark.IR.SOACS.SOAC: soacType :: SOAC lore -> [Type]
+ Futhark.IR.SOACS.SOAC: soacType :: SOAC rep -> [Type]
- Futhark.IR.SOACS.SOAC: typeCheckSOAC :: Checkable lore => SOAC (Aliases lore) -> TypeM lore ()
+ Futhark.IR.SOACS.SOAC: typeCheckSOAC :: Checkable rep => SOAC (Aliases rep) -> TypeM rep ()
- Futhark.IR.SOACS.Simplify: asSOAC :: HasSOAC lore => Op lore -> Maybe (SOAC lore)
+ Futhark.IR.SOACS.Simplify: asSOAC :: HasSOAC rep => Op rep -> Maybe (SOAC rep)
- Futhark.IR.SOACS.Simplify: class HasSOAC lore
+ Futhark.IR.SOACS.Simplify: class HasSOAC rep
- Futhark.IR.SOACS.Simplify: liftIdentityMapping :: forall lore. (Bindable lore, SimplifiableLore lore, HasSOAC (Wise lore)) => TopDownRuleOp (Wise lore)
+ Futhark.IR.SOACS.Simplify: liftIdentityMapping :: forall rep. (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SOACS.Simplify: removeReplicateMapping :: (Bindable lore, SimplifiableLore lore, HasSOAC (Wise lore)) => TopDownRuleOp (Wise lore)
+ Futhark.IR.SOACS.Simplify: removeReplicateMapping :: (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SOACS.Simplify: simplifyKnownIterationSOAC :: (Bindable lore, SimplifiableLore lore, HasSOAC (Wise lore)) => TopDownRuleOp (Wise lore)
+ Futhark.IR.SOACS.Simplify: simplifyKnownIterationSOAC :: (Bindable rep, SimplifiableRep rep, HasSOAC (Wise rep)) => TopDownRuleOp (Wise rep)
- Futhark.IR.SOACS.Simplify: simplifySOAC :: SimplifiableLore lore => SimplifyOp lore (SOAC lore)
+ Futhark.IR.SOACS.Simplify: simplifySOAC :: SimplifiableRep rep => SimplifyOp rep (SOAC rep)
- Futhark.IR.SOACS.Simplify: soacOp :: HasSOAC lore => SOAC lore -> Op lore
+ Futhark.IR.SOACS.Simplify: soacOp :: HasSOAC rep => SOAC rep -> Op rep
- Futhark.IR.SegOp: HistOp :: SubExp -> SubExp -> [VName] -> [SubExp] -> Shape -> Lambda lore -> HistOp lore
+ Futhark.IR.SegOp: HistOp :: SubExp -> SubExp -> [VName] -> [SubExp] -> Shape -> Lambda rep -> HistOp rep
- Futhark.IR.SegOp: KernelBody :: BodyDec lore -> Stms lore -> [KernelResult] -> KernelBody lore
+ Futhark.IR.SegOp: KernelBody :: BodyDec rep -> Stms rep -> [KernelResult] -> KernelBody rep
- Futhark.IR.SegOp: SegBinOp :: Commutativity -> Lambda lore -> [SubExp] -> Shape -> SegBinOp lore
+ Futhark.IR.SegOp: SegBinOp :: Commutativity -> Lambda rep -> [SubExp] -> Shape -> SegBinOp rep
- Futhark.IR.SegOp: SegHist :: lvl -> SegSpace -> [HistOp lore] -> [Type] -> KernelBody lore -> SegOp lvl lore
+ Futhark.IR.SegOp: SegHist :: lvl -> SegSpace -> [HistOp rep] -> [Type] -> KernelBody rep -> SegOp lvl rep
- Futhark.IR.SegOp: SegMap :: lvl -> SegSpace -> [Type] -> KernelBody lore -> SegOp lvl lore
+ Futhark.IR.SegOp: SegMap :: lvl -> SegSpace -> [Type] -> KernelBody rep -> SegOp lvl rep
- Futhark.IR.SegOp: SegOpMapper :: (SubExp -> m SubExp) -> (Lambda flore -> m (Lambda tlore)) -> (KernelBody flore -> m (KernelBody tlore)) -> (VName -> m VName) -> (lvl -> m lvl) -> SegOpMapper lvl flore tlore m
+ Futhark.IR.SegOp: SegOpMapper :: (SubExp -> m SubExp) -> (Lambda frep -> m (Lambda trep)) -> (KernelBody frep -> m (KernelBody trep)) -> (VName -> m VName) -> (lvl -> m lvl) -> SegOpMapper lvl frep trep m
- Futhark.IR.SegOp: SegRed :: lvl -> SegSpace -> [SegBinOp lore] -> [Type] -> KernelBody lore -> SegOp lvl lore
+ Futhark.IR.SegOp: SegRed :: lvl -> SegSpace -> [SegBinOp rep] -> [Type] -> KernelBody rep -> SegOp lvl rep
- Futhark.IR.SegOp: SegScan :: lvl -> SegSpace -> [SegBinOp lore] -> [Type] -> KernelBody lore -> SegOp lvl lore
+ Futhark.IR.SegOp: SegScan :: lvl -> SegSpace -> [SegBinOp rep] -> [Type] -> KernelBody rep -> SegOp lvl rep
- Futhark.IR.SegOp: [histDest] :: HistOp lore -> [VName]
+ Futhark.IR.SegOp: [histDest] :: HistOp rep -> [VName]
- Futhark.IR.SegOp: [histNeutral] :: HistOp lore -> [SubExp]
+ Futhark.IR.SegOp: [histNeutral] :: HistOp rep -> [SubExp]
- Futhark.IR.SegOp: [histOp] :: HistOp lore -> Lambda lore
+ Futhark.IR.SegOp: [histOp] :: HistOp rep -> Lambda rep
- Futhark.IR.SegOp: [histRaceFactor] :: HistOp lore -> SubExp
+ Futhark.IR.SegOp: [histRaceFactor] :: HistOp rep -> SubExp
- Futhark.IR.SegOp: [histShape] :: HistOp lore -> Shape
+ Futhark.IR.SegOp: [histShape] :: HistOp rep -> Shape
- Futhark.IR.SegOp: [histWidth] :: HistOp lore -> SubExp
+ Futhark.IR.SegOp: [histWidth] :: HistOp rep -> SubExp
- Futhark.IR.SegOp: [kernelBodyResult] :: KernelBody lore -> [KernelResult]
+ Futhark.IR.SegOp: [kernelBodyResult] :: KernelBody rep -> [KernelResult]
- Futhark.IR.SegOp: [kernelBodyStms] :: KernelBody lore -> Stms lore
+ Futhark.IR.SegOp: [kernelBodyStms] :: KernelBody rep -> Stms rep
- Futhark.IR.SegOp: [mapOnSegOpBody] :: SegOpMapper lvl flore tlore m -> KernelBody flore -> m (KernelBody tlore)
+ Futhark.IR.SegOp: [mapOnSegOpBody] :: SegOpMapper lvl frep trep m -> KernelBody frep -> m (KernelBody trep)
- Futhark.IR.SegOp: [mapOnSegOpLambda] :: SegOpMapper lvl flore tlore m -> Lambda flore -> m (Lambda tlore)
+ Futhark.IR.SegOp: [mapOnSegOpLambda] :: SegOpMapper lvl frep trep m -> Lambda frep -> m (Lambda trep)
- Futhark.IR.SegOp: [mapOnSegOpLevel] :: SegOpMapper lvl flore tlore m -> lvl -> m lvl
+ Futhark.IR.SegOp: [mapOnSegOpLevel] :: SegOpMapper lvl frep trep m -> lvl -> m lvl
- Futhark.IR.SegOp: [mapOnSegOpSubExp] :: SegOpMapper lvl flore tlore m -> SubExp -> m SubExp
+ Futhark.IR.SegOp: [mapOnSegOpSubExp] :: SegOpMapper lvl frep trep m -> SubExp -> m SubExp
- Futhark.IR.SegOp: [mapOnSegOpVName] :: SegOpMapper lvl flore tlore m -> VName -> m VName
+ Futhark.IR.SegOp: [mapOnSegOpVName] :: SegOpMapper lvl frep trep m -> VName -> m VName
- Futhark.IR.SegOp: [segBinOpComm] :: SegBinOp lore -> Commutativity
+ Futhark.IR.SegOp: [segBinOpComm] :: SegBinOp rep -> Commutativity
- Futhark.IR.SegOp: [segBinOpLambda] :: SegBinOp lore -> Lambda lore
+ Futhark.IR.SegOp: [segBinOpLambda] :: SegBinOp rep -> Lambda rep
- Futhark.IR.SegOp: [segBinOpNeutral] :: SegBinOp lore -> [SubExp]
+ Futhark.IR.SegOp: [segBinOpNeutral] :: SegBinOp rep -> [SubExp]
- Futhark.IR.SegOp: [segBinOpShape] :: SegBinOp lore -> Shape
+ Futhark.IR.SegOp: [segBinOpShape] :: SegBinOp rep -> Shape
- Futhark.IR.SegOp: aliasAnalyseKernelBody :: (ASTLore lore, CanBeAliased (Op lore)) => AliasTable -> KernelBody lore -> KernelBody (Aliases lore)
+ Futhark.IR.SegOp: aliasAnalyseKernelBody :: (ASTRep rep, CanBeAliased (Op rep)) => AliasTable -> KernelBody rep -> KernelBody (Aliases rep)
- Futhark.IR.SegOp: asSegOp :: HasSegOp lore => Op lore -> Maybe (SegOp (SegOpLevel lore) lore)
+ Futhark.IR.SegOp: asSegOp :: HasSegOp rep => Op rep -> Maybe (SegOp (SegOpLevel rep) rep)
- Futhark.IR.SegOp: class HasSegOp lore where {
+ Futhark.IR.SegOp: class HasSegOp rep where {
- Futhark.IR.SegOp: consumedInKernelBody :: Aliased lore => KernelBody lore -> Names
+ Futhark.IR.SegOp: consumedInKernelBody :: Aliased rep => KernelBody rep -> Names
- Futhark.IR.SegOp: data HistOp lore
+ Futhark.IR.SegOp: data HistOp rep
- Futhark.IR.SegOp: data KernelBody lore
+ Futhark.IR.SegOp: data KernelBody rep
- Futhark.IR.SegOp: data SegBinOp lore
+ Futhark.IR.SegOp: data SegBinOp rep
- Futhark.IR.SegOp: data SegOp lvl lore
+ Futhark.IR.SegOp: data SegOp lvl rep
- Futhark.IR.SegOp: data SegOpMapper lvl flore tlore m
+ Futhark.IR.SegOp: data SegOpMapper lvl frep trep m
- Futhark.IR.SegOp: histType :: HistOp lore -> [Type]
+ Futhark.IR.SegOp: histType :: HistOp rep -> [Type]
- Futhark.IR.SegOp: identitySegOpMapper :: Monad m => SegOpMapper lvl lore lore m
+ Futhark.IR.SegOp: identitySegOpMapper :: Monad m => SegOpMapper lvl rep rep m
- Futhark.IR.SegOp: mapSegOpM :: (Applicative m, Monad m) => SegOpMapper lvl flore tlore m -> SegOp lvl flore -> m (SegOp lvl tlore)
+ Futhark.IR.SegOp: mapSegOpM :: (Applicative m, Monad m) => SegOpMapper lvl frep trep m -> SegOp lvl frep -> m (SegOp lvl trep)
- Futhark.IR.SegOp: scopeOfSegSpace :: SegSpace -> Scope lore
+ Futhark.IR.SegOp: scopeOfSegSpace :: SegSpace -> Scope rep
- Futhark.IR.SegOp: segBinOpChunks :: [SegBinOp lore] -> [a] -> [[a]]
+ Futhark.IR.SegOp: segBinOpChunks :: [SegBinOp rep] -> [a] -> [[a]]
- Futhark.IR.SegOp: segBinOpResults :: [SegBinOp lore] -> Int
+ Futhark.IR.SegOp: segBinOpResults :: [SegBinOp rep] -> Int
- Futhark.IR.SegOp: segLevel :: SegOp lvl lore -> lvl
+ Futhark.IR.SegOp: segLevel :: SegOp lvl rep -> lvl
- Futhark.IR.SegOp: segOp :: HasSegOp lore => SegOp (SegOpLevel lore) lore -> Op lore
+ Futhark.IR.SegOp: segOp :: HasSegOp rep => SegOp (SegOpLevel rep) rep -> Op rep
- Futhark.IR.SegOp: segOpReturns :: (Mem lore, Monad m, HasScope lore m) => SegOp lvl lore -> m [ExpReturns]
+ Futhark.IR.SegOp: segOpReturns :: (Mem rep, Monad m, HasScope rep m) => SegOp lvl rep -> m [ExpReturns]
- Futhark.IR.SegOp: segOpRules :: (HasSegOp lore, BinderOps lore, Bindable lore) => RuleBook lore
+ Futhark.IR.SegOp: segOpRules :: (HasSegOp rep, BinderOps rep, Bindable rep) => RuleBook rep
- Futhark.IR.SegOp: segSpace :: SegOp lvl lore -> SegSpace
+ Futhark.IR.SegOp: segSpace :: SegOp lvl rep -> SegSpace
- Futhark.IR.SegOp: simplifySegOp :: (SimplifiableLore lore, BodyDec lore ~ (), Simplifiable lvl) => SegOp lvl lore -> SimpleM lore (SegOp lvl (Wise lore), Stms (Wise lore))
+ Futhark.IR.SegOp: simplifySegOp :: (SimplifiableRep rep, BodyDec rep ~ (), Simplifiable lvl) => SegOp lvl rep -> SimpleM rep (SegOp lvl (Wise rep), Stms (Wise rep))
- Futhark.IR.SegOp: type family SegOpLevel lore;
+ Futhark.IR.SegOp: type family SegOpLevel rep;
- Futhark.IR.SegOp: typeCheckSegOp :: Checkable lore => (lvl -> TypeM lore ()) -> SegOp lvl (Aliases lore) -> TypeM lore ()
+ Futhark.IR.SegOp: typeCheckSegOp :: Checkable rep => (lvl -> TypeM rep ()) -> SegOp lvl (Aliases rep) -> TypeM rep ()
- Futhark.IR.Syntax: Apply :: Name -> [(SubExp, Diet)] -> [RetType lore] -> (Safety, SrcLoc, [SrcLoc]) -> ExpT lore
+ Futhark.IR.Syntax: Apply :: Name -> [(SubExp, Diet)] -> [RetType rep] -> (Safety, SrcLoc, [SrcLoc]) -> ExpT rep
- Futhark.IR.Syntax: BasicOp :: BasicOp -> ExpT lore
+ Futhark.IR.Syntax: BasicOp :: BasicOp -> ExpT rep
- Futhark.IR.Syntax: Body :: BodyDec lore -> Stms lore -> Result -> BodyT lore
+ Futhark.IR.Syntax: Body :: BodyDec rep -> Stms rep -> Result -> BodyT rep
- Futhark.IR.Syntax: DoLoop :: [(FParam lore, SubExp)] -> [(FParam lore, SubExp)] -> LoopForm lore -> BodyT lore -> ExpT lore
+ Futhark.IR.Syntax: DoLoop :: [(FParam rep, SubExp)] -> [(FParam rep, SubExp)] -> LoopForm rep -> BodyT rep -> ExpT rep
- Futhark.IR.Syntax: ForLoop :: VName -> IntType -> SubExp -> [(LParam lore, VName)] -> LoopForm lore
+ Futhark.IR.Syntax: ForLoop :: VName -> IntType -> SubExp -> [(LParam rep, VName)] -> LoopForm rep
- Futhark.IR.Syntax: FunDef :: Maybe EntryPoint -> Attrs -> Name -> [RetType lore] -> [FParam lore] -> BodyT lore -> FunDef lore
+ Futhark.IR.Syntax: FunDef :: Maybe EntryPoint -> Attrs -> Name -> [RetType rep] -> [FParam rep] -> BodyT rep -> FunDef rep
- Futhark.IR.Syntax: If :: SubExp -> BodyT lore -> BodyT lore -> IfDec (BranchType lore) -> ExpT lore
+ Futhark.IR.Syntax: If :: SubExp -> BodyT rep -> BodyT rep -> IfDec (BranchType rep) -> ExpT rep
- Futhark.IR.Syntax: Lambda :: [LParam lore] -> BodyT lore -> [Type] -> LambdaT lore
+ Futhark.IR.Syntax: Lambda :: [LParam rep] -> BodyT rep -> [Type] -> LambdaT rep
- Futhark.IR.Syntax: Let :: Pattern lore -> StmAux (ExpDec lore) -> Exp lore -> Stm lore
+ Futhark.IR.Syntax: Let :: Pattern rep -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
- Futhark.IR.Syntax: Op :: Op lore -> ExpT lore
+ Futhark.IR.Syntax: Op :: Op rep -> ExpT rep
- Futhark.IR.Syntax: Prog :: Stms lore -> [FunDef lore] -> Prog lore
+ Futhark.IR.Syntax: Prog :: Stms rep -> [FunDef rep] -> Prog rep
- Futhark.IR.Syntax: TypeDirect :: EntryPointType
+ Futhark.IR.Syntax: TypeDirect :: Uniqueness -> EntryPointType
- Futhark.IR.Syntax: TypeOpaque :: String -> Int -> EntryPointType
+ Futhark.IR.Syntax: TypeOpaque :: Uniqueness -> String -> Int -> EntryPointType
- Futhark.IR.Syntax: TypeUnsigned :: EntryPointType
+ Futhark.IR.Syntax: TypeUnsigned :: Uniqueness -> EntryPointType
- Futhark.IR.Syntax: WhileLoop :: VName -> LoopForm lore
+ Futhark.IR.Syntax: WhileLoop :: VName -> LoopForm rep
- Futhark.IR.Syntax: WithAcc :: [(Shape, [VName], Maybe (Lambda lore, [SubExp]))] -> Lambda lore -> ExpT lore
+ Futhark.IR.Syntax: WithAcc :: [(Shape, [VName], Maybe (Lambda rep, [SubExp]))] -> Lambda rep -> ExpT rep
- Futhark.IR.Syntax: [bodyDec] :: BodyT lore -> BodyDec lore
+ Futhark.IR.Syntax: [bodyDec] :: BodyT rep -> BodyDec rep
- Futhark.IR.Syntax: [bodyResult] :: BodyT lore -> Result
+ Futhark.IR.Syntax: [bodyResult] :: BodyT rep -> Result
- Futhark.IR.Syntax: [bodyStms] :: BodyT lore -> Stms lore
+ Futhark.IR.Syntax: [bodyStms] :: BodyT rep -> Stms rep
- Futhark.IR.Syntax: [funDefAttrs] :: FunDef lore -> Attrs
+ Futhark.IR.Syntax: [funDefAttrs] :: FunDef rep -> Attrs
- Futhark.IR.Syntax: [funDefBody] :: FunDef lore -> BodyT lore
+ Futhark.IR.Syntax: [funDefBody] :: FunDef rep -> BodyT rep
- Futhark.IR.Syntax: [funDefEntryPoint] :: FunDef lore -> Maybe EntryPoint
+ Futhark.IR.Syntax: [funDefEntryPoint] :: FunDef rep -> Maybe EntryPoint
- Futhark.IR.Syntax: [funDefName] :: FunDef lore -> Name
+ Futhark.IR.Syntax: [funDefName] :: FunDef rep -> Name
- Futhark.IR.Syntax: [funDefParams] :: FunDef lore -> [FParam lore]
+ Futhark.IR.Syntax: [funDefParams] :: FunDef rep -> [FParam rep]
- Futhark.IR.Syntax: [funDefRetType] :: FunDef lore -> [RetType lore]
+ Futhark.IR.Syntax: [funDefRetType] :: FunDef rep -> [RetType rep]
- Futhark.IR.Syntax: [lambdaBody] :: LambdaT lore -> BodyT lore
+ Futhark.IR.Syntax: [lambdaBody] :: LambdaT rep -> BodyT rep
- Futhark.IR.Syntax: [lambdaParams] :: LambdaT lore -> [LParam lore]
+ Futhark.IR.Syntax: [lambdaParams] :: LambdaT rep -> [LParam rep]
- Futhark.IR.Syntax: [lambdaReturnType] :: LambdaT lore -> [Type]
+ Futhark.IR.Syntax: [lambdaReturnType] :: LambdaT rep -> [Type]
- Futhark.IR.Syntax: [progConsts] :: Prog lore -> Stms lore
+ Futhark.IR.Syntax: [progConsts] :: Prog rep -> Stms rep
- Futhark.IR.Syntax: [progFuns] :: Prog lore -> [FunDef lore]
+ Futhark.IR.Syntax: [progFuns] :: Prog rep -> [FunDef rep]
- Futhark.IR.Syntax: [stmAux] :: Stm lore -> StmAux (ExpDec lore)
+ Futhark.IR.Syntax: [stmAux] :: Stm rep -> StmAux (ExpDec rep)
- Futhark.IR.Syntax: [stmExp] :: Stm lore -> Exp lore
+ Futhark.IR.Syntax: [stmExp] :: Stm rep -> Exp rep
- Futhark.IR.Syntax: [stmPattern] :: Stm lore -> Pattern lore
+ Futhark.IR.Syntax: [stmPattern] :: Stm rep -> Pattern rep
- Futhark.IR.Syntax: data BodyT lore
+ Futhark.IR.Syntax: data BodyT rep
- Futhark.IR.Syntax: data ExpT lore
+ Futhark.IR.Syntax: data ExpT rep
- Futhark.IR.Syntax: data FunDef lore
+ Futhark.IR.Syntax: data FunDef rep
- Futhark.IR.Syntax: data LambdaT lore
+ Futhark.IR.Syntax: data LambdaT rep
- Futhark.IR.Syntax: data LoopForm lore
+ Futhark.IR.Syntax: data LoopForm rep
- Futhark.IR.Syntax: data Prog lore
+ Futhark.IR.Syntax: data Prog rep
- Futhark.IR.Syntax: data Stm lore
+ Futhark.IR.Syntax: data Stm rep
- Futhark.IR.Syntax: oneStm :: Stm lore -> Stms lore
+ Futhark.IR.Syntax: oneStm :: Stm rep -> Stms rep
- Futhark.IR.Syntax: stmsFromList :: [Stm lore] -> Stms lore
+ Futhark.IR.Syntax: stmsFromList :: [Stm rep] -> Stms rep
- Futhark.IR.Syntax: stmsHead :: Stms lore -> Maybe (Stm lore, Stms lore)
+ Futhark.IR.Syntax: stmsHead :: Stms rep -> Maybe (Stm rep, Stms rep)
- Futhark.IR.Syntax: stmsToList :: Stms lore -> [Stm lore]
+ Futhark.IR.Syntax: stmsToList :: Stms rep -> [Stm rep]
- Futhark.IR.Syntax: type FParam lore = Param (FParamInfo lore)
+ Futhark.IR.Syntax: type FParam rep = Param (FParamInfo rep)
- Futhark.IR.Syntax: type LParam lore = Param (LParamInfo lore)
+ Futhark.IR.Syntax: type LParam rep = Param (LParamInfo rep)
- Futhark.IR.Syntax: type PatElem lore = PatElemT (LetDec lore)
+ Futhark.IR.Syntax: type PatElem rep = PatElemT (LetDec rep)
- Futhark.IR.Syntax: type Pattern lore = PatternT (LetDec lore)
+ Futhark.IR.Syntax: type Pattern rep = PatternT (LetDec rep)
- Futhark.IR.Syntax: type Stms lore = Seq (Stm lore)
+ Futhark.IR.Syntax: type Stms rep = Seq (Stm rep)
- Futhark.IR.Traversals: Mapper :: (SubExp -> m SubExp) -> (Scope tlore -> Body flore -> m (Body tlore)) -> (VName -> m VName) -> (RetType flore -> m (RetType tlore)) -> (BranchType flore -> m (BranchType tlore)) -> (FParam flore -> m (FParam tlore)) -> (LParam flore -> m (LParam tlore)) -> (Op flore -> m (Op tlore)) -> Mapper flore tlore m
+ Futhark.IR.Traversals: Mapper :: (SubExp -> m SubExp) -> (Scope trep -> Body frep -> m (Body trep)) -> (VName -> m VName) -> (RetType frep -> m (RetType trep)) -> (BranchType frep -> m (BranchType trep)) -> (FParam frep -> m (FParam trep)) -> (LParam frep -> m (LParam trep)) -> (Op frep -> m (Op trep)) -> Mapper frep trep m
- Futhark.IR.Traversals: Walker :: (SubExp -> m ()) -> (Scope lore -> Body lore -> m ()) -> (VName -> m ()) -> (RetType lore -> m ()) -> (BranchType lore -> m ()) -> (FParam lore -> m ()) -> (LParam lore -> m ()) -> (Op lore -> m ()) -> Walker lore m
+ Futhark.IR.Traversals: Walker :: (SubExp -> m ()) -> (Scope rep -> Body rep -> m ()) -> (VName -> m ()) -> (RetType rep -> m ()) -> (BranchType rep -> m ()) -> (FParam rep -> m ()) -> (LParam rep -> m ()) -> (Op rep -> m ()) -> Walker rep m
- Futhark.IR.Traversals: [mapOnBody] :: Mapper flore tlore m -> Scope tlore -> Body flore -> m (Body tlore)
+ Futhark.IR.Traversals: [mapOnBody] :: Mapper frep trep m -> Scope trep -> Body frep -> m (Body trep)
- Futhark.IR.Traversals: [mapOnBranchType] :: Mapper flore tlore m -> BranchType flore -> m (BranchType tlore)
+ Futhark.IR.Traversals: [mapOnBranchType] :: Mapper frep trep m -> BranchType frep -> m (BranchType trep)
- Futhark.IR.Traversals: [mapOnFParam] :: Mapper flore tlore m -> FParam flore -> m (FParam tlore)
+ Futhark.IR.Traversals: [mapOnFParam] :: Mapper frep trep m -> FParam frep -> m (FParam trep)
- Futhark.IR.Traversals: [mapOnLParam] :: Mapper flore tlore m -> LParam flore -> m (LParam tlore)
+ Futhark.IR.Traversals: [mapOnLParam] :: Mapper frep trep m -> LParam frep -> m (LParam trep)
- Futhark.IR.Traversals: [mapOnOp] :: Mapper flore tlore m -> Op flore -> m (Op tlore)
+ Futhark.IR.Traversals: [mapOnOp] :: Mapper frep trep m -> Op frep -> m (Op trep)
- Futhark.IR.Traversals: [mapOnRetType] :: Mapper flore tlore m -> RetType flore -> m (RetType tlore)
+ Futhark.IR.Traversals: [mapOnRetType] :: Mapper frep trep m -> RetType frep -> m (RetType trep)
- Futhark.IR.Traversals: [mapOnSubExp] :: Mapper flore tlore m -> SubExp -> m SubExp
+ Futhark.IR.Traversals: [mapOnSubExp] :: Mapper frep trep m -> SubExp -> m SubExp
- Futhark.IR.Traversals: [mapOnVName] :: Mapper flore tlore m -> VName -> m VName
+ Futhark.IR.Traversals: [mapOnVName] :: Mapper frep trep m -> VName -> m VName
- Futhark.IR.Traversals: [walkOnBody] :: Walker lore m -> Scope lore -> Body lore -> m ()
+ Futhark.IR.Traversals: [walkOnBody] :: Walker rep m -> Scope rep -> Body rep -> m ()
- Futhark.IR.Traversals: [walkOnBranchType] :: Walker lore m -> BranchType lore -> m ()
+ Futhark.IR.Traversals: [walkOnBranchType] :: Walker rep m -> BranchType rep -> m ()
- Futhark.IR.Traversals: [walkOnFParam] :: Walker lore m -> FParam lore -> m ()
+ Futhark.IR.Traversals: [walkOnFParam] :: Walker rep m -> FParam rep -> m ()
- Futhark.IR.Traversals: [walkOnLParam] :: Walker lore m -> LParam lore -> m ()
+ Futhark.IR.Traversals: [walkOnLParam] :: Walker rep m -> LParam rep -> m ()
- Futhark.IR.Traversals: [walkOnOp] :: Walker lore m -> Op lore -> m ()
+ Futhark.IR.Traversals: [walkOnOp] :: Walker rep m -> Op rep -> m ()
- Futhark.IR.Traversals: [walkOnRetType] :: Walker lore m -> RetType lore -> m ()
+ Futhark.IR.Traversals: [walkOnRetType] :: Walker rep m -> RetType rep -> m ()
- Futhark.IR.Traversals: [walkOnSubExp] :: Walker lore m -> SubExp -> m ()
+ Futhark.IR.Traversals: [walkOnSubExp] :: Walker rep m -> SubExp -> m ()
- Futhark.IR.Traversals: [walkOnVName] :: Walker lore m -> VName -> m ()
+ Futhark.IR.Traversals: [walkOnVName] :: Walker rep m -> VName -> m ()
- Futhark.IR.Traversals: data Mapper flore tlore m
+ Futhark.IR.Traversals: data Mapper frep trep m
- Futhark.IR.Traversals: data Walker lore m
+ Futhark.IR.Traversals: data Walker rep m
- Futhark.IR.Traversals: identityMapper :: Monad m => Mapper lore lore m
+ Futhark.IR.Traversals: identityMapper :: Monad m => Mapper rep rep m
- Futhark.IR.Traversals: identityWalker :: Monad m => Walker lore m
+ Futhark.IR.Traversals: identityWalker :: Monad m => Walker rep m
- Futhark.IR.Traversals: mapExp :: Mapper flore tlore Identity -> Exp flore -> Exp tlore
+ Futhark.IR.Traversals: mapExp :: Mapper frep trep Identity -> Exp frep -> Exp trep
- Futhark.IR.Traversals: mapExpM :: (Applicative m, Monad m) => Mapper flore tlore m -> Exp flore -> m (Exp tlore)
+ Futhark.IR.Traversals: mapExpM :: (Applicative m, Monad m) => Mapper frep trep m -> Exp frep -> m (Exp trep)
- Futhark.IR.Traversals: walkExpM :: Monad m => Walker lore m -> Exp lore -> m ()
+ Futhark.IR.Traversals: walkExpM :: Monad m => Walker rep m -> Exp rep -> m ()
- Futhark.Optimise.BlkRegTiling: doRegTiling3D :: Stm Kernels -> TileM (Maybe (Stms Kernels, Stm Kernels))
+ Futhark.Optimise.BlkRegTiling: doRegTiling3D :: Stm GPU -> TileM (Maybe (Stms GPU, Stm GPU))
- Futhark.Optimise.BlkRegTiling: mmBlkRegTiling :: Stm Kernels -> TileM (Maybe (Stms Kernels, Stm Kernels))
+ Futhark.Optimise.BlkRegTiling: mmBlkRegTiling :: Stm GPU -> TileM (Maybe (Stms GPU, Stm GPU))
- Futhark.Optimise.CSE: performCSE :: (ASTLore lore, CanBeAliased (Op lore), CSEInOp (OpWithAliases (Op lore))) => Bool -> Pass lore lore
+ Futhark.Optimise.CSE: performCSE :: (ASTRep rep, CanBeAliased (Op rep), CSEInOp (OpWithAliases (Op rep))) => Bool -> Pass rep rep
- Futhark.Optimise.CSE: performCSEOnFunDef :: (ASTLore lore, CanBeAliased (Op lore), CSEInOp (OpWithAliases (Op lore))) => Bool -> FunDef lore -> FunDef lore
+ Futhark.Optimise.CSE: performCSEOnFunDef :: (ASTRep rep, CanBeAliased (Op rep), CSEInOp (OpWithAliases (Op rep))) => Bool -> FunDef rep -> FunDef rep
- Futhark.Optimise.CSE: performCSEOnStms :: (ASTLore lore, CanBeAliased (Op lore), CSEInOp (OpWithAliases (Op lore))) => Bool -> Stms lore -> Stms lore
+ Futhark.Optimise.CSE: performCSEOnStms :: (ASTRep rep, CanBeAliased (Op rep), CSEInOp (OpWithAliases (Op rep))) => Bool -> Stms rep -> Stms rep
- Futhark.Optimise.Fusion.Composing: fuseMaps :: Bindable lore => Names -> Lambda lore -> [Input] -> [(VName, Ident)] -> Lambda lore -> [Input] -> (Lambda lore, [Input])
+ Futhark.Optimise.Fusion.Composing: fuseMaps :: Bindable rep => Names -> Lambda rep -> [Input] -> [(VName, Ident)] -> Lambda rep -> [Input] -> (Lambda rep, [Input])
- Futhark.Optimise.Fusion.Composing: fuseRedomap :: Bindable lore => Names -> [VName] -> Lambda lore -> [SubExp] -> [SubExp] -> [Input] -> [(VName, Ident)] -> Lambda lore -> [SubExp] -> [SubExp] -> [Input] -> (Lambda lore, [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: mergeReduceOps :: Lambda lore -> Lambda lore -> Lambda lore
+ Futhark.Optimise.Fusion.Composing: mergeReduceOps :: Lambda rep -> Lambda rep -> Lambda rep
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdate :: (MonadFreshNames m, Bindable lore, LetDec lore ~ Type, CanBeAliased (Op lore)) => LowerUpdate lore m
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: lowerUpdate :: (MonadFreshNames m, Bindable rep, LetDec rep ~ Type, CanBeAliased (Op rep)) => LowerUpdate rep m
- Futhark.Optimise.InPlaceLowering.LowerIntoStm: type LowerUpdate lore m = Scope (Aliases lore) -> Stm (Aliases lore) -> [DesiredUpdate (LetDec (Aliases lore))] -> Maybe (m [Stm (Aliases lore)])
+ Futhark.Optimise.InPlaceLowering.LowerIntoStm: type LowerUpdate rep m = Scope (Aliases rep) -> Stm (Aliases rep) -> [DesiredUpdate (LetDec (Aliases rep))] -> Maybe (m [Stm (Aliases rep)])
- Futhark.Optimise.InPlaceLowering.SubstituteIndices: substituteIndices :: (MonadFreshNames m, BinderOps lore, Bindable lore, Aliased lore, LetDec lore ~ dec) => IndexSubstitutions dec -> Stms lore -> m (IndexSubstitutions dec, Stms lore)
+ 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.Simplify: SimpleOps :: (SymbolTable (Wise lore) -> Pattern (Wise lore) -> Exp (Wise lore) -> SimpleM lore (ExpDec (Wise lore))) -> (SymbolTable (Wise lore) -> Stms (Wise lore) -> Result -> SimpleM lore (Body (Wise lore))) -> Protect (Binder (Wise lore)) -> (Op (Wise lore) -> UsageTable) -> SimplifyOp lore (Op lore) -> SimpleOps lore
+ 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: [mkBodyS] :: SimpleOps lore -> SymbolTable (Wise lore) -> Stms (Wise lore) -> Result -> SimpleM lore (Body (Wise lore))
+ Futhark.Optimise.Simplify: [mkBodyS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))
- Futhark.Optimise.Simplify: [mkExpDecS] :: SimpleOps lore -> SymbolTable (Wise lore) -> Pattern (Wise lore) -> Exp (Wise lore) -> SimpleM lore (ExpDec (Wise lore))
+ Futhark.Optimise.Simplify: [mkExpDecS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Pattern (Wise rep) -> Exp (Wise rep) -> SimpleM rep (ExpDec (Wise rep))
- Futhark.Optimise.Simplify: [opUsageS] :: SimpleOps lore -> Op (Wise lore) -> UsageTable
+ Futhark.Optimise.Simplify: [opUsageS] :: SimpleOps rep -> Op (Wise rep) -> UsageTable
- Futhark.Optimise.Simplify: [protectHoistedOpS] :: SimpleOps lore -> Protect (Binder (Wise lore))
+ Futhark.Optimise.Simplify: [protectHoistedOpS] :: SimpleOps rep -> Protect (Binder (Wise rep))
- Futhark.Optimise.Simplify: [simplifyOpS] :: SimpleOps lore -> SimplifyOp lore (Op lore)
+ Futhark.Optimise.Simplify: [simplifyOpS] :: SimpleOps rep -> SimplifyOp rep (Op rep)
- Futhark.Optimise.Simplify: bindableSimpleOps :: (SimplifiableLore lore, Bindable lore) => SimplifyOp lore (Op lore) -> SimpleOps lore
+ Futhark.Optimise.Simplify: bindableSimpleOps :: (SimplifiableRep rep, Bindable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify: data HoistBlockers lore
+ Futhark.Optimise.Simplify: data HoistBlockers rep
- Futhark.Optimise.Simplify: data RuleBook lore
+ Futhark.Optimise.Simplify: data RuleBook rep
- Futhark.Optimise.Simplify: data SimpleM lore a
+ Futhark.Optimise.Simplify: data SimpleM rep a
- Futhark.Optimise.Simplify: data SimpleOps lore
+ Futhark.Optimise.Simplify: data SimpleOps rep
- Futhark.Optimise.Simplify: neverHoist :: HoistBlockers lore
+ Futhark.Optimise.Simplify: neverHoist :: HoistBlockers rep
- Futhark.Optimise.Simplify: noExtraHoistBlockers :: HoistBlockers lore
+ Futhark.Optimise.Simplify: noExtraHoistBlockers :: HoistBlockers rep
- Futhark.Optimise.Simplify: simplifyFun :: (MonadFreshNames m, SimplifiableLore lore) => SimpleOps lore -> RuleBook (Wise lore) -> HoistBlockers lore -> SymbolTable (Wise lore) -> FunDef lore -> m (FunDef lore)
+ Futhark.Optimise.Simplify: simplifyFun :: (MonadFreshNames m, SimplifiableRep rep) => SimpleOps rep -> RuleBook (Wise rep) -> HoistBlockers rep -> SymbolTable (Wise rep) -> FunDef rep -> m (FunDef rep)
- Futhark.Optimise.Simplify: simplifyLambda :: (MonadFreshNames m, HasScope lore m, SimplifiableLore lore) => SimpleOps lore -> RuleBook (Wise lore) -> HoistBlockers lore -> Lambda lore -> m (Lambda lore)
+ Futhark.Optimise.Simplify: simplifyLambda :: (MonadFreshNames m, HasScope rep m, SimplifiableRep rep) => SimpleOps rep -> RuleBook (Wise rep) -> HoistBlockers rep -> Lambda rep -> m (Lambda rep)
- Futhark.Optimise.Simplify: simplifyProg :: SimplifiableLore lore => SimpleOps lore -> RuleBook (Wise lore) -> HoistBlockers lore -> Prog lore -> PassM (Prog lore)
+ Futhark.Optimise.Simplify: simplifyProg :: SimplifiableRep rep => SimpleOps rep -> RuleBook (Wise rep) -> HoistBlockers rep -> Prog rep -> PassM (Prog rep)
- Futhark.Optimise.Simplify: simplifySomething :: (MonadFreshNames m, SimplifiableLore lore) => (a -> SimpleM lore b) -> (b -> a) -> SimpleOps lore -> RuleBook (Wise lore) -> HoistBlockers lore -> SymbolTable (Wise lore) -> a -> m a
+ Futhark.Optimise.Simplify: simplifySomething :: (MonadFreshNames m, SimplifiableRep rep) => (a -> SimpleM rep b) -> (b -> a) -> SimpleOps rep -> RuleBook (Wise rep) -> HoistBlockers rep -> SymbolTable (Wise rep) -> a -> m a
- Futhark.Optimise.Simplify: simplifyStms :: (MonadFreshNames m, SimplifiableLore lore) => SimpleOps lore -> RuleBook (Wise lore) -> HoistBlockers lore -> Scope lore -> Stms lore -> m (SymbolTable (Wise lore), Stms lore)
+ Futhark.Optimise.Simplify: simplifyStms :: (MonadFreshNames m, SimplifiableRep rep) => SimpleOps rep -> RuleBook (Wise rep) -> HoistBlockers rep -> Scope rep -> Stms rep -> m (SymbolTable (Wise rep), Stms rep)
- Futhark.Optimise.Simplify: type SimplifyOp lore op = op -> SimpleM lore (OpWithWisdom op, Stms (Wise lore))
+ Futhark.Optimise.Simplify: type SimplifyOp rep op = op -> SimpleM rep (OpWithWisdom op, Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: HoistBlockers :: BlockPred (Wise lore) -> BlockPred (Wise lore) -> BlockPred (Wise lore) -> (Stm (Wise lore) -> Bool) -> HoistBlockers lore
+ Futhark.Optimise.Simplify.Engine: HoistBlockers :: BlockPred (Wise rep) -> BlockPred (Wise rep) -> BlockPred (Wise rep) -> (Stm (Wise rep) -> Bool) -> HoistBlockers rep
- Futhark.Optimise.Simplify.Engine: SimpleOps :: (SymbolTable (Wise lore) -> Pattern (Wise lore) -> Exp (Wise lore) -> SimpleM lore (ExpDec (Wise lore))) -> (SymbolTable (Wise lore) -> Stms (Wise lore) -> Result -> SimpleM lore (Body (Wise lore))) -> Protect (Binder (Wise lore)) -> (Op (Wise lore) -> UsageTable) -> SimplifyOp lore (Op lore) -> SimpleOps lore
+ 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: [blockHoistBranch] :: HoistBlockers lore -> BlockPred (Wise lore)
+ Futhark.Optimise.Simplify.Engine: [blockHoistBranch] :: HoistBlockers rep -> BlockPred (Wise rep)
- Futhark.Optimise.Simplify.Engine: [blockHoistPar] :: HoistBlockers lore -> BlockPred (Wise lore)
+ Futhark.Optimise.Simplify.Engine: [blockHoistPar] :: HoistBlockers rep -> BlockPred (Wise rep)
- Futhark.Optimise.Simplify.Engine: [blockHoistSeq] :: HoistBlockers lore -> BlockPred (Wise lore)
+ Futhark.Optimise.Simplify.Engine: [blockHoistSeq] :: HoistBlockers rep -> BlockPred (Wise rep)
- Futhark.Optimise.Simplify.Engine: [isAllocation] :: HoistBlockers lore -> Stm (Wise lore) -> Bool
+ Futhark.Optimise.Simplify.Engine: [isAllocation] :: HoistBlockers rep -> Stm (Wise rep) -> Bool
- Futhark.Optimise.Simplify.Engine: [mkBodyS] :: SimpleOps lore -> SymbolTable (Wise lore) -> Stms (Wise lore) -> Result -> SimpleM lore (Body (Wise lore))
+ Futhark.Optimise.Simplify.Engine: [mkBodyS] :: SimpleOps rep -> SymbolTable (Wise rep) -> Stms (Wise rep) -> Result -> SimpleM rep (Body (Wise rep))
- Futhark.Optimise.Simplify.Engine: [mkExpDecS] :: SimpleOps lore -> SymbolTable (Wise lore) -> Pattern (Wise lore) -> Exp (Wise lore) -> SimpleM lore (ExpDec (Wise lore))
+ 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: [opUsageS] :: SimpleOps lore -> Op (Wise lore) -> UsageTable
+ Futhark.Optimise.Simplify.Engine: [opUsageS] :: SimpleOps rep -> Op (Wise rep) -> UsageTable
- Futhark.Optimise.Simplify.Engine: [protectHoistedOpS] :: SimpleOps lore -> Protect (Binder (Wise lore))
+ Futhark.Optimise.Simplify.Engine: [protectHoistedOpS] :: SimpleOps rep -> Protect (Binder (Wise rep))
- Futhark.Optimise.Simplify.Engine: [simplifyOpS] :: SimpleOps lore -> SimplifyOp lore (Op lore)
+ Futhark.Optimise.Simplify.Engine: [simplifyOpS] :: SimpleOps rep -> SimplifyOp rep (Op rep)
- Futhark.Optimise.Simplify.Engine: askVtable :: SimpleM lore (SymbolTable (Wise lore))
+ Futhark.Optimise.Simplify.Engine: askVtable :: SimpleM rep (SymbolTable (Wise rep))
- Futhark.Optimise.Simplify.Engine: asksEngineEnv :: (Env lore -> a) -> SimpleM lore a
+ Futhark.Optimise.Simplify.Engine: asksEngineEnv :: (Env rep -> a) -> SimpleM rep a
- Futhark.Optimise.Simplify.Engine: bindLParams :: SimplifiableLore lore => [LParam (Wise lore)] -> SimpleM lore a -> SimpleM lore a
+ Futhark.Optimise.Simplify.Engine: bindLParams :: SimplifiableRep rep => [LParam (Wise rep)] -> SimpleM rep a -> SimpleM rep a
- Futhark.Optimise.Simplify.Engine: bindableSimpleOps :: (SimplifiableLore lore, Bindable lore) => SimplifyOp lore (Op lore) -> SimpleOps lore
+ Futhark.Optimise.Simplify.Engine: bindableSimpleOps :: (SimplifiableRep rep, Bindable rep) => SimplifyOp rep (Op rep) -> SimpleOps rep
- Futhark.Optimise.Simplify.Engine: blockIf :: SimplifiableLore lore => BlockPred (Wise lore) -> SimpleM lore (SimplifiedBody lore a) -> SimpleM lore ((Stms (Wise lore), a), Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: blockIf :: SimplifiableRep rep => BlockPred (Wise rep) -> SimpleM rep (SimplifiedBody rep a) -> SimpleM rep ((Stms (Wise rep), a), Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: data Env lore
+ Futhark.Optimise.Simplify.Engine: data Env rep
- Futhark.Optimise.Simplify.Engine: data HoistBlockers lore
+ Futhark.Optimise.Simplify.Engine: data HoistBlockers rep
- Futhark.Optimise.Simplify.Engine: data SimpleM lore a
+ Futhark.Optimise.Simplify.Engine: data SimpleM rep a
- Futhark.Optimise.Simplify.Engine: data SimpleOps lore
+ Futhark.Optimise.Simplify.Engine: data SimpleOps rep
- Futhark.Optimise.Simplify.Engine: data SymbolTable lore
+ Futhark.Optimise.Simplify.Engine: data SymbolTable rep
- Futhark.Optimise.Simplify.Engine: emptyEnv :: RuleBook (Wise lore) -> HoistBlockers lore -> Env lore
+ Futhark.Optimise.Simplify.Engine: emptyEnv :: RuleBook (Wise rep) -> HoistBlockers rep -> Env rep
- Futhark.Optimise.Simplify.Engine: enterLoop :: SimpleM lore a -> SimpleM lore a
+ Futhark.Optimise.Simplify.Engine: enterLoop :: SimpleM rep a -> SimpleM rep a
- Futhark.Optimise.Simplify.Engine: hasFree :: ASTLore lore => Names -> BlockPred lore
+ Futhark.Optimise.Simplify.Engine: hasFree :: ASTRep rep => Names -> BlockPred rep
- Futhark.Optimise.Simplify.Engine: hoistStms :: SimplifiableLore lore => RuleBook (Wise lore) -> BlockPred (Wise lore) -> SymbolTable (Wise lore) -> UsageTable -> Stms (Wise lore) -> SimpleM lore (Stms (Wise lore), Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: hoistStms :: SimplifiableRep rep => RuleBook (Wise rep) -> BlockPred (Wise rep) -> SymbolTable (Wise rep) -> UsageTable -> Stms (Wise rep) -> SimpleM rep (Stms (Wise rep), Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: isConsumed :: BlockPred lore
+ Futhark.Optimise.Simplify.Engine: isConsumed :: BlockPred rep
- Futhark.Optimise.Simplify.Engine: isFalse :: Bool -> BlockPred lore
+ Futhark.Optimise.Simplify.Engine: isFalse :: Bool -> BlockPred rep
- Futhark.Optimise.Simplify.Engine: isNotSafe :: ASTLore lore => BlockPred lore
+ Futhark.Optimise.Simplify.Engine: isNotSafe :: ASTRep rep => BlockPred rep
- Futhark.Optimise.Simplify.Engine: isOp :: BlockPred lore
+ Futhark.Optimise.Simplify.Engine: isOp :: BlockPred rep
- Futhark.Optimise.Simplify.Engine: localVtable :: (SymbolTable (Wise lore) -> SymbolTable (Wise lore)) -> SimpleM lore a -> SimpleM lore a
+ Futhark.Optimise.Simplify.Engine: localVtable :: (SymbolTable (Wise rep) -> SymbolTable (Wise rep)) -> SimpleM rep a -> SimpleM rep a
- Futhark.Optimise.Simplify.Engine: neverBlocks :: BlockPred lore
+ Futhark.Optimise.Simplify.Engine: neverBlocks :: BlockPred rep
- Futhark.Optimise.Simplify.Engine: neverHoist :: HoistBlockers lore
+ Futhark.Optimise.Simplify.Engine: neverHoist :: HoistBlockers rep
- Futhark.Optimise.Simplify.Engine: noExtraHoistBlockers :: HoistBlockers lore
+ Futhark.Optimise.Simplify.Engine: noExtraHoistBlockers :: HoistBlockers rep
- Futhark.Optimise.Simplify.Engine: orIf :: BlockPred lore -> BlockPred lore -> BlockPred lore
+ Futhark.Optimise.Simplify.Engine: orIf :: BlockPred rep -> BlockPred rep -> BlockPred rep
- Futhark.Optimise.Simplify.Engine: runSimpleM :: SimpleM lore a -> SimpleOps lore -> Env lore -> VNameSource -> ((a, Bool), VNameSource)
+ Futhark.Optimise.Simplify.Engine: runSimpleM :: SimpleM rep a -> SimpleOps rep -> Env rep -> VNameSource -> ((a, Bool), VNameSource)
- Futhark.Optimise.Simplify.Engine: simplify :: (Simplifiable e, SimplifiableLore lore) => e -> SimpleM lore e
+ Futhark.Optimise.Simplify.Engine: simplify :: (Simplifiable e, SimplifiableRep rep) => e -> SimpleM rep e
- Futhark.Optimise.Simplify.Engine: simplifyBody :: SimplifiableLore lore => [Diet] -> Body lore -> SimpleM lore (SimplifiedBody lore Result)
+ Futhark.Optimise.Simplify.Engine: simplifyBody :: SimplifiableRep rep => [Diet] -> Body rep -> SimpleM rep (SimplifiedBody rep Result)
- Futhark.Optimise.Simplify.Engine: simplifyFun :: SimplifiableLore lore => FunDef lore -> SimpleM lore (FunDef (Wise lore))
+ Futhark.Optimise.Simplify.Engine: simplifyFun :: SimplifiableRep rep => FunDef rep -> SimpleM rep (FunDef (Wise rep))
- Futhark.Optimise.Simplify.Engine: simplifyLambda :: SimplifiableLore lore => Lambda lore -> SimpleM lore (Lambda (Wise lore), Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: simplifyLambda :: SimplifiableRep rep => Lambda rep -> SimpleM rep (Lambda (Wise rep), Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: simplifyLambdaNoHoisting :: SimplifiableLore lore => Lambda lore -> SimpleM lore (Lambda (Wise lore))
+ Futhark.Optimise.Simplify.Engine: simplifyLambdaNoHoisting :: SimplifiableRep rep => Lambda rep -> SimpleM rep (Lambda (Wise rep))
- Futhark.Optimise.Simplify.Engine: simplifyStms :: SimplifiableLore lore => Stms lore -> SimpleM lore (a, Stms (Wise lore)) -> SimpleM lore (a, Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: simplifyStms :: SimplifiableRep rep => Stms rep -> SimpleM rep (a, Stms (Wise rep)) -> SimpleM rep (a, Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: type BlockPred lore = SymbolTable lore -> UsageTable -> Stm lore -> Bool
+ Futhark.Optimise.Simplify.Engine: type BlockPred rep = SymbolTable rep -> UsageTable -> Stm rep -> Bool
- Futhark.Optimise.Simplify.Engine: type SimplifiedBody lore a = ((a, UsageTable), Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: type SimplifiedBody rep a = ((a, UsageTable), Stms (Wise rep))
- Futhark.Optimise.Simplify.Engine: type SimplifyOp lore op = op -> SimpleM lore (OpWithWisdom op, Stms (Wise lore))
+ Futhark.Optimise.Simplify.Engine: type SimplifyOp rep op = op -> SimpleM rep (OpWithWisdom op, Stms (Wise rep))
- Futhark.Optimise.Simplify.Rule: RuleBasicOp :: RuleBasicOp lore a -> SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: RuleBasicOp :: RuleBasicOp rep a -> SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: RuleDoLoop :: RuleDoLoop lore a -> SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: RuleDoLoop :: RuleDoLoop rep a -> SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: RuleGeneric :: RuleGeneric lore a -> SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: RuleGeneric :: RuleGeneric rep a -> SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: RuleIf :: RuleIf lore a -> SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: RuleIf :: RuleIf rep a -> SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: RuleOp :: RuleOp lore a -> SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: RuleOp :: RuleOp rep a -> SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: Simplify :: RuleM lore () -> Rule lore
+ Futhark.Optimise.Simplify.Rule: Simplify :: RuleM rep () -> Rule rep
- Futhark.Optimise.Simplify.Rule: Skip :: Rule lore
+ Futhark.Optimise.Simplify.Rule: Skip :: Rule rep
- Futhark.Optimise.Simplify.Rule: bottomUpSimplifyStm :: (MonadFreshNames m, HasScope lore m) => RuleBook lore -> (SymbolTable lore, UsageTable) -> Stm lore -> m (Maybe (Stms lore))
+ Futhark.Optimise.Simplify.Rule: bottomUpSimplifyStm :: (MonadFreshNames m, HasScope rep m) => RuleBook rep -> (SymbolTable rep, UsageTable) -> Stm rep -> m (Maybe (Stms rep))
- Futhark.Optimise.Simplify.Rule: cannotSimplify :: RuleM lore a
+ Futhark.Optimise.Simplify.Rule: cannotSimplify :: RuleM rep a
- Futhark.Optimise.Simplify.Rule: data Rule lore
+ Futhark.Optimise.Simplify.Rule: data Rule rep
- Futhark.Optimise.Simplify.Rule: data RuleBook lore
+ Futhark.Optimise.Simplify.Rule: data RuleBook rep
- Futhark.Optimise.Simplify.Rule: data RuleM lore a
+ Futhark.Optimise.Simplify.Rule: data RuleM rep a
- Futhark.Optimise.Simplify.Rule: data SimplificationRule lore a
+ Futhark.Optimise.Simplify.Rule: data SimplificationRule rep a
- Futhark.Optimise.Simplify.Rule: liftMaybe :: Maybe a -> RuleM lore a
+ Futhark.Optimise.Simplify.Rule: liftMaybe :: Maybe a -> RuleM rep a
- Futhark.Optimise.Simplify.Rule: topDownSimplifyStm :: (MonadFreshNames m, HasScope lore m) => RuleBook lore -> SymbolTable lore -> Stm lore -> m (Maybe (Stms lore))
+ Futhark.Optimise.Simplify.Rule: topDownSimplifyStm :: (MonadFreshNames m, HasScope rep m) => RuleBook rep -> SymbolTable rep -> Stm rep -> m (Maybe (Stms rep))
- Futhark.Optimise.Simplify.Rule: type BottomUp lore = (SymbolTable lore, UsageTable)
+ Futhark.Optimise.Simplify.Rule: type BottomUp rep = (SymbolTable rep, UsageTable)
- Futhark.Optimise.Simplify.Rule: type BottomUpRule lore = SimplificationRule lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRule rep = SimplificationRule rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type BottomUpRuleBasicOp lore = RuleBasicOp lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRuleBasicOp rep = RuleBasicOp rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type BottomUpRuleDoLoop lore = RuleDoLoop lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRuleDoLoop rep = RuleDoLoop rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type BottomUpRuleGeneric lore = RuleGeneric lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRuleGeneric rep = RuleGeneric rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type BottomUpRuleIf lore = RuleIf lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRuleIf rep = RuleIf rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type BottomUpRuleOp lore = RuleOp lore (BottomUp lore)
+ Futhark.Optimise.Simplify.Rule: type BottomUpRuleOp rep = RuleOp rep (BottomUp rep)
- Futhark.Optimise.Simplify.Rule: type RuleBasicOp lore a = (a -> Pattern lore -> StmAux (ExpDec lore) -> BasicOp -> Rule lore)
+ Futhark.Optimise.Simplify.Rule: type RuleBasicOp rep a = (a -> Pattern rep -> StmAux (ExpDec rep) -> BasicOp -> Rule rep)
- Futhark.Optimise.Simplify.Rule: type RuleDoLoop lore a = a -> Pattern lore -> StmAux (ExpDec lore) -> ([(FParam lore, SubExp)], [(FParam lore, SubExp)], LoopForm lore, BodyT lore) -> Rule lore
+ 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 RuleGeneric lore a = a -> Stm lore -> Rule lore
+ Futhark.Optimise.Simplify.Rule: type RuleGeneric rep a = a -> Stm rep -> Rule rep
- Futhark.Optimise.Simplify.Rule: type RuleIf lore a = a -> Pattern lore -> StmAux (ExpDec lore) -> (SubExp, BodyT lore, BodyT lore, IfDec (BranchType lore)) -> Rule lore
+ 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 TopDown lore = SymbolTable lore
+ Futhark.Optimise.Simplify.Rule: type TopDown rep = SymbolTable rep
- Futhark.Optimise.Simplify.Rule: type TopDownRule lore = SimplificationRule lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRule rep = SimplificationRule rep (TopDown rep)
- Futhark.Optimise.Simplify.Rule: type TopDownRuleBasicOp lore = RuleBasicOp lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRuleBasicOp rep = RuleBasicOp rep (TopDown rep)
- Futhark.Optimise.Simplify.Rule: type TopDownRuleDoLoop lore = RuleDoLoop lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRuleDoLoop rep = RuleDoLoop rep (TopDown rep)
- Futhark.Optimise.Simplify.Rule: type TopDownRuleGeneric lore = RuleGeneric lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRuleGeneric rep = RuleGeneric rep (TopDown rep)
- Futhark.Optimise.Simplify.Rule: type TopDownRuleIf lore = RuleIf lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRuleIf rep = RuleIf rep (TopDown rep)
- Futhark.Optimise.Simplify.Rule: type TopDownRuleOp lore = RuleOp lore (TopDown lore)
+ Futhark.Optimise.Simplify.Rule: type TopDownRuleOp rep = RuleOp rep (TopDown rep)
- Futhark.Optimise.Simplify.Rules: removeUnnecessaryCopy :: (BinderOps lore, Aliased lore) => BottomUpRuleBasicOp lore
+ Futhark.Optimise.Simplify.Rules: removeUnnecessaryCopy :: (BinderOps rep, Aliased rep) => BottomUpRuleBasicOp rep
- Futhark.Optimise.Simplify.Rules: standardRules :: (BinderOps lore, Aliased lore) => RuleBook lore
+ Futhark.Optimise.Simplify.Rules: standardRules :: (BinderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.BasicOp: basicOpRules :: (BinderOps lore, Aliased lore) => RuleBook lore
+ Futhark.Optimise.Simplify.Rules.BasicOp: basicOpRules :: (BinderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.ClosedForm: foldClosedForm :: (ASTLore lore, BinderOps lore) => VarLookup lore -> Pattern lore -> Lambda lore -> [SubExp] -> [VName] -> RuleM lore ()
+ 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: loopClosedForm :: (ASTLore lore, BinderOps lore) => Pattern lore -> [(FParam lore, SubExp)] -> Names -> IntType -> SubExp -> Body lore -> RuleM lore ()
+ 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.Index: simplifyIndexing :: MonadBinder m => SymbolTable (Lore m) -> TypeLookup -> VName -> Slice SubExp -> Bool -> Maybe (m IndexResult)
+ Futhark.Optimise.Simplify.Rules.Index: simplifyIndexing :: MonadBinder m => SymbolTable (Rep m) -> TypeLookup -> VName -> Slice SubExp -> Bool -> Maybe (m IndexResult)
- Futhark.Optimise.Simplify.Rules.Loop: loopRules :: (BinderOps lore, Aliased lore) => RuleBook lore
+ Futhark.Optimise.Simplify.Rules.Loop: loopRules :: (BinderOps rep, Aliased rep) => RuleBook rep
- Futhark.Optimise.Simplify.Rules.Simple: applySimpleRules :: VarLookup lore -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)
+ Futhark.Optimise.Simplify.Rules.Simple: applySimpleRules :: VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)
- Futhark.Optimise.Simplify.Rules.Simple: type VarLookup lore = VName -> Maybe (Exp lore, Certificates)
+ Futhark.Optimise.Simplify.Rules.Simple: type VarLookup rep = VName -> Maybe (Exp rep, Certificates)
- Futhark.Optimise.TileLoops: tileLoops :: Pass Kernels Kernels
+ Futhark.Optimise.TileLoops: tileLoops :: Pass GPU GPU
- Futhark.Optimise.TileLoops.Shared: isTileableRedomap :: Stm Kernels -> Maybe (SubExp, [VName], (Commutativity, Lambda Kernels, [SubExp], Lambda Kernels))
+ Futhark.Optimise.TileLoops.Shared: isTileableRedomap :: Stm GPU -> Maybe (SubExp, [VName], (Commutativity, Lambda GPU, [SubExp], Lambda GPU))
- Futhark.Optimise.TileLoops.Shared: segMap2D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp) -> ((VName, VName) -> Binder Kernels [SubExp]) -> Binder Kernels [VName]
+ Futhark.Optimise.TileLoops.Shared: segMap2D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp) -> ((VName, VName) -> Binder GPU [SubExp]) -> Binder GPU [VName]
- Futhark.Optimise.TileLoops.Shared: segMap3D :: String -> SegLevel -> ResultManifest -> (SubExp, SubExp, SubExp) -> ((VName, VName, VName) -> Binder Kernels [SubExp]) -> Binder Kernels [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: segScatter2D :: String -> SubExp -> VName -> SegLevel -> (SubExp, SubExp) -> ((VName, VName) -> Binder Kernels (SubExp, SubExp)) -> Binder Kernels [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: type TileM = ReaderT (Scope Kernels) (State VNameSource)
+ Futhark.Optimise.TileLoops.Shared: type TileM = ReaderT (Scope GPU) (State VNameSource)
- Futhark.Optimise.TileLoops.Shared: varianceInStms :: VarianceTable -> Stms Kernels -> VarianceTable
+ Futhark.Optimise.TileLoops.Shared: varianceInStms :: VarianceTable -> Stms GPU -> VarianceTable
- Futhark.Pass: Pass :: String -> String -> (Prog fromlore -> PassM (Prog tolore)) -> Pass fromlore tolore
+ Futhark.Pass: Pass :: String -> String -> (Prog fromrep -> PassM (Prog torep)) -> Pass fromrep torep
- Futhark.Pass: [passDescription] :: Pass fromlore tolore -> String
+ Futhark.Pass: [passDescription] :: Pass fromrep torep -> String
- Futhark.Pass: [passFunction] :: Pass fromlore tolore -> Prog fromlore -> PassM (Prog tolore)
+ Futhark.Pass: [passFunction] :: Pass fromrep torep -> Prog fromrep -> PassM (Prog torep)
- Futhark.Pass: [passName] :: Pass fromlore tolore -> String
+ Futhark.Pass: [passName] :: Pass fromrep torep -> String
- Futhark.Pass: data Pass fromlore tolore
+ Futhark.Pass: data Pass fromrep torep
- Futhark.Pass: intraproceduralTransformation :: (Scope lore -> Stms lore -> PassM (Stms lore)) -> Prog lore -> PassM (Prog lore)
+ Futhark.Pass: intraproceduralTransformation :: (Scope rep -> Stms rep -> PassM (Stms rep)) -> Prog rep -> PassM (Prog rep)
- Futhark.Pass: intraproceduralTransformationWithConsts :: (Stms fromlore -> PassM (Stms tolore)) -> (Stms tolore -> FunDef fromlore -> PassM (FunDef tolore)) -> Prog fromlore -> PassM (Prog tolore)
+ Futhark.Pass: intraproceduralTransformationWithConsts :: (Stms fromrep -> PassM (Stms torep)) -> (Stms torep -> FunDef fromrep -> PassM (FunDef torep)) -> Prog fromrep -> PassM (Prog torep)
- Futhark.Pass: passLongOption :: Pass fromlore tolore -> String
+ Futhark.Pass: passLongOption :: Pass fromrep torep -> String
- Futhark.Pass.ExpandAllocations: expandAllocations :: Pass KernelsMem KernelsMem
+ Futhark.Pass.ExpandAllocations: expandAllocations :: Pass GPUMem GPUMem
- Futhark.Pass.ExplicitAllocations: AllocEnv :: ChunkMap -> Bool -> Space -> Set VName -> (Op fromlore -> AllocM fromlore tolore (Op tolore)) -> (Exp tolore -> AllocM fromlore tolore [ExpHint]) -> AllocEnv fromlore tolore
+ Futhark.Pass.ExplicitAllocations: AllocEnv :: ChunkMap -> Bool -> Space -> Set VName -> (Op fromrep -> AllocM fromrep torep (Op torep)) -> (Exp torep -> AllocM fromrep torep [ExpHint]) -> AllocEnv fromrep torep
- Futhark.Pass.ExplicitAllocations: [aggressiveReuse] :: AllocEnv fromlore tolore -> Bool
+ Futhark.Pass.ExplicitAllocations: [aggressiveReuse] :: AllocEnv fromrep torep -> Bool
- Futhark.Pass.ExplicitAllocations: [allocInOp] :: AllocEnv fromlore tolore -> Op fromlore -> AllocM fromlore tolore (Op tolore)
+ Futhark.Pass.ExplicitAllocations: [allocInOp] :: AllocEnv fromrep torep -> Op fromrep -> AllocM fromrep torep (Op torep)
- Futhark.Pass.ExplicitAllocations: [allocSpace] :: AllocEnv fromlore tolore -> Space
+ Futhark.Pass.ExplicitAllocations: [allocSpace] :: AllocEnv fromrep torep -> Space
- Futhark.Pass.ExplicitAllocations: [chunkMap] :: AllocEnv fromlore tolore -> ChunkMap
+ Futhark.Pass.ExplicitAllocations: [chunkMap] :: AllocEnv fromrep torep -> ChunkMap
- Futhark.Pass.ExplicitAllocations: [envConsts] :: AllocEnv fromlore tolore -> Set VName
+ Futhark.Pass.ExplicitAllocations: [envConsts] :: AllocEnv fromrep torep -> Set VName
- Futhark.Pass.ExplicitAllocations: [envExpHints] :: AllocEnv fromlore tolore -> Exp tolore -> AllocM fromlore tolore [ExpHint]
+ Futhark.Pass.ExplicitAllocations: [envExpHints] :: AllocEnv fromrep torep -> Exp torep -> AllocM fromrep torep [ExpHint]
- Futhark.Pass.ExplicitAllocations: addAllocStm :: (Allocator lore m, Allocable fromlore lore, m ~ AllocM fromlore lore) => AllocStm -> m ()
+ Futhark.Pass.ExplicitAllocations: addAllocStm :: (Allocator rep m, Allocable fromrep rep, m ~ AllocM fromrep rep) => AllocStm -> m ()
- Futhark.Pass.ExplicitAllocations: allocForArray :: Allocator lore m => Type -> Space -> m VName
+ Futhark.Pass.ExplicitAllocations: allocForArray :: Allocator rep m => Type -> Space -> m VName
- Futhark.Pass.ExplicitAllocations: allocInStms :: Allocable fromlore tolore => Stms fromlore -> AllocM fromlore tolore a -> AllocM fromlore tolore a
+ Futhark.Pass.ExplicitAllocations: allocInStms :: Allocable fromrep torep => Stms fromrep -> AllocM fromrep torep a -> AllocM fromrep torep a
- Futhark.Pass.ExplicitAllocations: askConsts :: Allocator lore m => m (Set VName)
+ Futhark.Pass.ExplicitAllocations: askConsts :: Allocator rep m => m (Set VName)
- Futhark.Pass.ExplicitAllocations: askDefaultSpace :: Allocator lore m => m Space
+ Futhark.Pass.ExplicitAllocations: askDefaultSpace :: Allocator rep m => m Space
- Futhark.Pass.ExplicitAllocations: class (MonadFreshNames m, LocalScope lore m, Mem lore) => Allocator lore m
+ Futhark.Pass.ExplicitAllocations: class (MonadFreshNames m, LocalScope rep m, Mem rep) => Allocator rep m
- Futhark.Pass.ExplicitAllocations: data AllocEnv fromlore tolore
+ Futhark.Pass.ExplicitAllocations: data AllocEnv fromrep torep
- Futhark.Pass.ExplicitAllocations: data AllocM fromlore tolore a
+ Futhark.Pass.ExplicitAllocations: data AllocM fromrep torep a
- Futhark.Pass.ExplicitAllocations: defaultExpHints :: (Monad m, ASTLore lore) => Exp lore -> m [ExpHint]
+ Futhark.Pass.ExplicitAllocations: defaultExpHints :: (Monad m, ASTRep rep) => Exp rep -> m [ExpHint]
- Futhark.Pass.ExplicitAllocations: dimAllocationSize :: (Allocator lore m, m ~ AllocM fromlore lore) => SubExp -> m SubExp
+ Futhark.Pass.ExplicitAllocations: dimAllocationSize :: (Allocator rep m, m ~ AllocM fromrep rep) => SubExp -> m SubExp
- Futhark.Pass.ExplicitAllocations: expHints :: Allocator lore m => Exp lore -> m [ExpHint]
+ Futhark.Pass.ExplicitAllocations: expHints :: Allocator rep m => Exp rep -> m [ExpHint]
- Futhark.Pass.ExplicitAllocations: explicitAllocationsGeneric :: (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) => (Op fromlore -> AllocM fromlore tolore (Op tolore)) -> (Exp tolore -> AllocM fromlore tolore [ExpHint]) -> Pass fromlore tolore
+ 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: explicitAllocationsInStmsGeneric :: (MonadFreshNames m, HasScope tolore m, Allocable fromlore tolore) => (Op fromlore -> AllocM fromlore tolore (Op tolore)) -> (Exp tolore -> AllocM fromlore tolore [ExpHint]) -> Stms fromlore -> m (Stms tolore)
+ 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: mkLetNamesB' :: (Op (Lore m) ~ MemOp inner, MonadBinder m, ExpDec (Lore m) ~ (), Allocator (Lore m) (PatAllocM (Lore m))) => ExpDec (Lore m) -> [VName] -> Exp (Lore m) -> m (Stm (Lore m))
+ 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'' :: (Op (Lore m) ~ MemOp inner, ExpDec lore ~ (), HasScope (Wise lore) m, Allocator lore (PatAllocM lore), MonadBinder m, CanBeWise (Op lore)) => [VName] -> Exp (Wise lore) -> m (Stm (Wise lore))
+ 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: simplifiable :: (SimplifiableLore lore, ExpDec lore ~ (), BodyDec lore ~ (), Op lore ~ MemOp inner, Allocator lore (PatAllocM lore)) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM lore (OpWithWisdom inner, Stms (Wise lore))) -> SimpleOps lore
+ 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: type Allocable fromlore tolore = (PrettyLore fromlore, PrettyLore tolore, Mem tolore, FParamInfo fromlore ~ DeclType, LParamInfo fromlore ~ Type, BranchType fromlore ~ ExtType, RetType fromlore ~ DeclExtType, BodyDec fromlore ~ (), BodyDec tolore ~ (), ExpDec tolore ~ (), SizeSubst (Op tolore), BinderOps tolore)
+ 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.SegOp: allocInBinOpLambda :: Allocable fromlore tolore => SubExp -> SegSpace -> Lambda fromlore -> AllocM fromlore tolore (Lambda tolore)
+ Futhark.Pass.ExplicitAllocations.SegOp: allocInBinOpLambda :: Allocable fromrep torep => SubExp -> SegSpace -> Lambda fromrep -> AllocM fromrep torep (Lambda torep)
- Futhark.Pass.ExplicitAllocations.SegOp: allocInKernelBody :: Allocable fromlore tolore => KernelBody fromlore -> AllocM fromlore tolore (KernelBody tolore)
+ Futhark.Pass.ExplicitAllocations.SegOp: allocInKernelBody :: Allocable fromrep torep => KernelBody fromrep -> AllocM fromrep torep (KernelBody torep)
- Futhark.Pass.ExplicitAllocations.Seq: simplifiable :: (SimplifiableLore lore, ExpDec lore ~ (), BodyDec lore ~ (), Op lore ~ MemOp inner, Allocator lore (PatAllocM lore)) => (OpWithWisdom inner -> UsageTable) -> (inner -> SimpleM lore (OpWithWisdom inner, Stms (Wise lore))) -> SimpleOps lore
+ 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.ExtractKernels: extractKernels :: Pass SOACS Kernels
+ Futhark.Pass.ExtractKernels: extractKernels :: Pass SOACS GPU
- Futhark.Pass.ExtractKernels.BlockedKernel: dummyDim :: (MonadFreshNames m, MonadBinder m, DistLore (Lore m)) => Pattern (Lore m) -> m (Pattern (Lore m), [(VName, SubExp)], m ())
+ 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: mapKernel :: (DistLore lore, HasScope lore m, MonadFreshNames m) => MkSegLevel lore m -> [(VName, SubExp)] -> [KernelInput] -> [Type] -> KernelBody lore -> m (SegOp (SegOpLevel lore) lore, Stms lore)
+ Futhark.Pass.ExtractKernels.BlockedKernel: mapKernel :: (DistRep rep, HasScope rep m, MonadFreshNames m) => MkSegLevel rep m -> [(VName, SubExp)] -> [KernelInput] -> [Type] -> KernelBody rep -> m (SegOp (SegOpLevel rep) rep, Stms rep)
- Futhark.Pass.ExtractKernels.BlockedKernel: nonSegRed :: (MonadFreshNames m, DistLore lore, HasScope lore m) => SegOpLevel lore -> Pattern lore -> SubExp -> [SegBinOp lore] -> Lambda lore -> [VName] -> m (Stms lore)
+ 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: readKernelInput :: (DistLore (Lore m), MonadBinder m) => KernelInput -> m ()
+ Futhark.Pass.ExtractKernels.BlockedKernel: readKernelInput :: (DistRep (Rep m), MonadBinder m) => KernelInput -> m ()
- Futhark.Pass.ExtractKernels.BlockedKernel: segHist :: (DistLore lore, MonadFreshNames m, HasScope lore m) => SegOpLevel lore -> Pattern lore -> SubExp -> [(VName, SubExp)] -> [KernelInput] -> [HistOp lore] -> Lambda lore -> [VName] -> m (Stms lore)
+ 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: segMap :: (MonadFreshNames m, DistLore lore, HasScope lore m) => SegOpLevel lore -> Pattern lore -> SubExp -> Lambda lore -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms lore)
+ 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: segRed :: (MonadFreshNames m, DistLore lore, HasScope lore m) => SegOpLevel lore -> Pattern lore -> SubExp -> [SegBinOp lore] -> Lambda lore -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms lore)
+ 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: segScan :: (MonadFreshNames m, DistLore lore, HasScope lore m) => SegOpLevel lore -> Pattern lore -> SubExp -> [SegBinOp lore] -> Lambda lore -> [VName] -> [(VName, SubExp)] -> [KernelInput] -> m (Stms lore)
+ 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: type MkSegLevel lore m = [SubExp] -> String -> ThreadRecommendation -> BinderT lore m (SegOpLevel lore)
+ Futhark.Pass.ExtractKernels.BlockedKernel: type MkSegLevel rep m = [SubExp] -> String -> ThreadRecommendation -> BinderT rep m (SegOpLevel rep)
- Futhark.Pass.ExtractKernels.DistributeNests: DistAcc :: Targets -> Stms lore -> DistAcc lore
+ Futhark.Pass.ExtractKernels.DistributeNests: DistAcc :: Targets -> Stms rep -> DistAcc rep
- Futhark.Pass.ExtractKernels.DistributeNests: DistEnv :: Nestings -> Scope lore -> (Stms SOACS -> DistNestT lore m (Stms lore)) -> (MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)) -> (Stm SOACS -> Binder lore (Stms lore)) -> (Lambda SOACS -> Binder lore (Lambda lore)) -> MkSegLevel lore m -> DistEnv lore 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 -> Binder rep (Stms rep)) -> (Lambda SOACS -> Binder rep (Lambda rep)) -> MkSegLevel rep m -> DistEnv rep m
- Futhark.Pass.ExtractKernels.DistributeNests: [distNest] :: DistEnv lore m -> Nestings
+ Futhark.Pass.ExtractKernels.DistributeNests: [distNest] :: DistEnv rep m -> Nestings
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnInnerMap] :: DistEnv lore m -> MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnInnerMap] :: DistEnv rep m -> MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep)
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSLambda] :: DistEnv lore m -> Lambda SOACS -> Binder lore (Lambda lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSLambda] :: DistEnv rep m -> Lambda SOACS -> Binder rep (Lambda rep)
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSStms] :: DistEnv lore m -> Stm SOACS -> Binder lore (Stms lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnSOACSStms] :: DistEnv rep m -> Stm SOACS -> Binder rep (Stms rep)
- Futhark.Pass.ExtractKernels.DistributeNests: [distOnTopLevelStms] :: DistEnv lore m -> Stms SOACS -> DistNestT lore m (Stms lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: [distOnTopLevelStms] :: DistEnv rep m -> Stms SOACS -> DistNestT rep m (Stms rep)
- Futhark.Pass.ExtractKernels.DistributeNests: [distScope] :: DistEnv lore m -> Scope lore
+ Futhark.Pass.ExtractKernels.DistributeNests: [distScope] :: DistEnv rep m -> Scope rep
- Futhark.Pass.ExtractKernels.DistributeNests: [distSegLevel] :: DistEnv lore m -> MkSegLevel lore m
+ Futhark.Pass.ExtractKernels.DistributeNests: [distSegLevel] :: DistEnv rep m -> MkSegLevel rep m
- Futhark.Pass.ExtractKernels.DistributeNests: [distStms] :: DistAcc lore -> Stms lore
+ Futhark.Pass.ExtractKernels.DistributeNests: [distStms] :: DistAcc rep -> Stms rep
- Futhark.Pass.ExtractKernels.DistributeNests: [distTargets] :: DistAcc lore -> Targets
+ Futhark.Pass.ExtractKernels.DistributeNests: [distTargets] :: DistAcc rep -> Targets
- Futhark.Pass.ExtractKernels.DistributeNests: addPostStms :: Monad m => PostStms lore -> DistNestT lore m ()
+ Futhark.Pass.ExtractKernels.DistributeNests: addPostStms :: Monad m => PostStms rep -> DistNestT rep m ()
- Futhark.Pass.ExtractKernels.DistributeNests: addStmToAcc :: (MonadFreshNames m, DistLore lore) => Stm SOACS -> DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: addStmToAcc :: (MonadFreshNames m, DistRep rep) => Stm SOACS -> DistAcc rep -> DistNestT rep m (DistAcc rep)
- Futhark.Pass.ExtractKernels.DistributeNests: addStmsToAcc :: Stms lore -> DistAcc lore -> DistAcc lore
+ Futhark.Pass.ExtractKernels.DistributeNests: addStmsToAcc :: Stms rep -> DistAcc rep -> DistAcc rep
- Futhark.Pass.ExtractKernels.DistributeNests: data DistAcc lore
+ Futhark.Pass.ExtractKernels.DistributeNests: data DistAcc rep
- Futhark.Pass.ExtractKernels.DistributeNests: data DistEnv lore m
+ Futhark.Pass.ExtractKernels.DistributeNests: data DistEnv rep m
- Futhark.Pass.ExtractKernels.DistributeNests: data DistNestT lore m a
+ Futhark.Pass.ExtractKernels.DistributeNests: data DistNestT rep m a
- Futhark.Pass.ExtractKernels.DistributeNests: distribute :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distribute :: (MonadFreshNames m, LocalScope rep m, DistRep rep) => DistAcc rep -> DistNestT rep m (DistAcc rep)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeMap :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeMap :: (MonadFreshNames m, LocalScope rep m, DistRep rep) => MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeMapBodyStms :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> Stms SOACS -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeMapBodyStms :: (MonadFreshNames m, LocalScope rep m, DistRep rep) => DistAcc rep -> Stms SOACS -> DistNestT rep m (DistAcc rep)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeSingleStm :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> Stm SOACS -> DistNestT lore m (Maybe (PostStms lore, Result, KernelNest, DistAcc lore))
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeSingleStm :: (MonadFreshNames m, LocalScope rep m, DistRep rep) => DistAcc rep -> Stm SOACS -> DistNestT rep m (Maybe (PostStms rep, Result, KernelNest, DistAcc rep))
- Futhark.Pass.ExtractKernels.DistributeNests: histKernel :: (MonadBinder m, DistLore (Lore m)) => (Lambda SOACS -> m (Lambda (Lore m))) -> SegOpLevel (Lore m) -> PatternT Type -> [(VName, SubExp)] -> [KernelInput] -> Certificates -> SubExp -> [HistOp SOACS] -> Lambda (Lore m) -> [VName] -> m (Stms (Lore m))
+ 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: inNesting :: (Monad m, DistLore lore) => KernelNest -> DistNestT lore m a -> DistNestT lore m a
+ Futhark.Pass.ExtractKernels.DistributeNests: inNesting :: (Monad m, DistRep rep) => KernelNest -> DistNestT rep m a -> DistNestT rep m a
- Futhark.Pass.ExtractKernels.DistributeNests: liftInner :: (LocalScope lore m, DistLore lore) => m a -> DistNestT lore m a
+ Futhark.Pass.ExtractKernels.DistributeNests: liftInner :: (LocalScope rep m, DistRep rep) => m a -> DistNestT rep m a
- Futhark.Pass.ExtractKernels.DistributeNests: postStm :: Monad m => Stms lore -> DistNestT lore m ()
+ Futhark.Pass.ExtractKernels.DistributeNests: postStm :: Monad m => Stms rep -> DistNestT rep m ()
- Futhark.Pass.ExtractKernels.DistributeNests: runDistNestT :: (MonadLogger m, DistLore lore) => DistEnv lore m -> DistNestT lore m (DistAcc lore) -> m (Stms lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: runDistNestT :: (MonadLogger m, DistRep rep) => DistEnv rep m -> DistNestT rep m (DistAcc rep) -> m (Stms rep)
- Futhark.Pass.ExtractKernels.Distribution: constructKernel :: (DistLore lore, MonadFreshNames m, LocalScope lore m) => MkSegLevel lore m -> KernelNest -> Body lore -> m (Stm lore, Stms lore)
+ Futhark.Pass.ExtractKernels.Distribution: constructKernel :: (DistRep rep, MonadFreshNames m, LocalScope rep m) => MkSegLevel rep m -> KernelNest -> Body rep -> m (Stm rep, Stms rep)
- Futhark.Pass.ExtractKernels.Distribution: scopeOfLoopNesting :: DistLore lore => LoopNesting -> Scope lore
+ Futhark.Pass.ExtractKernels.Distribution: scopeOfLoopNesting :: DistRep rep => LoopNesting -> Scope rep
- Futhark.Pass.ExtractKernels.Distribution: targetsScope :: DistLore lore => Targets -> Scope lore
+ Futhark.Pass.ExtractKernels.Distribution: targetsScope :: DistRep rep => Targets -> Scope rep
- Futhark.Pass.ExtractKernels.Distribution: tryDistribute :: (DistLore lore, MonadFreshNames m, LocalScope lore m, MonadLogger m) => MkSegLevel lore m -> Nestings -> Targets -> Stms lore -> m (Maybe (Targets, Stms lore))
+ Futhark.Pass.ExtractKernels.Distribution: tryDistribute :: (DistRep rep, MonadFreshNames m, LocalScope rep m, MonadLogger m) => MkSegLevel rep m -> Nestings -> Targets -> Stms rep -> m (Maybe (Targets, Stms rep))
- Futhark.Pass.ExtractKernels.Distribution: tryDistributeStm :: (MonadFreshNames m, HasScope t m, ASTLore lore) => Nestings -> Targets -> Stm lore -> m (Maybe (Result, Targets, KernelNest))
+ Futhark.Pass.ExtractKernels.Distribution: tryDistributeStm :: (MonadFreshNames m, HasScope t m, ASTRep rep) => Nestings -> Targets -> Stm rep -> m (Maybe (Result, Targets, KernelNest))
- Futhark.Pass.ExtractKernels.ISRWIM: irwim :: (MonadBinder m, Lore m ~ SOACS) => Pattern -> SubExp -> Commutativity -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
+ Futhark.Pass.ExtractKernels.ISRWIM: irwim :: (MonadBinder m, Rep m ~ SOACS) => Pattern -> SubExp -> Commutativity -> Lambda -> [(SubExp, VName)] -> Maybe (m ())
- Futhark.Pass.ExtractKernels.ISRWIM: iswim :: (MonadBinder m, Lore m ~ SOACS) => Pattern -> SubExp -> 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.Intragroup: intraGroupParallelise :: (MonadFreshNames m, LocalScope Kernels m) => KernelNest -> Lambda -> m (Maybe ((SubExp, SubExp), SubExp, Log, Stms Kernels, Stms Kernels))
+ Futhark.Pass.ExtractKernels.Intragroup: intraGroupParallelise :: (MonadFreshNames m, LocalScope GPU m) => KernelNest -> Lambda -> m (Maybe ((SubExp, SubExp), SubExp, Log, Stms GPU, Stms GPU))
- Futhark.Pass.ExtractKernels.StreamKernel: segThreadCapped :: MonadFreshNames m => MkSegLevel Kernels m
+ Futhark.Pass.ExtractKernels.StreamKernel: segThreadCapped :: MonadFreshNames m => MkSegLevel GPU m
- Futhark.Pass.ExtractKernels.StreamKernel: streamMap :: (MonadFreshNames m, HasScope Kernels m) => MkSegLevel Kernels m -> [String] -> [PatElem Kernels] -> SubExp -> Commutativity -> Lambda Kernels -> [SubExp] -> [VName] -> m ((SubExp, [VName]), Stms Kernels)
+ Futhark.Pass.ExtractKernels.StreamKernel: streamMap :: (MonadFreshNames m, HasScope GPU m) => MkSegLevel GPU m -> [String] -> [PatElem GPU] -> SubExp -> Commutativity -> Lambda GPU -> [SubExp] -> [VName] -> m ((SubExp, [VName]), Stms GPU)
- Futhark.Pass.ExtractKernels.StreamKernel: streamRed :: (MonadFreshNames m, HasScope Kernels m) => MkSegLevel Kernels m -> Pattern Kernels -> SubExp -> Commutativity -> Lambda Kernels -> Lambda Kernels -> [SubExp] -> [VName] -> m (Stms Kernels)
+ 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.FirstOrderTransform: firstOrderTransform :: FirstOrderLore lore => Pass SOACS lore
+ Futhark.Pass.FirstOrderTransform: firstOrderTransform :: FirstOrderRep rep => Pass SOACS rep
- Futhark.Pass.KernelBabysitting: babysitKernels :: Pass Kernels Kernels
+ Futhark.Pass.KernelBabysitting: babysitKernels :: Pass GPU GPU
- Futhark.Pass.Simplify: simplify :: (Prog lore -> PassM (Prog lore)) -> Pass lore lore
+ Futhark.Pass.Simplify: simplify :: (Prog rep -> PassM (Prog rep)) -> Pass rep rep
- Futhark.Passes: gpuPipeline :: Pipeline SOACS KernelsMem
+ Futhark.Passes: gpuPipeline :: Pipeline SOACS GPUMem
- Futhark.Passes: kernelsPipeline :: Pipeline SOACS Kernels
+ Futhark.Passes: kernelsPipeline :: Pipeline SOACS GPU
- Futhark.Pipeline: Action :: String -> String -> (Prog lore -> FutharkM ()) -> Action lore
+ Futhark.Pipeline: Action :: String -> String -> (Prog rep -> FutharkM ()) -> Action rep
- Futhark.Pipeline: [actionDescription] :: Action lore -> String
+ Futhark.Pipeline: [actionDescription] :: Action rep -> String
- Futhark.Pipeline: [actionName] :: Action lore -> String
+ Futhark.Pipeline: [actionName] :: Action rep -> String
- Futhark.Pipeline: [actionProcedure] :: Action lore -> Prog lore -> FutharkM ()
+ Futhark.Pipeline: [actionProcedure] :: Action rep -> Prog rep -> FutharkM ()
- Futhark.Pipeline: data Action lore
+ Futhark.Pipeline: data Action rep
- Futhark.Pipeline: data Pipeline fromlore tolore
+ Futhark.Pipeline: data Pipeline fromrep torep
- Futhark.Pipeline: onePass :: Checkable tolore => Pass fromlore tolore -> Pipeline fromlore tolore
+ Futhark.Pipeline: onePass :: Checkable torep => Pass fromrep torep -> Pipeline fromrep torep
- Futhark.Pipeline: passes :: Checkable lore => [Pass lore lore] -> Pipeline lore lore
+ Futhark.Pipeline: passes :: Checkable rep => [Pass rep rep] -> Pipeline rep rep
- Futhark.Pipeline: runPipeline :: Pipeline fromlore tolore -> PipelineConfig -> Prog fromlore -> FutharkM (Prog tolore)
+ Futhark.Pipeline: runPipeline :: Pipeline fromrep torep -> PipelineConfig -> Prog fromrep -> FutharkM (Prog torep)
- Futhark.Script: withScriptServer :: FilePath -> [FilePath] -> (ScriptServer -> IO a) -> IO a
+ Futhark.Script: withScriptServer :: ServerCfg -> (ScriptServer -> IO a) -> IO a
- Futhark.Test: compareValues :: [Value] -> [Value] -> [Mismatch]
+ Futhark.Test: compareValues :: Tolerance -> Value -> Value -> [Mismatch]
- Futhark.Test: readResults :: (MonadIO m, MonadError Text m) => Server -> [VarName] -> FilePath -> m [Value]
+ Futhark.Test: readResults :: (MonadIO m, MonadError Text m) => Server -> [VarName] -> m [Value]
- Futhark.Test.Values: mkCompound :: [v] -> Compound v
+ Futhark.Test.Values: mkCompound :: [Compound v] -> Compound v
- Futhark.Tools: dissectScrema :: (MonadBinder m, Op (Lore m) ~ SOAC (Lore m), Bindable (Lore m)) => Pattern (Lore m) -> SubExp -> ScremaForm (Lore m) -> [VName] -> m ()
+ 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: redomapToMapAndReduce :: (MonadFreshNames m, Bindable lore, ExpDec lore ~ (), Op lore ~ SOAC lore) => Pattern lore -> (SubExp, Commutativity, LambdaT lore, LambdaT lore, [SubExp], [VName]) -> m (Stm lore, Stm lore)
+ 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: sequentialStreamWholeArray :: (MonadBinder m, Bindable (Lore m)) => Pattern (Lore m) -> SubExp -> [SubExp] -> LambdaT (Lore m) -> [VName] -> m ()
+ Futhark.Tools: sequentialStreamWholeArray :: (MonadBinder m, Bindable (Rep m)) => Pattern (Rep m) -> SubExp -> [SubExp] -> LambdaT (Rep m) -> [VName] -> m ()
- Futhark.Transform.CopyPropagate: copyPropagateInFun :: (MonadFreshNames m, SimplifiableLore lore) => SimpleOps lore -> SymbolTable (Wise lore) -> FunDef lore -> m (FunDef lore)
+ Futhark.Transform.CopyPropagate: copyPropagateInFun :: (MonadFreshNames m, SimplifiableRep rep) => SimpleOps rep -> SymbolTable (Wise rep) -> FunDef rep -> m (FunDef rep)
- Futhark.Transform.CopyPropagate: copyPropagateInProg :: SimplifiableLore lore => SimpleOps lore -> Prog lore -> PassM (Prog lore)
+ Futhark.Transform.CopyPropagate: copyPropagateInProg :: SimplifiableRep rep => SimpleOps rep -> Prog rep -> PassM (Prog rep)
- Futhark.Transform.CopyPropagate: copyPropagateInStms :: (MonadFreshNames m, SimplifiableLore lore) => SimpleOps lore -> Scope lore -> Stms lore -> m (SymbolTable (Wise lore), Stms lore)
+ Futhark.Transform.CopyPropagate: copyPropagateInStms :: (MonadFreshNames m, SimplifiableRep rep) => SimpleOps rep -> Scope rep -> Stms rep -> m (SymbolTable (Wise rep), Stms rep)
- Futhark.Transform.FirstOrderTransform: transformConsts :: (MonadFreshNames m, FirstOrderLore tolore) => Stms SOACS -> m (Stms tolore)
+ Futhark.Transform.FirstOrderTransform: transformConsts :: (MonadFreshNames m, FirstOrderRep torep) => Stms SOACS -> m (Stms torep)
- Futhark.Transform.FirstOrderTransform: transformFunDef :: (MonadFreshNames m, FirstOrderLore tolore) => Scope tolore -> FunDef SOACS -> m (FunDef tolore)
+ Futhark.Transform.FirstOrderTransform: transformFunDef :: (MonadFreshNames m, FirstOrderRep torep) => Scope torep -> FunDef SOACS -> m (FunDef torep)
- Futhark.Transform.FirstOrderTransform: transformLambda :: (MonadFreshNames m, Bindable lore, BinderOps lore, LocalScope somelore m, SameScope somelore lore, LetDec lore ~ LetDec SOACS, CanBeAliased (Op lore)) => Lambda -> m (Lambda lore)
+ 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: transformSOAC :: Transformer m => Pattern (Lore m) -> SOAC (Lore m) -> m ()
+ Futhark.Transform.FirstOrderTransform: transformSOAC :: Transformer m => Pattern (Rep m) -> SOAC (Rep m) -> m ()
- Futhark.Transform.FirstOrderTransform: transformStmRecursively :: (Transformer m, LetDec (Lore m) ~ LetDec SOACS) => Stm -> m ()
+ Futhark.Transform.FirstOrderTransform: transformStmRecursively :: (Transformer m, LetDec (Rep m) ~ LetDec SOACS) => Stm -> m ()
- Futhark.Transform.FirstOrderTransform: type Transformer m = (MonadBinder m, LocalScope (Lore m) m, Bindable (Lore m), BinderOps (Lore m), LParamInfo SOACS ~ LParamInfo (Lore m), CanBeAliased (Op (Lore m)))
+ 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.Rename: renameBody :: (Renameable lore, MonadFreshNames m) => Body lore -> m (Body lore)
+ Futhark.Transform.Rename: renameBody :: (Renameable rep, MonadFreshNames m) => Body rep -> m (Body rep)
- Futhark.Transform.Rename: renameExp :: (Renameable lore, MonadFreshNames m) => Exp lore -> m (Exp lore)
+ Futhark.Transform.Rename: renameExp :: (Renameable rep, MonadFreshNames m) => Exp rep -> m (Exp rep)
- Futhark.Transform.Rename: renameLambda :: (Renameable lore, MonadFreshNames m) => Lambda lore -> m (Lambda lore)
+ Futhark.Transform.Rename: renameLambda :: (Renameable rep, MonadFreshNames m) => Lambda rep -> m (Lambda rep)
- Futhark.Transform.Rename: renameProg :: (Renameable lore, MonadFreshNames m) => Prog lore -> m (Prog lore)
+ Futhark.Transform.Rename: renameProg :: (Renameable rep, MonadFreshNames m) => Prog rep -> m (Prog rep)
- Futhark.Transform.Rename: renameStm :: (Renameable lore, MonadFreshNames m) => Stm lore -> m (Stm lore)
+ Futhark.Transform.Rename: renameStm :: (Renameable rep, MonadFreshNames m) => Stm rep -> m (Stm rep)
- Futhark.Transform.Rename: renamingStms :: Renameable lore => Stms lore -> (Stms lore -> RenameM a) -> RenameM a
+ Futhark.Transform.Rename: renamingStms :: Renameable rep => Stms rep -> (Stms rep -> RenameM a) -> RenameM a
- Futhark.Transform.Rename: type Renameable lore = (Rename (LetDec lore), Rename (ExpDec lore), Rename (BodyDec lore), Rename (FParamInfo lore), Rename (LParamInfo lore), Rename (RetType lore), Rename (BranchType lore), Rename (Op lore))
+ Futhark.Transform.Rename: type Renameable rep = (Rename (LetDec rep), Rename (ExpDec rep), Rename (BodyDec rep), Rename (FParamInfo rep), Rename (LParamInfo rep), Rename (RetType rep), Rename (BranchType rep), Rename (Op rep))
- Futhark.Transform.Substitute: type Substitutable lore = (Decorations lore, Substitute (ExpDec lore), Substitute (BodyDec lore), Substitute (LetDec lore), Substitute (FParamInfo lore), Substitute (LParamInfo lore), Substitute (RetType lore), Substitute (BranchType lore), Substitute (Op lore))
+ Futhark.Transform.Substitute: type Substitutable rep = (RepTypes rep, Substitute (ExpDec rep), Substitute (BodyDec rep), Substitute (LetDec rep), Substitute (FParamInfo rep), Substitute (LParamInfo rep), Substitute (RetType rep), Substitute (BranchType rep), Substitute (Op rep))
- Futhark.TypeCheck: BadAnnotation :: String -> Type -> Type -> ErrorCase lore
+ Futhark.TypeCheck: BadAnnotation :: String -> Type -> Type -> ErrorCase rep
- Futhark.TypeCheck: DupDefinitionError :: Name -> ErrorCase lore
+ Futhark.TypeCheck: DupDefinitionError :: Name -> ErrorCase rep
- Futhark.TypeCheck: DupParamError :: Name -> VName -> ErrorCase lore
+ Futhark.TypeCheck: DupParamError :: Name -> VName -> ErrorCase rep
- Futhark.TypeCheck: DupPatternError :: VName -> ErrorCase lore
+ Futhark.TypeCheck: DupPatternError :: VName -> ErrorCase rep
- Futhark.TypeCheck: Error :: [String] -> ErrorCase lore -> TypeError lore
+ Futhark.TypeCheck: Error :: [String] -> ErrorCase rep -> TypeError rep
- Futhark.TypeCheck: InvalidPatternError :: Pattern (Aliases lore) -> [ExtType] -> Maybe String -> ErrorCase lore
+ Futhark.TypeCheck: InvalidPatternError :: Pattern (Aliases rep) -> [ExtType] -> Maybe String -> ErrorCase rep
- Futhark.TypeCheck: NotAnArray :: VName -> Type -> ErrorCase lore
+ Futhark.TypeCheck: NotAnArray :: VName -> Type -> ErrorCase rep
- Futhark.TypeCheck: ParameterMismatch :: Maybe Name -> [Type] -> [Type] -> ErrorCase lore
+ Futhark.TypeCheck: ParameterMismatch :: Maybe Name -> [Type] -> [Type] -> ErrorCase rep
- Futhark.TypeCheck: PermutationError :: [Int] -> Int -> Maybe VName -> ErrorCase lore
+ Futhark.TypeCheck: PermutationError :: [Int] -> Int -> Maybe VName -> ErrorCase rep
- Futhark.TypeCheck: ReturnAliased :: Name -> VName -> ErrorCase lore
+ Futhark.TypeCheck: ReturnAliased :: Name -> VName -> ErrorCase rep
- Futhark.TypeCheck: ReturnTypeError :: Name -> [ExtType] -> [ExtType] -> ErrorCase lore
+ Futhark.TypeCheck: ReturnTypeError :: Name -> [ExtType] -> [ExtType] -> ErrorCase rep
- Futhark.TypeCheck: SlicingError :: Int -> Int -> ErrorCase lore
+ Futhark.TypeCheck: SlicingError :: Int -> Int -> ErrorCase rep
- Futhark.TypeCheck: TypeError :: String -> ErrorCase lore
+ Futhark.TypeCheck: TypeError :: String -> ErrorCase rep
- Futhark.TypeCheck: UnexpectedType :: Exp lore -> Type -> [Type] -> ErrorCase lore
+ Futhark.TypeCheck: UnexpectedType :: Exp rep -> Type -> [Type] -> ErrorCase rep
- Futhark.TypeCheck: UniqueReturnAliased :: Name -> ErrorCase lore
+ Futhark.TypeCheck: UniqueReturnAliased :: Name -> ErrorCase rep
- Futhark.TypeCheck: UnknownFunctionError :: Name -> ErrorCase lore
+ Futhark.TypeCheck: UnknownFunctionError :: Name -> ErrorCase rep
- Futhark.TypeCheck: UnknownVariableError :: VName -> ErrorCase lore
+ Futhark.TypeCheck: UnknownVariableError :: VName -> ErrorCase rep
- Futhark.TypeCheck: alternative :: TypeM lore a -> TypeM lore b -> TypeM lore (a, b)
+ Futhark.TypeCheck: alternative :: TypeM rep a -> TypeM rep b -> TypeM rep (a, b)
- Futhark.TypeCheck: bad :: ErrorCase lore -> TypeM lore a
+ Futhark.TypeCheck: bad :: ErrorCase rep -> TypeM rep a
- Futhark.TypeCheck: binding :: Checkable lore => Scope (Aliases lore) -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: binding :: Checkable rep => Scope (Aliases rep) -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: checkArg :: Checkable lore => SubExp -> TypeM lore Arg
+ Futhark.TypeCheck: checkArg :: Checkable rep => SubExp -> TypeM rep Arg
- Futhark.TypeCheck: checkBody :: Checkable lore => Body (Aliases lore) -> TypeM lore [Names]
+ Futhark.TypeCheck: checkBody :: Checkable rep => Body (Aliases rep) -> TypeM rep [Names]
- Futhark.TypeCheck: checkExp :: Checkable lore => Exp (Aliases lore) -> TypeM lore ()
+ Futhark.TypeCheck: checkExp :: Checkable rep => Exp (Aliases rep) -> TypeM rep ()
- Futhark.TypeCheck: checkExtType :: Checkable lore => TypeBase ExtShape u -> TypeM lore ()
+ Futhark.TypeCheck: checkExtType :: Checkable rep => TypeBase ExtShape u -> TypeM rep ()
- Futhark.TypeCheck: checkLambda :: Checkable lore => Lambda (Aliases lore) -> [Arg] -> TypeM lore ()
+ Futhark.TypeCheck: checkLambda :: Checkable rep => Lambda (Aliases rep) -> [Arg] -> TypeM rep ()
- Futhark.TypeCheck: checkOp :: CheckableOp lore => OpWithAliases (Op lore) -> TypeM lore ()
+ Futhark.TypeCheck: checkOp :: CheckableOp rep => OpWithAliases (Op rep) -> TypeM rep ()
- Futhark.TypeCheck: checkOpWith :: (OpWithAliases (Op lore) -> TypeM lore ()) -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: checkOpWith :: (OpWithAliases (Op rep) -> TypeM rep ()) -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: checkProg :: Checkable lore => Prog (Aliases lore) -> Either (TypeError lore) ()
+ Futhark.TypeCheck: checkProg :: Checkable rep => Prog (Aliases rep) -> Either (TypeError rep) ()
- Futhark.TypeCheck: checkRetType :: (Checkable lore, RetType lore ~ DeclExtType) => [RetType lore] -> TypeM lore ()
+ Futhark.TypeCheck: checkRetType :: (Checkable rep, RetType rep ~ DeclExtType) => [RetType rep] -> TypeM rep ()
- Futhark.TypeCheck: checkSOACArrayArgs :: Checkable lore => SubExp -> [VName] -> TypeM lore [Arg]
+ Futhark.TypeCheck: checkSOACArrayArgs :: Checkable rep => SubExp -> [VName] -> TypeM rep [Arg]
- Futhark.TypeCheck: checkStm :: Checkable lore => Stm (Aliases lore) -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: checkStm :: Checkable rep => Stm (Aliases rep) -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: checkStms :: Checkable lore => Stms (Aliases lore) -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: checkStms :: Checkable rep => Stms (Aliases rep) -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: checkSubExp :: Checkable lore => SubExp -> TypeM lore Type
+ Futhark.TypeCheck: checkSubExp :: Checkable rep => SubExp -> TypeM rep Type
- Futhark.TypeCheck: checkType :: Checkable lore => TypeBase Shape u -> TypeM lore ()
+ Futhark.TypeCheck: checkType :: Checkable rep => TypeBase Shape u -> TypeM rep ()
- Futhark.TypeCheck: class (ASTLore lore, CanBeAliased (Op lore), CheckableOp lore) => Checkable lore
+ Futhark.TypeCheck: class (ASTRep rep, CanBeAliased (Op rep), CheckableOp rep) => Checkable rep
- Futhark.TypeCheck: class ASTLore lore => CheckableOp lore
+ Futhark.TypeCheck: class ASTRep rep => CheckableOp rep
- Futhark.TypeCheck: consume :: Checkable lore => Names -> TypeM lore ()
+ Futhark.TypeCheck: consume :: Checkable rep => Names -> TypeM rep ()
- Futhark.TypeCheck: consumeOnlyParams :: [(VName, Names)] -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: consumeOnlyParams :: [(VName, Names)] -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: context :: String -> TypeM lore a -> TypeM lore a
+ Futhark.TypeCheck: context :: String -> TypeM rep a -> TypeM rep a
- Futhark.TypeCheck: data ErrorCase lore
+ Futhark.TypeCheck: data ErrorCase rep
- Futhark.TypeCheck: data TypeError lore
+ Futhark.TypeCheck: data TypeError rep
- Futhark.TypeCheck: data TypeM lore a
+ Futhark.TypeCheck: data TypeM rep a
- Futhark.TypeCheck: lookupAliases :: Checkable lore => VName -> TypeM lore Names
+ Futhark.TypeCheck: lookupAliases :: Checkable rep => VName -> TypeM rep Names
- Futhark.TypeCheck: lookupVar :: VName -> TypeM lore (NameInfo (Aliases lore))
+ Futhark.TypeCheck: lookupVar :: VName -> TypeM rep (NameInfo (Aliases rep))
- Futhark.TypeCheck: matchBranchType :: (Checkable lore, BranchType lore ~ ExtType) => [BranchType lore] -> Body (Aliases lore) -> TypeM lore ()
+ Futhark.TypeCheck: matchBranchType :: (Checkable rep, BranchType rep ~ ExtType) => [BranchType rep] -> Body (Aliases rep) -> TypeM rep ()
- Futhark.TypeCheck: matchExtBranchType :: Checkable lore => [ExtType] -> Body (Aliases lore) -> TypeM lore ()
+ Futhark.TypeCheck: matchExtBranchType :: Checkable rep => [ExtType] -> Body (Aliases rep) -> TypeM rep ()
- Futhark.TypeCheck: matchExtPattern :: Checkable lore => Pattern (Aliases lore) -> [ExtType] -> TypeM lore ()
+ Futhark.TypeCheck: matchExtPattern :: Checkable rep => Pattern (Aliases rep) -> [ExtType] -> TypeM rep ()
- Futhark.TypeCheck: matchLoopResult :: (Checkable lore, FParamInfo lore ~ DeclType) => [FParam (Aliases lore)] -> [FParam (Aliases lore)] -> [SubExp] -> TypeM lore ()
+ Futhark.TypeCheck: matchLoopResult :: (Checkable rep, FParamInfo rep ~ DeclType) => [FParam (Aliases rep)] -> [FParam (Aliases rep)] -> [SubExp] -> TypeM rep ()
- Futhark.TypeCheck: matchPattern :: Checkable lore => Pattern (Aliases lore) -> Exp (Aliases lore) -> TypeM lore ()
+ Futhark.TypeCheck: matchPattern :: Checkable rep => Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep ()
- Futhark.TypeCheck: matchReturnType :: (Checkable lore, RetType lore ~ DeclExtType) => [RetType lore] -> Result -> TypeM lore ()
+ Futhark.TypeCheck: matchReturnType :: (Checkable rep, RetType rep ~ DeclExtType) => [RetType rep] -> Result -> TypeM rep ()
- Futhark.TypeCheck: primFParam :: (Checkable lore, FParamInfo lore ~ DeclType) => VName -> PrimType -> TypeM lore (FParam (Aliases lore))
+ Futhark.TypeCheck: primFParam :: (Checkable rep, FParamInfo rep ~ DeclType) => VName -> PrimType -> TypeM rep (FParam (Aliases rep))
- Futhark.TypeCheck: require :: Checkable lore => [Type] -> SubExp -> TypeM lore ()
+ Futhark.TypeCheck: require :: Checkable rep => [Type] -> SubExp -> TypeM rep ()
- Futhark.TypeCheck: requireI :: Checkable lore => [Type] -> VName -> TypeM lore ()
+ Futhark.TypeCheck: requireI :: Checkable rep => [Type] -> VName -> TypeM rep ()
- Futhark.TypeCheck: requirePrimExp :: Checkable lore => PrimType -> PrimExp VName -> TypeM lore ()
+ Futhark.TypeCheck: requirePrimExp :: Checkable rep => PrimType -> PrimExp VName -> TypeM rep ()
Files
- docs/c-api.rst +10/−1
- docs/man/futhark-literate.rst +2/−2
- docs/server-protocol.rst +16/−4
- docs/usage.rst +32/−0
- futhark.cabal +33/−29
- rts/c/server.h +8/−0
- src/Futhark/Actions.hs +10/−10
- src/Futhark/Analysis/Alias.hs +27/−27
- src/Futhark/Analysis/DataDependencies.hs +3/−3
- src/Futhark/Analysis/HORep/MapNest.hs +22/−22
- src/Futhark/Analysis/HORep/SOAC.hs +30/−30
- src/Futhark/Analysis/Interference.hs +326/−0
- src/Futhark/Analysis/LastUse.hs +161/−0
- src/Futhark/Analysis/Metrics.hs +6/−6
- src/Futhark/Analysis/PrimExp/Convert.hs +2/−2
- src/Futhark/Analysis/PrimExp/Simplify.hs +7/−7
- src/Futhark/Analysis/Rephrase.hs +15/−15
- src/Futhark/Analysis/SymbolTable.hs +96/−96
- src/Futhark/Analysis/UsageTable.hs +7/−7
- src/Futhark/Bench.hs +6/−3
- src/Futhark/Binder.hs +67/−67
- src/Futhark/Binder/Class.hs +38/−38
- src/Futhark/CLI/Autotune.hs +1/−1
- src/Futhark/CLI/Bench.hs +33/−17
- src/Futhark/CLI/Datacmp.hs +3/−2
- src/Futhark/CLI/Dataset.hs +30/−26
- src/Futhark/CLI/Dev.hs +77/−71
- src/Futhark/CLI/Literate.hs +9/−7
- src/Futhark/CLI/Pkg.hs +9/−0
- src/Futhark/CLI/Test.hs +14/−11
- src/Futhark/CodeGen/Backends/CCUDA.hs +2/−2
- src/Futhark/CodeGen/Backends/COpenCL.hs +2/−2
- src/Futhark/CodeGen/Backends/GenericC.hs +85/−91
- src/Futhark/CodeGen/Backends/GenericC/CLI.hs +11/−11
- src/Futhark/CodeGen/Backends/GenericC/Server.hs +24/−7
- src/Futhark/CodeGen/Backends/GenericPython.hs +28/−27
- src/Futhark/CodeGen/Backends/MulticoreC.hs +6/−4
- src/Futhark/CodeGen/Backends/PyOpenCL.hs +3/−2
- src/Futhark/CodeGen/Backends/PyOpenCL/Boilerplate.hs +1/−1
- src/Futhark/CodeGen/Backends/SimpleRep.hs +3/−3
- src/Futhark/CodeGen/ImpCode.hs +16/−13
- src/Futhark/CodeGen/ImpCode/GPU.hs +266/−0
- src/Futhark/CodeGen/ImpCode/Kernels.hs +0/−266
- src/Futhark/CodeGen/ImpCode/OpenCL.hs +2/−2
- src/Futhark/CodeGen/ImpGen.hs +193/−197
- src/Futhark/CodeGen/ImpGen/CUDA.hs +4/−4
- src/Futhark/CodeGen/ImpGen/GPU.hs +431/−0
- src/Futhark/CodeGen/ImpGen/GPU/Base.hs +1785/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegHist.hs +1151/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegMap.hs +61/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegRed.hs +842/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegScan.hs +68/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegScan/SinglePass.hs +565/−0
- src/Futhark/CodeGen/ImpGen/GPU/SegScan/TwoPass.hs +506/−0
- src/Futhark/CodeGen/ImpGen/GPU/ToOpenCL.hs +888/−0
- src/Futhark/CodeGen/ImpGen/GPU/Transpose.hs +386/−0
- src/Futhark/CodeGen/ImpGen/Kernels.hs +0/−431
- src/Futhark/CodeGen/ImpGen/Kernels/Base.hs +0/−1803
- src/Futhark/CodeGen/ImpGen/Kernels/SegHist.hs +0/−1151
- src/Futhark/CodeGen/ImpGen/Kernels/SegMap.hs +0/−61
- src/Futhark/CodeGen/ImpGen/Kernels/SegRed.hs +0/−838
- src/Futhark/CodeGen/ImpGen/Kernels/SegScan.hs +0/−68
- src/Futhark/CodeGen/ImpGen/Kernels/SegScan/SinglePass.hs +0/−489
- src/Futhark/CodeGen/ImpGen/Kernels/SegScan/TwoPass.hs +0/−506
- src/Futhark/CodeGen/ImpGen/Kernels/ToOpenCL.hs +0/−888
- src/Futhark/CodeGen/ImpGen/Kernels/Transpose.hs +0/−386
- src/Futhark/CodeGen/ImpGen/Multicore/Base.hs +9/−29
- src/Futhark/CodeGen/ImpGen/Multicore/SegHist.hs +1/−1
- src/Futhark/CodeGen/ImpGen/OpenCL.hs +4/−4
- src/Futhark/CodeGen/SetDefaultSpace.hs +4/−4
- src/Futhark/Compiler.hs +4/−4
- src/Futhark/Compiler/CLI.hs +2/−2
- src/Futhark/Construct.hs +76/−76
- src/Futhark/IR.hs +1/−4
- src/Futhark/IR/Aliases.hs +69/−72
- src/Futhark/IR/Decorations.hs +0/−92
- src/Futhark/IR/GPU.hs +61/−0
- src/Futhark/IR/GPU/Kernel.hs +346/−0
- src/Futhark/IR/GPU/Simplify.hs +113/−0
- src/Futhark/IR/GPU/Sizes.hs +88/−0
- src/Futhark/IR/GPUMem.hs +111/−0
- src/Futhark/IR/Kernels.hs +0/−62
- src/Futhark/IR/Kernels/Kernel.hs +0/−346
- src/Futhark/IR/Kernels/Simplify.hs +0/−113
- src/Futhark/IR/Kernels/Sizes.hs +0/−88
- src/Futhark/IR/KernelsMem.hs +0/−111
- src/Futhark/IR/MC.hs +4/−5
- src/Futhark/IR/MC/Op.hs +29/−29
- src/Futhark/IR/MCMem.hs +6/−6
- src/Futhark/IR/Mem.hs +49/−50
- src/Futhark/IR/Mem/Simplify.hs +35/−35
- src/Futhark/IR/Parse.hs +70/−67
- src/Futhark/IR/Pretty.hs +35/−35
- src/Futhark/IR/Prop.hs +51/−30
- src/Futhark/IR/Prop/Aliases.hs +10/−16
- src/Futhark/IR/Prop/Names.hs +69/−69
- src/Futhark/IR/Prop/Patterns.hs +4/−4
- src/Futhark/IR/Prop/Reshape.hs +1/−1
- src/Futhark/IR/Prop/Scope.hs +61/−61
- src/Futhark/IR/Prop/TypeOf.hs +10/−10
- src/Futhark/IR/Rep.hs +92/−0
- src/Futhark/IR/SOACS.hs +5/−6
- src/Futhark/IR/SOACS/SOAC.hs +75/−75
- src/Futhark/IR/SOACS/Simplify.hs +24/−24
- src/Futhark/IR/SegOp.hs +145/−135
- src/Futhark/IR/Seq.hs +4/−5
- src/Futhark/IR/SeqMem.hs +6/−8
- src/Futhark/IR/Syntax.hs +75/−74
- src/Futhark/IR/Syntax/Core.hs +15/−1
- src/Futhark/IR/Traversals.hs +32/−32
- src/Futhark/Internalise/Defunctionalise.hs +16/−20
- src/Futhark/Internalise/Exps.hs +6/−5
- src/Futhark/Internalise/Monad.hs +1/−1
- src/Futhark/Optimise/BlkRegTiling.hs +22/−22
- src/Futhark/Optimise/CSE.hs +69/−69
- src/Futhark/Optimise/DoubleBuffer.hs +57/−57
- src/Futhark/Optimise/Fusion/Composing.hs +16/−16
- src/Futhark/Optimise/Fusion/LoopKernel.hs +3/−3
- src/Futhark/Optimise/InPlaceLowering.hs +64/−64
- src/Futhark/Optimise/InPlaceLowering/LowerIntoStm.hs +45/−45
- src/Futhark/Optimise/InPlaceLowering/SubstituteIndices.hs +33/−33
- src/Futhark/Optimise/InliningDeadFun.hs +1/−1
- src/Futhark/Optimise/ReuseAllocations.hs +255/−0
- src/Futhark/Optimise/ReuseAllocations/GreedyColoring.hs +61/−0
- src/Futhark/Optimise/Simplify.hs +39/−39
- src/Futhark/Optimise/Simplify/Engine.hs +177/−177
- src/Futhark/Optimise/Simplify/Lore.hs +0/−284
- src/Futhark/Optimise/Simplify/Rep.hs +278/−0
- src/Futhark/Optimise/Simplify/Rule.hs +88/−88
- src/Futhark/Optimise/Simplify/Rules.hs +11/−11
- src/Futhark/Optimise/Simplify/Rules/BasicOp.hs +6/−6
- src/Futhark/Optimise/Simplify/Rules/ClosedForm.hs +16/−16
- src/Futhark/Optimise/Simplify/Rules/Index.hs +1/−1
- src/Futhark/Optimise/Simplify/Rules/Loop.hs +14/−14
- src/Futhark/Optimise/Simplify/Rules/Simple.hs +18/−18
- src/Futhark/Optimise/Sink.hs +41/−41
- src/Futhark/Optimise/TileLoops.hs +91/−103
- src/Futhark/Optimise/TileLoops/Shared.hs +38/−15
- src/Futhark/Optimise/Unstream.hs +41/−41
- src/Futhark/Pass.hs +13/−13
- src/Futhark/Pass/ExpandAllocations.hs +55/−55
- src/Futhark/Pass/ExplicitAllocations.hs +178/−175
- src/Futhark/Pass/ExplicitAllocations/GPU.hs +192/−0
- src/Futhark/Pass/ExplicitAllocations/Kernels.hs +0/−192
- src/Futhark/Pass/ExplicitAllocations/MC.hs +1/−1
- src/Futhark/Pass/ExplicitAllocations/SegOp.hs +16/−16
- src/Futhark/Pass/ExtractKernels.hs +47/−45
- src/Futhark/Pass/ExtractKernels/BlockedKernel.hs +56/−57
- src/Futhark/Pass/ExtractKernels/DistributeNests.hs +112/−112
- src/Futhark/Pass/ExtractKernels/Distribution.hs +21/−21
- src/Futhark/Pass/ExtractKernels/ISRWIM.hs +2/−2
- src/Futhark/Pass/ExtractKernels/Interchange.hs +14/−5
- src/Futhark/Pass/ExtractKernels/Intragroup.hs +24/−24
- src/Futhark/Pass/ExtractKernels/StreamKernel.hs +24/−24
- src/Futhark/Pass/ExtractKernels/ToGPU.hs +85/−0
- src/Futhark/Pass/ExtractKernels/ToKernels.hs +0/−85
- src/Futhark/Pass/ExtractMulticore.hs +1/−1
- src/Futhark/Pass/FirstOrderTransform.hs +2/−2
- src/Futhark/Pass/KernelBabysitting.hs +16/−16
- src/Futhark/Pass/Simplify.hs +10/−10
- src/Futhark/Passes.hs +19/−16
- src/Futhark/Pipeline.hs +19/−19
- src/Futhark/Script.hs +26/−44
- src/Futhark/Server.hs +0/−211
- src/Futhark/Test.hs +50/−63
- src/Futhark/Test/Values.hs +16/−815
- src/Futhark/Test/Values/Parser.hs +0/−167
- src/Futhark/Tools.hs +15/−15
- src/Futhark/Transform/CopyPropagate.hs +15/−15
- src/Futhark/Transform/FirstOrderTransform.hs +33/−33
- src/Futhark/Transform/Rename.hs +32/−32
- src/Futhark/Transform/Substitute.hs +18/−18
- src/Futhark/TypeCheck.hs +187/−187
- src/Futhark/Util.hs +14/−0
- src/Futhark/Util/Loc.hs +0/−2
- src/Futhark/Util/Pretty.hs +0/−1
- src/Language/Futhark/Core.hs +0/−15
- src/Language/Futhark/Syntax.hs +1/−0
- unittests/Futhark/IR/Syntax/CoreTests.hs +1/−1
- unittests/Futhark/Optimise/ReuseAllocations/GreedyColoringTests.hs +70/−0
- unittests/futhark_tests.hs +3/−1
docs/c-api.rst view
@@ -301,6 +301,11 @@ be careful to check the return code of *both* the entry point itself, and :c:func:`futhark_context_sync`. +For the rules on entry points that consume their input, see+:ref:`api-consumption`. Note that even if a value has been consumed,+you must still manually free it. This is the only operation that is+permitted on a consumed value.+ GPU --- @@ -432,7 +437,6 @@ value less than ``1``, then the runtime system will use one thread per detected core. - General guarantees ------------------ @@ -459,3 +463,8 @@ OpenCL) may perform file system operations during startup, and perhaps for caching GPU kernels in some cases. This is beyond Futhark's control.++Violation the restrictions of consumption (see :ref:`api-consumption`)+can result in undefined behaviour. This does not matter for programs+whose entry points do not have unique parameter types+(:ref:`in-place-updates`).
docs/man/futhark-literate.rst view
@@ -83,7 +83,7 @@ DIRECTIVES ========== -A directive is a way to show the result of running a funtion.+A directive is a way to show the result of running a function. Depending on the directive, this can be as simple as printing the textual representation of the result, or as complex as running an external plotting program and referencing a generated image.@@ -205,7 +205,7 @@ Note that empty arrays must be written using the ``empty(t)`` notation, e.g. ``empty([0]i32)``. -Function applications are either of Futhark funtions or *builtin+Function applications are either of Futhark functions or *builtin functions*. The latter are prefixed with ``$`` and are magical (usually impure) functions that could not possibly be implemented in Futhark. The following builtins are supported:
docs/server-protocol.rst view
@@ -52,9 +52,20 @@ produce outputs of defined types. The notion of transparent and opaque types are the same as in the C API: primitives and array of primitives are directly supported, and everything else is treated as-opaque. See also :ref:`valuemapping`. When printed, types-follow basic Futhark type syntax *without* sizes (e.g. ``[][]i32``).+opaque. See also :ref:`valuemapping`. When printed, types follow+basic Futhark type syntax *without* sizes (e.g. ``[][]i32``).+Uniqueness is not part of the types, but is indicated with an asterisk+in the ``inputs`` and ``outputs`` commands (see below). +Consumption and aliasing+------------------------++Since the server protocol closely models the C API, the same rules+apply to entry points that consume their arguments (see+:ref:`api-consumption`). In particular, consumed variables must still+be freed with the ``free`` command - but this is the only operation+that may be used on consumed variables.+ Commands -------- @@ -92,13 +103,14 @@ .................. Print the types of inputs accepted by the given entry point, one per-line.+line. If the given input is consumed, the type is prefixed by `*`. ``outputs`` *entry* ................... Print the types of outputs produced by the given entry point, one per-line.+line. If the given output is guaranteed to be unique (does not alias+any inputs), the type is prefixed by `*`. ``clear`` .........
docs/usage.rst view
@@ -340,6 +340,38 @@ rule does not apply when the entry point has been given a return type ascription that is not syntactically a tuple type. +.. _api-consumption:++Consumption and Aliasing+~~~~~~~~~~~~~~~~~~~~~~~~++Futhark's support for :ref:`in-place-updates` has implications for the+generated API. Unfortunately, The type system of most languages+(e.g. C) is not rich enough to express the rules, so they are not+statically (or currently even dynamically checked). Since Futhark+will never infer a unique/consuming type for an entry point parameter,+this section can be ignored unless uniqueness annotations have been+manually added to the entry points parameter types. The rules are+essentially the same as in the language itself:++1. Each entry point input parameter is either *consuming* or+ *nonconsuming* (the default). This corresponds to unique and+ nonunique types in the original Futhark program. A value passed+ for a consuming parameter is considered *consumed*, now has an+ unspecified value, and may never be used again. It must still be+ manually freed, if applicable.+ Further, any *aliases* of that value are also considered consumed+ and may not be used.++2. Each entry point output is either *unique* or *nonunique*. A+ unique output has no aliases. A nonunique output aliases *every*+ nonconsuming input parameter.++Note that these distinctions are currently usually not visible in the+generated API, and so correct usage requires knowledge of the original+types in the Futhark function. The safest strategy is to not expose+unique types in entry points.+ Generating C ^^^^^^^^^^^^
futhark.cabal view
@@ -1,7 +1,6 @@ cabal-version: 2.4--- Run 'cabal2nix . >futhark.nix' after adding deps. name: futhark-version: 0.19.6+version: 0.19.7 synopsis: An optimising compiler for a functional, array-oriented language. description: Futhark is a small programming language designed to be compiled to@@ -26,7 +25,7 @@ . <<docs/assets/ohyes.png You too can go fast once you rewrite your program in Futhark.>> -category: Language+category: Futhark homepage: https://futhark-lang.org bug-reports: https://github.com/diku-dk/futhark/issues maintainer: Troels Henriksen athas@sigkill.dk@@ -58,12 +57,14 @@ Futhark.Analysis.DataDependencies Futhark.Analysis.HORep.MapNest Futhark.Analysis.HORep.SOAC+ Futhark.Analysis.Interference+ Futhark.Analysis.LastUse Futhark.Analysis.Metrics Futhark.Analysis.Metrics.Type Futhark.Analysis.PrimExp- Futhark.Analysis.PrimExp.Parse Futhark.Analysis.PrimExp.Convert Futhark.Analysis.PrimExp.Generalize+ Futhark.Analysis.PrimExp.Parse Futhark.Analysis.PrimExp.Simplify Futhark.Analysis.Rephrase Futhark.Analysis.SymbolTable@@ -97,8 +98,8 @@ Futhark.CodeGen.Backends.COpenCL.Boilerplate Futhark.CodeGen.Backends.GenericC Futhark.CodeGen.Backends.GenericC.CLI- Futhark.CodeGen.Backends.GenericC.Server Futhark.CodeGen.Backends.GenericC.Options+ Futhark.CodeGen.Backends.GenericC.Server Futhark.CodeGen.Backends.GenericPython Futhark.CodeGen.Backends.GenericPython.AST Futhark.CodeGen.Backends.GenericPython.Definitions@@ -111,22 +112,22 @@ Futhark.CodeGen.Backends.SequentialPython Futhark.CodeGen.Backends.SimpleRep Futhark.CodeGen.ImpCode- Futhark.CodeGen.ImpCode.Kernels+ Futhark.CodeGen.ImpCode.GPU Futhark.CodeGen.ImpCode.Multicore Futhark.CodeGen.ImpCode.OpenCL Futhark.CodeGen.ImpCode.Sequential Futhark.CodeGen.ImpGen Futhark.CodeGen.ImpGen.CUDA- Futhark.CodeGen.ImpGen.Kernels- Futhark.CodeGen.ImpGen.Kernels.Base- Futhark.CodeGen.ImpGen.Kernels.SegHist- Futhark.CodeGen.ImpGen.Kernels.SegMap- Futhark.CodeGen.ImpGen.Kernels.SegRed- Futhark.CodeGen.ImpGen.Kernels.SegScan- Futhark.CodeGen.ImpGen.Kernels.SegScan.SinglePass- Futhark.CodeGen.ImpGen.Kernels.SegScan.TwoPass- Futhark.CodeGen.ImpGen.Kernels.ToOpenCL- Futhark.CodeGen.ImpGen.Kernels.Transpose+ Futhark.CodeGen.ImpGen.GPU+ Futhark.CodeGen.ImpGen.GPU.Base+ Futhark.CodeGen.ImpGen.GPU.SegHist+ Futhark.CodeGen.ImpGen.GPU.SegMap+ Futhark.CodeGen.ImpGen.GPU.SegRed+ Futhark.CodeGen.ImpGen.GPU.SegScan+ Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass+ Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass+ Futhark.CodeGen.ImpGen.GPU.ToOpenCL+ Futhark.CodeGen.ImpGen.GPU.Transpose Futhark.CodeGen.ImpGen.Multicore Futhark.CodeGen.ImpGen.Multicore.Base Futhark.CodeGen.ImpGen.Multicore.SegHist@@ -148,19 +149,18 @@ Futhark.FreshNames Futhark.IR Futhark.IR.Aliases- Futhark.IR.Decorations- Futhark.IR.Parse- Futhark.IR.Kernels- Futhark.IR.Kernels.Kernel- Futhark.IR.Kernels.Simplify- Futhark.IR.Kernels.Sizes- Futhark.IR.KernelsMem+ Futhark.IR.GPU+ Futhark.IR.GPU.Kernel+ Futhark.IR.GPU.Simplify+ Futhark.IR.GPU.Sizes+ Futhark.IR.GPUMem Futhark.IR.MC Futhark.IR.MC.Op Futhark.IR.MCMem Futhark.IR.Mem Futhark.IR.Mem.IxFun Futhark.IR.Mem.Simplify+ Futhark.IR.Parse Futhark.IR.Pretty Futhark.IR.Primitive Futhark.IR.Primitive.Parse@@ -174,6 +174,7 @@ Futhark.IR.Prop.Scope Futhark.IR.Prop.TypeOf Futhark.IR.Prop.Types+ Futhark.IR.Rep Futhark.IR.RetType Futhark.IR.SOACS Futhark.IR.SOACS.SOAC@@ -207,9 +208,11 @@ Futhark.Optimise.InPlaceLowering.LowerIntoStm Futhark.Optimise.InPlaceLowering.SubstituteIndices Futhark.Optimise.InliningDeadFun+ Futhark.Optimise.ReuseAllocations+ Futhark.Optimise.ReuseAllocations.GreedyColoring Futhark.Optimise.Simplify Futhark.Optimise.Simplify.Engine- Futhark.Optimise.Simplify.Lore+ Futhark.Optimise.Simplify.Rep Futhark.Optimise.Simplify.Rule Futhark.Optimise.Simplify.Rules Futhark.Optimise.Simplify.Rules.BasicOp@@ -224,10 +227,10 @@ Futhark.Pass Futhark.Pass.ExpandAllocations Futhark.Pass.ExplicitAllocations- Futhark.Pass.ExplicitAllocations.Kernels+ Futhark.Pass.ExplicitAllocations.GPU+ Futhark.Pass.ExplicitAllocations.MC Futhark.Pass.ExplicitAllocations.SegOp Futhark.Pass.ExplicitAllocations.Seq- Futhark.Pass.ExplicitAllocations.MC Futhark.Pass.ExtractKernels Futhark.Pass.ExtractKernels.BlockedKernel Futhark.Pass.ExtractKernels.DistributeNests@@ -236,7 +239,7 @@ Futhark.Pass.ExtractKernels.Interchange Futhark.Pass.ExtractKernels.Intragroup Futhark.Pass.ExtractKernels.StreamKernel- Futhark.Pass.ExtractKernels.ToKernels+ Futhark.Pass.ExtractKernels.ToGPU Futhark.Pass.ExtractMulticore Futhark.Pass.FirstOrderTransform Futhark.Pass.KernelBabysitting@@ -247,10 +250,8 @@ Futhark.Pkg.Solve Futhark.Pkg.Types Futhark.Script- Futhark.Server Futhark.Test Futhark.Test.Values- Futhark.Test.Values.Parser Futhark.Tools Futhark.Transform.CopyPropagate Futhark.Transform.FirstOrderTransform@@ -314,6 +315,8 @@ , file-embed >=0.0.9 , filepath >=1.4.1.1 , free >=4.12.4+ , futhark-data >= 1.0.0.1+ , futhark-server >= 1.1.0.0 , gitrev >=1.2.0 , hashable , haskeline@@ -372,6 +375,7 @@ Futhark.IR.PrimitiveTests Language.Futhark.CoreTests Language.Futhark.SyntaxTests+ Futhark.Optimise.ReuseAllocations.GreedyColoringTests Paths_futhark hs-source-dirs: unittests
rts/c/server.h view
@@ -131,7 +131,9 @@ const char *name; entry_point_fn f; struct type **out_types;+ bool *out_unique; struct type **in_types;+ bool *in_unique; }; int entry_num_ins(struct entry_point *e) {@@ -459,6 +461,9 @@ int num_ins = entry_num_ins(e); for (int i = 0; i < num_ins; i++) {+ if (e->in_unique[i]) {+ putchar('*');+ } puts(e->in_types[i]->name); } }@@ -475,6 +480,9 @@ int num_outs = entry_num_outs(e); for (int i = 0; i < num_outs; i++) {+ if (e->out_unique[i]) {+ putchar('*');+ } puts(e->out_types[i]->name); } }
src/Futhark/Actions.hs view
@@ -29,12 +29,12 @@ 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.ImpGen.Kernels as ImpGenKernels+import qualified Futhark.CodeGen.ImpGen.GPU as ImpGenGPU import qualified Futhark.CodeGen.ImpGen.Multicore as ImpGenMulticore import qualified Futhark.CodeGen.ImpGen.Sequential as ImpGenSequential import Futhark.Compiler.CLI import Futhark.IR-import Futhark.IR.KernelsMem (KernelsMem)+import Futhark.IR.GPUMem (GPUMem) import Futhark.IR.MCMem (MCMem) import Futhark.IR.Prop.Aliases import Futhark.IR.SeqMem (SeqMem)@@ -46,7 +46,7 @@ import qualified System.Info -- | Print the result to stdout.-printAction :: ASTLore lore => Action lore+printAction :: ASTRep rep => Action rep printAction = Action { actionName = "Prettyprint",@@ -55,7 +55,7 @@ } -- | Print the result to stdout, alias annotations.-printAliasesAction :: (ASTLore lore, CanBeAliased (Op lore)) => Action lore+printAliasesAction :: (ASTRep rep, CanBeAliased (Op rep)) => Action rep printAliasesAction = Action { actionName = "Prettyprint",@@ -64,7 +64,7 @@ } -- | Print metrics about AST node counts to stdout.-metricsAction :: OpMetrics (Op lore) => Action lore+metricsAction :: OpMetrics (Op rep) => Action rep metricsAction = Action { actionName = "Compute metrics",@@ -82,12 +82,12 @@ } -- | Convert the program to GPU ImpCode and print it to stdout.-kernelImpCodeGenAction :: Action KernelsMem+kernelImpCodeGenAction :: Action GPUMem kernelImpCodeGenAction = Action { actionName = "Compile imperative kernels", actionDescription = "Translate program into imperative IL with kernels and write it on standard output.",- actionProcedure = liftIO . putStrLn . pretty . snd <=< ImpGenKernels.compileProgOpenCL+ actionProcedure = liftIO . putStrLn . pretty . snd <=< ImpGenGPU.compileProgOpenCL } -- | Convert the program to CPU multicore ImpCode and print it to stdout.@@ -173,7 +173,7 @@ runCC cpath outpath ["-O3", "-std=c99"] ["-lm"] -- | The @futhark opencl@ action.-compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem+compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem compileOpenCLAction fcfg mode outpath = Action { actionName = "Compile to OpenCL",@@ -206,7 +206,7 @@ runCC cpath outpath ["-O", "-std=c99"] ("-lm" : extra_options) -- | The @futhark cuda@ action.-compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem+compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem compileCUDAAction fcfg mode outpath = Action { actionName = "Compile to CUDA",@@ -291,7 +291,7 @@ actionProcedure = pythonCommon SequentialPy.compileProg fcfg mode outpath } -compilePyOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem+compilePyOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action GPUMem compilePyOpenCLAction fcfg mode outpath = Action { actionName = "Compile to PyOpenCL",
src/Futhark/Analysis/Alias.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} -- | Alias analysis of a full Futhark program. Takes as input a--- program with an arbitrary lore and produces one with aliases. This+-- program with an arbitrary rep and produces one with aliases. This -- module does not implement the aliasing logic itself, and derives -- its information from definitions in -- "Futhark.IR.Prop.Aliases" and@@ -26,37 +26,37 @@ -- | Perform alias analysis on a Futhark program. aliasAnalysis ::- (ASTLore lore, CanBeAliased (Op lore)) =>- Prog lore ->- Prog (Aliases lore)+ (ASTRep rep, CanBeAliased (Op rep)) =>+ Prog rep ->+ Prog (Aliases rep) aliasAnalysis (Prog consts funs) = Prog (fst (analyseStms mempty consts)) (map analyseFun funs) analyseFun ::- (ASTLore lore, CanBeAliased (Op lore)) =>- FunDef lore ->- FunDef (Aliases lore)+ (ASTRep rep, CanBeAliased (Op rep)) =>+ FunDef rep ->+ FunDef (Aliases rep) analyseFun (FunDef entry attrs fname restype params body) = FunDef entry attrs fname restype params body' where body' = analyseBody mempty body analyseBody ::- ( ASTLore lore,- CanBeAliased (Op lore)+ ( ASTRep rep,+ CanBeAliased (Op rep) ) => AliasTable ->- Body lore ->- Body (Aliases lore)-analyseBody atable (Body lore stms result) =+ Body rep ->+ Body (Aliases rep)+analyseBody atable (Body rep stms result) = let (stms', _atable') = analyseStms atable stms- in mkAliasedBody lore stms' result+ in mkAliasedBody rep stms' result analyseStms ::- (ASTLore lore, CanBeAliased (Op lore)) =>+ (ASTRep rep, CanBeAliased (Op rep)) => AliasTable ->- Stms lore ->- (Stms (Aliases lore), AliasesAndConsumed)+ Stms rep ->+ (Stms (Aliases rep), AliasesAndConsumed) analyseStms orig_aliases = foldl' f (mempty, (orig_aliases, mempty)) . stmsToList where@@ -66,21 +66,21 @@ in (stms <> oneStm stm', atable') analyseStm ::- (ASTLore lore, CanBeAliased (Op lore)) =>+ (ASTRep rep, CanBeAliased (Op rep)) => AliasTable ->- Stm lore ->- Stm (Aliases lore)+ Stm rep ->+ Stm (Aliases rep) analyseStm aliases (Let pat (StmAux cs attrs dec) e) = let e' = analyseExp aliases e pat' = addAliasesToPattern pat e'- lore' = (AliasDec $ consumedInExp e', dec)- in Let pat' (StmAux cs attrs lore') e'+ rep' = (AliasDec $ consumedInExp e', dec)+ in Let pat' (StmAux cs attrs rep') e' analyseExp ::- (ASTLore lore, CanBeAliased (Op lore)) =>+ (ASTRep rep, CanBeAliased (Op rep)) => AliasTable ->- Exp lore ->- Exp (Aliases lore)+ Exp rep ->+ Exp (Aliases rep) -- Would be better to put this in a BranchType annotation, but that -- requires a lot of other work. analyseExp aliases (If cond tb fb dec) =@@ -115,10 +115,10 @@ } analyseLambda ::- (ASTLore lore, CanBeAliased (Op lore)) =>+ (ASTRep rep, CanBeAliased (Op rep)) => AliasTable ->- Lambda lore ->- Lambda (Aliases lore)+ Lambda rep ->+ Lambda (Aliases rep) analyseLambda aliases lam = let body = analyseBody aliases $ lambdaBody lam in lam
src/Futhark/Analysis/DataDependencies.hs view
@@ -18,13 +18,13 @@ type Dependencies = M.Map VName Names -- | Compute the data dependencies for an entire body.-dataDependencies :: ASTLore lore => Body lore -> Dependencies+dataDependencies :: ASTRep rep => Body rep -> Dependencies dataDependencies = dataDependencies' M.empty dataDependencies' ::- ASTLore lore =>+ ASTRep rep => Dependencies ->- Body lore ->+ Body rep -> Dependencies dataDependencies' startdeps = foldl grow startdeps . bodyStms where
src/Futhark/Analysis/HORep/MapNest.hs view
@@ -24,7 +24,7 @@ import qualified Futhark.IR.SOACS.SOAC as Futhark import Futhark.Transform.Substitute -data Nesting lore = Nesting+data Nesting rep = Nesting { nestingParamNames :: [VName], nestingResult :: [VName], nestingReturnType :: [Type],@@ -32,25 +32,25 @@ } deriving (Eq, Ord, Show) -data MapNest lore = MapNest SubExp (Lambda lore) [Nesting lore] [SOAC.Input]+data MapNest rep = MapNest SubExp (Lambda rep) [Nesting rep] [SOAC.Input] deriving (Show) -typeOf :: MapNest lore -> [Type]+typeOf :: MapNest rep -> [Type] typeOf (MapNest w lam [] _) = map (`arrayOfRow` w) $ lambdaReturnType lam typeOf (MapNest w _ (nest : _) _) = map (`arrayOfRow` w) $ nestingReturnType nest -params :: MapNest lore -> [VName]+params :: MapNest rep -> [VName] params (MapNest _ lam [] _) = map paramName $ lambdaParams lam params (MapNest _ _ (nest : _) _) = nestingParamNames nest -inputs :: MapNest lore -> [SOAC.Input]+inputs :: MapNest rep -> [SOAC.Input] inputs (MapNest _ _ _ inps) = inps -setInputs :: [SOAC.Input] -> MapNest lore -> MapNest lore+setInputs :: [SOAC.Input] -> MapNest rep -> MapNest rep setInputs [] (MapNest w body ns _) = MapNest w body ns [] setInputs (inp : inps) (MapNest _ body ns _) = MapNest w body ns' (inp : inps) where@@ -60,24 +60,24 @@ setDepth n nw = n {nestingWidth = nw} fromSOAC ::- ( Bindable lore,+ ( Bindable rep, MonadFreshNames m,- LocalScope lore m,- Op lore ~ Futhark.SOAC lore+ LocalScope rep m,+ Op rep ~ Futhark.SOAC rep ) =>- SOAC lore ->- m (Maybe (MapNest lore))+ SOAC rep ->+ m (Maybe (MapNest rep)) fromSOAC = fromSOAC' mempty fromSOAC' ::- ( Bindable lore,+ ( Bindable rep, MonadFreshNames m,- LocalScope lore m,- Op lore ~ Futhark.SOAC lore+ LocalScope rep m,+ Op rep ~ Futhark.SOAC rep ) => [Ident] ->- SOAC lore ->- m (Maybe (MapNest lore))+ SOAC rep ->+ m (Maybe (MapNest rep)) fromSOAC' bound (SOAC.Screma w (SOAC.ScremaForm [] [] lam) inps) = do maybenest <- case ( stmsToList $ bodyStms $ lambdaBody lam, bodyResult $ lambdaBody lam@@ -142,13 +142,13 @@ toSOAC :: ( MonadFreshNames m,- HasScope lore m,- Bindable lore,- BinderOps lore,- Op lore ~ Futhark.SOAC lore+ HasScope rep m,+ Bindable rep,+ BinderOps rep,+ Op rep ~ Futhark.SOAC rep ) =>- MapNest lore ->- m (SOAC lore)+ MapNest rep ->+ m (SOAC rep) toSOAC (MapNest w lam [] inps) = return $ SOAC.Screma w (Futhark.mapSOAC lam) inps toSOAC (MapNest w lam (Nesting npnames nres nrettype nw : ns) inps) = do
src/Futhark/Analysis/HORep/SOAC.hs view
@@ -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 lore -> Maybe (VName, ArrayTransform)+transformFromExp :: Certificates -> Exp rep -> Maybe (VName, ArrayTransform) transformFromExp cs (BasicOp (Futhark.Rearrange perm v)) = Just (v, Rearrange cs perm) transformFromExp cs (BasicOp (Futhark.Reshape shape v)) =@@ -374,11 +374,11 @@ addTransform (Rearrange mempty $ transposeIndex k n [0 .. inputRank inp -1]) inp -- | A definite representation of a SOAC expression.-data SOAC lore- = Stream SubExp (StreamForm lore) (Lambda lore) [SubExp] [Input]- | Scatter SubExp (Lambda lore) [Input] [(Shape, Int, VName)]- | Screma SubExp (ScremaForm lore) [Input]- | Hist SubExp [HistOp lore] (Lambda lore) [Input]+data SOAC rep+ = Stream SubExp (StreamForm rep) (Lambda rep) [SubExp] [Input]+ | Scatter SubExp (Lambda rep) [Input] [(Shape, Int, VName)]+ | Screma SubExp (ScremaForm rep) [Input]+ | Hist SubExp [HistOp rep] (Lambda rep) [Input] deriving (Eq, Show) instance PP.Pretty Input where@@ -395,21 +395,21 @@ f e (Replicate cs ne) = text "replicate" <> ppr cs <> PP.apply [ppr ne, e] -instance PrettyLore lore => PP.Pretty (SOAC lore) where+instance PrettyRep rep => PP.Pretty (SOAC rep) where ppr (Screma w form arrs) = Futhark.ppScrema w arrs form ppr (Hist len ops bucket_fun imgs) = Futhark.ppHist len ops bucket_fun imgs ppr soac = text $ show soac -- | Returns the inputs used in a SOAC.-inputs :: SOAC lore -> [Input]+inputs :: SOAC rep -> [Input] inputs (Stream _ _ _ _ arrs) = arrs inputs (Scatter _len _lam ivs _as) = ivs inputs (Screma _ _ arrs) = arrs inputs (Hist _ _ _ inps) = inps -- | Set the inputs to a SOAC.-setInputs :: [Input] -> SOAC lore -> SOAC lore+setInputs :: [Input] -> SOAC rep -> SOAC rep setInputs arrs (Stream w form lam nes _) = Stream (newWidth arrs w) form lam nes arrs setInputs arrs (Scatter w lam _ivs as) =@@ -424,14 +424,14 @@ newWidth (inp : _) _ = arraySize 0 $ inputType inp -- | The lambda used in a given SOAC.-lambda :: SOAC lore -> Lambda lore+lambda :: SOAC rep -> Lambda rep lambda (Stream _ _ lam _ _) = lam lambda (Scatter _len lam _ivs _as) = lam lambda (Screma _ (ScremaForm _ _ lam) _) = lam lambda (Hist _ _ lam _) = lam -- | Set the lambda used in the SOAC.-setLambda :: Lambda lore -> SOAC lore -> SOAC lore+setLambda :: Lambda rep -> SOAC rep -> SOAC rep setLambda lam (Stream w form _ nes arrs) = Stream w form lam nes arrs setLambda lam (Scatter len _lam ivs as) =@@ -442,7 +442,7 @@ Hist w ops lam inps -- | The return type of a SOAC.-typeOf :: SOAC lore -> [Type]+typeOf :: SOAC rep -> [Type] typeOf (Stream w _ lam nes _) = let accrtps = take (length nes) $ lambdaReturnType lam arrtps =@@ -464,7 +464,7 @@ -- | The "width" of a SOAC is the expected outer size of its array -- inputs _after_ input-transforms have been carried out.-width :: SOAC lore -> SubExp+width :: SOAC rep -> SubExp width (Stream w _ _ _ _) = w width (Scatter len _lam _ivs _as) = len width (Screma w _ _) = w@@ -472,16 +472,16 @@ -- | Convert a SOAC to the corresponding expression. toExp ::- (MonadBinder m, Op (Lore m) ~ Futhark.SOAC (Lore m)) =>- SOAC (Lore m) ->- m (Exp (Lore m))+ (MonadBinder 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 =>- SOAC (Lore m) ->- m (Futhark.SOAC (Lore m))+ SOAC (Rep m) ->+ m (Futhark.SOAC (Rep m)) toSOAC (Stream w form lam nes inps) = Futhark.Stream w <$> inputsToSubExps inps <*> pure form <*> pure nes <*> pure lam toSOAC (Scatter len lam ivs dests) = do@@ -503,9 +503,9 @@ -- representation, or a reason why the expression does not have the -- valid form. fromExp ::- (Op lore ~ Futhark.SOAC lore, HasScope lore m) =>- Exp lore ->- m (Either NotSOAC (SOAC lore))+ (Op rep ~ Futhark.SOAC rep, HasScope rep m) =>+ Exp rep ->+ m (Either NotSOAC (SOAC rep)) fromExp (Op (Futhark.Stream w as form nes lam)) = Right . Stream w form lam nes <$> traverse varInput as fromExp (Op (Futhark.Scatter len lam ivs as)) =@@ -520,9 +520,9 @@ -- Returns the Stream SOAC and the -- extra-accumulator body-result ident if any. soacToStream ::- (MonadFreshNames m, Bindable lore, Op lore ~ Futhark.SOAC lore) =>- SOAC lore ->- m (SOAC lore, [Ident])+ (MonadFreshNames m, Bindable rep, Op rep ~ Futhark.SOAC rep) =>+ SOAC rep ->+ m (SOAC rep, [Ident]) soacToStream soac = do chunk_param <- newParam "chunk" $ Prim int64 let chvar = Futhark.Var $ paramName chunk_param@@ -690,10 +690,10 @@ _ -> return (soac, []) where mkMapPlusAccLam ::- (MonadFreshNames m, Bindable lore) =>+ (MonadFreshNames m, Bindable rep) => [SubExp] ->- Lambda lore ->- m (Lambda lore)+ Lambda rep ->+ m (Lambda rep) mkMapPlusAccLam accs plus = do let (accpars, rempars) = splitAt (length accs) $ lambdaParams plus parbnds =@@ -715,10 +715,10 @@ renameLambda $ Lambda rempars newlambdy $ lambdaReturnType plus mkPlusBnds ::- (MonadFreshNames m, Bindable lore) =>- Lambda lore ->+ (MonadFreshNames m, Bindable rep) =>+ Lambda rep -> [SubExp] ->- m (Body lore)+ m (Body rep) mkPlusBnds plus accels = do plus' <- renameLambda plus let parbnds =
+ src/Futhark/Analysis/Interference.hs view
@@ -0,0 +1,326 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | Interference analysis for Futhark programs.+module Futhark.Analysis.Interference (Graph, analyseGPU) where++import Control.Monad.Reader+import Data.Foldable (toList)+import Data.Function ((&))+import Data.Functor ((<&>))+import Data.Map (Map)+import qualified Data.Map as M+import Data.Maybe (catMaybes, fromMaybe)+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.+type InUse = Names++-- | 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`.+type Graph a = Set (a, a)++-- | Insert an edge between two values into the graph.+makeEdge :: Ord a => a -> a -> Graph a+makeEdge v1 v2+ | v1 == v2 = mempty+ | otherwise = S.singleton (min v1 v2, max v1 v2)++-- | Compute the cartesian product of two foldable collections, using the given+-- combinator function.+cartesian :: (Monoid m, Foldable t) => (a -> a -> m) -> t a -> t a -> m+cartesian f xs ys =+ [(x, y) | x <- toList xs, y <- toList ys]+ & foldMap (uncurry f)++analyseStm ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ Stm GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseStm lumap inuse0 stm =+ inScopeOf stm $ do+ let pat_name = patElemName $ head $ patternValueElements $ stmPattern stm++ new_mems <-+ stmPattern stm+ & patternValueElements+ & mapM (memInfo . patElemName)+ <&> catMaybes+ <&> namesFromList++ -- `new_mems` should interfere with any mems inside the statement expression+ let inuse_outside = inuse0 <> new_mems++ -- `inuse` is the set of memory blocks that are inuse at the end of any code+ -- bodies inside the expression. `lus` is the set of all memory blocks that+ -- have reached their last use in any code bodies inside the+ -- expression. `graph` is the interference graph computed for any code+ -- bodies inside the expression.+ (inuse, lus, graph) <- analyseExp lumap inuse_outside (stmExp stm)++ last_use_mems <-+ M.lookup pat_name lumap+ & fromMaybe mempty+ & namesToList+ & mapM memInfo+ <&> catMaybes+ <&> namesFromList+ <&> namesIntersection inuse_outside++ return+ ( (inuse_outside `namesSubtract` last_use_mems `namesSubtract` lus)+ <> new_mems,+ (lus <> last_use_mems) `namesSubtract` new_mems,+ graph+ <> cartesian+ makeEdge+ (namesToList inuse_outside)+ (namesToList $ inuse_outside <> inuse <> lus <> last_use_mems)+ )++analyseExp ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ Exp GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseExp lumap inuse_outside expr =+ case expr of+ If _ then_body else_body _ -> do+ 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+ Op (Inner (SegOp segop)) -> do+ analyseSegOp lumap inuse_outside segop+ _ ->+ return mempty++analyseKernelBody ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ KernelBody GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseKernelBody lumap inuse body = analyseStms lumap inuse $ kernelBodyStms body++analyseBody ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ Body GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseBody lumap inuse body = analyseStms lumap inuse $ bodyStms body++analyseStms ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ Stms GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseStms lumap inuse0 stms = do+ inScopeOf stms $ foldM helper (inuse0, mempty, mempty) $ stmsToList stms+ where+ helper (inuse, lus, graph) stm = do+ (inuse', lus', graph') <- analyseStm lumap inuse stm+ return (inuse', lus' <> lus, graph' <> graph)++analyseSegOp ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ SegOp lvl GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseSegOp lumap inuse (SegMap _ _ _ body) =+ analyseKernelBody lumap inuse body+analyseSegOp lumap inuse (SegRed _ _ binops _ body) =+ segWithBinOps lumap inuse binops body+analyseSegOp lumap inuse (SegScan _ _ binops _ body) = do+ segWithBinOps lumap inuse binops body+analyseSegOp lumap inuse (SegHist _ _ histops _ body) = do+ (inuse', lus', graph) <- analyseKernelBody lumap inuse body+ (inuse'', lus'', graph') <- mconcat <$> mapM (analyseHistOp lumap inuse') histops+ return (inuse'', lus' <> lus'', graph <> graph')++segWithBinOps ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ [SegBinOp GPUMem] ->+ KernelBody GPUMem ->+ m (InUse, LastUsed, Graph VName)+segWithBinOps lumap inuse binops body = do+ (inuse', lus', graph) <- analyseKernelBody lumap inuse body+ (inuse'', lus'', graph') <-+ mconcat+ <$> mapM+ (analyseSegBinOp lumap inuse')+ binops+ return (inuse'', lus' <> lus'', graph <> graph')++analyseSegBinOp ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ SegBinOp GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseSegBinOp lumap inuse (SegBinOp _ lambda _ _) =+ analyseLambda lumap inuse lambda++analyseHistOp ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ HistOp GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseHistOp lumap inuse histop =+ analyseLambda lumap inuse (histOp histop)++analyseLambda ::+ LocalScope GPUMem m =>+ LastUseMap ->+ InUse ->+ Lambda GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseLambda lumap inuse (Lambda _ body _) =+ analyseBody lumap inuse body++-- | Perform interference analysis on the given statements. The result is a+-- triple of the names currently in use, names that hit their last use somewhere+-- within, and the resulting graph.+analyseGPU ::+ LocalScope GPUMem m =>+ LastUseMap ->+ Stms GPUMem ->+ m (Graph VName)+analyseGPU lumap stms = do+ (_, _, graph) <- analyseGPU' lumap stms+ -- We need to insert edges between memory blocks which differ in size, if they+ -- are in DefaultSpace. The problem is that during memory expansion,+ -- DefaultSpace arrays in kernels are interleaved. If the element sizes of two+ -- merged memory blocks are different, threads might try to read and write to+ -- overlapping memory positions. More information here:+ -- https://munksgaard.me/technical-diary/2020-12-30.html#org210775b+ spaces <- M.filter (== DefaultSpace) <$> memSpaces stms+ inv_size_map <-+ memSizes stms+ <&> flip M.restrictKeys (S.fromList $ M.keys spaces)+ <&> invertMap+ let new_edges =+ cartesian+ (\x y -> if x /= y then cartesian makeEdge x y else mempty)+ inv_size_map+ inv_size_map+ return $ graph <> new_edges++-- | Return a mapping from memory blocks to their element sizes in the given+-- statements.+memSizes :: LocalScope GPUMem m => Stms GPUMem -> m (Map VName Int)+memSizes stms =+ inScopeOf stms $ fmap mconcat <$> mapM memSizesStm $ stmsToList stms+ where+ memSizesStm :: LocalScope GPUMem m => Stm GPUMem -> m (Map VName Int)+ memSizesStm (Let pat _ e) = do+ arraySizes <- fmap mconcat <$> mapM memElemSize $ patternNames pat+ arraySizes' <- memSizesExp e+ return $ arraySizes <> arraySizes'+ memSizesExp :: LocalScope GPUMem m => Exp GPUMem -> m (Map VName Int)+ memSizesExp (Op (Inner (SegOp segop))) =+ let body = segBody segop+ in inScopeOf (kernelBodyStms body) $+ fmap mconcat+ <$> mapM memSizesStm+ $ stmsToList $ kernelBodyStms body+ memSizesExp (If _ then_body else_body _) = do+ then_res <- memSizes $ bodyStms then_body+ else_res <- memSizes $ bodyStms else_body+ return $ then_res <> else_res+ memSizesExp (DoLoop _ _ _ body) =+ memSizes $ bodyStms body+ memSizesExp _ = return mempty++-- | Return a mapping from memory blocks to the space they are allocated in.+memSpaces :: LocalScope GPUMem m => Stms GPUMem -> m (Map VName Space)+memSpaces stms =+ return $ foldMap getSpacesStm stms+ where+ getSpacesStm :: Stm GPUMem -> Map VName Space+ getSpacesStm (Let (Pattern [] [PatElem name _]) _ (Op (Alloc _ sp))) =+ M.singleton name sp+ getSpacesStm (Let _ _ (Op (Alloc _ _))) = error "impossible"+ getSpacesStm (Let _ _ (Op (Inner (SegOp segop)))) =+ foldMap getSpacesStm $ kernelBodyStms $ segBody segop+ getSpacesStm (Let _ _ (If _ then_body else_body _)) =+ foldMap getSpacesStm (bodyStms then_body)+ <> foldMap getSpacesStm (bodyStms else_body)+ getSpacesStm (Let _ _ (DoLoop _ _ _ body)) =+ foldMap getSpacesStm (bodyStms body)+ getSpacesStm _ = mempty++analyseGPU' ::+ LocalScope GPUMem m =>+ LastUseMap ->+ Stms GPUMem ->+ m (InUse, LastUsed, Graph VName)+analyseGPU' lumap stms =+ mconcat . toList <$> mapM helper stms+ where+ helper ::+ LocalScope GPUMem m =>+ Stm GPUMem ->+ m (InUse, LastUsed, Graph VName)+ helper stm@Let {stmExp = Op (Inner (SegOp segop))} =+ inScopeOf stm $ analyseSegOp lumap mempty segop+ helper stm@Let {stmExp = If _ then_body else_body _} =+ inScopeOf stm $ do+ res1 <- analyseGPU' lumap (bodyStms then_body)+ res2 <- analyseGPU' lumap (bodyStms else_body)+ return (res1 <> res2)+ helper stm@Let {stmExp = DoLoop _ _ _ body} =+ inScopeOf stm $+ analyseGPU' lumap $ bodyStms body+ helper stm =+ inScopeOf stm $ return mempty++nameInfoToMemInfo :: Mem rep => NameInfo rep -> MemBound NoUniqueness+nameInfoToMemInfo info =+ case info of+ FParamName summary -> noUniquenessReturns summary+ LParamName summary -> summary+ LetName summary -> summary+ IndexName it -> MemPrim $ IntType it++memInfo :: LocalScope GPUMem m => VName -> m (Maybe VName)+memInfo vname = do+ summary <- asksScope (fmap nameInfoToMemInfo . M.lookup vname)+ case summary of+ Just (MemArray _ _ _ (ArrayIn mem _)) ->+ return $ Just mem+ _ ->+ return Nothing++-- | Returns a mapping from memory block to element size. The input is the+-- `VName` of a variable (supposedly an array), and the result is a mapping from+-- the memory block of that array to element size of the array.+memElemSize :: LocalScope GPUMem m => VName -> m (Map VName Int)+memElemSize vname = do+ summary <- asksScope (fmap nameInfoToMemInfo . M.lookup vname)+ case summary of+ Just (MemArray pt _ _ (ArrayIn mem _)) ->+ return $ M.singleton mem (primByteSize pt)+ _ ->+ return mempty
+ src/Futhark/Analysis/LastUse.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | Provides last-use analysis for Futhark programs.+module Futhark.Analysis.LastUse (LastUseMap, analyseProg) where++import Data.Bifunctor (first)+import Data.Foldable+import Data.Function ((&))+import Data.Map (Map)+import qualified Data.Map as M+import Data.Tuple+import Futhark.Analysis.Alias (aliasAnalysis)+import Futhark.IR.Aliases+import Futhark.IR.GPUMem++-- | `LastUseMap` tells which names were last used in a given statement.+-- Statements are uniquely identified by the `VName` of the first value+-- parameter in the statement pattern. `Names` is the set of names last used.+type LastUseMap = Map VName Names++-- | `LastUse` is a mapping from a `VName` to the statement identifying it's+-- last use. `LastUseMap` is the inverse of `LastUse`.+type LastUse = Map VName VName++-- | `Used` is the set of `VName` that were used somewhere in a statement, body+-- or otherwise.+type Used = Names++-- | Analyses a program to return a last-use map, mapping each simple statement+-- in the program to the values that were last used within that statement, and+-- the set of all `VName` that were used inside.+analyseProg :: Prog GPUMem -> (LastUseMap, Used)+analyseProg prog =+ let consts =+ progConsts prog+ & concatMap (toList . fmap patElemName . patternValueElements . stmPattern)+ & namesFromList+ funs = progFuns $ aliasAnalysis prog+ (lus, used) = foldMap (analyseFun mempty consts) funs+ in (flipMap lus, used)++analyseFun :: LastUse -> Used -> FunDef (Aliases GPUMem) -> (LastUse, Used)+analyseFun lumap used fun =+ let (lumap', used') = analyseBody lumap used $ funDefBody fun+ in (lumap', used' <> freeIn (funDefParams fun))++analyseStms :: LastUse -> Used -> Stms (Aliases GPUMem) -> (LastUse, Used)+analyseStms lumap used stms = foldr analyseStm (lumap, used) $ stmsToList stms++analyseStm :: Stm (Aliases GPUMem) -> (LastUse, Used) -> (LastUse, Used)+analyseStm (Let pat _ e) (lumap0, used0) =+ let (lumap', used') = patternValueElements pat & foldl helper (lumap0, used0)+ in analyseExp (lumap', used') e+ where+ helper (lumap_acc, used_acc) (PatElem name (aliases, _)) =+ -- Any aliases of `name` should have the same last-use as `name`+ ( case M.lookup name lumap_acc of+ Just name' ->+ insertNames name' (unAliases aliases) lumap_acc+ Nothing -> lumap_acc,+ used_acc <> unAliases aliases+ )++ pat_name = patElemName $ head $ patternValueElements pat+ analyseExp :: (LastUse, Used) -> Exp (Aliases GPUMem) -> (LastUse, Used)+ analyseExp (lumap, used) (BasicOp _) =+ let nms = freeIn e `namesSubtract` used+ in (insertNames pat_name nms lumap, used <> nms)+ analyseExp (lumap, used) (Apply _ args _ _) =+ let nms = freeIn $ map fst args+ in (insertNames pat_name nms lumap, used <> nms)+ analyseExp (lumap, used) (If cse then_body else_body dec) =+ let (lumap_then, used_then) = analyseBody lumap used then_body+ (lumap_else, used_else) = analyseBody lumap used else_body+ 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) =+ let (lumap', used') = analyseBody lumap used body+ nms = (freeIn ctx <> freeIn vals <> 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+ in (insertNames pat_name nms lumap, used <> nms)+ analyseExp (lumap, used) (Op (Inner (SizeOp sop))) =+ let nms = freeIn sop `namesSubtract` used+ in (insertNames pat_name nms lumap, used <> nms)+ analyseExp (lumap, used) (Op (Inner (OtherOp ()))) =+ (lumap, used)+ analyseExp (lumap, used) (Op (Inner (SegOp (SegMap lvl _ tps body)))) =+ let (lumap', used') = analyseKernelBody (lumap, used) body+ nms = (freeIn lvl <> freeIn tps) `namesSubtract` used'+ in (insertNames pat_name nms lumap', used' <> nms)+ analyseExp (lumap, used) (Op (Inner (SegOp (SegRed lvl _ binops tps body)))) =+ segOpHelper lumap used lvl binops tps body+ analyseExp (lumap, used) (Op (Inner (SegOp (SegScan lvl _ binops tps body)))) =+ segOpHelper lumap used lvl binops tps body+ analyseExp (lumap, used) (Op (Inner (SegOp (SegHist lvl _ binops tps body)))) =+ let (lumap', used') = foldr analyseHistOp (lumap, used) binops+ (lumap'', used'') = analyseKernelBody (lumap', used') body+ nms = (freeIn lvl <> freeIn tps) `namesSubtract` used''+ in (insertNames pat_name nms lumap'', used'' <> nms)+ analyseExp (lumap, used) (WithAcc _ l) =+ analyseLambda (lumap, used) l+ segOpHelper lumap used lvl binops tps body =+ let (lumap', used') = foldr analyseSegBinOp (lumap, used) binops+ (lumap'', used'') = analyseKernelBody (lumap', used') body+ nms = (freeIn lvl <> freeIn tps) `namesSubtract` used''+ in (insertNames pat_name nms lumap'', used'' <> nms)++analyseBody :: LastUse -> Used -> Body (Aliases GPUMem) -> (LastUse, Used)+analyseBody lumap used (Body _ stms result) =+ let used' = used <> freeIn result+ in analyseStms lumap used' stms++analyseKernelBody ::+ (LastUse, Used) ->+ KernelBody (Aliases GPUMem) ->+ (LastUse, Used)+analyseKernelBody (lumap, used) (KernelBody _ stms result) =+ let used' = used <> freeIn result+ in analyseStms lumap used' stms++analyseSegBinOp ::+ SegBinOp (Aliases GPUMem) ->+ (LastUse, Used) ->+ (LastUse, Used)+analyseSegBinOp (SegBinOp _ lambda neutral shp) (lumap, used) =+ let (lumap', used') = analyseLambda (lumap, used) lambda+ nms = (freeIn neutral <> freeIn shp) `namesSubtract` used'+ in (lumap', used' <> nms)++analyseHistOp ::+ HistOp (Aliases GPUMem) ->+ (LastUse, Used) ->+ (LastUse, Used)+analyseHistOp (HistOp width race dest neutral shp lambda) (lumap, used) =+ let (lumap', used') = analyseLambda (lumap, used) lambda+ nms =+ ( freeIn width <> freeIn race <> freeIn dest <> freeIn neutral+ <> freeIn shp+ )+ `namesSubtract` used'+ in (lumap', used' <> nms)++analyseLambda :: (LastUse, Used) -> Lambda (Aliases GPUMem) -> (LastUse, Used)+analyseLambda (lumap, used) (Lambda params body ret) =+ let (lumap', used') = analyseBody lumap used body+ used'' = used' <> freeIn params <> freeIn ret+ in (lumap', used'')++flipMap :: Map VName VName -> Map VName Names+flipMap m =+ M.toList m+ & fmap (swap . first oneName)+ & foldr (uncurry $ M.insertWith (<>)) mempty++insertNames :: VName -> Names -> LastUse -> LastUse+insertNames name names lumap =+ foldr (flip (M.insertWith $ \_ x -> x) name) lumap $ namesToList names
src/Futhark/Analysis/Metrics.hs view
@@ -80,7 +80,7 @@ addWhat' (ctx, k) = (what : ctx, k) -- | Compute the metrics for a program.-progMetrics :: OpMetrics (Op lore) => Prog lore -> AstMetrics+progMetrics :: OpMetrics (Op rep) => Prog rep -> AstMetrics progMetrics prog = actualMetrics $ execWriter $@@ -88,17 +88,17 @@ mapM_ funDefMetrics $ progFuns prog mapM_ stmMetrics $ progConsts prog -funDefMetrics :: OpMetrics (Op lore) => FunDef lore -> MetricsM ()+funDefMetrics :: OpMetrics (Op rep) => FunDef rep -> MetricsM () funDefMetrics = bodyMetrics . funDefBody -bodyMetrics :: OpMetrics (Op lore) => Body lore -> MetricsM ()+bodyMetrics :: OpMetrics (Op rep) => Body rep -> MetricsM () bodyMetrics = mapM_ stmMetrics . bodyStms -- | Compute metrics for this statement.-stmMetrics :: OpMetrics (Op lore) => Stm lore -> MetricsM ()+stmMetrics :: OpMetrics (Op rep) => Stm rep -> MetricsM () stmMetrics = expMetrics . stmExp -expMetrics :: OpMetrics (Op lore) => Exp lore -> MetricsM ()+expMetrics :: OpMetrics (Op rep) => Exp rep -> MetricsM () expMetrics (BasicOp op) = seen "BasicOp" >> primOpMetrics op expMetrics (DoLoop _ _ ForLoop {} body) =@@ -139,5 +139,5 @@ primOpMetrics UpdateAcc {} = seen "UpdateAcc" -- | Compute metrics for this lambda.-lambdaMetrics :: OpMetrics (Op lore) => Lambda lore -> MetricsM ()+lambdaMetrics :: OpMetrics (Op rep) => Lambda rep -> MetricsM () lambdaMetrics = bodyMetrics . lambdaBody
src/Futhark/Analysis/PrimExp/Convert.hs view
@@ -60,9 +60,9 @@ -- This includes constants and variable names, which are passed as -- t'SubExp's. primExpFromExp ::- (Fail.MonadFail m, Decorations lore) =>+ (Fail.MonadFail m, RepTypes rep) => (VName -> m (PrimExp v)) ->- Exp lore ->+ Exp rep -> m (PrimExp v) primExpFromExp f (BasicOp (BinOp op x y)) = BinOpExp op <$> primExpFromSubExpM f x <*> primExpFromSubExpM f y
src/Futhark/Analysis/PrimExp/Simplify.hs view
@@ -11,9 +11,9 @@ -- refers to a name that is a 'Constant', the node turns into a -- 'ValueExp'. simplifyPrimExp ::- SimplifiableLore lore =>+ SimplifiableRep rep => PrimExp VName ->- SimpleM lore (PrimExp VName)+ SimpleM rep (PrimExp VName) simplifyPrimExp = simplifyAnyPrimExp onLeaf where onLeaf v pt = do@@ -24,9 +24,9 @@ -- | Like 'simplifyPrimExp', but where leaves may be 'Ext's. simplifyExtPrimExp ::- SimplifiableLore lore =>+ SimplifiableRep rep => PrimExp (Ext VName) ->- SimpleM lore (PrimExp (Ext VName))+ SimpleM rep (PrimExp (Ext VName)) simplifyExtPrimExp = simplifyAnyPrimExp onLeaf where onLeaf (Free v) pt = do@@ -37,10 +37,10 @@ onLeaf (Ext i) pt = return $ LeafExp (Ext i) pt simplifyAnyPrimExp ::- SimplifiableLore lore =>- (a -> PrimType -> SimpleM lore (PrimExp a)) ->+ SimplifiableRep rep =>+ (a -> PrimType -> SimpleM rep (PrimExp a)) -> PrimExp a ->- SimpleM lore (PrimExp a)+ SimpleM rep (PrimExp a) simplifyAnyPrimExp f (LeafExp v pt) = f v pt simplifyAnyPrimExp _ (ValueExp pv) = return $ ValueExp pv
src/Futhark/Analysis/Rephrase.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE ConstraintKinds #-} --- | Facilities for changing the lore of some fragment, with no+-- | Facilities for changing the rep of some fragment, with no -- context. We call this "rephrasing", for no deep reason. module Futhark.Analysis.Rephrase ( rephraseProg,@@ -20,14 +20,14 @@ -- | A collection of functions that together allow us to rephrase some -- IR fragment, in some monad @m@. If we let @m@ be the 'Maybe' -- monad, we can conveniently do rephrasing that might fail. This is--- useful if you want to see if some IR in e.g. the @Kernels@ lore+-- useful if you want to see if some IR in e.g. the @Kernels@ rep -- actually uses any @Kernels@-specific operations. data Rephraser m from to = Rephraser- { rephraseExpLore :: ExpDec from -> m (ExpDec to),- rephraseLetBoundLore :: LetDec from -> m (LetDec to),- rephraseFParamLore :: FParamInfo from -> m (FParamInfo to),- rephraseLParamLore :: LParamInfo from -> m (LParamInfo to),- rephraseBodyLore :: BodyDec from -> m (BodyDec to),+ { rephraseExpDec :: ExpDec from -> m (ExpDec to),+ rephraseLetBoundDec :: LetDec from -> m (LetDec to),+ rephraseFParamDec :: FParamInfo from -> m (FParamInfo to),+ rephraseLParamDec :: LParamInfo from -> m (LParamInfo to),+ rephraseBodyDec :: BodyDec from -> m (BodyDec to), rephraseRetType :: RetType from -> m (RetType to), rephraseBranchType :: BranchType from -> m (BranchType to), rephraseOp :: Op from -> m (Op to)@@ -44,7 +44,7 @@ rephraseFunDef :: Monad m => Rephraser m from to -> FunDef from -> m (FunDef to) rephraseFunDef rephraser fundec = do body' <- rephraseBody rephraser $ funDefBody fundec- params' <- mapM (rephraseParam $ rephraseFParamLore rephraser) $ funDefParams fundec+ params' <- mapM (rephraseParam $ rephraseFParamDec rephraser) $ funDefParams fundec rettype' <- mapM (rephraseRetType rephraser) $ funDefRetType fundec return fundec {funDefBody = body', funDefParams = params', funDefRetType = rettype'} @@ -56,8 +56,8 @@ rephraseStm :: Monad m => Rephraser m from to -> Stm from -> m (Stm to) rephraseStm rephraser (Let pat (StmAux cs attrs dec) e) = Let- <$> rephrasePattern (rephraseLetBoundLore rephraser) pat- <*> (StmAux cs attrs <$> rephraseExpLore rephraser dec)+ <$> rephrasePattern (rephraseLetBoundDec rephraser) pat+ <*> (StmAux cs attrs <$> rephraseExpDec rephraser dec) <*> rephraseExp rephraser e -- | Rephrase a pattern.@@ -80,9 +80,9 @@ -- | Rephrase a body. rephraseBody :: Monad m => Rephraser m from to -> Body from -> m (Body to)-rephraseBody rephraser (Body lore bnds res) =+rephraseBody rephraser (Body rep bnds res) = Body- <$> rephraseBodyLore rephraser lore+ <$> rephraseBodyDec rephraser rep <*> (stmsFromList <$> mapM (rephraseStm rephraser) (stmsToList bnds)) <*> pure res @@ -90,7 +90,7 @@ rephraseLambda :: Monad m => Rephraser m from to -> Lambda from -> m (Lambda to) rephraseLambda rephraser lam = do body' <- rephraseBody rephraser $ lambdaBody lam- params' <- mapM (rephraseParam $ rephraseLParamLore rephraser) $ lambdaParams lam+ params' <- mapM (rephraseParam $ rephraseLParamDec rephraser) $ lambdaParams lam return lam {lambdaBody = body', lambdaParams = params'} mapper :: Monad m => Rephraser m from to -> Mapper from to m@@ -99,7 +99,7 @@ { mapOnBody = const $ rephraseBody rephraser, mapOnRetType = rephraseRetType rephraser, mapOnBranchType = rephraseBranchType rephraser,- mapOnFParam = rephraseParam (rephraseFParamLore rephraser),- mapOnLParam = rephraseParam (rephraseLParamLore rephraser),+ mapOnFParam = rephraseParam (rephraseFParamDec rephraser),+ mapOnLParam = rephraseParam (rephraseLParamDec rephraser), mapOnOp = rephraseOp rephraser }
src/Futhark/Analysis/SymbolTable.hs view
@@ -61,9 +61,9 @@ import qualified Futhark.IR.Prop.Aliases as Aliases import Prelude hiding (elem, lookup) -data SymbolTable lore = SymbolTable+data SymbolTable rep = SymbolTable { loopDepth :: Int,- bindings :: M.Map VName (Entry lore),+ bindings :: M.Map VName (Entry rep), -- | Which names are available just before the most enclosing -- loop? availableAtClosestLoop :: Names,@@ -73,7 +73,7 @@ simplifyMemory :: Bool } -instance Semigroup (SymbolTable lore) where+instance Semigroup (SymbolTable rep) where table1 <> table2 = SymbolTable { loopDepth = max (loopDepth table1) (loopDepth table2),@@ -84,21 +84,21 @@ simplifyMemory = simplifyMemory table1 || simplifyMemory table2 } -instance Monoid (SymbolTable lore) where+instance Monoid (SymbolTable rep) where mempty = empty -empty :: SymbolTable lore+empty :: SymbolTable rep empty = SymbolTable 0 M.empty mempty False -fromScope :: ASTLore lore => Scope lore -> SymbolTable lore+fromScope :: ASTRep rep => Scope rep -> SymbolTable rep fromScope = M.foldlWithKey' insertFreeVar' empty where insertFreeVar' m k dec = insertFreeVar k dec m -toScope :: SymbolTable lore -> Scope lore+toScope :: SymbolTable rep -> Scope rep toScope = M.map entryInfo . bindings -deepen :: SymbolTable lore -> SymbolTable lore+deepen :: SymbolTable rep -> SymbolTable rep deepen vtable = vtable { loopDepth = loopDepth vtable + 1,@@ -125,59 +125,59 @@ -- | Indexing a delayed array if possible. type IndexArray = [TPrimExp Int64 VName] -> Maybe Indexed -data Entry lore = Entry+data Entry rep = Entry { -- | True if consumed. entryConsumed :: Bool, entryDepth :: Int, -- | True if this name has been used as an array size, -- implying that it is non-negative. entryIsSize :: Bool,- entryType :: EntryType lore+ entryType :: EntryType rep } -data EntryType lore- = LoopVar (LoopVarEntry lore)- | LetBound (LetBoundEntry lore)- | FParam (FParamEntry lore)- | LParam (LParamEntry lore)- | FreeVar (FreeVarEntry lore)+data EntryType rep+ = LoopVar (LoopVarEntry rep)+ | LetBound (LetBoundEntry rep)+ | FParam (FParamEntry rep)+ | LParam (LParamEntry rep)+ | FreeVar (FreeVarEntry rep) -data LoopVarEntry lore = LoopVarEntry+data LoopVarEntry rep = LoopVarEntry { loopVarType :: IntType, loopVarBound :: SubExp } -data LetBoundEntry lore = LetBoundEntry- { letBoundDec :: LetDec lore,+data LetBoundEntry rep = LetBoundEntry+ { letBoundDec :: LetDec rep, letBoundAliases :: Names,- letBoundStm :: Stm lore,+ letBoundStm :: Stm rep, -- | Index a delayed array, if possible. letBoundIndex :: Int -> IndexArray } -data FParamEntry lore = FParamEntry- { fparamDec :: FParamInfo lore,+data FParamEntry rep = FParamEntry+ { fparamDec :: FParamInfo rep, fparamAliases :: Names, -- | If a loop parameter, the initial value and the eventual -- result. The result need not be in scope in the symbol table. fparamMerge :: Maybe (SubExp, SubExp) } -data LParamEntry lore = LParamEntry- { lparamDec :: LParamInfo lore,+data LParamEntry rep = LParamEntry+ { lparamDec :: LParamInfo rep, lparamIndex :: IndexArray } -data FreeVarEntry lore = FreeVarEntry- { freeVarDec :: NameInfo lore,+data FreeVarEntry rep = FreeVarEntry+ { freeVarDec :: NameInfo rep, -- | Index a delayed array, if possible. freeVarIndex :: VName -> IndexArray } -instance ASTLore lore => Typed (Entry lore) where+instance ASTRep rep => Typed (Entry rep) where typeOf = typeOf . entryInfo -entryInfo :: Entry lore -> NameInfo lore+entryInfo :: Entry rep -> NameInfo rep entryInfo e = case entryType e of LetBound entry -> LetName $ letBoundDec entry LoopVar entry -> IndexName $ loopVarType entry@@ -185,54 +185,54 @@ LParam entry -> LParamName $ lparamDec entry FreeVar entry -> freeVarDec entry -isLetBound :: Entry lore -> Maybe (LetBoundEntry lore)+isLetBound :: Entry rep -> Maybe (LetBoundEntry rep) isLetBound e = case entryType e of LetBound entry -> Just entry _ -> Nothing -entryStm :: Entry lore -> Maybe (Stm lore)+entryStm :: Entry rep -> Maybe (Stm rep) entryStm = fmap letBoundStm . isLetBound -entryFParam :: Entry lore -> Maybe (FParamInfo lore)+entryFParam :: Entry rep -> Maybe (FParamInfo rep) entryFParam e = case entryType e of FParam e' -> Just $ fparamDec e' _ -> Nothing -entryLetBoundDec :: Entry lore -> Maybe (LetDec lore)+entryLetBoundDec :: Entry rep -> Maybe (LetDec rep) entryLetBoundDec = fmap letBoundDec . isLetBound -elem :: VName -> SymbolTable lore -> Bool+elem :: VName -> SymbolTable rep -> Bool elem name = isJust . lookup name -lookup :: VName -> SymbolTable lore -> Maybe (Entry lore)+lookup :: VName -> SymbolTable rep -> Maybe (Entry rep) lookup name = M.lookup name . bindings -lookupStm :: VName -> SymbolTable lore -> Maybe (Stm lore)+lookupStm :: VName -> SymbolTable rep -> Maybe (Stm rep) lookupStm name vtable = entryStm =<< lookup name vtable -lookupExp :: VName -> SymbolTable lore -> Maybe (Exp lore, Certificates)+lookupExp :: VName -> SymbolTable rep -> Maybe (Exp rep, Certificates) lookupExp name vtable = (stmExp &&& stmCerts) <$> lookupStm name vtable -lookupBasicOp :: VName -> SymbolTable lore -> Maybe (BasicOp, Certificates)+lookupBasicOp :: VName -> SymbolTable rep -> Maybe (BasicOp, Certificates) lookupBasicOp name vtable = case lookupExp name vtable of Just (BasicOp e, cs) -> Just (e, cs) _ -> Nothing -lookupType :: ASTLore lore => VName -> SymbolTable lore -> Maybe Type+lookupType :: ASTRep rep => VName -> SymbolTable rep -> Maybe Type lookupType name vtable = typeOf <$> lookup name vtable -lookupSubExpType :: ASTLore lore => SubExp -> SymbolTable lore -> Maybe Type+lookupSubExpType :: ASTRep rep => SubExp -> SymbolTable rep -> Maybe Type lookupSubExpType (Var v) = lookupType v lookupSubExpType (Constant v) = const $ Just $ Prim $ primValueType v -lookupSubExp :: VName -> SymbolTable lore -> Maybe (SubExp, Certificates)+lookupSubExp :: VName -> SymbolTable rep -> Maybe (SubExp, Certificates) lookupSubExp name vtable = do (e, cs) <- lookupExp name vtable case e of BasicOp (SubExp se) -> Just (se, cs) _ -> Nothing -lookupAliases :: VName -> SymbolTable lore -> Names+lookupAliases :: VName -> SymbolTable rep -> Names lookupAliases name vtable = case entryType <$> M.lookup name (bindings vtable) of Just (LetBound e) -> letBoundAliases e@@ -241,25 +241,25 @@ -- | If the given variable name is the name of a 'ForLoop' parameter, -- then return the bound of that loop.-lookupLoopVar :: VName -> SymbolTable lore -> Maybe SubExp+lookupLoopVar :: VName -> SymbolTable rep -> Maybe SubExp lookupLoopVar name vtable = do LoopVar e <- entryType <$> M.lookup name (bindings vtable) return $ loopVarBound e -lookupLoopParam :: VName -> SymbolTable lore -> Maybe (SubExp, SubExp)+lookupLoopParam :: VName -> SymbolTable rep -> Maybe (SubExp, SubExp) lookupLoopParam name vtable = do FParam e <- entryType <$> M.lookup name (bindings vtable) fparamMerge e -- | In symbol table and not consumed.-available :: VName -> SymbolTable lore -> Bool+available :: VName -> SymbolTable rep -> Bool available name = maybe False (not . entryConsumed) . M.lookup name . bindings index ::- ASTLore lore =>+ ASTRep rep => VName -> [SubExp] ->- SymbolTable lore ->+ SymbolTable rep -> Maybe Indexed index name is table = do is' <- mapM asPrimExp is@@ -272,7 +272,7 @@ index' :: VName -> [TPrimExp Int64 VName] ->- SymbolTable lore ->+ SymbolTable rep -> Maybe Indexed index' name is vtable = do entry <- lookup name vtable@@ -290,8 +290,8 @@ class IndexOp op where indexOp ::- (ASTLore lore, IndexOp (Op lore)) =>- SymbolTable lore ->+ (ASTRep rep, IndexOp (Op rep)) =>+ SymbolTable rep -> Int -> op -> [TPrimExp Int64 VName] ->@@ -301,9 +301,9 @@ instance IndexOp () indexExp ::- (IndexOp (Op lore), ASTLore lore) =>- SymbolTable lore ->- Exp lore ->+ (IndexOp (Op rep), ASTRep rep) =>+ SymbolTable rep ->+ Exp rep -> Int -> IndexArray indexExp vtable (Op op) k is =@@ -345,12 +345,12 @@ indexExp _ _ _ _ = Nothing defBndEntry ::- (ASTLore lore, IndexOp (Op lore)) =>- SymbolTable lore ->- PatElem lore ->+ (ASTRep rep, IndexOp (Op rep)) =>+ SymbolTable rep ->+ PatElem rep -> Names ->- Stm lore ->- LetBoundEntry lore+ Stm rep ->+ LetBoundEntry rep defBndEntry vtable patElem als bnd = LetBoundEntry { letBoundDec = patElemDec patElem,@@ -362,10 +362,10 @@ } bindingEntries ::- (ASTLore lore, Aliases.Aliased lore, IndexOp (Op lore)) =>- Stm lore ->- SymbolTable lore ->- [LetBoundEntry lore]+ (ASTRep rep, Aliases.Aliased rep, IndexOp (Op rep)) =>+ Stm rep ->+ SymbolTable rep ->+ [LetBoundEntry rep] bindingEntries bnd@(Let pat _ _) vtable = do pat_elem <- patternElements pat return $ defBndEntry vtable pat_elem (Aliases.aliasesOf pat_elem) bnd@@ -374,11 +374,11 @@ adjustSeveral f = flip $ foldl' $ flip $ M.adjust f insertEntry ::- ASTLore lore =>+ ASTRep rep => VName ->- EntryType lore ->- SymbolTable lore ->- SymbolTable lore+ EntryType rep ->+ SymbolTable rep ->+ SymbolTable rep insertEntry name entry vtable = let entry' = Entry@@ -396,20 +396,20 @@ } insertEntries ::- ASTLore lore =>- [(VName, EntryType lore)] ->- SymbolTable lore ->- SymbolTable lore+ ASTRep rep =>+ [(VName, EntryType rep)] ->+ SymbolTable rep ->+ SymbolTable rep insertEntries entries vtable = foldl' add vtable entries where add vtable' (name, entry) = insertEntry name entry vtable' insertStm ::- (ASTLore lore, IndexOp (Op lore), Aliases.Aliased lore) =>- Stm lore ->- SymbolTable lore ->- SymbolTable lore+ (ASTRep rep, IndexOp (Op rep), Aliases.Aliased rep) =>+ Stm rep ->+ SymbolTable rep ->+ SymbolTable rep insertStm stm vtable = flip (foldl' $ flip consume) (namesToList stm_consumed) $ flip (foldl' addRevAliases) (patternElements $ stmPattern stm) $@@ -435,23 +435,23 @@ update' e = e insertStms ::- (ASTLore lore, IndexOp (Op lore), Aliases.Aliased lore) =>- Stms lore ->- SymbolTable lore ->- SymbolTable lore+ (ASTRep rep, IndexOp (Op rep), Aliases.Aliased rep) =>+ Stms rep ->+ SymbolTable rep ->+ SymbolTable rep insertStms stms vtable = foldl' (flip insertStm) vtable $ stmsToList stms -expandAliases :: Names -> SymbolTable lore -> Names+expandAliases :: Names -> SymbolTable rep -> Names expandAliases names vtable = names <> aliasesOfAliases where aliasesOfAliases = mconcat . map (`lookupAliases` vtable) . namesToList $ names insertFParam ::- ASTLore lore =>- AST.FParam lore ->- SymbolTable lore ->- SymbolTable lore+ ASTRep rep =>+ AST.FParam rep ->+ SymbolTable rep ->+ SymbolTable rep insertFParam fparam = insertEntry name entry where name = AST.paramName fparam@@ -464,13 +464,13 @@ } insertFParams ::- ASTLore lore =>- [AST.FParam lore] ->- SymbolTable lore ->- SymbolTable lore+ ASTRep rep =>+ [AST.FParam rep] ->+ SymbolTable rep ->+ SymbolTable rep insertFParams fparams symtable = foldl' (flip insertFParam) symtable fparams -insertLParam :: ASTLore lore => LParam lore -> SymbolTable lore -> SymbolTable lore+insertLParam :: ASTRep rep => LParam rep -> SymbolTable rep -> SymbolTable rep insertLParam param = insertEntry name bind where bind =@@ -489,10 +489,10 @@ -- used to help some loop optimisations detect invariant loop -- parameters. insertLoopMerge ::- ASTLore lore =>- [(AST.FParam lore, SubExp, SubExp)] ->- SymbolTable lore ->- SymbolTable lore+ ASTRep rep =>+ [(AST.FParam rep, SubExp, SubExp)] ->+ SymbolTable rep ->+ SymbolTable rep insertLoopMerge = flip $ foldl' $ flip bind where bind (p, initial, res) =@@ -504,7 +504,7 @@ fparamMerge = Just (initial, res) } -insertLoopVar :: ASTLore lore => VName -> IntType -> SubExp -> SymbolTable lore -> SymbolTable lore+insertLoopVar :: ASTRep rep => VName -> IntType -> SubExp -> SymbolTable rep -> SymbolTable rep insertLoopVar name it bound = insertEntry name bind where bind =@@ -514,7 +514,7 @@ loopVarBound = bound } -insertFreeVar :: ASTLore lore => VName -> NameInfo lore -> SymbolTable lore -> SymbolTable lore+insertFreeVar :: ASTRep rep => VName -> NameInfo rep -> SymbolTable rep -> SymbolTable rep insertFreeVar name dec = insertEntry name entry where entry =@@ -524,7 +524,7 @@ freeVarIndex = \_ _ -> Nothing } -consume :: VName -> SymbolTable lore -> SymbolTable lore+consume :: VName -> SymbolTable rep -> SymbolTable rep consume consumee vtable = foldl' consume' vtable $ namesToList $@@ -535,7 +535,7 @@ consume'' e = e {entryConsumed = True} -- | Hide definitions of those entries that satisfy some predicate.-hideIf :: (Entry lore -> Bool) -> SymbolTable lore -> SymbolTable lore+hideIf :: (Entry rep -> Bool) -> SymbolTable rep -> SymbolTable rep hideIf hide vtable = vtable {bindings = M.map maybeHide $ bindings vtable} where maybeHide entry@@ -552,7 +552,7 @@ -- | Hide these definitions, if they are protected by certificates in -- the set of names.-hideCertified :: Names -> SymbolTable lore -> SymbolTable lore+hideCertified :: Names -> SymbolTable rep -> SymbolTable rep hideCertified to_hide = hideIf $ maybe False hide . entryStm where hide = any (`nameIn` to_hide) . unCertificates . stmCerts
src/Futhark/Analysis/UsageTable.hs view
@@ -141,16 +141,16 @@ withoutU :: Usages -> Usages -> Usages withoutU (Usages x) (Usages y) = Usages $ x .&. complement y -usageInBody :: Aliased lore => Body lore -> UsageTable+usageInBody :: Aliased rep => Body rep -> UsageTable usageInBody = foldMap consumedUsage . namesToList . consumedInBody -- | Produce a usage table reflecting the use of the free variables in -- a single statement.-usageInStm :: (ASTLore lore, Aliased lore) => Stm lore -> UsageTable-usageInStm (Let pat lore e) =+usageInStm :: (ASTRep rep, Aliased rep) => Stm rep -> UsageTable+usageInStm (Let pat rep e) = mconcat [ usageInPat,- usageInExpLore,+ usageInExpDec, usageInExp e, usages (freeIn e) ]@@ -161,10 +161,10 @@ `namesSubtract` namesFromList (patternNames pat) ) <> sizeUsages (foldMap (freeIn . patElemType) (patternElements pat))- usageInExpLore =- usages $ freeIn lore+ usageInExpDec =+ usages $ freeIn rep -usageInExp :: Aliased lore => Exp lore -> UsageTable+usageInExp :: Aliased rep => Exp rep -> UsageTable usageInExp (Apply _ args _ _) = mconcat [ mconcat $
src/Futhark/Bench.hs view
@@ -158,11 +158,13 @@ cmdMaybe . liftIO $ cmdClear server - valuesAsVars server (zip ins input_types) futhark dir input_spec- let freeOuts = cmdMaybe (cmdFree server outs) freeIns = cmdMaybe (cmdFree server ins)+ loadInput = valuesAsVars server (zip ins $ map inputType input_types) futhark dir input_spec+ reloadInput = freeIns >> loadInput + loadInput+ let runtime l | Just l' <- T.stripPrefix "runtime: " l, [(x, "")] <- reads $ T.unpack l' =@@ -172,6 +174,7 @@ doRun = do call_lines <- cmdEither (cmdCall server entry outs ins)+ when (any inputConsumed input_types) reloadInput case mapMaybe runtime call_lines of [call_runtime] -> do liftIO $ fromMaybe (const $ pure ()) (runResultAction opts) call_runtime@@ -197,7 +200,7 @@ report <- cmdEither $ cmdReport server - vs <- readResults server outs program <* freeOuts+ vs <- readResults server outs <* freeOuts maybe_expected <- liftIO $ maybe (return Nothing) (fmap Just . getExpectedValues) expected_spec
src/Futhark/Binder.hs view
@@ -42,44 +42,44 @@ import Futhark.IR -- | A 'BinderT' (and by extension, a 'Binder') is only an instance of--- 'MonadBinder' for lores that implement this type class, which--- contains methods for constructing statements.-class ASTLore lore => BinderOps lore where+-- 'MonadBinder' for representations that implement this type class,+-- which contains methods for constructing statements.+class ASTRep rep => BinderOps rep where mkExpDecB ::- (MonadBinder m, Lore m ~ lore) =>- Pattern lore ->- Exp lore ->- m (ExpDec lore)+ (MonadBinder m, Rep m ~ rep) =>+ Pattern rep ->+ Exp rep ->+ m (ExpDec rep) mkBodyB ::- (MonadBinder m, Lore m ~ lore) =>- Stms lore ->+ (MonadBinder m, Rep m ~ rep) =>+ Stms rep -> Result ->- m (Body lore)+ m (Body rep) mkLetNamesB ::- (MonadBinder m, Lore m ~ lore) =>+ (MonadBinder m, Rep m ~ rep) => [VName] ->- Exp lore ->- m (Stm lore)+ Exp rep ->+ m (Stm rep) default mkExpDecB ::- (MonadBinder m, Bindable lore) =>- Pattern lore ->- Exp lore ->- m (ExpDec lore)+ (MonadBinder m, Bindable rep) =>+ Pattern rep ->+ Exp rep ->+ m (ExpDec rep) mkExpDecB pat e = return $ mkExpDec pat e default mkBodyB ::- (MonadBinder m, Bindable lore) =>- Stms lore ->+ (MonadBinder m, Bindable rep) =>+ Stms rep -> Result ->- m (Body lore)+ m (Body rep) mkBodyB stms res = return $ mkBody stms res default mkLetNamesB ::- (MonadBinder m, Lore m ~ lore, Bindable lore) =>+ (MonadBinder m, Rep m ~ rep, Bindable rep) => [VName] ->- Exp lore ->- m (Stm lore)+ Exp rep ->+ m (Stm rep) mkLetNamesB = mkLetNames -- | A monad transformer that tracks statements and provides a@@ -88,22 +88,22 @@ -- 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 lore m a = BinderT (StateT (Stms lore, Scope lore) m a)+newtype BinderT rep m a = BinderT (StateT (Stms rep, Scope rep) m a) deriving (Functor, Monad, Applicative) -instance MonadTrans (BinderT lore) where+instance MonadTrans (BinderT rep) where lift = BinderT . lift -- | The most commonly used binder monad.-type Binder lore = BinderT lore (State VNameSource)+type Binder rep = BinderT rep (State VNameSource) -instance MonadFreshNames m => MonadFreshNames (BinderT lore m) where+instance MonadFreshNames m => MonadFreshNames (BinderT rep m) where getNameSource = lift getNameSource putNameSource = lift . putNameSource instance- (ASTLore lore, Monad m) =>- HasScope lore (BinderT lore m)+ (ASTRep rep, Monad m) =>+ HasScope rep (BinderT rep m) where lookupType name = do t <- BinderT $ gets $ M.lookup name . snd@@ -113,8 +113,8 @@ askScope = BinderT $ gets snd instance- (ASTLore lore, Monad m) =>- LocalScope lore (BinderT lore m)+ (ASTRep rep, Monad m) =>+ LocalScope rep (BinderT rep m) where localScope types (BinderT m) = BinderT $ do modify $ second (M.union types)@@ -123,10 +123,10 @@ return x instance- (ASTLore lore, MonadFreshNames m, BinderOps lore) =>- MonadBinder (BinderT lore m)+ (ASTRep rep, MonadFreshNames m, BinderOps rep) =>+ MonadBinder (BinderT rep m) where- type Lore (BinderT lore m) = lore+ type Rep (BinderT rep m) = rep mkExpDecM = mkExpDecB mkBodyM = mkBodyB mkLetNamesM = mkLetNamesB@@ -148,9 +148,9 @@ -- the statements added ('addStm') during the action. runBinderT :: MonadFreshNames m =>- BinderT lore m a ->- Scope lore ->- m (a, Stms lore)+ BinderT rep m a ->+ Scope rep ->+ m (a, Stms rep) runBinderT (BinderT m) scope = do (x, (stms, _)) <- runStateT m (mempty, scope) return (x, stms)@@ -158,17 +158,17 @@ -- | Like 'runBinderT', but return only the statements. runBinderT_ :: MonadFreshNames m =>- BinderT lore m () ->- Scope lore ->- m (Stms lore)+ 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 somelore m, SameScope somelore lore) =>- BinderT lore m a ->- m (a, Stms lore)+ (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@@ -176,9 +176,9 @@ -- | Like 'runBinderT_', but get the initial scope from the current -- monad. runBinderT'_ ::- (MonadFreshNames m, HasScope somelore m, SameScope somelore lore) =>- BinderT lore m a ->- m (Stms lore)+ (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@@ -186,11 +186,11 @@ -- provides initial scope and name source. runBinder :: ( MonadFreshNames m,- HasScope somelore m,- SameScope somelore lore+ HasScope somerep m,+ SameScope somerep rep ) =>- Binder lore a ->- m (a, Stms lore)+ Binder rep a ->+ m (a, Stms rep) runBinder m = do types <- askScope modifyNameSource $ runState $ runBinderT m $ castScope types@@ -199,23 +199,23 @@ -- added statements. runBinder_ :: ( MonadFreshNames m,- HasScope somelore m,- SameScope somelore lore+ HasScope somerep m,+ SameScope somerep rep ) =>- Binder lore a ->- m (Stms lore)+ 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 lore,+ ( Bindable rep, MonadFreshNames m,- HasScope somelore m,- SameScope somelore lore+ HasScope somerep m,+ SameScope somerep rep ) =>- Binder lore (Body lore) ->- m (Body lore)+ Binder rep (Body rep) ->+ m (Body rep) runBodyBinder = fmap (uncurry $ flip insertStms) . runBinder -- Utility instance defintions for MTL classes. These require@@ -223,26 +223,26 @@ mapInner :: Monad m =>- ( m (a, (Stms lore, Scope lore)) ->- m (b, (Stms lore, Scope lore))+ ( m (a, (Stms rep, Scope rep)) ->+ m (b, (Stms rep, Scope rep)) ) ->- BinderT lore m a ->- BinderT lore m b+ 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 lore m) where+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 lore m) where+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 lore m) where+instance MonadWriter w m => MonadWriter w (BinderT rep m) where tell = BinderT . lift . tell pass = mapInner $ \m -> pass $ do ((x, f), s) <- m@@ -251,7 +251,7 @@ ((x, s), y) <- listen m return ((x, y), s) -instance MonadError e m => MonadError e (BinderT lore m) where+instance MonadError e m => MonadError e (BinderT rep m) where throwError = lift . throwError catchError (BinderT m) f = BinderT $ catchError m $ unBinder . f
src/Futhark/Binder/Class.hs view
@@ -26,33 +26,33 @@ import Futhark.IR import Futhark.MonadFreshNames --- | The class of lores 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+-- | 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- ( ASTLore lore,- FParamInfo lore ~ DeclType,- LParamInfo lore ~ Type,- RetType lore ~ DeclExtType,- BranchType lore ~ ExtType,- SetType (LetDec lore)+ ( ASTRep rep,+ FParamInfo rep ~ DeclType,+ LParamInfo rep ~ Type,+ RetType rep ~ DeclExtType,+ BranchType rep ~ ExtType,+ SetType (LetDec rep) ) =>- Bindable lore+ Bindable rep where- mkExpPat :: [Ident] -> [Ident] -> Exp lore -> Pattern lore- mkExpDec :: Pattern lore -> Exp lore -> ExpDec lore- mkBody :: Stms lore -> Result -> Body lore+ mkExpPat :: [Ident] -> [Ident] -> Exp rep -> Pattern rep+ mkExpDec :: Pattern rep -> Exp rep -> ExpDec rep+ mkBody :: Stms rep -> Result -> Body rep mkLetNames ::- (MonadFreshNames m, HasScope lore m) =>+ (MonadFreshNames m, HasScope rep m) => [VName] ->- Exp lore ->- m (Stm lore)+ Exp rep ->+ m (Stm rep) -- | A monad that supports the creation of bindings from expressions--- and bodies from bindings, with a specific lore. This is the main+-- 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@@ -63,29 +63,29 @@ -- results thrown away. It is acceptable for them to create new -- bindings, however. class- ( ASTLore (Lore m),+ ( ASTRep (Rep m), MonadFreshNames m, Applicative m, Monad m,- LocalScope (Lore m) m+ LocalScope (Rep m) m ) => MonadBinder m where- type Lore m :: Data.Kind.Type- mkExpDecM :: Pattern (Lore m) -> Exp (Lore m) -> m (ExpDec (Lore m))- mkBodyM :: Stms (Lore m) -> Result -> m (Body (Lore m))- mkLetNamesM :: [VName] -> Exp (Lore m) -> m (Stm (Lore m))+ 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 (Lore m) -> m ()+ addStm :: Stm (Rep m) -> m () addStm = addStms . oneStm -- | Add multiple statements to the 'Stms' under construction.- addStms :: Stms (Lore m) -> m ()+ 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 (Lore m))+ collectStms :: m a -> m (a, Stms (Rep m)) -- | Add the provided certificates to any statements added during -- execution of the action.@@ -95,7 +95,7 @@ -- | Apply a function to the statements added by this action. censorStms :: MonadBinder m =>- (Stms (Lore m) -> Stms (Lore m)) ->+ (Stms (Rep m) -> Stms (Rep m)) -> m a -> m a censorStms f m = do@@ -112,7 +112,7 @@ -- | Add the certificates and attributes to any statements added by -- this action.-auxing :: MonadBinder m => StmAux anylore -> m a -> m a+auxing :: MonadBinder m => StmAux anyrep -> m a -> m a auxing (StmAux cs attrs _) = censorStms $ fmap onStm where onStm (Let pat aux e) =@@ -127,15 +127,15 @@ -- | Add a statement with the given pattern and expression. letBind :: MonadBinder m =>- Pattern (Lore m) ->- Exp (Lore 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 lore => [Ident] -> [Ident] -> Exp lore -> Stm lore+mkLet :: Bindable rep => [Ident] -> [Ident] -> Exp rep -> Stm rep mkLet ctx val e = let pat = mkExpPat ctx val e dec = mkExpDec pat e@@ -143,7 +143,7 @@ -- | Like mkLet, but also take attributes and certificates from the -- given 'StmAux'.-mkLet' :: Bindable lore => [Ident] -> [Ident] -> StmAux a -> Exp lore -> Stm lore+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@@ -151,23 +151,23 @@ -- | Add a statement with the given pattern element names and -- expression.-letBindNames :: MonadBinder m => [VName] -> Exp (Lore m) -> m ()+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 (Lore m))+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 (Lore m) -> m [SubExp]+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 lore => Stms lore -> Body lore -> Body lore+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 lore => Stm lore -> Body lore -> Body lore+insertStm :: Bindable rep => Stm rep -> Body rep -> Body rep insertStm = insertStms . oneStm
src/Futhark/CLI/Autotune.hs view
@@ -141,7 +141,7 @@ -- run, but unfortunately we can only set threshold parameters -- on startup. let progbin = "." </> dropExtension prog- withServer progbin (serverOptions path opts) $ \server ->+ withServer (futharkServerCfg progbin (serverOptions path opts)) $ \server -> either (Left . T.unpack) (Right . bestRuntime) <$> benchmarkDataset server
src/Futhark/CLI/Bench.hs view
@@ -177,7 +177,7 @@ | null runner = (binpath, extra_options) | otherwise = (runner, binpath : extra_options) - liftIO $ (Just <$> withServer to_run to_run_args f) `catch` onError+ liftIO $ (Just <$> withServer (futharkServerCfg to_run to_run_args) f) `catch` onError where onError :: SomeException -> IO (Maybe a) onError e = do@@ -242,16 +242,30 @@ descString :: String -> Int -> String descString desc pad_to = desc ++ ": " ++ replicate (pad_to - length desc) ' ' +interimResult :: Int -> Int -> Int -> String+interimResult us_sum i runs =+ printf "%10.0fμs " avg ++ progressBar i runs 10+ where+ avg :: Double+ avg = fromIntegral us_sum / fromIntegral i+ mkProgressPrompt :: Int -> Int -> String -> IO (Maybe Int -> IO ()) mkProgressPrompt runs pad_to dataset_desc | fancyTerminal = do- count <- newIORef (0 :: Int)+ count <- newIORef (0, 0) return $ \us -> do putStr "\r" -- Go to start of line.- i <- readIORef count- let i' = if isJust us then i + 1 else i- writeIORef count i'- putStr $ descString (atMostChars 40 dataset_desc) pad_to ++ progressBar i' runs 10+ let p s =+ putStr $+ descString (atMostChars 40 dataset_desc) pad_to ++ s+ (us_sum, i) <- readIORef count+ case us of+ Nothing -> p $ replicate 13 ' ' ++ progressBar i runs 10+ Just us' -> do+ let us_sum' = us_sum + us'+ i' = i + 1+ writeIORef count (us_sum', i')+ p $ interimResult us_sum' i' runs putStr " " -- Just to move the cursor away from the progress bar. hFlush stdout | otherwise = do@@ -260,17 +274,19 @@ return $ const $ return () reportResult :: [RunResult] -> IO ()-reportResult results = do- let runtimes = map (fromIntegral . runMicroseconds) results- avg = sum runtimes / fromIntegral (length runtimes)- rsd = stddevp runtimes / mean runtimes :: Double- putStrLn $- printf- "%10.0fμs (RSD: %.3f; min: %3.0f%%; max: %+3.0f%%)"- avg- rsd- ((minimum runtimes / avg - 1) * 100)- ((maxinum runtimes / avg - 1) * 100)+reportResult = putStrLn . reportString+ where+ reportString results =+ printf+ "%10.0fμs (RSD: %.3f; min: %3.0f%%; max: %+3.0f%%)"+ avg+ rsd+ ((minimum runtimes / avg - 1) * 100)+ ((maxinum runtimes / avg - 1) * 100)+ where+ runtimes = map (fromIntegral . runMicroseconds) results+ avg = sum runtimes / fromIntegral (length runtimes)+ rsd = stddevp runtimes / mean runtimes :: Double runBenchmarkCase :: Server ->
src/Futhark/CLI/Datacmp.hs view
@@ -5,7 +5,8 @@ import Control.Exception import qualified Data.ByteString.Lazy.Char8 as BS-import Futhark.Test.Values+import Futhark.Data.Compare+import Futhark.Data.Reader import Futhark.Util.Options import System.Exit import System.IO@@ -41,7 +42,7 @@ hPutStrLn stderr $ "Error reading values from " ++ file_b exitFailure (Just vs_a, Just vs_b) ->- case compareValues vs_a vs_b of+ case compareSeveralValues (Tolerance 0.002) vs_a vs_b of [] -> return () es -> do mapM_ print es
src/Futhark/CLI/Dataset.hs view
@@ -8,17 +8,18 @@ import Control.Monad.ST import qualified Data.Binary as Bin import qualified Data.ByteString.Lazy.Char8 as BS-import qualified Data.Map.Strict as M import qualified Data.Text as T+import qualified Data.Text.IO as T import Data.Vector.Generic (freeze) import qualified Data.Vector.Storable as SVec import qualified Data.Vector.Storable.Mutable as USVec import Data.Word-import Futhark.Test.Values+import qualified Futhark.Data as V+import Futhark.Data.Reader (readValues) import Futhark.Util.Options import Language.Futhark.Parser import Language.Futhark.Pretty ()-import Language.Futhark.Prop (UncheckedTypeExp, namesToPrimTypes)+import Language.Futhark.Prop (UncheckedTypeExp) import Language.Futhark.Syntax hiding ( FloatValue (..), IntValue (..),@@ -43,9 +44,9 @@ exitFailure Just vs -> case format config of- Text -> mapM_ (putStrLn . pretty) vs+ Text -> mapM_ (T.putStrLn . V.valueText) vs Binary -> mapM_ (BS.putStr . Bin.encode) vs- Type -> mapM_ (putStrLn . pretty . valueType) vs+ Type -> mapM_ (T.putStrLn . V.valueTypeText . V.valueType) vs | otherwise = Just $ zipWithM_@@ -178,11 +179,11 @@ outValue fmt v where name = "option " ++ t- outValue Text = putStrLn . pretty+ outValue Text = T.putStrLn . V.valueText outValue Binary = BS.putStr . Bin.encode- outValue Type = putStrLn . pretty . valueType+ outValue Type = T.putStrLn . V.valueTypeText . V.valueType -toValueType :: UncheckedTypeExp -> Either String ValueType+toValueType :: UncheckedTypeExp -> Either String V.ValueType toValueType TETuple {} = Left "Cannot handle tuples yet." toValueType TERecord {} = Left "Cannot handle records yet." toValueType TEApply {} = Left "Cannot handle type applications yet."@@ -191,13 +192,16 @@ toValueType (TEUnique t _) = toValueType t toValueType (TEArray t d _) = do d' <- constantDim d- ValueType ds t' <- toValueType t- return $ ValueType (d' : ds) t'+ V.ValueType ds t' <- toValueType t+ return $ V.ValueType (d' : ds) t' where constantDim (DimExpConst k _) = Right k constantDim _ = Left "Array has non-constant dimension declaration." toValueType (TEVar (QualName [] v) _)- | Just t <- M.lookup v namesToPrimTypes = Right $ ValueType [] t+ | Just t <- lookup v m = Right $ V.ValueType [] t+ where+ m = map f [minBound .. maxBound]+ f t = (nameFromText (V.primTypeText t), t) toValueType (TEVar v _) = Left $ "Unknown type " ++ pretty v @@ -263,30 +267,30 @@ (0.0, 1.0) (0.0, 1.0) -randomValue :: RandomConfiguration -> ValueType -> Word64 -> Value-randomValue conf (ValueType ds t) seed =+randomValue :: RandomConfiguration -> V.ValueType -> Word64 -> V.Value+randomValue conf (V.ValueType ds t) seed = case t of- Signed Int8 -> gen i8Range Int8Value- Signed Int16 -> gen i16Range Int16Value- Signed Int32 -> gen i32Range Int32Value- Signed Int64 -> gen i64Range Int64Value- Unsigned Int8 -> gen u8Range Word8Value- Unsigned Int16 -> gen u16Range Word16Value- Unsigned Int32 -> gen u32Range Word32Value- Unsigned Int64 -> gen u64Range Word64Value- FloatType Float32 -> gen f32Range Float32Value- FloatType Float64 -> gen f64Range Float64Value- Bool -> gen (const (False, True)) BoolValue+ V.I8 -> gen i8Range V.I8Value+ V.I16 -> gen i16Range V.I16Value+ V.I32 -> gen i32Range V.I32Value+ V.I64 -> gen i64Range V.I64Value+ V.U8 -> gen u8Range V.U8Value+ V.U16 -> gen u16Range V.U16Value+ V.U32 -> gen u32Range V.U32Value+ V.U64 -> gen u64Range V.U64Value+ V.F32 -> gen f32Range V.F32Value+ V.F64 -> gen f64Range V.F64Value+ V.Bool -> gen (const (False, True)) V.BoolValue where gen range final = randomVector (range conf) final ds seed randomVector :: (SVec.Storable v, Variate v) => Range v ->- (SVec.Vector Int -> SVec.Vector v -> Value) ->+ (SVec.Vector Int -> SVec.Vector v -> V.Value) -> [Int] -> Word64 ->- Value+ V.Value randomVector range final ds seed = runST $ do -- USe some nice impure computation where we can preallocate a -- vector of the desired size, populate it via the random number
src/Futhark/CLI/Dev.hs view
@@ -12,11 +12,12 @@ import qualified Data.Text as T import qualified Data.Text.IO as T import Futhark.Actions+import qualified Futhark.Analysis.Alias as Alias import Futhark.Analysis.Metrics (OpMetrics) import Futhark.Compiler.CLI-import Futhark.IR (ASTLore, Op, Prog, pretty)-import qualified Futhark.IR.Kernels as Kernels-import qualified Futhark.IR.KernelsMem as KernelsMem+import Futhark.IR (ASTRep, Op, Prog, pretty)+import qualified Futhark.IR.GPU as GPU+import qualified Futhark.IR.GPUMem as GPUMem import qualified Futhark.IR.MC as MC import qualified Futhark.IR.MCMem as MCMem import Futhark.IR.Parse@@ -33,12 +34,13 @@ import Futhark.Optimise.Fusion import Futhark.Optimise.InPlaceLowering import Futhark.Optimise.InliningDeadFun+import qualified Futhark.Optimise.ReuseAllocations as ReuseAllocations import Futhark.Optimise.Sink import Futhark.Optimise.TileLoops import Futhark.Optimise.Unstream import Futhark.Pass import Futhark.Pass.ExpandAllocations-import qualified Futhark.Pass.ExplicitAllocations.Kernels as Kernels+import qualified Futhark.Pass.ExplicitAllocations.GPU as GPU import qualified Futhark.Pass.ExplicitAllocations.Seq as Seq import Futhark.Pass.ExtractKernels import Futhark.Pass.ExtractMulticore@@ -46,7 +48,7 @@ import Futhark.Pass.KernelBabysitting import Futhark.Pass.Simplify import Futhark.Passes-import Futhark.TypeCheck (Checkable)+import Futhark.TypeCheck (Checkable, checkProg) import Futhark.Util.Log import Futhark.Util.Options import qualified Futhark.Util.Pretty as PP@@ -95,10 +97,10 @@ data UntypedPassState = SOACS (Prog SOACS.SOACS)- | Kernels (Prog Kernels.Kernels)+ | GPU (Prog GPU.GPU) | MC (Prog MC.MC) | Seq (Prog Seq.Seq)- | KernelsMem (Prog KernelsMem.KernelsMem)+ | GPUMem (Prog GPUMem.GPUMem) | MCMem (Prog MCMem.MCMem) | SeqMem (Prog SeqMem.SeqMem) @@ -113,21 +115,21 @@ instance Representation UntypedPassState where representation (SOACS _) = "SOACS"- representation (Kernels _) = "Kernels"+ representation (GPU _) = "GPU" representation (MC _) = "MC" representation (Seq _) = "Seq"- representation (KernelsMem _) = "KernelsMem"+ representation (GPUMem _) = "GPUMem" representation (MCMem _) = "MCMem" representation (SeqMem _) = "SeqMEm" instance PP.Pretty UntypedPassState where ppr (SOACS prog) = PP.ppr prog- ppr (Kernels prog) = PP.ppr prog+ ppr (GPU prog) = PP.ppr prog ppr (MC prog) = PP.ppr prog ppr (Seq prog) = PP.ppr prog ppr (SeqMem prog) = PP.ppr prog ppr (MCMem prog) = PP.ppr prog- ppr (KernelsMem prog) = PP.ppr prog+ ppr (GPUMem prog) = PP.ppr prog newtype UntypedPass = UntypedPass@@ -138,31 +140,31 @@ data UntypedAction = SOACSAction (Action SOACS.SOACS)- | KernelsAction (Action Kernels.Kernels)- | KernelsMemAction (FilePath -> Action KernelsMem.KernelsMem)+ | GPUAction (Action GPU.GPU)+ | GPUMemAction (FilePath -> Action GPUMem.GPUMem) | MCMemAction (FilePath -> Action MCMem.MCMem) | SeqMemAction (FilePath -> Action SeqMem.SeqMem) | PolyAction- ( forall lore.- ( ASTLore lore,- (CanBeAliased (Op lore)),- (OpMetrics (Op lore))+ ( forall rep.+ ( ASTRep rep,+ (CanBeAliased (Op rep)),+ (OpMetrics (Op rep)) ) =>- Action lore+ Action rep ) untypedActionName :: UntypedAction -> String untypedActionName (SOACSAction a) = actionName a-untypedActionName (KernelsAction a) = actionName a+untypedActionName (GPUAction a) = actionName a untypedActionName (SeqMemAction a) = actionName $ a ""-untypedActionName (KernelsMemAction 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 (KernelsAction _) = "Kernels"- representation (KernelsMemAction _) = "KernelsMem"+ representation (GPUAction _) = "GPU"+ representation (GPUMemAction _) = "GPUMem" representation (MCMemAction _) = "MCMem" representation (SeqMemAction _) = "SeqMem" representation PolyAction {} = "<any>"@@ -194,13 +196,13 @@ kernelsMemProg :: String -> UntypedPassState ->- FutharkM (Prog KernelsMem.KernelsMem)-kernelsMemProg _ (KernelsMem prog) =+ FutharkM (Prog GPUMem.GPUMem)+kernelsMemProg _ (GPUMem prog) = return prog kernelsMemProg name rep = externalErrorS $ "Pass " ++ name- ++ " expects KernelsMem representation, but got "+ ++ " expects GPUMem representation, but got " ++ representation rep soacsProg :: String -> UntypedPassState -> FutharkM (Prog SOACS.SOACS)@@ -212,18 +214,18 @@ ++ " expects SOACS representation, but got " ++ representation rep -kernelsProg :: String -> UntypedPassState -> FutharkM (Prog Kernels.Kernels)-kernelsProg _ (Kernels prog) =+kernelsProg :: String -> UntypedPassState -> FutharkM (Prog GPU.GPU)+kernelsProg _ (GPU prog) = return prog kernelsProg name rep = externalErrorS $- "Pass " ++ name ++ " expects Kernels representation, but got " ++ representation rep+ "Pass " ++ name ++ " expects GPU representation, but got " ++ representation rep typedPassOption ::- Checkable tolore =>- (String -> UntypedPassState -> FutharkM (Prog fromlore)) ->- (Prog tolore -> UntypedPassState) ->- Pass fromlore tolore ->+ Checkable torep =>+ (String -> UntypedPassState -> FutharkM (Prog fromrep)) ->+ (Prog torep -> UntypedPassState) ->+ Pass fromrep torep -> String -> FutharkOption typedPassOption getProg putProg pass short =@@ -240,18 +242,18 @@ typedPassOption soacsProg SOACS kernelsPassOption ::- Pass Kernels.Kernels Kernels.Kernels ->+ Pass GPU.GPU GPU.GPU -> String -> FutharkOption kernelsPassOption =- typedPassOption kernelsProg Kernels+ typedPassOption kernelsProg GPU kernelsMemPassOption ::- Pass KernelsMem.KernelsMem KernelsMem.KernelsMem ->+ Pass GPUMem.GPUMem GPUMem.GPUMem -> String -> FutharkOption kernelsMemPassOption =- typedPassOption kernelsMemProg KernelsMem+ typedPassOption kernelsMemProg GPUMem simplifyOption :: String -> FutharkOption simplifyOption short =@@ -259,16 +261,16 @@ where perform (SOACS prog) config = SOACS <$> runPipeline (onePass simplifySOACS) config prog- perform (Kernels prog) config =- Kernels <$> runPipeline (onePass simplifyKernels) config prog+ perform (GPU prog) config =+ GPU <$> runPipeline (onePass simplifyGPU) config prog perform (MC prog) config = MC <$> runPipeline (onePass simplifyMC) config prog perform (Seq prog) config = Seq <$> runPipeline (onePass simplifySeq) config prog perform (SeqMem prog) config = SeqMem <$> runPipeline (onePass simplifySeqMem) config prog- perform (KernelsMem prog) config =- KernelsMem <$> runPipeline (onePass simplifyKernelsMem) config prog+ perform (GPUMem prog) config =+ GPUMem <$> runPipeline (onePass simplifyGPUMem) config prog perform (MCMem prog) config = MCMem <$> runPipeline (onePass simplifyMCMem) config prog @@ -279,9 +281,9 @@ allocateOption short = passOption (passDescription pass) (UntypedPass perform) short long where- perform (Kernels prog) config =- KernelsMem- <$> runPipeline (onePass Kernels.explicitAllocations) config prog+ perform (GPU prog) config =+ GPUMem+ <$> runPipeline (onePass GPU.explicitAllocations) config prog perform (Seq prog) config = SeqMem <$> runPipeline (onePass Seq.explicitAllocations) config prog@@ -296,9 +298,9 @@ iplOption short = passOption (passDescription pass) (UntypedPass perform) short long where- perform (Kernels prog) config =- Kernels- <$> runPipeline (onePass inPlaceLoweringKernels) config prog+ perform (GPU prog) config =+ GPU+ <$> runPipeline (onePass inPlaceLoweringGPU) config prog perform (Seq prog) config = Seq <$> runPipeline (onePass inPlaceLoweringSeq) config prog@@ -315,16 +317,16 @@ where perform (SOACS prog) config = SOACS <$> runPipeline (onePass $ performCSE True) config prog- perform (Kernels prog) config =- Kernels <$> runPipeline (onePass $ performCSE True) config prog+ perform (GPU prog) config =+ GPU <$> runPipeline (onePass $ performCSE True) config prog perform (MC prog) config = MC <$> runPipeline (onePass $ performCSE True) config prog perform (Seq prog) config = Seq <$> runPipeline (onePass $ performCSE True) config prog perform (SeqMem prog) config = SeqMem <$> runPipeline (onePass $ performCSE False) config prog- perform (KernelsMem prog) config =- KernelsMem <$> runPipeline (onePass $ performCSE False) config prog+ perform (GPUMem prog) config =+ GPUMem <$> runPipeline (onePass $ performCSE False) config prog perform (MCMem prog) config = MCMem <$> runPipeline (onePass $ performCSE False) config prog @@ -332,11 +334,11 @@ pass = performCSE True :: Pass SOACS.SOACS SOACS.SOACS pipelineOption ::- (UntypedPassState -> Maybe (Prog fromlore)) ->+ (UntypedPassState -> Maybe (Prog fromrep)) -> String ->- (Prog tolore -> UntypedPassState) ->+ (Prog torep -> UntypedPassState) -> String ->- Pipeline fromlore tolore ->+ Pipeline fromrep torep -> String -> [String] -> FutharkOption@@ -413,7 +415,7 @@ ["compile-imperative-kernels"] ( NoArg $ Right $ \opts ->- opts {futharkAction = KernelsMemAction $ const kernelImpCodeGenAction}+ opts {futharkAction = GPUMemAction $ const kernelImpCodeGenAction} ) "Translate program into the imperative IL with kernels and write it on standard output.", Option@@ -429,7 +431,7 @@ ["compile-opencl"] ( NoArg $ Right $ \opts ->- opts {futharkAction = KernelsMemAction $ compileOpenCLAction newFutharkConfig ToExecutable}+ opts {futharkAction = GPUMemAction $ compileOpenCLAction newFutharkConfig ToExecutable} ) "Compile the program using the OpenCL backend.", Option@@ -503,14 +505,15 @@ soacsPassOption inlineFunctions [], kernelsPassOption babysitKernels [], kernelsPassOption tileLoops [],- kernelsPassOption unstreamKernels [],- kernelsPassOption sinkKernels [],- typedPassOption soacsProg Kernels extractKernels [],+ kernelsPassOption unstreamGPU [],+ kernelsPassOption sinkGPU [],+ typedPassOption soacsProg GPU extractKernels [], typedPassOption soacsProg MC extractMulticore [], iplOption [], allocateOption "a",- kernelsMemPassOption doubleBufferKernels [],+ kernelsMemPassOption doubleBufferGPU [], kernelsMemPassOption expandAllocations [],+ kernelsMemPassOption ReuseAllocations.optimise [], cseOption [], simplifyOption "e", soacsPipelineOption@@ -520,23 +523,23 @@ ["standard"], pipelineOption getSOACSProg- "Kernels"- Kernels+ "GPU"+ GPU "Run the default optimised kernels pipeline" kernelsPipeline [] ["kernels"], pipelineOption getSOACSProg- "KernelsMem"- KernelsMem+ "GPUMem"+ GPUMem "Run the full GPU compilation pipeline" gpuPipeline [] ["gpu"], pipelineOption getSOACSProg- "KernelsMem"+ "GPUMem" SeqMem "Run the sequential CPU compilation pipeline" sequentialCpuPipeline@@ -637,7 +640,10 @@ input <- liftIO $ T.readFile file case parse file input of Left err -> externalErrorS $ T.unpack err- Right prog -> runPolyPasses config base $ construct prog+ Right prog ->+ case checkProg $ Alias.aliasAnalysis prog of+ Left err -> externalErrorS $ show err+ Right () -> runPolyPasses config base $ construct prog handlers = [ ( ".fut",@@ -648,8 +654,8 @@ (".fut_soacs", readCore parseSOACS SOACS), (".fut_seq", readCore parseSeq Seq), (".fut_seq_mem", readCore parseSeqMem SeqMem),- (".fut_kernels", readCore parseKernels Kernels),- (".fut_kernels_mem", readCore parseKernelsMem KernelsMem),+ (".fut_kernels", readCore parseGPU GPU),+ (".fut_kernels_mem", readCore parseGPUMem GPUMem), (".fut_mc", readCore parseMC MC), (".fut_mc_mem", readCore parseMCMem MCMem) ]@@ -675,23 +681,23 @@ case (end_prog, futharkAction config) of (SOACS prog, SOACSAction action) -> actionProcedure action prog- (Kernels prog, KernelsAction action) ->+ (GPU prog, GPUAction action) -> actionProcedure action prog (SeqMem prog, SeqMemAction action) -> actionProcedure (action base) prog- (KernelsMem prog, KernelsMemAction action) ->+ (GPUMem prog, GPUMemAction action) -> actionProcedure (action base) prog (MCMem prog, MCMemAction action) -> actionProcedure (action base) prog (SOACS soacs_prog, PolyAction acs) -> actionProcedure acs soacs_prog- (Kernels kernels_prog, PolyAction acs) ->+ (GPU kernels_prog, PolyAction acs) -> actionProcedure acs kernels_prog (MC mc_prog, PolyAction acs) -> actionProcedure acs mc_prog (Seq seq_prog, PolyAction acs) -> actionProcedure acs seq_prog- (KernelsMem mem_prog, PolyAction acs) ->+ (GPUMem mem_prog, PolyAction acs) -> actionProcedure acs mem_prog (SeqMem mem_prog, PolyAction acs) -> actionProcedure acs mem_prog
src/Futhark/CLI/Literate.hs view
@@ -27,6 +27,7 @@ import qualified Data.Vector.Storable.ByteString as SVec import Data.Void import Data.Word (Word32, Word8)+import Futhark.Data import Futhark.Script import Futhark.Server import Futhark.Test@@ -345,19 +346,19 @@ in fromIntegral c :: Word8 valueToBMP :: Value -> Maybe LBS.ByteString-valueToBMP v@(Word32Value _ bytes)+valueToBMP v@(U32Value _ bytes) | [h, w] <- valueShape v = Just $ vecToBMP h w bytes-valueToBMP v@(Int32Value _ bytes)+valueToBMP v@(I32Value _ bytes) | [h, w] <- valueShape v = Just $ vecToBMP h w $ SVec.map fromIntegral bytes-valueToBMP v@(Float32Value _ bytes)+valueToBMP v@(F32Value _ bytes) | [h, w] <- valueShape v = Just $ vecToBMP h w $ greyFloatToImg bytes-valueToBMP v@(Word8Value _ bytes)+valueToBMP v@(U8Value _ bytes) | [h, w] <- valueShape v = Just $ vecToBMP h w $ greyByteToImg bytes-valueToBMP v@(Float64Value _ bytes)+valueToBMP v@(F64Value _ bytes) | [h, w] <- valueShape v = Just $ vecToBMP h w $ greyFloatToImg bytes valueToBMP v@(BoolValue _ bytes)@@ -454,7 +455,7 @@ b = fromIntegral $ bmp_bs `BS.index` (l' * 4 + 2) a = fromIntegral $ bmp_bs `BS.index` (l' * 4 + 3) in (a `shiftL` 24) .|. (r `shiftL` 16) .|. (g `shiftL` 8) .|. b- pure $ ValueAtom $ Word32Value shape $ SVec.generate (w * h) pix+ pure $ ValueAtom $ U32Value shape $ SVec.generate (w * h) pix loadImage :: FilePath -> ScriptM (Compound Value) loadImage imgfile =@@ -878,8 +879,9 @@ let mdfile = fromMaybe (prog `replaceExtension` "md") $ scriptOutput opts imgdir = dropExtension mdfile <> "-img" run_options = scriptExtraOptions opts+ cfg = futharkServerCfg ("." </> dropExtension prog) run_options - withScriptServer ("." </> dropExtension prog) run_options $ \server -> do+ withScriptServer cfg $ \server -> do let env = Env { envServer = server,
src/Futhark/CLI/Pkg.hs view
@@ -344,7 +344,16 @@ [p] -> Just $ runPkgM cfg $ doCreate' $ T.pack p _ -> Nothing where+ validPkgPath p =+ not $ any (`elem` [".", ".."]) $ splitDirectories $ T.unpack p+ doCreate' p = do+ unless (validPkgPath p) . liftIO $ do+ T.putStrLn $ "Not a valid package path: " <> p+ T.putStrLn "Note: package paths are usually URIs."+ T.putStrLn "Note: 'futhark init' is only needed when creating a package, not to use packages."+ exitFailure+ exists <- liftIO $ (||) <$> doesFileExist futharkPkg <*> doesDirectoryExist futharkPkg when exists $ liftIO $ do
src/Futhark/CLI/Test.hs view
@@ -23,7 +23,6 @@ import Futhark.Util (atMostChars, fancyTerminal) import Futhark.Util.Console import Futhark.Util.Options-import Futhark.Util.Pretty (prettyText) import Futhark.Util.Table import System.Console.ANSI import qualified System.Console.Terminal.Size as Terminal@@ -97,7 +96,7 @@ "Running " <> T.pack (unwords $ binpath : extra_options) context prog_ctx $- pureTestResults $ liftIO $ withServer to_run to_run_args f+ pureTestResults $ liftIO $ withServer (futharkServerCfg to_run to_run_args) f data TestCase = TestCase { _testCaseMode :: TestMode,@@ -185,7 +184,7 @@ runInterpretedCase run@(TestRun _ inputValues _ index _) = unless (any (`elem` runTags run) ["compiled", "script"]) $ context ("Entry point: " <> entry <> "; dataset: " <> T.pack (runDescription run)) $ do- input <- T.unlines . map prettyText <$> getValues (FutharkExe futhark) dir inputValues+ input <- T.unlines . map valueText <$> getValues (FutharkExe futhark) dir inputValues expectedResult' <- getExpectedResult (FutharkExe futhark) program entry run (code, output, err) <- liftIO $@@ -271,12 +270,16 @@ runCompiledEntry :: FutharkExe -> Server -> FilePath -> InputOutputs -> IO [TestResult] runCompiledEntry futhark server program (InputOutputs entry run_cases) = do- Right output_types <- cmdOutputs server entry- Right input_types <- cmdInputs server entry- let outs = ["out" <> T.pack (show i) | i <- [0 .. length output_types -1]]- ins = ["in" <> T.pack (show i) | i <- [0 .. length input_types -1]]- onRes = either (Failure . pure) (const Success)- mapM (fmap onRes . runCompiledCase input_types outs ins) run_cases+ output_types <- cmdOutputs server entry+ input_types <- cmdInputs server entry+ case (,) <$> output_types <*> input_types of+ Left (CmdFailure _ err) ->+ pure [Failure err]+ Right (output_types', input_types') -> do+ let outs = ["out" <> T.pack (show i) | i <- [0 .. length output_types' -1]]+ ins = ["in" <> T.pack (show i) | i <- [0 .. length input_types' -1]]+ onRes = either (Failure . pure) (const Success)+ mapM (fmap onRes . runCompiledCase input_types' outs ins) run_cases where dir = takeDirectory program @@ -289,7 +292,7 @@ context1 case_ctx $ do expected <- getExpectedResult futhark program entry run - valuesAsVars server (zip ins input_types) futhark dir input_spec+ valuesAsVars server (zip ins (map inputType input_types)) futhark dir input_spec call_r <- liftIO $ cmdCall server entry outs ins liftCommand $ cmdFree server ins@@ -299,7 +302,7 @@ pure $ ErrorResult $ T.unlines err Right _ -> SuccessResult- <$> readResults server outs program+ <$> readResults server outs <* liftCommand (cmdFree server outs) compareResult entry index program expected res
src/Futhark/CodeGen/Backends/CCUDA.hs view
@@ -20,7 +20,7 @@ import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.ImpCode.OpenCL import qualified Futhark.CodeGen.ImpGen.CUDA as ImpGen-import Futhark.IR.KernelsMem hiding+import Futhark.IR.GPUMem hiding ( CmpSizeLe, GetSize, GetSizeMax,@@ -29,7 +29,7 @@ import qualified Language.C.Quote.OpenCL as C -- | Compile the program to C with calls to CUDA.-compileProg :: MonadFreshNames m => Prog KernelsMem -> m (ImpGen.Warnings, GC.CParts)+compileProg :: MonadFreshNames m => Prog GPUMem -> m (ImpGen.Warnings, GC.CParts) compileProg prog = do (ws, Program cuda_code cuda_prelude kernels _ sizes failures prog') <- ImpGen.compileProg prog
src/Futhark/CodeGen/Backends/COpenCL.hs view
@@ -19,7 +19,7 @@ import Futhark.CodeGen.Backends.GenericC.Options import Futhark.CodeGen.ImpCode.OpenCL import qualified Futhark.CodeGen.ImpGen.OpenCL as ImpGen-import Futhark.IR.KernelsMem hiding+import Futhark.IR.GPUMem hiding ( CmpSizeLe, GetSize, GetSizeMax,@@ -29,7 +29,7 @@ import qualified Language.C.Syntax as C -- | Compile the program to C with calls to OpenCL.-compileProg :: MonadFreshNames m => Prog KernelsMem -> m (ImpGen.Warnings, GC.CParts)+compileProg :: MonadFreshNames m => Prog GPUMem -> m (ImpGen.Warnings, GC.CParts) compileProg prog = do ( ws, Program
src/Futhark/CodeGen/Backends/GenericC.hs view
@@ -99,9 +99,17 @@ import qualified Language.C.Quote.OpenCL as C import qualified Language.C.Syntax as C +-- How public an array type definition sould be. Public types show up+-- in the generated API, while private types are used only to+-- implement the members of opaques.+data Publicness = Private | Public+ deriving (Eq, Ord, Show)++type ArrayType = (Space, Signedness, PrimType, Int)+ data CompilerState s = CompilerState- { compArrayStructs :: [((C.Type, Int), (C.Type, [C.Definition]))],- compOpaqueStructs :: [(String, (C.Type, [C.Definition]))],+ { compArrayTypes :: M.Map ArrayType Publicness,+ compOpaqueTypes :: M.Map String [ValueDesc], compEarlyDecls :: DL.DList C.Definition, compInit :: [C.Stm], compNameSrc :: VNameSource,@@ -118,8 +126,8 @@ newCompilerState :: VNameSource -> s -> CompilerState s newCompilerState src s = CompilerState- { compArrayStructs = [],- compOpaqueStructs = [],+ { compArrayTypes = mempty,+ compOpaqueTypes = mempty, compEarlyDecls = mempty, compInit = [], compNameSrc = src,@@ -318,10 +326,6 @@ envFatMemory :: CompilerEnv op s -> Bool envFatMemory = opsFatMemory . envOperations -arrayDefinitions, opaqueDefinitions :: CompilerState s -> [C.Definition]-arrayDefinitions = concatMap (snd . snd) . compArrayStructs-opaqueDefinitions = concatMap (snd . snd) . compOpaqueStructs- 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@@ -795,14 +799,14 @@ |] arrayLibraryFunctions ::+ Publicness -> Space -> PrimType -> Signedness ->- [DimSize] ->+ Int -> CompilerM op s [C.Definition]-arrayLibraryFunctions space pt signed shape = do- let rank = length shape- pt' = signedPrimTypeToCType signed pt+arrayLibraryFunctions pub space pt signed rank = do+ let pt' = signedPrimTypeToCType signed pt name = arrayName pt signed rank arr_name = "futhark_" ++ name array_type = [C.cty|struct $id:arr_name|]@@ -871,26 +875,23 @@ ctx_ty <- contextType ops <- asks envOperations - headerDecl- (ArrayDecl name)+ let proto = case pub of+ Public -> headerDecl (ArrayDecl name)+ Private -> libDecl++ proto [C.cedecl|struct $id:arr_name;|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|$ty:array_type* $id:new_array($ty:ctx_ty *ctx, const $ty:pt' *data, $params:shape_params);|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|$ty:array_type* $id:new_raw_array($ty:ctx_ty *ctx, const $ty:memty data, int offset, $params:shape_params);|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|int $id:free_array($ty:ctx_ty *ctx, $ty:array_type *arr);|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|int $id:values_array($ty:ctx_ty *ctx, $ty:array_type *arr, $ty:pt' *data);|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|$ty:memty $id:values_raw_array($ty:ctx_ty *ctx, $ty:array_type *arr);|]- headerDecl- (ArrayDecl name)+ proto [C.cedecl|const typename int64_t* $id:shape_array($ty:ctx_ty *ctx, $ty:array_type *arr);|] return@@ -1033,6 +1034,9 @@ headerDecl (OpaqueDecl desc)+ [C.cedecl|struct $id:name;|]+ headerDecl+ (OpaqueDecl desc) [C.cedecl|int $id:free_opaque($ty:ctx_ty *ctx, $ty:opaque_type *obj);|] headerDecl (OpaqueDecl desc)@@ -1076,53 +1080,47 @@ } |] -valueDescToCType :: ValueDesc -> CompilerM op s C.Type-valueDescToCType (ScalarValue pt signed _) =+valueDescToCType :: Publicness -> ValueDesc -> CompilerM op s C.Type+valueDescToCType _ (ScalarValue pt signed _) = return $ signedPrimTypeToCType signed pt-valueDescToCType (ArrayValue mem space pt signed shape) = do- let pt' = signedPrimTypeToCType signed pt- rank = length shape- exists <- gets $ lookup (pt', rank) . compArrayStructs- case exists of- Just (cty, _) -> return cty- Nothing -> do- memty <- memToCType mem space- name <- publicName $ arrayName pt signed rank- let struct = [C.cedecl|struct $id:name { $ty:memty mem; typename int64_t shape[$int:rank]; };|]- stype = [C.cty|struct $id:name|]- library <- arrayLibraryFunctions space pt signed shape- modify $ \s ->- s- { compArrayStructs =- ((pt', rank), (stype, struct : library)) : compArrayStructs s- }- return stype+valueDescToCType pub (ArrayValue _ space pt signed shape) = do+ let rank = length shape+ name <- publicName $ arrayName pt signed rank+ let add = M.insertWith max (space, signed, pt, rank) pub+ modify $ \s -> s {compArrayTypes = add $ compArrayTypes s}+ pure [C.cty|struct $id:name|] opaqueToCType :: String -> [ValueDesc] -> CompilerM op s C.Type opaqueToCType desc vds = do name <- publicName $ opaqueName desc vds- exists <- gets $ lookup name . compOpaqueStructs- case exists of- Just (ty, _) -> return ty- Nothing -> do- members <- zipWithM field vds [(0 :: Int) ..]- let struct = [C.cedecl|struct $id:name { $sdecls:members };|]- stype = [C.cty|struct $id:name|]- headerDecl (OpaqueDecl desc) [C.cedecl|struct $id:name;|]- library <- opaqueLibraryFunctions desc vds- modify $ \s ->- s- { compOpaqueStructs =- (name, (stype, struct : library)) :- compOpaqueStructs s- }- return stype+ let add = M.insert desc vds+ modify $ \s -> s {compOpaqueTypes = add $ compOpaqueTypes s}+ -- Now ensure that the constituent array types will exist.+ mapM_ (valueDescToCType Private) vds+ pure [C.cty|struct $id:name|]++generateAPITypes :: CompilerM op s ()+generateAPITypes = do+ mapM_ generateArray . M.toList =<< gets compArrayTypes+ mapM_ generateOpaque . M.toList =<< gets compOpaqueTypes where+ generateArray ((space, signed, pt, rank), pub) = do+ name <- publicName $ arrayName pt signed rank+ let memty = fatMemType space+ libDecl [C.cedecl|struct $id:name { $ty:memty mem; typename int64_t shape[$int:rank]; };|]+ mapM libDecl =<< arrayLibraryFunctions pub space pt signed rank++ generateOpaque (desc, vds) = do+ name <- publicName $ opaqueName desc vds+ members <- zipWithM field vds [(0 :: Int) ..]+ libDecl [C.cedecl|struct $id:name { $sdecls:members };|]+ mapM libDecl =<< opaqueLibraryFunctions desc vds+ field vd@ScalarValue {} i = do- ct <- valueDescToCType vd+ ct <- valueDescToCType Private vd return [C.csdecl|$ty:ct $id:(tupleField i);|] field vd i = do- ct <- valueDescToCType vd+ ct <- valueDescToCType Private vd return [C.csdecl|$ty:ct *$id:(tupleField i);|] allTrue :: [C.Exp] -> C.Exp@@ -1136,35 +1134,35 @@ prepareEntryInputs args = collect' $ zipWithM prepare [(0 :: Int) ..] args where arg_names = namesFromList $ concatMap evNames args- evNames (OpaqueValue _ vds) = map vdName vds- evNames (TransparentValue vd) = [vdName vd]+ evNames (OpaqueValue _ _ vds) = map vdName vds+ evNames (TransparentValue _ vd) = [vdName vd] vdName (ArrayValue v _ _ _ _) = v vdName (ScalarValue _ _ v) = v - prepare pno (TransparentValue vd) = do+ prepare pno (TransparentValue _ vd) = do let pname = "in" ++ show pno- (ty, check) <- prepareValue [C.cexp|$id:pname|] vd+ (ty, check) <- prepareValue Public [C.cexp|$id:pname|] vd return ( [C.cparam|const $ty:ty $id:pname|], allTrue check )- prepare pno (OpaqueValue desc vds) = do+ prepare pno (OpaqueValue _ desc vds) = do ty <- opaqueToCType desc vds let pname = "in" ++ show pno field i ScalarValue {} = [C.cexp|$id:pname->$id:(tupleField i)|] field i ArrayValue {} = [C.cexp|$id:pname->$id:(tupleField i)|]- checks <- map snd <$> zipWithM prepareValue (zipWith field [0 ..] vds) vds+ checks <- map snd <$> zipWithM (prepareValue Private) (zipWith field [0 ..] vds) vds return ( [C.cparam|const $ty:ty *$id:pname|], allTrue $ concat checks ) - prepareValue src (ScalarValue pt signed name) = do+ prepareValue _ src (ScalarValue pt signed name) = do let pt' = signedPrimTypeToCType signed pt stm [C.cstm|$id:name = $exp:src;|] return (pt', [])- prepareValue src vd@(ArrayValue mem _ _ _ shape) = do- ty <- valueDescToCType vd+ prepareValue pub src vd@(ArrayValue mem _ _ _ shape) = do+ ty <- valueDescToCType pub vd stm [C.cstm|$exp:mem = $exp:src->mem;|] @@ -1188,9 +1186,9 @@ prepareEntryOutputs :: [ExternalValue] -> CompilerM op s ([C.Param], [C.BlockItem]) prepareEntryOutputs = collect' . zipWithM prepare [(0 :: Int) ..] where- prepare pno (TransparentValue vd) = do+ prepare pno (TransparentValue _ vd) = do let pname = "out" ++ show pno- ty <- valueDescToCType vd+ ty <- valueDescToCType Public vd case vd of ArrayValue {} -> do@@ -1200,10 +1198,10 @@ ScalarValue {} -> do prepareValue [C.cexp|*$id:pname|] vd return [C.cparam|$ty:ty *$id:pname|]- prepare pno (OpaqueValue desc vds) = do+ prepare pno (OpaqueValue _ desc vds) = do let pname = "out" ++ show pno ty <- opaqueToCType desc vds- vd_ts <- mapM valueDescToCType vds+ vd_ts <- mapM (valueDescToCType Private) vds stm [C.cstm|assert((*$id:pname = ($ty:ty*) malloc(sizeof($ty:ty))) != NULL);|] @@ -1338,7 +1336,12 @@ disableWarnings = pretty [C.cunit|-$esc:("#ifdef __GNUC__")+$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\"")@@ -1346,12 +1349,6 @@ $esc:("#pragma GCC diagnostic ignored \"-Wunused-but-set-variable\"") $esc:("#endif") -$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:("#endif") |] -- | Produce header and implementation files.@@ -1467,11 +1464,7 @@ $edecls:lib_decls -$edecls:(map funcToDef definitions)--$edecls:(arrayDefinitions endstate)--$edecls:(opaqueDefinitions endstate)+$edecls:definitions $edecls:entry_point_decls |]@@ -1495,7 +1488,7 @@ ctx_ty <- contextType - (prototypes, definitions) <-+ (prototypes, functions) <- unzip <$> mapM (compileFun get_consts [[C.cparam|$ty:ctx_ty *ctx|]]) funs mapM_ earlyDecl memstructs@@ -1508,7 +1501,7 @@ commonLibFuns memreport - return (prototypes, definitions, entry_points)+ return (prototypes, map funcToDef functions, entry_points) funcToDef func = C.FuncDef func loc where@@ -1527,6 +1520,7 @@ commonLibFuns :: [C.BlockItem] -> CompilerM op s () commonLibFuns memreport = do+ generateAPITypes ctx <- contextType ops <- asks envOperations profilereport <- gets $ DL.toList . compProfileItems
src/Futhark/CodeGen/Backends/GenericC/CLI.hs view
@@ -156,8 +156,8 @@ in [C.cty|struct $id:name|] externalValueToCType :: ExternalValue -> C.Type-externalValueToCType (TransparentValue vd) = valueDescToCType vd-externalValueToCType (OpaqueValue desc vds) = opaqueToCType desc vds+externalValueToCType (TransparentValue _ vd) = valueDescToCType vd+externalValueToCType (OpaqueValue _ desc vds) = opaqueToCType desc vds primTypeInfo :: PrimType -> Signedness -> C.Exp primTypeInfo (IntType it) t = case (it, t) of@@ -184,14 +184,14 @@ }|] readInput :: Int -> ExternalValue -> ([C.BlockItem], C.Stm, C.Stm, C.Stm, C.Exp)-readInput i (OpaqueValue desc _) =+readInput i (OpaqueValue _ desc _) = ( [C.citems|futhark_panic(1, "Cannot read input #%d of type %s\n", $int:i, $string:desc);|], [C.cstm|;|], [C.cstm|;|], [C.cstm|;|], [C.cexp|NULL|] )-readInput i (TransparentValue (ScalarValue t ept _)) =+readInput i (TransparentValue _ (ScalarValue t ept _)) = let dest = "read_value_" ++ show i in ( [C.citems|$ty:(primTypeToCType t) $id:dest; $stm:(readPrimStm dest i t ept);|],@@ -200,7 +200,7 @@ [C.cstm|;|], [C.cexp|$id:dest|] )-readInput i (TransparentValue (ArrayValue _ _ t ept dims)) =+readInput i (TransparentValue _ (ArrayValue _ _ t ept dims)) = let dest = "read_value_" ++ show i shape = "read_shape_" ++ show i arr = "read_arr_" ++ show i@@ -252,19 +252,19 @@ result = "result_" ++ show i case ev of- TransparentValue ScalarValue {} ->+ TransparentValue _ ScalarValue {} -> ( [C.citem|$ty:ty $id:result;|], [C.cexp|$id:result|], [C.cstm|;|] )- TransparentValue (ArrayValue _ _ t ept dims) ->+ TransparentValue _ (ArrayValue _ _ t ept dims) -> let name = arrayName t ept $ length dims free_array = "futhark_free_" ++ name in ( [C.citem|$ty:ty *$id:result;|], [C.cexp|$id:result|], [C.cstm|assert($id:free_array(ctx, $id:result) == 0);|] )- OpaqueValue desc vds ->+ OpaqueValue _ desc vds -> let free_opaque = "futhark_free_" ++ opaqueName desc vds in ( [C.citem|$ty:ty *$id:result;|], [C.cexp|$id:result|],@@ -277,11 +277,11 @@ -- | Return a statement printing the given external value. printStm :: ExternalValue -> C.Exp -> C.Stm-printStm (OpaqueValue desc _) _ =+printStm (OpaqueValue _ desc _) _ = [C.cstm|printf("#<opaque %s>", $string:desc);|]-printStm (TransparentValue (ScalarValue bt ept _)) e =+printStm (TransparentValue _ (ScalarValue bt ept _)) e = printPrimStm [C.cexp|stdout|] e bt ept-printStm (TransparentValue (ArrayValue _ _ bt ept shape)) e =+printStm (TransparentValue _ (ArrayValue _ _ bt ept shape)) e = let values_array = "futhark_values_" ++ name shape_array = "futhark_shape_" ++ name num_elems = cproduct [[C.cexp|$id:shape_array(ctx, $exp:e)[$int:i]|] | i <- [0 .. rank -1]]
src/Futhark/CodeGen/Backends/GenericC/Server.hs view
@@ -101,22 +101,22 @@ ] typeStructName :: ExternalValue -> String-typeStructName (TransparentValue (ScalarValue pt signed _)) =+typeStructName (TransparentValue _ (ScalarValue pt signed _)) = let name = prettySigned (signed == TypeUnsigned) pt in "type_" ++ name-typeStructName (TransparentValue (ArrayValue _ _ pt signed shape)) =+typeStructName (TransparentValue _ (ArrayValue _ _ pt signed shape)) = let rank = length shape name = arrayName pt signed rank in "type_" ++ name-typeStructName (OpaqueValue name vds) =+typeStructName (OpaqueValue _ name vds) = "type_" ++ opaqueName name vds valueDescBoilerplate :: ExternalValue -> (String, (C.Initializer, [C.Definition]))-valueDescBoilerplate ev@(TransparentValue (ScalarValue pt signed _)) =+valueDescBoilerplate ev@(TransparentValue _ (ScalarValue pt signed _)) = let name = prettySigned (signed == TypeUnsigned) pt type_name = typeStructName ev in (name, ([C.cinit|&$id:type_name|], mempty))-valueDescBoilerplate ev@(TransparentValue (ArrayValue _ _ pt signed shape)) =+valueDescBoilerplate ev@(TransparentValue _ (ArrayValue _ _ pt signed shape)) = let rank = length shape name = arrayName pt signed rank pt_name = prettySigned (signed == TypeUnsigned) pt@@ -156,7 +156,7 @@ };|] ) )-valueDescBoilerplate ev@(OpaqueValue name vds) =+valueDescBoilerplate ev@(OpaqueValue _ name vds) = let type_name = typeStructName ev aux_name = type_name ++ "_aux" opaque_free = "futhark_free_" ++ opaqueName name vds@@ -199,6 +199,8 @@ in_types = functionArgs fun out_types_name = pretty name ++ "_out_types" in_types_name = pretty name ++ "_in_types"+ out_unique_name = pretty name ++ "_out_unique"+ in_unique_name = pretty name ++ "_in_unique" (out_items, out_args) | null out_types = ([C.citems|(void)outs;|], mempty) | otherwise = unzip $ zipWith loadOut [0 ..] out_types@@ -211,10 +213,16 @@ $inits:(map typeStructInit out_types), NULL };+ bool $id:out_unique_name[] = {+ $inits:(map typeUniqueInit out_types)+ }; struct type* $id:in_types_name[] = { $inits:(map typeStructInit in_types), NULL };+ bool $id:in_unique_name[] = {+ $inits:(map typeUniqueInit in_types)+ }; int $id:call_f(struct futhark_context *ctx, void **outs, void **ins) { $items:out_items $items:in_items@@ -225,11 +233,20 @@ .name = $string:(pretty ename), .f = $id:call_f, .in_types = $id:in_types_name,- .out_types = $id:out_types_name+ .out_types = $id:out_types_name,+ .in_unique = $id:in_unique_name,+ .out_unique = $id:out_unique_name }|] ) where typeStructInit t = [C.cinit|&$id:(typeStructName t)|]+ typeUniqueInit t =+ case typeUnique t of+ Unique -> [C.cinit|true|]+ Nonunique -> [C.cinit|false|]++ typeUnique (TransparentValue u _) = u+ typeUnique (OpaqueValue u _ _) = u loadOut i ev = let v = "out" ++ show (i :: Int)
src/Futhark/CodeGen/Backends/GenericPython.hs view
@@ -59,6 +59,7 @@ import Futhark.IR.Syntax (Space (..)) import Futhark.MonadFreshNames import Futhark.Util (zEncodeString)+import Futhark.Util.Pretty (pretty) -- | A substitute expression compiler, tried before the main -- compilation function.@@ -330,7 +331,7 @@ filter (isJust . Imp.functionEntry . snd) funs where evd Imp.TransparentValue {} = mempty- evd (Imp.OpaqueValue name vds) =+ evd (Imp.OpaqueValue _ name vds) = M.singleton name $ map (String . vd) vds vd (Imp.ScalarValue pt s _) = readTypeEnum pt s@@ -538,18 +539,18 @@ ] entryPointOutput :: Imp.ExternalValue -> CompilerM op s PyExp-entryPointOutput (Imp.OpaqueValue desc vs) =+entryPointOutput (Imp.OpaqueValue u desc vs) = simpleCall "opaque" . (String (pretty desc) :)- <$> mapM (entryPointOutput . Imp.TransparentValue) vs-entryPointOutput (Imp.TransparentValue (Imp.ScalarValue bt ept name)) = do+ <$> mapM (entryPointOutput . Imp.TransparentValue u) vs+entryPointOutput (Imp.TransparentValue _ (Imp.ScalarValue bt ept name)) = do name' <- compileVar name return $ simpleCall tf [name'] where tf = compilePrimToExtNp bt ept-entryPointOutput (Imp.TransparentValue (Imp.ArrayValue mem (Imp.Space sid) bt ept dims)) = do+entryPointOutput (Imp.TransparentValue _ (Imp.ArrayValue mem (Imp.Space sid) bt ept dims)) = do pack_output <- asks envEntryOutput pack_output mem sid bt ept dims-entryPointOutput (Imp.TransparentValue (Imp.ArrayValue mem _ bt ept dims)) = do+entryPointOutput (Imp.TransparentValue _ (Imp.ArrayValue mem _ bt ept dims)) = do mem' <- compileVar mem let cast = Cast mem' (compilePrimTypeExt bt ept) dims' <- mapM compileDim dims@@ -615,14 +616,14 @@ declEntryPointInputSizes :: [Imp.ExternalValue] -> CompilerM op s () declEntryPointInputSizes = mapM_ onSize . concatMap sizes where- sizes (Imp.TransparentValue v) = valueSizes v- sizes (Imp.OpaqueValue _ vs) = concatMap valueSizes vs+ sizes (Imp.TransparentValue _ v) = valueSizes v+ sizes (Imp.OpaqueValue _ _ vs) = concatMap valueSizes vs valueSizes (Imp.ArrayValue _ _ _ _ dims) = subExpVars dims valueSizes Imp.ScalarValue {} = [] onSize v = stm $ Assign (Var (compileName v)) None entryPointInput :: (Int, Imp.ExternalValue, PyExp) -> CompilerM op s ()-entryPointInput (i, Imp.OpaqueValue desc vs, e) = do+entryPointInput (i, Imp.OpaqueValue u desc vs, e) = do let type_is_ok = BinOp "and"@@ -630,9 +631,9 @@ (BinOp "==" (Field e "desc") (String desc)) stm $ If (UnOp "not" type_is_ok) [badInput i e desc] [] mapM_ entryPointInput $- zip3 (repeat i) (map Imp.TransparentValue vs) $+ zip3 (repeat i) (map (Imp.TransparentValue u) vs) $ map (Index (Field e "data") . IdxExp . Integer) [0 ..]-entryPointInput (i, Imp.TransparentValue (Imp.ScalarValue bt s name), e) = do+entryPointInput (i, Imp.TransparentValue _ (Imp.ScalarValue bt s name), e) = do vname' <- compileVar name let -- HACK: A Numpy int64 will signal an OverflowError if we pass -- it a number bigger than 2**63. This does not happen if we@@ -650,7 +651,7 @@ (Tuple [Var "TypeError", Var "AssertionError"]) [badInput i e $ prettySigned (s == Imp.TypeUnsigned) bt] ]-entryPointInput (i, Imp.TransparentValue (Imp.ArrayValue mem (Imp.Space sid) bt ept dims), e) = do+entryPointInput (i, Imp.TransparentValue _ (Imp.ArrayValue mem (Imp.Space sid) bt ept dims), e) = do unpack_input <- asks envEntryInput mem' <- compileVar mem unpack <- collect $ unpack_input mem' sid bt ept dims e@@ -664,7 +665,7 @@ ++ prettySigned (ept == Imp.TypeUnsigned) bt ] ]-entryPointInput (i, Imp.TransparentValue (Imp.ArrayValue mem _ t s dims), e) = do+entryPointInput (i, Imp.TransparentValue _ (Imp.ArrayValue mem _ t s dims), e) = do let type_is_wrong = UnOp "not" $ BinOp "in" (simpleCall "type" [e]) $ List [Var "np.ndarray"] let dtype_is_wrong = UnOp "not" $ BinOp "==" (Field e "dtype") $ Var $ compilePrimToExtNp t s let dim_is_wrong = UnOp "not" $ BinOp "==" (Field e "ndim") $ Integer $ toInteger $ length dims@@ -700,9 +701,9 @@ stm $ Assign dest unwrap_call extValueDescName :: Imp.ExternalValue -> String-extValueDescName (Imp.TransparentValue v) = extName $ valueDescName v-extValueDescName (Imp.OpaqueValue desc []) = extName $ zEncodeString desc-extValueDescName (Imp.OpaqueValue desc (v : _)) =+extValueDescName (Imp.TransparentValue _ v) = extName $ valueDescName v+extValueDescName (Imp.OpaqueValue _ desc []) = extName $ zEncodeString desc+extValueDescName (Imp.OpaqueValue _ desc (v : _)) = extName $ zEncodeString desc ++ "_" ++ pretty (baseTag (valueDescVName v)) extName :: String -> String@@ -731,15 +732,15 @@ readTypeEnum Unit _ = "bool" readInput :: Imp.ExternalValue -> PyStmt-readInput (Imp.OpaqueValue desc _) =+readInput (Imp.OpaqueValue _ desc _) = Raise $ simpleCall "Exception" [String $ "Cannot read argument of type " ++ desc ++ "."]-readInput decl@(Imp.TransparentValue (Imp.ScalarValue bt ept _)) =+readInput decl@(Imp.TransparentValue _ (Imp.ScalarValue bt ept _)) = let type_name = readTypeEnum bt ept in Assign (Var $ extValueDescName decl) $ simpleCall "read_value" [String type_name]-readInput decl@(Imp.TransparentValue (Imp.ArrayValue _ _ bt ept dims)) =+readInput decl@(Imp.TransparentValue _ (Imp.ArrayValue _ _ bt ept dims)) = let type_name = readTypeEnum bt ept in Assign (Var $ extValueDescName decl) $ simpleCall@@ -754,17 +755,17 @@ -- that returns an equivalent Numpy array. This works for PyOpenCL, -- but we will probably need yet another plugin mechanism here in -- the future.- printValue' (Imp.OpaqueValue desc _) _ =+ printValue' (Imp.OpaqueValue _ desc _) _ = return [ Exp $ simpleCall "sys.stdout.write" [String $ "#<opaque " ++ desc ++ ">"] ]- printValue' (Imp.TransparentValue (Imp.ArrayValue mem (Space _) bt ept shape)) e =- printValue' (Imp.TransparentValue (Imp.ArrayValue mem DefaultSpace bt ept shape)) $+ printValue' (Imp.TransparentValue u (Imp.ArrayValue mem (Space _) bt ept shape)) e =+ printValue' (Imp.TransparentValue u (Imp.ArrayValue mem DefaultSpace bt ept shape)) $ simpleCall (pretty e ++ ".get") []- printValue' (Imp.TransparentValue _) e =+ printValue' (Imp.TransparentValue _ _) e = return [ Exp $ Call@@ -919,10 +920,10 @@ map desc $ Imp.functionResult func ) where- desc (Imp.OpaqueValue d _) = d- desc (Imp.TransparentValue (Imp.ScalarValue pt s _)) = readTypeEnum pt s- desc (Imp.TransparentValue (Imp.ArrayValue _ _ pt s dims)) =- concat (replicate (length dims) "[]") ++ readTypeEnum pt s+ desc (Imp.OpaqueValue u d _) = pretty u <> d+ desc (Imp.TransparentValue u (Imp.ScalarValue pt s _)) = pretty u <> readTypeEnum pt s+ desc (Imp.TransparentValue u (Imp.ArrayValue _ _ pt s dims)) =+ pretty u <> concat (replicate (length dims) "[]") <> readTypeEnum pt s callEntryFun :: [PyStmt] ->
src/Futhark/CodeGen/Backends/MulticoreC.hs view
@@ -647,9 +647,9 @@ atomicOps aop doAtomic ::- (C.ToIdent a1, C.ToIdent a2) =>+ (C.ToIdent a1) => a1 ->- a2 ->+ VName -> Count u (TExp Int32) -> Exp -> String ->@@ -658,15 +658,17 @@ doAtomic old arr ind val op ty = do ind' <- GC.compileExp $ untyped $ unCount ind val' <- GC.compileExp val- GC.stm [C.cstm|$id:old = $id:op(&(($ty:ty*)$id:arr.mem)[$exp:ind'], ($ty:ty) $exp:val', __ATOMIC_RELAXED);|]+ arr' <- GC.rawMem arr+ GC.stm [C.cstm|$id:old = $id:op(&(($ty:ty*)$exp:arr')[$exp:ind'], ($ty:ty) $exp:val', __ATOMIC_RELAXED);|] atomicOps :: AtomicOp -> GC.CompilerM op s () atomicOps (AtomicCmpXchg t old arr ind res val) = do ind' <- GC.compileExp $ untyped $ unCount ind new_val' <- GC.compileExp val let cast = [C.cty|$ty:(GC.primTypeToCType t)*|]+ arr' <- GC.rawMem arr GC.stm- [C.cstm|$id:res = $id:op(&(($ty:cast)$id:arr.mem)[$exp:ind'],+ [C.cstm|$id:res = $id:op(&(($ty:cast)$exp:arr')[$exp:ind'], ($ty:cast)&$id:old, $exp:new_val', 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);|]
src/Futhark/CodeGen/Backends/PyOpenCL.hs view
@@ -15,16 +15,17 @@ import Futhark.CodeGen.Backends.PyOpenCL.Boilerplate import qualified Futhark.CodeGen.ImpCode.OpenCL as Imp import qualified Futhark.CodeGen.ImpGen.OpenCL as ImpGen-import Futhark.IR.KernelsMem (KernelsMem, Prog)+import Futhark.IR.GPUMem (GPUMem, Prog) import Futhark.MonadFreshNames import Futhark.Util (zEncodeString)+import Futhark.Util.Pretty (pretty) -- | Compile the program to Python with calls to OpenCL. compileProg :: MonadFreshNames m => Py.CompilerMode -> String ->- Prog KernelsMem ->+ Prog GPUMem -> m (ImpGen.Warnings, String) compileProg mode class_name prog = do ( ws,
src/Futhark/CodeGen/Backends/PyOpenCL/Boilerplate.hs view
@@ -26,7 +26,7 @@ untyped, ) import Futhark.CodeGen.OpenCL.Heuristics-import Futhark.Util.Pretty (prettyText)+import Futhark.Util.Pretty (pretty, prettyText) import NeatInterpolation (text) errorMsgNumArgs :: ErrorMsg a -> Int
src/Futhark/CodeGen/Backends/SimpleRep.hs view
@@ -127,11 +127,11 @@ -- | The type used to expose a Futhark value in the C API. A pointer -- in the case of arrays and opaques. externalValueType :: ExternalValue -> C.Type-externalValueType (OpaqueValue desc vds) =+externalValueType (OpaqueValue _ desc vds) = [C.cty|struct $id:("futhark_" ++ opaqueName desc vds)*|]-externalValueType (TransparentValue (ArrayValue _ _ pt signed shape)) =+externalValueType (TransparentValue _ (ArrayValue _ _ pt signed shape)) = [C.cty|struct $id:("futhark_" ++ arrayName pt signed (length shape))*|]-externalValueType (TransparentValue (ScalarValue pt signed _)) =+externalValueType (TransparentValue _ (ScalarValue pt signed _)) = signedPrimTypeToCType signed pt -- | Return an expression multiplying together the given expressions.
src/Futhark/CodeGen/ImpCode.hs view
@@ -52,10 +52,11 @@ withElemType, -- * Re-exports from other modules.+ pretty, module Language.Futhark.Core, module Futhark.IR.Primitive, module Futhark.Analysis.PrimExp,- module Futhark.IR.Kernels.Sizes,+ module Futhark.IR.GPU.Sizes, module Futhark.IR.Prop.Names, ) where@@ -65,7 +66,7 @@ import qualified Data.Set as S import Data.Traversable import Futhark.Analysis.PrimExp-import Futhark.IR.Kernels.Sizes (Count (..))+import Futhark.IR.GPU.Sizes (Count (..)) import Futhark.IR.Pretty () import Futhark.IR.Primitive import Futhark.IR.Prop.Names@@ -131,7 +132,7 @@ data Signedness = TypeUnsigned | TypeDirect- deriving (Eq, Show)+ deriving (Eq, Ord, Show) -- | A description of an externally meaningful value. data ValueDesc@@ -144,12 +145,14 @@ -- | ^ An externally visible value. This can be an opaque value -- (covering several physical internal values), or a single value that--- can be used externally.+-- can be used externally. We record the uniqueness because it is+-- important to the external interface as well. data ExternalValue- = -- | The string is a human-readable description- -- with no other semantics.- OpaqueValue String [ValueDesc]- | TransparentValue ValueDesc+ = -- | The string is a human-readable description with no other+ -- semantics.+ -- not matter.+ OpaqueValue Uniqueness String [ValueDesc]+ | TransparentValue Uniqueness ValueDesc deriving (Show) -- | A imperative function, containing the body as well as its@@ -438,9 +441,9 @@ TypeDirect -> mempty instance Pretty ExternalValue where- ppr (TransparentValue v) = ppr v- ppr (OpaqueValue desc vs) =- text "opaque" <+> text desc+ ppr (TransparentValue u v) = ppr u <> ppr v+ ppr (OpaqueValue u desc vs) =+ ppr u <> text "opaque" <+> text desc <+> nestedBlock "{" "}" (stack $ map ppr vs) instance Pretty ArrayContents where@@ -625,8 +628,8 @@ freeIn' ScalarValue {} = mempty instance FreeIn ExternalValue where- freeIn' (TransparentValue vd) = freeIn' vd- freeIn' (OpaqueValue _ vds) = foldMap freeIn' vds+ freeIn' (TransparentValue _ vd) = freeIn' vd+ freeIn' (OpaqueValue _ _ vds) = foldMap freeIn' vds instance FreeIn a => FreeIn (Code a) where freeIn' (x :>>: y) =
+ src/Futhark/CodeGen/ImpCode/GPU.hs view
@@ -0,0 +1,266 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Variation of "Futhark.CodeGen.ImpCode" that contains the notion+-- of a kernel invocation.+module Futhark.CodeGen.ImpCode.GPU+ ( Program,+ Function,+ FunctionT (Function),+ Code,+ KernelCode,+ KernelConst (..),+ KernelConstExp,+ HostOp (..),+ KernelOp (..),+ Fence (..),+ AtomicOp (..),+ Kernel (..),+ KernelUse (..),+ module Futhark.CodeGen.ImpCode,+ module Futhark.IR.GPU.Sizes,+ )+where++import Futhark.CodeGen.ImpCode hiding (Code, Function)+import qualified Futhark.CodeGen.ImpCode as Imp+import Futhark.IR.GPU.Sizes+import Futhark.IR.Pretty ()+import Futhark.Util.Pretty++-- | A program that calls kernels.+type Program = Imp.Definitions HostOp++-- | A function that calls kernels.+type Function = Imp.Function HostOp++-- | Host-level code that can call kernels.+type Code = Imp.Code HostOp++-- | Code inside a kernel.+type KernelCode = Imp.Code KernelOp++-- | A run-time constant related to kernels.+newtype KernelConst = SizeConst Name+ deriving (Eq, Ord, Show)++-- | An expression whose variables are kernel constants.+type KernelConstExp = PrimExp KernelConst++-- | An operation that runs on the host (CPU).+data HostOp+ = CallKernel Kernel+ | GetSize VName Name SizeClass+ | CmpSizeLe VName Name SizeClass Imp.Exp+ | GetSizeMax VName SizeClass+ deriving (Show)++-- | A generic kernel containing arbitrary kernel code.+data Kernel = Kernel+ { kernelBody :: Imp.Code KernelOp,+ -- | The host variables referenced by the kernel.+ kernelUses :: [KernelUse],+ kernelNumGroups :: [Imp.Exp],+ kernelGroupSize :: [Imp.Exp],+ -- | A short descriptive and _unique_ name - should be+ -- alphanumeric and without spaces.+ kernelName :: Name,+ -- | If true, this kernel does not need to check+ -- whether we are in a failing state, as it can cope.+ -- Intuitively, it means that the kernel does not+ -- depend on any non-scalar parameters to make control+ -- flow decisions. Replication, transpose, and copy+ -- kernels are examples of this.+ kernelFailureTolerant :: Bool+ }+ deriving (Show)++-- | Information about a host-level variable that is used inside this+-- kernel. When generating the actual kernel code, this is used to+-- deduce which parameters are needed.+data KernelUse+ = ScalarUse VName PrimType+ | MemoryUse VName+ | ConstUse VName KernelConstExp+ deriving (Eq, Ord, Show)++instance Pretty KernelConst where+ ppr (SizeConst key) = text "get_size" <> parens (ppr key)++instance Pretty KernelUse where+ ppr (ScalarUse name t) =+ oneLine $ text "scalar_copy" <> parens (commasep [ppr name, ppr t])+ ppr (MemoryUse name) =+ oneLine $ text "mem_copy" <> parens (commasep [ppr name])+ ppr (ConstUse name e) =+ oneLine $ text "const" <> parens (commasep [ppr name, ppr e])++instance Pretty HostOp where+ ppr (GetSize dest key size_class) =+ ppr dest <+> text "<-"+ <+> text "get_size" <> parens (commasep [ppr key, ppr size_class])+ ppr (GetSizeMax dest size_class) =+ ppr dest <+> text "<-" <+> text "get_size_max" <> parens (ppr size_class)+ ppr (CmpSizeLe dest name size_class x) =+ ppr dest <+> text "<-"+ <+> text "get_size" <> parens (commasep [ppr name, ppr size_class])+ <+> text "<"+ <+> ppr x+ ppr (CallKernel c) =+ ppr c++instance FreeIn HostOp where+ freeIn' (CallKernel c) =+ freeIn' c+ freeIn' (CmpSizeLe dest _ _ x) =+ freeIn' dest <> freeIn' x+ freeIn' (GetSizeMax dest _) =+ freeIn' dest+ freeIn' (GetSize dest _ _) =+ freeIn' dest++instance FreeIn Kernel where+ freeIn' kernel =+ freeIn' (kernelBody kernel)+ <> freeIn' [kernelNumGroups kernel, kernelGroupSize kernel]++instance Pretty Kernel where+ ppr kernel =+ text "kernel"+ <+> brace+ ( text "groups" <+> brace (ppr $ kernelNumGroups kernel)+ </> text "group_size" <+> brace (ppr $ kernelGroupSize kernel)+ </> text "uses" <+> brace (commasep $ map ppr $ kernelUses kernel)+ </> text "failure_tolerant" <+> brace (ppr $ kernelFailureTolerant kernel)+ </> text "body" <+> brace (ppr $ kernelBody kernel)+ )++-- | When we do a barrier or fence, is it at the local or global+-- level?+data Fence = FenceLocal | FenceGlobal+ deriving (Show)++-- | An operation that occurs within a kernel body.+data KernelOp+ = GetGroupId VName Int+ | GetLocalId VName Int+ | GetLocalSize VName Int+ | GetGlobalSize VName Int+ | GetGlobalId VName Int+ | GetLockstepWidth VName+ | Atomic Space AtomicOp+ | Barrier Fence+ | MemFence Fence+ | LocalAlloc VName (Count Bytes (Imp.TExp Int64))+ | -- | Perform a barrier and also check whether any+ -- threads have failed an assertion. Make sure all+ -- threads would reach all 'ErrorSync's if any of them+ -- do. A failing assertion will jump to the next+ -- following 'ErrorSync', so make sure it's not inside+ -- control flow or similar.+ ErrorSync Fence+ deriving (Show)++-- | Atomic operations return the value stored before the update.+-- This old value is stored in the first 'VName'. The second 'VName'+-- is the memory block to update. The 'Exp' is the new value.+data AtomicOp+ = AtomicAdd IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicFAdd FloatType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicSMax IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicSMin IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicUMax IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicUMin IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicAnd IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicOr IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicXor IntType VName VName (Count Elements (Imp.TExp Int64)) Exp+ | AtomicCmpXchg PrimType VName VName (Count Elements (Imp.TExp Int64)) Exp Exp+ | AtomicXchg PrimType VName VName (Count Elements (Imp.TExp Int64)) Exp+ deriving (Show)++instance FreeIn AtomicOp where+ freeIn' (AtomicAdd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicFAdd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicSMax _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicSMin _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicUMax _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicUMin _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicAnd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicOr _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicXor _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x+ freeIn' (AtomicCmpXchg _ _ arr i x y) = freeIn' arr <> freeIn' i <> freeIn' x <> freeIn' y+ freeIn' (AtomicXchg _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x++instance Pretty KernelOp where+ ppr (GetGroupId dest i) =+ ppr dest <+> "<-"+ <+> "get_group_id" <> parens (ppr i)+ ppr (GetLocalId dest i) =+ ppr dest <+> "<-"+ <+> "get_local_id" <> parens (ppr i)+ ppr (GetLocalSize dest i) =+ ppr dest <+> "<-"+ <+> "get_local_size" <> parens (ppr i)+ ppr (GetGlobalSize dest i) =+ ppr dest <+> "<-"+ <+> "get_global_size" <> parens (ppr i)+ ppr (GetGlobalId dest i) =+ ppr dest <+> "<-"+ <+> "get_global_id" <> parens (ppr i)+ ppr (GetLockstepWidth dest) =+ ppr dest <+> "<-"+ <+> "get_lockstep_width()"+ ppr (Barrier FenceLocal) =+ "local_barrier()"+ ppr (Barrier FenceGlobal) =+ "global_barrier()"+ ppr (MemFence FenceLocal) =+ "mem_fence_local()"+ ppr (MemFence FenceGlobal) =+ "mem_fence_global()"+ ppr (LocalAlloc name size) =+ ppr name <+> equals <+> "local_alloc" <> parens (ppr size)+ ppr (ErrorSync FenceLocal) =+ "error_sync_local()"+ ppr (ErrorSync FenceGlobal) =+ "error_sync_global()"+ ppr (Atomic _ (AtomicAdd t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_add_" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicFAdd t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_fadd_" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicSMax t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_smax" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicSMin t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_smin" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicUMax t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_umax" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicUMin t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_umin" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicAnd t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_and" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicOr t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_or" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicXor t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_xor" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])+ ppr (Atomic _ (AtomicCmpXchg t old arr ind x y)) =+ ppr old <+> "<-" <+> "atomic_cmp_xchg" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x, ppr y])+ ppr (Atomic _ (AtomicXchg t old arr ind x)) =+ ppr old <+> "<-" <+> "atomic_xchg" <> ppr t+ <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])++instance FreeIn KernelOp where+ freeIn' (Atomic _ op) = freeIn' op+ freeIn' _ = mempty++brace :: Doc -> Doc+brace body = " {" </> indent 2 body </> "}"
− src/Futhark/CodeGen/ImpCode/Kernels.hs
@@ -1,266 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}---- | Variation of "Futhark.CodeGen.ImpCode" that contains the notion--- of a kernel invocation.-module Futhark.CodeGen.ImpCode.Kernels- ( Program,- Function,- FunctionT (Function),- Code,- KernelCode,- KernelConst (..),- KernelConstExp,- HostOp (..),- KernelOp (..),- Fence (..),- AtomicOp (..),- Kernel (..),- KernelUse (..),- module Futhark.CodeGen.ImpCode,- module Futhark.IR.Kernels.Sizes,- )-where--import Futhark.CodeGen.ImpCode hiding (Code, Function)-import qualified Futhark.CodeGen.ImpCode as Imp-import Futhark.IR.Kernels.Sizes-import Futhark.IR.Pretty ()-import Futhark.Util.Pretty---- | A program that calls kernels.-type Program = Imp.Definitions HostOp---- | A function that calls kernels.-type Function = Imp.Function HostOp---- | Host-level code that can call kernels.-type Code = Imp.Code HostOp---- | Code inside a kernel.-type KernelCode = Imp.Code KernelOp---- | A run-time constant related to kernels.-newtype KernelConst = SizeConst Name- deriving (Eq, Ord, Show)---- | An expression whose variables are kernel constants.-type KernelConstExp = PrimExp KernelConst---- | An operation that runs on the host (CPU).-data HostOp- = CallKernel Kernel- | GetSize VName Name SizeClass- | CmpSizeLe VName Name SizeClass Imp.Exp- | GetSizeMax VName SizeClass- deriving (Show)---- | A generic kernel containing arbitrary kernel code.-data Kernel = Kernel- { kernelBody :: Imp.Code KernelOp,- -- | The host variables referenced by the kernel.- kernelUses :: [KernelUse],- kernelNumGroups :: [Imp.Exp],- kernelGroupSize :: [Imp.Exp],- -- | A short descriptive and _unique_ name - should be- -- alphanumeric and without spaces.- kernelName :: Name,- -- | If true, this kernel does not need to check- -- whether we are in a failing state, as it can cope.- -- Intuitively, it means that the kernel does not- -- depend on any non-scalar parameters to make control- -- flow decisions. Replication, transpose, and copy- -- kernels are examples of this.- kernelFailureTolerant :: Bool- }- deriving (Show)---- | Information about a host-level variable that is used inside this--- kernel. When generating the actual kernel code, this is used to--- deduce which parameters are needed.-data KernelUse- = ScalarUse VName PrimType- | MemoryUse VName- | ConstUse VName KernelConstExp- deriving (Eq, Ord, Show)--instance Pretty KernelConst where- ppr (SizeConst key) = text "get_size" <> parens (ppr key)--instance Pretty KernelUse where- ppr (ScalarUse name t) =- oneLine $ text "scalar_copy" <> parens (commasep [ppr name, ppr t])- ppr (MemoryUse name) =- oneLine $ text "mem_copy" <> parens (commasep [ppr name])- ppr (ConstUse name e) =- oneLine $ text "const" <> parens (commasep [ppr name, ppr e])--instance Pretty HostOp where- ppr (GetSize dest key size_class) =- ppr dest <+> text "<-"- <+> text "get_size" <> parens (commasep [ppr key, ppr size_class])- ppr (GetSizeMax dest size_class) =- ppr dest <+> text "<-" <+> text "get_size_max" <> parens (ppr size_class)- ppr (CmpSizeLe dest name size_class x) =- ppr dest <+> text "<-"- <+> text "get_size" <> parens (commasep [ppr name, ppr size_class])- <+> text "<"- <+> ppr x- ppr (CallKernel c) =- ppr c--instance FreeIn HostOp where- freeIn' (CallKernel c) =- freeIn' c- freeIn' (CmpSizeLe dest _ _ x) =- freeIn' dest <> freeIn' x- freeIn' (GetSizeMax dest _) =- freeIn' dest- freeIn' (GetSize dest _ _) =- freeIn' dest--instance FreeIn Kernel where- freeIn' kernel =- freeIn' (kernelBody kernel)- <> freeIn' [kernelNumGroups kernel, kernelGroupSize kernel]--instance Pretty Kernel where- ppr kernel =- text "kernel"- <+> brace- ( text "groups" <+> brace (ppr $ kernelNumGroups kernel)- </> text "group_size" <+> brace (ppr $ kernelGroupSize kernel)- </> text "uses" <+> brace (commasep $ map ppr $ kernelUses kernel)- </> text "failure_tolerant" <+> brace (ppr $ kernelFailureTolerant kernel)- </> text "body" <+> brace (ppr $ kernelBody kernel)- )---- | When we do a barrier or fence, is it at the local or global--- level?-data Fence = FenceLocal | FenceGlobal- deriving (Show)---- | An operation that occurs within a kernel body.-data KernelOp- = GetGroupId VName Int- | GetLocalId VName Int- | GetLocalSize VName Int- | GetGlobalSize VName Int- | GetGlobalId VName Int- | GetLockstepWidth VName- | Atomic Space AtomicOp- | Barrier Fence- | MemFence Fence- | LocalAlloc VName (Count Bytes (Imp.TExp Int64))- | -- | Perform a barrier and also check whether any- -- threads have failed an assertion. Make sure all- -- threads would reach all 'ErrorSync's if any of them- -- do. A failing assertion will jump to the next- -- following 'ErrorSync', so make sure it's not inside- -- control flow or similar.- ErrorSync Fence- deriving (Show)---- | Atomic operations return the value stored before the update.--- This old value is stored in the first 'VName'. The second 'VName'--- is the memory block to update. The 'Exp' is the new value.-data AtomicOp- = AtomicAdd IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicFAdd FloatType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicSMax IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicSMin IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicUMax IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicUMin IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicAnd IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicOr IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicXor IntType VName VName (Count Elements (Imp.TExp Int64)) Exp- | AtomicCmpXchg PrimType VName VName (Count Elements (Imp.TExp Int64)) Exp Exp- | AtomicXchg PrimType VName VName (Count Elements (Imp.TExp Int64)) Exp- deriving (Show)--instance FreeIn AtomicOp where- freeIn' (AtomicAdd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicFAdd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicSMax _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicSMin _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicUMax _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicUMin _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicAnd _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicOr _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicXor _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x- freeIn' (AtomicCmpXchg _ _ arr i x y) = freeIn' arr <> freeIn' i <> freeIn' x <> freeIn' y- freeIn' (AtomicXchg _ _ arr i x) = freeIn' arr <> freeIn' i <> freeIn' x--instance Pretty KernelOp where- ppr (GetGroupId dest i) =- ppr dest <+> "<-"- <+> "get_group_id" <> parens (ppr i)- ppr (GetLocalId dest i) =- ppr dest <+> "<-"- <+> "get_local_id" <> parens (ppr i)- ppr (GetLocalSize dest i) =- ppr dest <+> "<-"- <+> "get_local_size" <> parens (ppr i)- ppr (GetGlobalSize dest i) =- ppr dest <+> "<-"- <+> "get_global_size" <> parens (ppr i)- ppr (GetGlobalId dest i) =- ppr dest <+> "<-"- <+> "get_global_id" <> parens (ppr i)- ppr (GetLockstepWidth dest) =- ppr dest <+> "<-"- <+> "get_lockstep_width()"- ppr (Barrier FenceLocal) =- "local_barrier()"- ppr (Barrier FenceGlobal) =- "global_barrier()"- ppr (MemFence FenceLocal) =- "mem_fence_local()"- ppr (MemFence FenceGlobal) =- "mem_fence_global()"- ppr (LocalAlloc name size) =- ppr name <+> equals <+> "local_alloc" <> parens (ppr size)- ppr (ErrorSync FenceLocal) =- "error_sync_local()"- ppr (ErrorSync FenceGlobal) =- "error_sync_global()"- ppr (Atomic _ (AtomicAdd t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_add_" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicFAdd t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_fadd_" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicSMax t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_smax" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicSMin t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_smin" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicUMax t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_umax" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicUMin t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_umin" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicAnd t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_and" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicOr t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_or" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicXor t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_xor" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])- ppr (Atomic _ (AtomicCmpXchg t old arr ind x y)) =- ppr old <+> "<-" <+> "atomic_cmp_xchg" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x, ppr y])- ppr (Atomic _ (AtomicXchg t old arr ind x)) =- ppr old <+> "<-" <+> "atomic_xchg" <> ppr t- <> parens (commasep [ppr arr <> brackets (ppr ind), ppr x])--instance FreeIn KernelOp where- freeIn' (Atomic _ op) = freeIn' op- freeIn' _ = mempty--brace :: Doc -> Doc-brace body = " {" </> indent 2 body </> "}"
src/Futhark/CodeGen/ImpCode/OpenCL.hs view
@@ -19,14 +19,14 @@ KernelTarget (..), FailureMsg (..), module Futhark.CodeGen.ImpCode,- module Futhark.IR.Kernels.Sizes,+ module Futhark.IR.GPU.Sizes, ) where import qualified Data.Map as M import Futhark.CodeGen.ImpCode hiding (Code, Function) import qualified Futhark.CodeGen.ImpCode as Imp-import Futhark.IR.Kernels.Sizes+import Futhark.IR.GPU.Sizes import Futhark.Util.Pretty -- | An program calling OpenCL kernels.
src/Futhark/CodeGen/ImpGen.hs view
@@ -151,39 +151,39 @@ import Prelude hiding (quot) -- | How to compile an t'Op'.-type OpCompiler lore r op = Pattern lore -> Op lore -> ImpM lore r op ()+type OpCompiler rep r op = Pattern rep -> Op rep -> ImpM rep r op () -- | How to compile some 'Stms'.-type StmsCompiler lore r op = Names -> Stms lore -> ImpM lore r op () -> ImpM lore r op ()+type StmsCompiler rep r op = Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op () -- | How to compile an 'Exp'.-type ExpCompiler lore r op = Pattern lore -> Exp lore -> ImpM lore r op ()+type ExpCompiler rep r op = Pattern rep -> Exp rep -> ImpM rep r op () -type CopyCompiler lore r op =+type CopyCompiler rep r op = PrimType -> MemLocation -> Slice (Imp.TExp Int64) -> MemLocation -> Slice (Imp.TExp Int64) ->- ImpM lore r op ()+ ImpM rep r op () -- | An alternate way of compiling an allocation.-type AllocCompiler lore r op = VName -> Count Bytes (Imp.TExp Int64) -> ImpM lore r op ()+type AllocCompiler rep r op = VName -> Count Bytes (Imp.TExp Int64) -> ImpM rep r op () -data Operations lore r op = Operations- { opsExpCompiler :: ExpCompiler lore r op,- opsOpCompiler :: OpCompiler lore r op,- opsStmsCompiler :: StmsCompiler lore r op,- opsCopyCompiler :: CopyCompiler lore r op,- opsAllocCompilers :: M.Map Space (AllocCompiler lore r op)+data Operations rep r op = Operations+ { opsExpCompiler :: ExpCompiler rep r op,+ opsOpCompiler :: OpCompiler rep r op,+ opsStmsCompiler :: StmsCompiler rep r op,+ opsCopyCompiler :: CopyCompiler rep r op,+ opsAllocCompilers :: M.Map Space (AllocCompiler rep r op) } -- | An operations set for which the expression compiler always -- returns 'defCompileExp'. defaultOperations ::- (Mem lore, FreeIn op) =>- OpCompiler lore r op ->- Operations lore r op+ (Mem rep, FreeIn op) =>+ OpCompiler rep r op ->+ Operations rep r op defaultOperations opc = Operations { opsExpCompiler = defCompileExp,@@ -219,11 +219,11 @@ deriving (Show) -- | Every non-scalar variable must be associated with an entry.-data VarEntry lore- = ArrayVar (Maybe (Exp lore)) ArrayEntry- | ScalarVar (Maybe (Exp lore)) ScalarEntry- | MemVar (Maybe (Exp lore)) MemEntry- | AccVar (Maybe (Exp lore)) (VName, Shape, [Type])+data VarEntry rep+ = ArrayVar (Maybe (Exp rep)) ArrayEntry+ | ScalarVar (Maybe (Exp rep)) ScalarEntry+ | MemVar (Maybe (Exp rep)) MemEntry+ | AccVar (Maybe (Exp rep)) (VName, Shape, [Type]) deriving (Show) -- | When compiling an expression, this is a description of where the@@ -247,12 +247,12 @@ ArrayDestination (Maybe MemLocation) deriving (Show) -data Env lore r op = Env- { envExpCompiler :: ExpCompiler lore r op,- envStmsCompiler :: StmsCompiler lore r op,- envOpCompiler :: OpCompiler lore r op,- envCopyCompiler :: CopyCompiler lore r op,- envAllocCompilers :: M.Map Space (AllocCompiler lore r op),+data Env rep r op = Env+ { envExpCompiler :: ExpCompiler rep r op,+ envStmsCompiler :: StmsCompiler rep r op,+ envOpCompiler :: OpCompiler rep r op,+ envCopyCompiler :: CopyCompiler rep r op,+ envAllocCompilers :: M.Map Space (AllocCompiler rep r op), envDefaultSpace :: Imp.Space, envVolatility :: Imp.Volatility, -- | User-extensible environment.@@ -264,7 +264,7 @@ envAttrs :: Attrs } -newEnv :: r -> Operations lore r op -> Imp.Space -> Env lore r op+newEnv :: r -> Operations rep r op -> Imp.Space -> Env rep r op newEnv r ops ds = Env { envExpCompiler = opsExpCompiler ops,@@ -280,10 +280,10 @@ } -- | The symbol table used during compilation.-type VTable lore = M.Map VName (VarEntry lore)+type VTable rep = M.Map VName (VarEntry rep) -data ImpState lore r op = ImpState- { stateVTable :: VTable lore,+data ImpState rep r op = ImpState+ { stateVTable :: VTable rep, stateFunctions :: Imp.Functions op, stateCode :: Imp.Code op, stateWarnings :: Warnings,@@ -293,30 +293,30 @@ -- accumulator throughout its lifetime. If the arrays -- backing an accumulator is not in this mapping, the -- accumulator is scatter-like.- stateAccs :: M.Map VName ([VName], Maybe (Lambda lore, [SubExp])),+ stateAccs :: M.Map VName ([VName], Maybe (Lambda rep, [SubExp])), stateNameSource :: VNameSource } -newState :: VNameSource -> ImpState lore r op+newState :: VNameSource -> ImpState rep r op newState = ImpState mempty mempty mempty mempty mempty -newtype ImpM lore r op a- = ImpM (ReaderT (Env lore r op) (State (ImpState lore r op)) a)+newtype ImpM rep r op a+ = ImpM (ReaderT (Env rep r op) (State (ImpState rep r op)) a) deriving ( Functor, Applicative, Monad,- MonadState (ImpState lore r op),- MonadReader (Env lore r op)+ MonadState (ImpState rep r op),+ MonadReader (Env rep r op) ) -instance MonadFreshNames (ImpM lore r op) where+instance MonadFreshNames (ImpM rep r op) where getNameSource = gets stateNameSource putNameSource src = modify $ \s -> s {stateNameSource = src} -- Cannot be an KernelsMem scope because the index functions have -- the wrong leaves (VName instead of Imp.Exp).-instance HasScope SOACS (ImpM lore r op) where+instance HasScope SOACS (ImpM rep r op) where askScope = gets $ M.map (LetName . entryType) . stateVTable where entryType (MemVar _ memEntry) =@@ -332,26 +332,26 @@ Acc acc ispace ts NoUniqueness runImpM ::- ImpM lore r op a ->+ ImpM rep r op a -> r ->- Operations lore r op ->+ Operations rep r op -> Imp.Space ->- ImpState lore r op ->- (a, ImpState lore r op)+ ImpState rep r op ->+ (a, ImpState rep r op) runImpM (ImpM m) r ops space = runState (runReaderT m $ newEnv r ops space) subImpM_ :: r' ->- Operations lore r' op' ->- ImpM lore r' op' a ->- ImpM lore r op (Imp.Code op')+ Operations rep r' op' ->+ ImpM rep r' op' a ->+ ImpM rep r op (Imp.Code op') subImpM_ r ops m = snd <$> subImpM r ops m subImpM :: r' ->- Operations lore r' op' ->- ImpM lore r' op' a ->- ImpM lore r op (a, Imp.Code op')+ Operations rep r' op' ->+ ImpM rep r' op' a ->+ ImpM rep r op (a, Imp.Code op') subImpM r ops (ImpM m) = do env <- ask s <- get@@ -382,10 +382,10 @@ -- | Execute a code generation action, returning the code that was -- emitted.-collect :: ImpM lore r op () -> ImpM lore r op (Imp.Code op)+collect :: ImpM rep r op () -> ImpM rep r op (Imp.Code op) collect = fmap snd . collect' -collect' :: ImpM lore r op a -> ImpM lore r op (a, Imp.Code op)+collect' :: ImpM rep r op a -> ImpM rep r op (a, Imp.Code op) collect' m = do prev_code <- gets stateCode modify $ \s -> s {stateCode = mempty}@@ -396,36 +396,36 @@ -- | Execute a code generation action, wrapping the generated code -- within a 'Imp.Comment' with the given description.-comment :: String -> ImpM lore r op () -> ImpM lore r op ()+comment :: String -> ImpM rep r op () -> ImpM rep r op () comment desc m = do code <- collect m emit $ Imp.Comment desc code -- | Emit some generated imperative code.-emit :: Imp.Code op -> ImpM lore r op ()+emit :: Imp.Code op -> ImpM rep r op () emit code = modify $ \s -> s {stateCode = stateCode s <> code} -warnings :: Warnings -> ImpM lore r op ()+warnings :: Warnings -> ImpM rep r op () warnings ws = modify $ \s -> s {stateWarnings = ws <> stateWarnings s} -- | Emit a warning about something the user should be aware of.-warn :: Located loc => loc -> [loc] -> String -> ImpM lore r op ()+warn :: Located loc => loc -> [loc] -> String -> ImpM rep r op () warn loc locs problem = warnings $ singleWarning' (srclocOf loc) (map srclocOf locs) (fromString problem) -- | Emit a function in the generated code.-emitFunction :: Name -> Imp.Function op -> ImpM lore r op ()+emitFunction :: Name -> Imp.Function op -> ImpM rep r op () emitFunction fname fun = do Imp.Functions fs <- gets stateFunctions modify $ \s -> s {stateFunctions = Imp.Functions $ (fname, fun) : fs} -- | Check if a function of a given name exists.-hasFunction :: Name -> ImpM lore r op Bool+hasFunction :: Name -> ImpM rep r op Bool hasFunction fname = gets $ \s -> let Imp.Functions fs = stateFunctions s in isJust $ lookup fname fs -constsVTable :: Mem lore => Stms lore -> VTable lore+constsVTable :: Mem rep => Stms rep -> VTable rep constsVTable = foldMap stmVtable where stmVtable (Let pat _ e) =@@ -434,11 +434,11 @@ M.singleton name $ memBoundToVarEntry (Just e) dec compileProg ::- (Mem lore, FreeIn op, MonadFreshNames m) =>+ (Mem rep, FreeIn op, MonadFreshNames m) => r ->- Operations lore r op ->+ Operations rep r op -> Imp.Space ->- Prog lore ->+ Prog rep -> m (Warnings, Imp.Definitions op) compileProg r ops space (Prog consts funs) = modifyNameSource $ \src ->@@ -473,7 +473,7 @@ mconcat $ map stateWarnings ss } -compileConsts :: Names -> Stms lore -> ImpM lore r op (Imp.Constants op)+compileConsts :: Names -> Stms rep -> ImpM rep r op (Imp.Constants op) compileConsts used_consts stms = do code <- collect $ compileStms used_consts stms $ pure () pure $ uncurry Imp.Constants $ first DL.toList $ extract code@@ -496,9 +496,9 @@ (mempty, s) compileInParam ::- Mem lore =>- FParam lore ->- ImpM lore r op (Either Imp.Param ArrayDecl)+ Mem rep =>+ FParam rep ->+ ImpM rep r op (Either Imp.Param ArrayDecl) compileInParam fparam = case paramDec fparam of MemPrim bt -> return $ Left $ Imp.ScalarParam name bt@@ -517,10 +517,10 @@ data ArrayDecl = ArrayDecl VName PrimType MemLocation compileInParams ::- Mem lore =>- [FParam lore] ->+ Mem rep =>+ [FParam rep] -> [EntryPointType] ->- ImpM lore r op ([Imp.Param], [ArrayDecl], [Imp.ExternalValue])+ ImpM rep r op ([Imp.Param], [ArrayDecl], [Imp.ExternalValue]) compileInParams params orig_epts = do let (ctx_params, val_params) = splitAt (length params - sum (map entryPointSize orig_epts)) params@@ -548,17 +548,18 @@ _ -> Nothing - mkExts (TypeOpaque desc n : epts) fparams =+ mkExts (TypeOpaque u desc n : epts) fparams = let (fparams', rest) = splitAt n fparams in Imp.OpaqueValue+ u desc (mapMaybe (`mkValueDesc` Imp.TypeDirect) fparams') : mkExts epts rest- mkExts (TypeUnsigned : epts) (fparam : fparams) =- maybeToList (Imp.TransparentValue <$> mkValueDesc fparam Imp.TypeUnsigned)+ mkExts (TypeUnsigned u : epts) (fparam : fparams) =+ maybeToList (Imp.TransparentValue u <$> mkValueDesc fparam Imp.TypeUnsigned) ++ mkExts epts fparams- mkExts (TypeDirect : epts) (fparam : fparams) =- maybeToList (Imp.TransparentValue <$> mkValueDesc fparam Imp.TypeDirect)+ mkExts (TypeDirect u : epts) (fparam : fparams) =+ maybeToList (Imp.TransparentValue u <$> mkValueDesc fparam Imp.TypeDirect) ++ mkExts epts fparams mkExts _ _ = [] @@ -567,10 +568,10 @@ isArrayDecl x (ArrayDecl y _ _) = x == y compileOutParams ::- Mem lore =>- [RetType lore] ->+ Mem rep =>+ [RetType rep] -> [EntryPointType] ->- ImpM lore r op ([Imp.ExternalValue], [Imp.Param], Destination)+ 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)@@ -579,26 +580,26 @@ where imp = lift . lift - mkExts (TypeOpaque desc n : epts) rts = do+ 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 desc evs : more_values,+ ( Imp.OpaqueValue u desc evs : more_values, dests ++ more_dests )- mkExts (TypeUnsigned : epts) (rt : rts) = do+ mkExts (TypeUnsigned u : epts) (rt : rts) = do (ev, dest) <- mkParam rt Imp.TypeUnsigned (more_values, more_dests) <- mkExts epts rts return- ( Imp.TransparentValue ev : more_values,+ ( Imp.TransparentValue u ev : more_values, dest : more_dests )- mkExts (TypeDirect : epts) (rt : rts) = do+ mkExts (TypeDirect u : epts) (rt : rts) = do (ev, dest) <- mkParam rt Imp.TypeDirect (more_values, more_dests) <- mkExts epts rts return- ( Imp.TransparentValue ev : more_values,+ ( Imp.TransparentValue u ev : more_values, dest : more_dests ) mkExts _ _ = return ([], [])@@ -646,9 +647,9 @@ return se compileFunDef ::- Mem lore =>- FunDef lore ->- ImpM lore r op ()+ Mem rep =>+ FunDef rep ->+ ImpM rep r op () compileFunDef (FunDef entry _ fname rettype params body) = local (\env -> env {envFunction = name_entry `mplus` Just fname}) $ do ((outparams, inparams, results, args), body') <- collect' compile@@ -657,8 +658,8 @@ (name_entry, params_entry, ret_entry) = case entry of Nothing -> ( Nothing,- replicate (length params) TypeDirect,- replicate (length rettype) TypeDirect+ replicate (length params) (TypeDirect mempty),+ replicate (length rettype) (TypeDirect mempty) ) Just (x, y, z) -> (Just x, y, z) compile = do@@ -673,18 +674,18 @@ return (outparams, inparams, results, args) -compileBody :: (Mem lore) => Pattern lore -> Body lore -> ImpM lore r op ()+compileBody :: (Mem rep) => Pattern rep -> Body rep -> ImpM rep r op () compileBody pat (Body _ bnds ses) = do Destination _ dests <- destinationFromPattern pat compileStms (freeIn ses) bnds $ forM_ (zip dests ses) $ \(d, se) -> copyDWIMDest d [] se [] -compileBody' :: [Param dec] -> Body lore -> ImpM lore r op ()+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 [] -compileLoopBody :: Typed dec => [Param dec] -> Body lore -> ImpM lore r op ()+compileLoopBody :: Typed dec => [Param dec] -> Body rep -> ImpM rep r op () compileLoopBody mergeparams (Body _ bnds ses) = do -- We cannot write the results to the merge parameters immediately, -- as some of the results may actually *be* merge parameters, and@@ -707,17 +708,17 @@ _ -> return $ return () sequence_ copy_to_merge_params -compileStms :: Names -> Stms lore -> ImpM lore r op () -> ImpM lore r op ()+compileStms :: Names -> Stms rep -> ImpM rep r op () -> ImpM rep r op () compileStms alive_after_stms all_stms m = do cb <- asks envStmsCompiler cb alive_after_stms all_stms m defCompileStms ::- (Mem lore, FreeIn op) =>+ (Mem rep, FreeIn op) => Names ->- Stms lore ->- ImpM lore r op () ->- ImpM lore r op ()+ Stms rep ->+ ImpM rep r op () ->+ ImpM rep r op () defCompileStms alive_after_stms all_stms m = -- We keep track of any memory blocks produced by the statements, -- and after the last time that memory block is used, we insert a@@ -752,16 +753,16 @@ Mem space -> Just (patElemName pe, space) _ -> Nothing -compileExp :: Pattern lore -> Exp lore -> ImpM lore r op ()+compileExp :: Pattern rep -> Exp rep -> ImpM rep r op () compileExp pat e = do ec <- asks envExpCompiler ec pat e defCompileExp ::- (Mem lore) =>- Pattern lore ->- Exp lore ->- ImpM lore r op ()+ (Mem rep) =>+ Pattern 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@@ -827,10 +828,10 @@ opc pat op defCompileBasicOp ::- Mem lore =>- Pattern lore ->+ Mem rep =>+ Pattern rep -> BasicOp ->- ImpM lore r op ()+ ImpM rep r op () defCompileBasicOp (Pattern _ [pe]) (SubExp se) = copyDWIM (patElemName pe) [] se [] defCompileBasicOp (Pattern _ [pe]) (Opaque se) =@@ -967,7 +968,7 @@ ++ pretty e -- | Note: a hack to be used only for functions.-addArrays :: [ArrayDecl] -> ImpM lore r op ()+addArrays :: [ArrayDecl] -> ImpM rep r op () addArrays = mapM_ addArray where addArray (ArrayDecl name bt location) =@@ -981,7 +982,7 @@ -- | Like 'dFParams', but does not create new declarations. -- Note: a hack to be used only for functions.-addFParams :: Mem lore => [FParam lore] -> ImpM lore r op ()+addFParams :: Mem rep => [FParam rep] -> ImpM rep r op () addFParams = mapM_ addFParam where addFParam fparam =@@ -989,25 +990,25 @@ memBoundToVarEntry Nothing $ noUniquenessReturns $ paramDec fparam -- | Another hack.-addLoopVar :: VName -> IntType -> ImpM lore r op ()+addLoopVar :: VName -> IntType -> ImpM rep r op () addLoopVar i it = addVar i $ ScalarVar Nothing $ ScalarEntry $ IntType it dVars ::- Mem lore =>- Maybe (Exp lore) ->- [PatElem lore] ->- ImpM lore r op ()+ Mem rep =>+ Maybe (Exp rep) ->+ [PatElem rep] ->+ ImpM rep r op () dVars e = mapM_ dVar where dVar = dScope e . scopeOfPatElem -dFParams :: Mem lore => [FParam lore] -> ImpM lore r op ()+dFParams :: Mem rep => [FParam rep] -> ImpM rep r op () dFParams = dScope Nothing . scopeOfFParams -dLParams :: Mem lore => [LParam lore] -> ImpM lore r op ()+dLParams :: Mem rep => [LParam rep] -> ImpM rep r op () dLParams = dScope Nothing . scopeOfLParams -dPrimVol :: String -> PrimType -> Imp.TExp t -> ImpM lore r op (TV t)+dPrimVol :: String -> PrimType -> Imp.TExp t -> ImpM rep r op (TV t) dPrimVol name t e = do name' <- newVName name emit $ Imp.DeclareScalar name' Imp.Volatile t@@ -1015,7 +1016,7 @@ name' <~~ untyped e return $ TV name' t -dPrim_ :: VName -> PrimType -> ImpM lore r op ()+dPrim_ :: VName -> PrimType -> ImpM rep r op () dPrim_ name t = do emit $ Imp.DeclareScalar name Imp.Nonvolatile t addVar name $ ScalarVar Nothing $ ScalarEntry t@@ -1023,35 +1024,35 @@ -- | The return type is polymorphic, so there is no guarantee it -- actually matches the 'PrimType', but at least we have to use it -- consistently.-dPrim :: String -> PrimType -> ImpM lore r op (TV t)+dPrim :: String -> PrimType -> ImpM rep r op (TV t) dPrim name t = do name' <- newVName name dPrim_ name' t return $ TV name' t -dPrimV_ :: VName -> Imp.TExp t -> ImpM lore r op ()+dPrimV_ :: VName -> Imp.TExp t -> ImpM rep r op () dPrimV_ name e = do dPrim_ name t TV name t <-- e where t = primExpType $ untyped e -dPrimV :: String -> Imp.TExp t -> ImpM lore r op (TV t)+dPrimV :: String -> Imp.TExp t -> ImpM rep r op (TV t) dPrimV name e = do name' <- dPrim name $ primExpType $ untyped e name' <-- e return name' -dPrimVE :: String -> Imp.TExp t -> ImpM lore r op (Imp.TExp t)+dPrimVE :: String -> Imp.TExp t -> ImpM rep r op (Imp.TExp t) dPrimVE name e = do name' <- dPrim name $ primExpType $ untyped e name' <-- e return $ tvExp name' memBoundToVarEntry ::- Maybe (Exp lore) ->+ Maybe (Exp rep) -> MemBound NoUniqueness ->- VarEntry lore+ VarEntry rep memBoundToVarEntry e (MemPrim bt) = ScalarVar e ScalarEntry {entryScalarType = bt} memBoundToVarEntry e (MemMem space) =@@ -1068,8 +1069,8 @@ } infoDec ::- Mem lore =>- NameInfo lore ->+ Mem rep =>+ NameInfo rep -> MemInfo SubExp NoUniqueness MemBind infoDec (LetName dec) = dec infoDec (FParamName dec) = noUniquenessReturns dec@@ -1077,11 +1078,11 @@ infoDec (IndexName it) = MemPrim $ IntType it dInfo ::- Mem lore =>- Maybe (Exp lore) ->+ Mem rep =>+ Maybe (Exp rep) -> VName ->- NameInfo lore ->- ImpM lore r op ()+ NameInfo rep ->+ ImpM rep r op () dInfo e name info = do let entry = memBoundToVarEntry e $ infoDec info case entry of@@ -1096,22 +1097,22 @@ addVar name entry dScope ::- Mem lore =>- Maybe (Exp lore) ->- Scope lore ->- ImpM lore r op ()+ Mem rep =>+ Maybe (Exp rep) ->+ Scope rep ->+ ImpM rep r op () dScope e = mapM_ (uncurry $ dInfo e) . M.toList -dArray :: VName -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM lore r op ()+dArray :: VName -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM rep r op () dArray name bt shape membind = addVar name $ memBoundToVarEntry Nothing $ MemArray bt shape NoUniqueness membind -everythingVolatile :: ImpM lore r op a -> ImpM lore r op a+everythingVolatile :: ImpM rep r op a -> ImpM rep r op a everythingVolatile = local $ \env -> env {envVolatility = Imp.Volatile} -- | Remove the array targets.-funcallTargets :: Destination -> ImpM lore r op [VName]+funcallTargets :: Destination -> ImpM rep r op [VName] funcallTargets (Destination _ dests) = concat <$> mapM funcallTarget dests where@@ -1151,7 +1152,7 @@ class ToExp a where -- | Compile to an 'Imp.Exp', where the type (must must still be a -- primitive) is deduced monadically.- toExp :: a -> ImpM lore r op Imp.Exp+ toExp :: a -> ImpM rep r op Imp.Exp -- | Compile where we know the type in advance. toExp' :: PrimType -> a -> Imp.Exp@@ -1178,44 +1179,44 @@ toExp = pure . fmap Imp.ScalarVar toExp' _ = fmap Imp.ScalarVar -addVar :: VName -> VarEntry lore -> ImpM lore r op ()+addVar :: VName -> VarEntry rep -> ImpM rep r op () addVar name entry = modify $ \s -> s {stateVTable = M.insert name entry $ stateVTable s} -localDefaultSpace :: Imp.Space -> ImpM lore r op a -> ImpM lore r op a+localDefaultSpace :: Imp.Space -> ImpM rep r op a -> ImpM rep r op a localDefaultSpace space = local (\env -> env {envDefaultSpace = space}) -askFunction :: ImpM lore r op (Maybe Name)+askFunction :: ImpM rep r op (Maybe Name) askFunction = asks envFunction -- | Generate a 'VName', prefixed with 'askFunction' if it exists.-newVNameForFun :: String -> ImpM lore r op VName+newVNameForFun :: String -> ImpM rep r op VName newVNameForFun s = do fname <- fmap nameToString <$> askFunction newVName $ maybe "" (++ ".") fname ++ s -- | Generate a 'Name', prefixed with 'askFunction' if it exists.-nameForFun :: String -> ImpM lore r op Name+nameForFun :: String -> ImpM rep r op Name nameForFun s = do fname <- askFunction return $ maybe "" (<> ".") fname <> nameFromString s -askEnv :: ImpM lore r op r+askEnv :: ImpM rep r op r askEnv = asks envEnv -localEnv :: (r -> r) -> ImpM lore r op a -> ImpM lore r op a+localEnv :: (r -> r) -> ImpM rep r op a -> ImpM rep r op a localEnv f = local $ \env -> env {envEnv = f $ envEnv env} -- | The active attributes, including those for the statement -- currently being compiled.-askAttrs :: ImpM lore r op Attrs+askAttrs :: ImpM rep r op Attrs askAttrs = asks envAttrs -- | Add more attributes to what is returning by 'askAttrs'.-localAttrs :: Attrs -> ImpM lore r op a -> ImpM lore r op a+localAttrs :: Attrs -> ImpM rep r op a -> ImpM rep r op a localAttrs attrs = local $ \env -> env {envAttrs = attrs <> envAttrs env} -localOps :: Operations lore r op -> ImpM lore r op a -> ImpM lore r op a+localOps :: Operations rep r op -> ImpM rep r op a -> ImpM rep r op a localOps ops = local $ \env -> env { envExpCompiler = opsExpCompiler ops,@@ -1226,15 +1227,15 @@ } -- | Get the current symbol table.-getVTable :: ImpM lore r op (VTable lore)+getVTable :: ImpM rep r op (VTable rep) getVTable = gets stateVTable -putVTable :: VTable lore -> ImpM lore r op ()+putVTable :: VTable rep -> ImpM rep r op () putVTable vtable = modify $ \s -> s {stateVTable = vtable} -- | Run an action with a modified symbol table. All changes to the -- symbol table will be reverted once the action is done!-localVTable :: (VTable lore -> VTable lore) -> ImpM lore r op a -> ImpM lore r op a+localVTable :: (VTable rep -> VTable rep) -> ImpM rep r op a -> ImpM rep r op a localVTable f m = do old_vtable <- getVTable putVTable $ f old_vtable@@ -1242,28 +1243,28 @@ putVTable old_vtable return a -lookupVar :: VName -> ImpM lore r op (VarEntry lore)+lookupVar :: VName -> ImpM rep r op (VarEntry rep) lookupVar name = do res <- gets $ M.lookup name . stateVTable case res of Just entry -> return entry _ -> error $ "Unknown variable: " ++ pretty name -lookupArray :: VName -> ImpM lore r op ArrayEntry+lookupArray :: VName -> ImpM rep r op ArrayEntry lookupArray name = do res <- lookupVar name case res of ArrayVar _ entry -> return entry _ -> error $ "ImpGen.lookupArray: not an array: " ++ pretty name -lookupMemory :: VName -> ImpM lore r op MemEntry+lookupMemory :: VName -> ImpM rep r op MemEntry lookupMemory name = do res <- lookupVar name case res of MemVar _ entry -> return entry _ -> error $ "Unknown memory block: " ++ pretty name -lookupArraySpace :: VName -> ImpM lore r op Space+lookupArraySpace :: VName -> ImpM rep r op Space lookupArraySpace = fmap entryMemSpace . lookupMemory <=< fmap (memLocationName . entryArrayLocation) . lookupArray@@ -1273,7 +1274,7 @@ lookupAcc :: VName -> [Imp.TExp Int64] ->- ImpM lore r op (VName, Space, [VName], [Imp.TExp Int64], Maybe (Lambda lore))+ ImpM rep r op (VName, Space, [VName], [Imp.TExp Int64], Maybe (Lambda rep)) lookupAcc name is = do res <- lookupVar name case res of@@ -1300,7 +1301,7 @@ error $ "ImpGen.lookupAcc: unlisted accumulator: " ++ pretty name _ -> error $ "ImpGen.lookupAcc: not an accumulator: " ++ pretty name -destinationFromPattern :: Mem lore => Pattern lore -> ImpM lore r op Destination+destinationFromPattern :: Mem rep => Pattern rep -> ImpM rep r op Destination destinationFromPattern pat = fmap (Destination (baseTag <$> maybeHead (patternNames pat))) . mapM inspect $ patternElements pat@@ -1321,7 +1322,7 @@ fullyIndexArray :: VName -> [Imp.TExp Int64] ->- ImpM lore r op (VName, Imp.Space, Count Elements (Imp.TExp Int64))+ ImpM rep r op (VName, Imp.Space, Count Elements (Imp.TExp Int64)) fullyIndexArray name indices = do arr <- lookupArray name fullyIndexArray' (entryArrayLocation arr) indices@@ -1329,23 +1330,18 @@ fullyIndexArray' :: MemLocation -> [Imp.TExp Int64] ->- ImpM lore r op (VName, Imp.Space, Count Elements (Imp.TExp Int64))+ ImpM rep r op (VName, Imp.Space, Count Elements (Imp.TExp Int64)) fullyIndexArray' (MemLocation mem _ ixfun) indices = do space <- entryMemSpace <$> lookupMemory mem- let indices' = case space of- ScalarSpace ds _ ->- let (zero_is, is) = splitFromEnd (length ds) indices- in map (const 0) zero_is ++ is- _ -> indices return ( mem, space,- elements $ IxFun.index ixfun indices'+ elements $ IxFun.index ixfun indices ) -- More complicated read/write operations that use index functions. -copy :: CopyCompiler lore r op+copy :: CopyCompiler rep r op copy bt dest destslice src srcslice = do cc <- asks envCopyCompiler cc bt dest destslice src srcslice@@ -1407,7 +1403,7 @@ mapTransposeName :: PrimType -> String mapTransposeName bt = "map_transpose_" ++ pretty bt -mapTransposeForType :: PrimType -> ImpM lore r op Name+mapTransposeForType :: PrimType -> ImpM rep r op Name mapTransposeForType bt = do let fname = nameFromString $ "builtin#" <> mapTransposeName bt @@ -1417,7 +1413,7 @@ return fname -- | Use an 'Imp.Copy' if possible, otherwise 'copyElementWise'.-defaultCopy :: CopyCompiler lore r op+defaultCopy :: CopyCompiler rep r op defaultCopy pt dest destslice src srcslice | Just ( destoffset,@@ -1471,7 +1467,7 @@ isScalarSpace ScalarSpace {} = True isScalarSpace _ = False -copyElementWise :: CopyCompiler lore r op+copyElementWise :: CopyCompiler rep r op copyElementWise bt dest destslice src srcslice = do let bounds = sliceDims srcslice is <- replicateM (length bounds) (newVName "i")@@ -1494,7 +1490,7 @@ [DimIndex (Imp.TExp Int64)] -> MemLocation -> [DimIndex (Imp.TExp Int64)] ->- ImpM lore r op (Imp.Code op)+ ImpM rep r op (Imp.Code op) copyArrayDWIM bt destlocation@(MemLocation _ destshape _)@@ -1544,7 +1540,7 @@ [DimIndex (Imp.TExp Int64)] -> SubExp -> [DimIndex (Imp.TExp Int64)] ->- ImpM lore r op ()+ ImpM rep r op () copyDWIMDest _ _ (Constant v) (_ : _) = error $ unwords ["copyDWIMDest: constant source", pretty v, "cannot be indexed."]@@ -1640,7 +1636,7 @@ [DimIndex (Imp.TExp Int64)] -> SubExp -> [DimIndex (Imp.TExp Int64)] ->- ImpM lore r op ()+ ImpM rep r op () copyDWIM dest dest_slice src src_slice = do dest_entry <- lookupVar dest let dest_target =@@ -1662,7 +1658,7 @@ [Imp.TExp Int64] -> SubExp -> [Imp.TExp Int64] ->- ImpM lore r op ()+ ImpM rep r op () copyDWIMFix dest dest_is src src_is = copyDWIM dest (map DimFix dest_is) src (map DimFix src_is) @@ -1670,11 +1666,11 @@ -- writing the result to @dest@, which must be a single -- 'MemoryDestination', compileAlloc ::- Mem lore =>- Pattern lore ->+ Mem rep =>+ Pattern rep -> SubExp -> Space ->- ImpM lore r op ()+ ImpM rep r op () compileAlloc (Pattern [] [mem]) e space = do let e' = Imp.bytes $ toInt64Exp e allocator <- asks $ M.lookup space . envAllocCompilers@@ -1703,7 +1699,7 @@ --- Building blocks for constructing code. -sFor' :: VName -> Imp.Exp -> ImpM lore r op () -> ImpM lore r op ()+sFor' :: VName -> Imp.Exp -> ImpM rep r op () -> ImpM rep r op () sFor' i bound body = do let it = case primExpType bound of IntType bound_t -> bound_t@@ -1712,72 +1708,72 @@ body' <- collect body emit $ Imp.For i bound body' -sFor :: String -> Imp.TExp t -> (Imp.TExp t -> ImpM lore r op ()) -> ImpM lore r op ()+sFor :: String -> Imp.TExp t -> (Imp.TExp t -> ImpM rep r op ()) -> ImpM rep r op () sFor i bound body = do i' <- newVName i sFor' i' (untyped bound) $ body $ TPrimExp $ Imp.var i' $ primExpType $ untyped bound -sWhile :: Imp.TExp Bool -> ImpM lore r op () -> ImpM lore r op ()+sWhile :: Imp.TExp Bool -> ImpM rep r op () -> ImpM rep r op () sWhile cond body = do body' <- collect body emit $ Imp.While cond body' -sComment :: String -> ImpM lore r op () -> ImpM lore r op ()+sComment :: String -> ImpM rep r op () -> ImpM rep r op () sComment s code = do code' <- collect code emit $ Imp.Comment s code' -sIf :: Imp.TExp Bool -> ImpM lore r op () -> ImpM lore r op () -> ImpM lore r op ()+sIf :: Imp.TExp Bool -> ImpM rep r op () -> ImpM rep r op () -> ImpM rep r op () sIf cond tbranch fbranch = do tbranch' <- collect tbranch fbranch' <- collect fbranch emit $ Imp.If cond tbranch' fbranch' -sWhen :: Imp.TExp Bool -> ImpM lore r op () -> ImpM lore r op ()+sWhen :: Imp.TExp Bool -> ImpM rep r op () -> ImpM rep r op () sWhen cond tbranch = sIf cond tbranch (return ()) -sUnless :: Imp.TExp Bool -> ImpM lore r op () -> ImpM lore r op ()+sUnless :: Imp.TExp Bool -> ImpM rep r op () -> ImpM rep r op () sUnless cond = sIf cond (return ()) -sOp :: op -> ImpM lore r op ()+sOp :: op -> ImpM rep r op () sOp = emit . Imp.Op -sDeclareMem :: String -> Space -> ImpM lore r op VName+sDeclareMem :: String -> Space -> ImpM rep r op VName sDeclareMem name space = do name' <- newVName name emit $ Imp.DeclareMem name' space addVar name' $ MemVar Nothing $ MemEntry space return name' -sAlloc_ :: VName -> Count Bytes (Imp.TExp Int64) -> Space -> ImpM lore r op ()+sAlloc_ :: VName -> Count Bytes (Imp.TExp Int64) -> Space -> ImpM rep r op () sAlloc_ name' size' space = do allocator <- asks $ M.lookup space . envAllocCompilers case allocator of Nothing -> emit $ Imp.Allocate name' size' space Just allocator' -> allocator' name' size' -sAlloc :: String -> Count Bytes (Imp.TExp Int64) -> Space -> ImpM lore r op VName+sAlloc :: String -> Count Bytes (Imp.TExp Int64) -> Space -> ImpM rep r op VName sAlloc name size space = do name' <- sDeclareMem name space sAlloc_ name' size space return name' -sArray :: String -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM lore r op VName+sArray :: String -> PrimType -> ShapeBase SubExp -> MemBind -> ImpM rep r op VName sArray name bt shape membind = do name' <- newVName name dArray name' bt shape membind return name' -- | Declare an array in row-major order in the given memory block.-sArrayInMem :: String -> PrimType -> ShapeBase SubExp -> VName -> ImpM lore r op VName+sArrayInMem :: String -> PrimType -> ShapeBase SubExp -> VName -> ImpM rep r op VName sArrayInMem name pt shape mem = sArray name pt shape $ ArrayIn mem $ IxFun.iota $ map (isInt64 . primExpFromSubExp int64) $ shapeDims shape -- | Like 'sAllocArray', but permute the in-memory representation of the indices as specified.-sAllocArrayPerm :: String -> PrimType -> ShapeBase SubExp -> Space -> [Int] -> ImpM lore r op VName+sAllocArrayPerm :: String -> PrimType -> ShapeBase SubExp -> Space -> [Int] -> ImpM rep r op VName sAllocArrayPerm name pt shape space perm = do let permuted_dims = rearrangeShape perm $ shapeDims shape mem <- sAlloc (name ++ "_mem") (typeSize (Array pt shape NoUniqueness)) space@@ -1786,12 +1782,12 @@ ArrayIn mem $ IxFun.permute iota_ixfun $ rearrangeInverse perm -- | Uses linear/iota index function.-sAllocArray :: String -> PrimType -> ShapeBase SubExp -> Space -> ImpM lore r op VName+sAllocArray :: String -> PrimType -> ShapeBase SubExp -> Space -> ImpM rep r op VName sAllocArray name pt shape space = sAllocArrayPerm name pt shape space [0 .. shapeRank shape -1] -- | Uses linear/iota index function.-sStaticArray :: String -> Space -> PrimType -> Imp.ArrayContents -> ImpM lore r op VName+sStaticArray :: String -> Space -> PrimType -> Imp.ArrayContents -> ImpM rep r op VName sStaticArray name space pt vs = do let num_elems = case vs of Imp.ArrayValues vs' -> length vs'@@ -1802,19 +1798,19 @@ addVar mem $ MemVar Nothing $ MemEntry space sArray name pt shape $ ArrayIn mem $ IxFun.iota [fromIntegral num_elems] -sWrite :: VName -> [Imp.TExp Int64] -> Imp.Exp -> ImpM lore r op ()+sWrite :: VName -> [Imp.TExp Int64] -> Imp.Exp -> ImpM rep r op () sWrite arr is v = do (mem, space, offset) <- fullyIndexArray arr is vol <- asks envVolatility emit $ Imp.Write mem offset (primExpType v) space vol v -sUpdate :: VName -> Slice (Imp.TExp Int64) -> SubExp -> ImpM lore r op ()+sUpdate :: VName -> Slice (Imp.TExp Int64) -> SubExp -> ImpM rep r op () sUpdate arr slice v = copyDWIM arr slice v [] sLoopNest :: Shape ->- ([Imp.TExp Int64] -> ImpM lore r op ()) ->- ImpM lore r op ()+ ([Imp.TExp Int64] -> ImpM rep r op ()) ->+ ImpM rep r op () sLoopNest = sLoopNest' [] . shapeDims where sLoopNest' is [] f = f $ reverse is@@ -1822,13 +1818,13 @@ sFor "nest_i" (toInt64Exp d) $ \i -> sLoopNest' (i : is) ds f -- | Untyped assignment.-(<~~) :: VName -> Imp.Exp -> ImpM lore r op ()+(<~~) :: VName -> Imp.Exp -> ImpM rep r op () x <~~ e = emit $ Imp.SetScalar x e infixl 3 <~~ -- | Typed assignment.-(<--) :: TV t -> Imp.TExp t -> ImpM lore r op ()+(<--) :: TV t -> Imp.TExp t -> ImpM rep r op () TV x _ <-- e = emit $ Imp.SetScalar x $ untyped e infixl 3 <--@@ -1839,8 +1835,8 @@ Name -> [Imp.Param] -> [Imp.Param] ->- ImpM lore r op () ->- ImpM lore r op ()+ ImpM rep r op () ->+ ImpM rep r op () function fname outputs inputs m = local newFunction $ do body <- collect $ do mapM_ addParam $ outputs ++ inputs@@ -1853,7 +1849,7 @@ addVar name $ ScalarVar Nothing $ ScalarEntry bt newFunction env = env {envFunction = Just fname} -dSlices :: [Imp.TExp Int64] -> ImpM lore r op [Imp.TExp Int64]+dSlices :: [Imp.TExp Int64] -> ImpM rep r op [Imp.TExp Int64] dSlices = fmap (drop 1 . snd) . dSlices' where dSlices' [] = pure (1, [1])@@ -1869,7 +1865,7 @@ dIndexSpace :: [(VName, Imp.TExp Int64)] -> Imp.TExp Int64 ->- ImpM lore r op ()+ ImpM rep r op () dIndexSpace vs_ds j = do slices <- dSlices (map snd vs_ds) loop (zip (map fst vs_ds) slices) j
src/Futhark/CodeGen/ImpGen/CUDA.hs view
@@ -7,11 +7,11 @@ import Data.Bifunctor (second) import Futhark.CodeGen.ImpCode.OpenCL-import Futhark.CodeGen.ImpGen.Kernels-import Futhark.CodeGen.ImpGen.Kernels.ToOpenCL-import Futhark.IR.KernelsMem+import Futhark.CodeGen.ImpGen.GPU+import Futhark.CodeGen.ImpGen.GPU.ToOpenCL+import Futhark.IR.GPUMem import Futhark.MonadFreshNames -- | Compile the program to ImpCode with CUDA kernels.-compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, Program)+compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, Program) compileProg prog = second kernelsToCUDA <$> compileProgCUDA prog
+ src/Futhark/CodeGen/ImpGen/GPU.hs view
@@ -0,0 +1,431 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}++-- | Compile a 'GPUMem' program to imperative code with kernels.+-- This is mostly (but not entirely) the same process no matter if we+-- are targeting OpenCL or CUDA. The important distinctions (the host+-- level code) are introduced later.+module Futhark.CodeGen.ImpGen.GPU+ ( compileProgOpenCL,+ compileProgCUDA,+ Warnings,+ )+where++import Control.Monad.Except+import Data.Bifunctor (second)+import Data.List (foldl')+import qualified Data.Map as M+import Data.Maybe+import Futhark.CodeGen.ImpCode.GPU (bytes)+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen hiding (compileProg)+import qualified Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.CodeGen.ImpGen.GPU.SegHist+import Futhark.CodeGen.ImpGen.GPU.SegMap+import Futhark.CodeGen.ImpGen.GPU.SegRed+import Futhark.CodeGen.ImpGen.GPU.SegScan+import Futhark.CodeGen.ImpGen.GPU.Transpose+import Futhark.CodeGen.SetDefaultSpace+import Futhark.Error+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.MonadFreshNames+import Futhark.Util.IntegralExp (IntegralExp, divUp, quot, rem)+import Prelude hiding (quot, rem)++callKernelOperations :: Operations GPUMem HostEnv Imp.HostOp+callKernelOperations =+ Operations+ { opsExpCompiler = expCompiler,+ opsCopyCompiler = callKernelCopy,+ opsOpCompiler = opCompiler,+ opsStmsCompiler = defCompileStms,+ opsAllocCompilers = mempty+ }++openclAtomics, cudaAtomics :: AtomicBinOp+(openclAtomics, cudaAtomics) = (flip lookup opencl, flip lookup cuda)+ where+ opencl64 =+ [ (Add Int64 OverflowUndef, Imp.AtomicAdd Int64),+ (SMax Int64, Imp.AtomicSMax Int64),+ (SMin Int64, Imp.AtomicSMin Int64),+ (UMax Int64, Imp.AtomicUMax Int64),+ (UMin Int64, Imp.AtomicUMin Int64),+ (And Int64, Imp.AtomicAnd Int64),+ (Or Int64, Imp.AtomicOr Int64),+ (Xor Int64, Imp.AtomicXor Int64)+ ]+ opencl32 =+ [ (Add Int32 OverflowUndef, Imp.AtomicAdd Int32),+ (SMax Int32, Imp.AtomicSMax Int32),+ (SMin Int32, Imp.AtomicSMin Int32),+ (UMax Int32, Imp.AtomicUMax Int32),+ (UMin Int32, Imp.AtomicUMin Int32),+ (And Int32, Imp.AtomicAnd Int32),+ (Or Int32, Imp.AtomicOr Int32),+ (Xor Int32, Imp.AtomicXor Int32)+ ]+ opencl = opencl32 ++ opencl64+ cuda =+ opencl+ ++ [ (FAdd Float32, Imp.AtomicFAdd Float32),+ (FAdd Float64, Imp.AtomicFAdd Float64)+ ]++compileProg ::+ MonadFreshNames m =>+ HostEnv ->+ Prog GPUMem ->+ m (Warnings, Imp.Program)+compileProg env prog =+ second (setDefaultSpace (Imp.Space "device"))+ <$> Futhark.CodeGen.ImpGen.compileProg env callKernelOperations (Imp.Space "device") prog++-- | Compile a 'GPUMem' program to low-level parallel code, with+-- either CUDA or OpenCL characteristics.+compileProgOpenCL,+ compileProgCUDA ::+ MonadFreshNames m => Prog GPUMem -> m (Warnings, Imp.Program)+compileProgOpenCL = compileProg $ HostEnv openclAtomics OpenCL mempty+compileProgCUDA = compileProg $ HostEnv cudaAtomics CUDA mempty++opCompiler ::+ Pattern GPUMem ->+ Op GPUMem ->+ CallKernelGen ()+opCompiler dest (Alloc e space) =+ compileAlloc dest e space+opCompiler (Pattern _ [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+ 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))) =+ sOp $ Imp.GetSizeMax (patElemName pe) size_class+opCompiler (Pattern _ [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 $+ Imp.GetSize (tvVar max_num_groups) (keyWithEntryPoint fname max_num_groups_key) $+ sizeClassWithEntryPoint fname SizeNumGroups++ -- If 'w' is small, we launch fewer groups than we normally would.+ -- We don't want any idle groups.+ --+ -- The calculations are done with 64-bit integers to avoid overflow+ -- issues.+ let num_groups_maybe_zero =+ sMin64 (toInt64Exp w64 `divUp` toInt64Exp group_size) $+ sExt64 (tvExp max_num_groups)+ -- We also don't want zero groups.+ let num_groups = sMax64 1 num_groups_maybe_zero+ mkTV (patElemName pe) int32 <-- sExt32 num_groups+opCompiler dest (Inner (SegOp op)) =+ segOpCompiler dest op+opCompiler pat e =+ compilerBugS $+ "opCompiler: Invalid pattern\n "+ ++ pretty pat+ ++ "\nfor expression\n "+ ++ pretty e++sizeClassWithEntryPoint :: Maybe Name -> Imp.SizeClass -> Imp.SizeClass+sizeClassWithEntryPoint fname (Imp.SizeThreshold path def) =+ Imp.SizeThreshold (map f path) def+ where+ f (name, x) = (keyWithEntryPoint fname name, x)+sizeClassWithEntryPoint _ size_class = size_class++segOpCompiler ::+ Pattern GPUMem ->+ SegOp SegLevel GPUMem ->+ CallKernelGen ()+segOpCompiler pat (SegMap lvl space _ kbody) =+ compileSegMap pat lvl space kbody+segOpCompiler pat (SegRed lvl@SegThread {} space reds _ kbody) =+ compileSegRed pat lvl space reds kbody+segOpCompiler pat (SegScan lvl@SegThread {} space scans _ kbody) =+ compileSegScan pat lvl space scans kbody+segOpCompiler pat (SegHist (SegThread num_groups group_size _) space ops _ kbody) =+ compileSegHist pat num_groups group_size space ops kbody+segOpCompiler pat segop =+ compilerBugS $ "segOpCompiler: unexpected " ++ pretty (segLevel segop) ++ " for rhs of pattern " ++ pretty pat++-- Create boolean expression that checks whether all kernels in the+-- enclosed code do not use more local memory than we have available.+-- We look at *all* the kernels here, even those that might be+-- otherwise protected by their own multi-versioning branches deeper+-- down. Currently the compiler will not generate multi-versioning+-- that makes this a problem, but it might in the future.+checkLocalMemoryReqs :: Imp.Code -> CallKernelGen (Maybe (Imp.TExp Bool))+checkLocalMemoryReqs code = do+ scope <- askScope+ let alloc_sizes = map (sum . map alignedSize . localAllocSizes . Imp.kernelBody) $ getGPU code++ -- If any of the sizes involve a variable that is not known at this+ -- point, then we cannot check the requirements.+ if any (`M.notMember` scope) (namesToList $ freeIn alloc_sizes)+ then return Nothing+ else do+ local_memory_capacity :: TV Int32 <- dPrim "local_memory_capacity" int32+ sOp $ Imp.GetSizeMax (tvVar local_memory_capacity) SizeLocalMemory++ let local_memory_capacity_64 =+ sExt64 $ tvExp local_memory_capacity+ fits size =+ unCount size .<=. local_memory_capacity_64+ return $ Just $ foldl' (.&&.) true (map fits alloc_sizes)+ where+ getGPU = foldMap getKernel+ getKernel (Imp.CallKernel k) = [k]+ getKernel _ = []++ localAllocSizes = foldMap localAllocSize+ localAllocSize (Imp.LocalAlloc _ size) = [size]+ localAllocSize _ = []++ -- These allocations will actually be padded to an 8-byte aligned+ -- size, so we should take that into account when checking whether+ -- they fit.+ alignedSize x = x + ((8 - (x `rem` 8)) `rem` 8)++withAcc ::+ Pattern GPUMem ->+ [(Shape, [VName], Maybe (Lambda GPUMem, [SubExp]))] ->+ Lambda GPUMem ->+ CallKernelGen ()+withAcc pat inputs lam = do+ atomics <- hostAtomics <$> askEnv+ locksForInputs atomics $ zip accs inputs+ where+ accs = map paramName $ lambdaParams lam+ locksForInputs _ [] =+ defCompileExp pat $ WithAcc inputs lam+ locksForInputs atomics ((c, (_, _, op)) : inputs')+ | Just (op_lam, _) <- op,+ AtomicLocking _ <- atomicUpdateLocking atomics op_lam = do+ let num_locks = 100151+ locks_arr <-+ sStaticArray "withacc_locks" (Space "device") int32 $+ Imp.ArrayZeros num_locks+ let locks = Locks locks_arr num_locks+ extend env = env {hostLocks = M.insert c locks $ hostLocks env}+ localEnv extend $ locksForInputs atomics inputs'+ | otherwise =+ locksForInputs atomics inputs'++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+ x' <- toExp x+ s' <- toExp s++ sIota (patElemName pe) (toInt64Exp n) x' s' et+expCompiler (Pattern _ [pe]) (BasicOp (Replicate _ se)) =+ sReplicate (patElemName pe) se+-- Allocation in the "local" space is just a placeholder.+expCompiler _ (Op (Alloc _ (Space "local"))) =+ return ()+expCompiler pat (WithAcc inputs lam) =+ withAcc pat inputs lam+-- This is a multi-versioning If created by incremental flattening.+-- We need to augment the conditional with a check that any local+-- memory requirements in tbranch are compatible with the hardware.+-- We do not check anything for fbranch, as we assume that it will+-- always be safe (and what would we do if none of the branches would+-- work?).+expCompiler dest (If cond tbranch fbranch (IfDec _ IfEquiv)) = do+ tcode <- collect $ compileBody dest tbranch+ fcode <- collect $ compileBody dest fbranch+ check <- checkLocalMemoryReqs tcode+ emit $ case check of+ Nothing -> fcode+ Just ok -> Imp.If (ok .&&. toBoolExp cond) tcode fcode+expCompiler dest e =+ 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++mapTransposeForType :: PrimType -> CallKernelGen Name+mapTransposeForType bt = do+ let fname = nameFromString $ "builtin#" <> mapTransposeName bt++ exists <- hasFunction fname+ unless exists $ emitFunction fname $ mapTransposeFunction bt++ return fname++mapTransposeName :: PrimType -> String+mapTransposeName bt = "gpu_map_transpose_" ++ pretty bt++mapTransposeFunction :: PrimType -> Imp.Function+mapTransposeFunction bt =+ Imp.Function Nothing [] params transpose_code [] []+ where+ params =+ [ memparam destmem,+ intparam destoffset,+ memparam srcmem,+ intparam srcoffset,+ intparam num_arrays,+ intparam x,+ intparam y+ ]++ space = Space "device"+ memparam v = Imp.MemParam v space+ intparam v = Imp.ScalarParam v $ IntType Int32++ [ destmem,+ destoffset,+ srcmem,+ srcoffset,+ num_arrays,+ x,+ y,+ mulx,+ muly,+ block+ ] =+ zipWith+ (VName . nameFromString)+ [ "destmem",+ "destoffset",+ "srcmem",+ "srcoffset",+ "num_arrays",+ "x_elems",+ "y_elems",+ -- The following is only used for low width/height+ -- transpose kernels+ "mulx",+ "muly",+ "block"+ ]+ [0 ..]++ block_dim_int = 16++ block_dim :: IntegralExp a => a+ block_dim = 16++ -- When an input array has either width==1 or height==1, performing a+ -- transpose will be the same as performing a copy.+ can_use_copy =+ let onearr = Imp.vi32 num_arrays .==. 1+ height_is_one = Imp.vi32 y .==. 1+ width_is_one = Imp.vi32 x .==. 1+ in onearr .&&. (width_is_one .||. height_is_one)++ transpose_code =+ Imp.If input_is_empty mempty $+ mconcat+ [ Imp.DeclareScalar muly Imp.Nonvolatile (IntType Int32),+ Imp.SetScalar muly $ untyped $ block_dim `quot` Imp.vi32 x,+ Imp.DeclareScalar mulx Imp.Nonvolatile (IntType Int32),+ Imp.SetScalar mulx $ untyped $ block_dim `quot` Imp.vi32 y,+ Imp.If can_use_copy copy_code $+ Imp.If should_use_lowwidth (callTransposeKernel TransposeLowWidth) $+ Imp.If should_use_lowheight (callTransposeKernel TransposeLowHeight) $+ Imp.If should_use_small (callTransposeKernel TransposeSmall) $+ callTransposeKernel TransposeNormal+ ]++ input_is_empty =+ Imp.vi32 num_arrays .==. 0 .||. Imp.vi32 x .==. 0 .||. Imp.vi32 y .==. 0++ should_use_small =+ Imp.vi32 x .<=. (block_dim `quot` 2)+ .&&. Imp.vi32 y .<=. (block_dim `quot` 2)++ should_use_lowwidth =+ Imp.vi32 x .<=. (block_dim `quot` 2)+ .&&. block_dim .<. Imp.vi32 y++ should_use_lowheight =+ Imp.vi32 y .<=. (block_dim `quot` 2)+ .&&. block_dim .<. Imp.vi32 x++ copy_code =+ let num_bytes = sExt64 $ Imp.vi32 x * Imp.vi32 y * primByteSize bt+ in Imp.Copy+ destmem+ (Imp.Count $ sExt64 $ Imp.vi32 destoffset)+ space+ srcmem+ (Imp.Count $ sExt64 $ Imp.vi32 srcoffset)+ space+ (Imp.Count num_bytes)++ callTransposeKernel =+ Imp.Op . Imp.CallKernel+ . mapTransposeKernel+ (mapTransposeName bt)+ block_dim_int+ ( destmem,+ Imp.vi32 destoffset,+ srcmem,+ Imp.vi32 srcoffset,+ Imp.vi32 x,+ Imp.vi32 y,+ Imp.vi32 mulx,+ Imp.vi32 muly,+ Imp.vi32 num_arrays,+ block+ )+ bt
+ src/Futhark/CodeGen/ImpGen/GPU/Base.hs view
@@ -0,0 +1,1785 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeFamilies #-}++module Futhark.CodeGen.ImpGen.GPU.Base+ ( KernelConstants (..),+ keyWithEntryPoint,+ CallKernelGen,+ InKernelGen,+ Locks (..),+ HostEnv (..),+ Target (..),+ KernelEnv (..),+ computeThreadChunkSize,+ groupReduce,+ groupScan,+ isActive,+ sKernelThread,+ sKernelGroup,+ sReplicate,+ sIota,+ sCopy,+ compileThreadResult,+ compileGroupResult,+ virtualiseGroups,+ groupLoop,+ kernelLoop,+ groupCoverSpace,+ precomputeSegOpIDs,+ atomicUpdateLocking,+ AtomicBinOp,+ Locking (..),+ AtomicUpdate (..),+ DoAtomicUpdate,+ )+where++import Control.Monad.Except+import Data.List (zip4)+import qualified Data.Map.Strict as M+import Data.Maybe+import qualified Data.Set as S+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.Error+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.MonadFreshNames+import Futhark.Transform.Rename+import Futhark.Util (chunks, dropLast, mapAccumLM, nubOrd, takeLast)+import Futhark.Util.IntegralExp (divUp, quot, rem)+import Prelude hiding (quot, rem)++-- | Which target are we ultimately generating code for? While most+-- of the kernels code is the same, there are some cases where we+-- generate special code based on the ultimate low-level API we are+-- targeting.+data Target = CUDA | OpenCL++-- | Information about the locks available for accumulators.+data Locks = Locks+ { locksArray :: VName,+ locksCount :: Int+ }++data HostEnv = HostEnv+ { hostAtomics :: AtomicBinOp,+ hostTarget :: Target,+ hostLocks :: M.Map VName Locks+ }++data KernelEnv = KernelEnv+ { kernelAtomics :: AtomicBinOp,+ kernelConstants :: KernelConstants,+ kernelLocks :: M.Map VName Locks+ }++type CallKernelGen = ImpM GPUMem HostEnv Imp.HostOp++type InKernelGen = ImpM GPUMem KernelEnv Imp.KernelOp++data KernelConstants = KernelConstants+ { kernelGlobalThreadId :: Imp.TExp Int32,+ kernelLocalThreadId :: Imp.TExp Int32,+ kernelGroupId :: Imp.TExp Int32,+ kernelGlobalThreadIdVar :: VName,+ kernelLocalThreadIdVar :: VName,+ kernelGroupIdVar :: VName,+ kernelNumGroups :: Imp.TExp Int64,+ kernelGroupSize :: Imp.TExp Int64,+ kernelNumThreads :: Imp.TExp Int32,+ kernelWaveSize :: Imp.TExp Int32,+ kernelThreadActive :: Imp.TExp Bool,+ -- | A mapping from dimensions of nested SegOps to already+ -- computed local thread IDs.+ kernelLocalIdMap :: M.Map [SubExp] [Imp.TExp Int32]+ }++segOpSizes :: Stms GPUMem -> S.Set [SubExp]+segOpSizes = onStms+ where+ onStms = foldMap (onExp . stmExp)+ onExp (Op (Inner (SegOp op))) =+ S.singleton $ map snd $ unSegSpace $ segSpace op+ onExp (If _ tbranch fbranch _) =+ onStms (bodyStms tbranch) <> onStms (bodyStms fbranch)+ onExp (DoLoop _ _ _ body) =+ onStms (bodyStms body)+ onExp _ = mempty++precomputeSegOpIDs :: Stms GPUMem -> InKernelGen a -> InKernelGen a+precomputeSegOpIDs stms m = do+ ltid <- kernelLocalThreadId . kernelConstants <$> askEnv+ new_ids <- M.fromList <$> mapM (mkMap ltid) (S.toList (segOpSizes stms))+ let f env =+ env+ { kernelConstants =+ (kernelConstants env) {kernelLocalIdMap = new_ids}+ }+ 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')++keyWithEntryPoint :: Maybe Name -> Name -> Name+keyWithEntryPoint fname key =+ nameFromString $ maybe "" ((++ ".") . nameToString) fname ++ nameToString key++allocLocal :: AllocCompiler GPUMem r Imp.KernelOp+allocLocal mem size =+ sOp $ Imp.LocalAlloc mem size++kernelAlloc ::+ Pattern GPUMem ->+ SubExp ->+ Space ->+ InKernelGen ()+kernelAlloc (Pattern _ [_]) _ 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") =+ allocLocal (patElemName mem) $ Imp.bytes $ toInt64Exp size+kernelAlloc (Pattern _ [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 ->+ SplitOrdering ->+ w ->+ i ->+ elems_per_thread ->+ ImpM rep r op ()+splitSpace (Pattern [] [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+ computeThreadChunkSize o i' elems_per_thread' num_elements (mkTV (patElemName size) int64)+splitSpace pat _ _ _ _ =+ error $ "Invalid target for splitSpace: " ++ pretty pat++updateAcc :: VName -> [SubExp] -> [SubExp] -> InKernelGen ()+updateAcc acc is vs = sComment "UpdateAcc" $ do+ -- 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) $+ case op of+ Nothing ->+ forM_ (zip arrs vs) $ \(arr, v) -> copyDWIMFix arr is' v []+ Just lam -> do+ dLParams $ lambdaParams lam+ let (_x_params, y_params) =+ splitAt (length vs) $ map paramName $ lambdaParams lam+ forM_ (zip y_params vs) $ \(yp, v) -> copyDWIM yp [] v []+ atomics <- kernelAtomics <$> askEnv+ case atomicUpdateLocking atomics lam of+ AtomicPrim f -> f space arrs is'+ AtomicCAS f -> f space arrs is'+ AtomicLocking f -> do+ c_locks <- M.lookup c . kernelLocks <$> askEnv+ case c_locks of+ Just (Locks locks num_locks) -> do+ let locking =+ Locking locks 0 1 0 $+ pure . (`rem` fromIntegral num_locks) . flattenIndex dims+ f locking space arrs is'+ Nothing ->+ error $ "Missing locks for " ++ pretty acc++compileThreadExp :: ExpCompiler GPUMem KernelEnv Imp.KernelOp+compileThreadExp (Pattern _ [dest]) (BasicOp (ArrayLit es _)) =+ forM_ (zip [0 ..] es) $ \(i, e) ->+ copyDWIMFix (patElemName dest) [fromIntegral (i :: Int64)] e []+compileThreadExp _ (BasicOp (UpdateAcc acc is vs)) =+ updateAcc acc is vs+compileThreadExp dest e =+ defCompileExp dest e++-- | Assign iterations of a for-loop to all threads in the kernel.+-- The passed-in function is invoked with the (symbolic) iteration.+-- 'threadOperations' will be in effect in the body. For+-- multidimensional loops, use 'groupCoverSpace'.+kernelLoop ::+ IntExp t =>+ Imp.TExp t ->+ Imp.TExp t ->+ Imp.TExp t ->+ (Imp.TExp t -> InKernelGen ()) ->+ InKernelGen ()+kernelLoop tid num_threads n f =+ localOps threadOperations $+ if n == num_threads+ then f tid+ else do+ -- Compute how many elements this thread is responsible for.+ -- Formula: (n - tid) / num_threads (rounded up).+ let elems_for_this = (n - tid) `divUp` num_threads++ sFor "i" elems_for_this $ \i -> f $ i * num_threads + tid++-- | Assign iterations of a for-loop to threads in the workgroup. The+-- passed-in function is invoked with the (symbolic) iteration. For+-- multidimensional loops, use 'groupCoverSpace'.+groupLoop ::+ Imp.TExp Int64 ->+ (Imp.TExp Int64 -> InKernelGen ()) ->+ InKernelGen ()+groupLoop n f = do+ constants <- kernelConstants <$> askEnv+ kernelLoop+ (sExt64 $ kernelLocalThreadId constants)+ (kernelGroupSize constants)+ n+ f++-- | Iterate collectively though a multidimensional space, such that+-- all threads in the group participate. The passed-in function is+-- invoked with a (symbolic) point in the index space.+groupCoverSpace ::+ [Imp.TExp Int64] ->+ ([Imp.TExp Int64] -> InKernelGen ()) ->+ InKernelGen ()+groupCoverSpace ds f =+ groupLoop (product ds) $ f . unflattenIndex ds++compileGroupExp :: ExpCompiler GPUMem KernelEnv Imp.KernelOp+-- The static arrays stuff does not work inside kernels.+compileGroupExp (Pattern _ [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+ 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+ n' <- toExp n+ e' <- toExp e+ s' <- toExp s+ groupLoop (TPrimExp n') $ \i' -> do+ x <-+ dPrimV "x" $+ TPrimExp $+ BinOpExp (Add it OverflowUndef) e' $+ BinOpExp (Mul it OverflowUndef) (untyped i') s'+ copyDWIMFix (patElemName dest) [i'] (Var (tvVar x)) []+ sOp $ Imp.Barrier Imp.FenceLocal++-- When generating code for a scalar in-place update, we must make+-- 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))+ | null $ sliceDims slice = do+ sOp $ Imp.Barrier Imp.FenceLocal+ ltid <- kernelLocalThreadId . kernelConstants <$> askEnv+ sWhen (ltid .==. 0) $+ copyDWIM (patElemName pe) (map (fmap toInt64Exp) slice) se []+ sOp $ Imp.Barrier Imp.FenceLocal+compileGroupExp dest e =+ defCompileExp dest e++sanityCheckLevel :: SegLevel -> InKernelGen ()+sanityCheckLevel SegThread {} = return ()+sanityCheckLevel SegGroup {} =+ error "compileGroupOp: unexpected group-level SegOp."++localThreadIDs :: [SubExp] -> InKernelGen [Imp.TExp Int64]+localThreadIDs dims = do+ ltid <- sExt64 . kernelLocalThreadId . kernelConstants <$> askEnv+ let dims' = map toInt64Exp dims+ maybe (unflattenIndex dims' ltid) (map sExt64)+ . M.lookup dims+ . kernelLocalIdMap+ . kernelConstants+ <$> askEnv++compileGroupSpace :: SegLevel -> SegSpace -> InKernelGen ()+compileGroupSpace lvl space = do+ sanityCheckLevel lvl+ let (ltids, dims) = unzip $ unSegSpace space+ zipWithM_ dPrimV_ ltids =<< localThreadIDs dims+ ltid <- kernelLocalThreadId . kernelConstants <$> askEnv+ dPrimV_ (segFlat space) ltid++-- Construct the necessary lock arrays for an intra-group histogram.+prepareIntraGroupSegHist ::+ Count GroupSize SubExp ->+ [HistOp GPUMem] ->+ InKernelGen [[Imp.TExp Int64] -> InKernelGen ()]+prepareIntraGroupSegHist group_size =+ fmap snd . mapAccumLM onOp Nothing+ where+ onOp l op = do+ constants <- kernelConstants <$> askEnv+ atomicBinOp <- kernelAtomics <$> askEnv++ let local_subhistos = histDest op++ case (l, atomicUpdateLocking atomicBinOp $ histOp op) of+ (_, AtomicPrim f) -> return (l, f (Space "local") local_subhistos)+ (_, AtomicCAS f) -> return (l, f (Space "local") local_subhistos)+ (Just l', AtomicLocking f) -> return (l, f l' (Space "local") local_subhistos)+ (Nothing, AtomicLocking f) -> do+ locks <- newVName "locks"++ let num_locks = toInt64Exp $ unCount group_size+ dims = map toInt64Exp $ shapeDims (histShape op) ++ [histWidth op]+ l' = Locking locks 0 1 0 (pure . (`rem` num_locks) . flattenIndex dims)+ locks_t = Array int32 (Shape [unCount group_size]) NoUniqueness++ locks_mem <- sAlloc "locks_mem" (typeSize locks_t) $ Space "local"+ dArray locks int32 (arrayShape locks_t) $+ ArrayIn locks_mem $+ IxFun.iota $+ map pe64 $ arrayDims locks_t++ sComment "All locks start out unlocked" $+ groupCoverSpace [kernelGroupSize constants] $ \is ->+ copyDWIMFix locks is (intConst Int32 0) []++ return (Just l', f l' (Space "local") local_subhistos)++whenActive :: SegLevel -> SegSpace -> InKernelGen () -> InKernelGen ()+whenActive lvl space m+ | SegNoVirtFull <- segVirt lvl = m+ | otherwise = do+ group_size <- kernelGroupSize . kernelConstants <$> askEnv+ -- XXX: the following check is too naive - we should also handle+ -- the multi-dimensional case.+ if [group_size] == map (toInt64Exp . snd) (unSegSpace space)+ then m+ else sWhen (isActive $ unSegSpace space) m++compileGroupOp :: OpCompiler GPUMem KernelEnv Imp.KernelOp+compileGroupOp pat (Alloc size space) =+ kernelAlloc pat size space+compileGroupOp pat (Inner (SizeOp (SplitSpace o w i elems_per_thread))) =+ splitSpace pat o w i elems_per_thread+compileGroupOp pat (Inner (SegOp (SegMap lvl space _ body))) = do+ void $ compileGroupSpace lvl space++ whenActive lvl space $+ localOps threadOperations $+ compileStms mempty (kernelBodyStms body) $+ zipWithM_ (compileThreadResult space) (patternElements pat) $+ kernelBodyResult body++ sOp $ Imp.ErrorSync Imp.FenceLocal+compileGroupOp pat (Inner (SegOp (SegScan lvl space scans _ body))) = do+ compileGroupSpace lvl space+ let (ltids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims++ whenActive lvl space $+ compileStms mempty (kernelBodyStms body) $+ forM_ (zip (patternNames pat) $ kernelBodyResult body) $ \(dest, res) ->+ copyDWIMFix+ dest+ (map Imp.vi64 ltids)+ (kernelResultSubExp res)+ []++ sOp $ Imp.ErrorSync Imp.FenceLocal++ let segment_size = last dims'+ crossesSegment from to =+ (sExt64 to - sExt64 from) .>. (sExt64 to `rem` segment_size)++ -- groupScan needs to treat the scan output as a one-dimensional+ -- array of scan elements, so we invent some new flattened arrays+ -- here. XXX: this assumes that the original index function is just+ -- 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)+ let pe_t = typeOf pe+ arr_dims = Var (tvVar dims_flat) : drop (length dims') (arrayDims pe_t)+ sArray+ (baseString (patElemName pe) ++ "_flat")+ (elemType pe_t)+ (Shape arr_dims)+ $ ArrayIn mem $ IxFun.iota $ map pe64 arr_dims++ num_scan_results = sum $ map (length . segBinOpNeutral) scans++ arrs_flat <- mapM flattened $ take num_scan_results $ patternElements pat++ forM_ scans $ \scan -> do+ let scan_op = segBinOpLambda scan+ groupScan (Just crossesSegment) (product dims') (product dims') scan_op arrs_flat+compileGroupOp pat (Inner (SegOp (SegRed lvl space ops _ body))) = do+ compileGroupSpace lvl space++ let (ltids, dims) = unzip $ unSegSpace space+ (red_pes, map_pes) =+ splitAt (segBinOpResults ops) $ patternElements pat++ dims' = map toInt64Exp dims++ mkTempArr t =+ sAllocArray "red_arr" (elemType t) (Shape dims <> arrayShape t) $ Space "local"++ tmp_arrs <- mapM mkTempArr $ concatMap (lambdaReturnType . segBinOpLambda) ops+ let tmps_for_ops = chunks (map (length . segBinOpNeutral) ops) tmp_arrs++ whenActive lvl space $+ compileStms mempty (kernelBodyStms body) $ do+ let (red_res, map_res) =+ splitAt (segBinOpResults ops) $ kernelBodyResult body+ forM_ (zip tmp_arrs red_res) $ \(dest, res) ->+ copyDWIMFix dest (map Imp.vi64 ltids) (kernelResultSubExp res) []+ zipWithM_ (compileThreadResult space) map_pes map_res++ sOp $ Imp.ErrorSync Imp.FenceLocal++ case dims' of+ -- Nonsegmented case (or rather, a single segment) - this we can+ -- handle directly with a group-level reduction.+ [dim'] -> do+ forM_ (zip ops tmps_for_ops) $ \(op, tmps) ->+ groupReduce (sExt32 dim') (segBinOpLambda op) tmps++ sOp $ Imp.ErrorSync Imp.FenceLocal++ forM_ (zip red_pes tmp_arrs) $ \(pe, arr) ->+ copyDWIMFix (patElemName pe) [] (Var arr) [0]+ _ -> do+ -- Segmented intra-group reductions are turned into (regular)+ -- segmented scans. It is possible that this can be done+ -- better, but at least this approach is simple.++ -- groupScan operates on flattened arrays. This does not+ -- involve copying anything; merely playing with the index+ -- function.+ dims_flat <- dPrimV "dims_flat" $ product dims'+ let flatten arr = do+ ArrayEntry arr_loc pt <- lookupArray arr+ let flat_shape =+ Shape $+ Var (tvVar dims_flat) :+ drop (length ltids) (memLocationShape arr_loc)+ sArray "red_arr_flat" pt flat_shape $+ ArrayIn (memLocationName arr_loc) $+ IxFun.iota $ map pe64 $ shapeDims flat_shape++ let segment_size = last dims'+ crossesSegment from to =+ (sExt64 to - sExt64 from) .>. (sExt64 to `rem` sExt64 segment_size)++ forM_ (zip ops tmps_for_ops) $ \(op, tmps) -> do+ tmps_flat <- mapM flatten tmps+ groupScan+ (Just crossesSegment)+ (product dims')+ (product dims')+ (segBinOpLambda op)+ tmps_flat++ sOp $ Imp.ErrorSync Imp.FenceLocal++ forM_ (zip red_pes tmp_arrs) $ \(pe, arr) ->+ copyDWIM+ (patElemName pe)+ []+ (Var arr)+ (map (unitSlice 0) (init dims') ++ [DimFix $ last dims' -1])++ sOp $ Imp.Barrier Imp.FenceLocal+compileGroupOp pat (Inner (SegOp (SegHist lvl space ops _ kbody))) = do+ compileGroupSpace lvl space+ let ltids = map fst $ unSegSpace space++ -- We don't need the red_pes, because it is guaranteed by our type+ -- rules that they occupy the same memory as the destinations for+ -- the ops.+ let num_red_res = length ops + sum (map (length . histNeutral) ops)+ (_red_pes, map_pes) =+ splitAt num_red_res $ patternElements pat++ ops' <- prepareIntraGroupSegHist (segGroupSize lvl) ops++ -- Ensure that all locks have been initialised.+ sOp $ Imp.Barrier Imp.FenceLocal++ whenActive lvl space $+ compileStms mempty (kernelBodyStms kbody) $ do+ let (red_res, map_res) = splitAt num_red_res $ kernelBodyResult kbody+ (red_is, red_vs) = splitAt (length ops) $ map kernelResultSubExp red_res+ zipWithM_ (compileThreadResult space) map_pes map_res++ let vs_per_op = chunks (map (length . histDest) ops) red_vs++ forM_ (zip4 red_is vs_per_op ops' ops) $+ \(bin, op_vs, do_op, HistOp dest_w _ _ _ shape lam) -> do+ let bin' = toInt64Exp bin+ dest_w' = toInt64Exp dest_w+ bin_in_bounds = 0 .<=. bin' .&&. bin' .<. dest_w'+ bin_is = map Imp.vi64 (init ltids) ++ [bin']+ vs_params = takeLast (length op_vs) $ lambdaParams lam++ sComment "perform atomic updates" $+ sWhen bin_in_bounds $ do+ dLParams $ lambdaParams lam+ sLoopNest shape $ \is -> do+ forM_ (zip vs_params op_vs) $ \(p, v) ->+ copyDWIMFix (paramName p) [] v is+ do_op (bin_is ++ is)++ sOp $ Imp.ErrorSync Imp.FenceLocal+compileGroupOp pat _ =+ compilerBugS $ "compileGroupOp: cannot compile rhs of binding " ++ pretty pat++compileThreadOp :: OpCompiler GPUMem KernelEnv Imp.KernelOp+compileThreadOp pat (Alloc size space) =+ kernelAlloc pat size space+compileThreadOp pat (Inner (SizeOp (SplitSpace o w i elems_per_thread))) =+ splitSpace pat o w i elems_per_thread+compileThreadOp pat _ =+ compilerBugS $ "compileThreadOp: cannot compile rhs of binding " ++ pretty pat++-- | Locking strategy used for an atomic update.+data Locking = Locking+ { -- | Array containing the lock.+ lockingArray :: VName,+ -- | Value for us to consider the lock free.+ lockingIsUnlocked :: Imp.TExp Int32,+ -- | What to write when we lock it.+ lockingToLock :: Imp.TExp Int32,+ -- | What to write when we unlock it.+ lockingToUnlock :: Imp.TExp Int32,+ -- | A transformation from the logical lock index to the+ -- physical position in the array. This can also be used+ -- to make the lock array smaller.+ lockingMapping :: [Imp.TExp Int64] -> [Imp.TExp Int64]+ }++-- | A function for generating code for an atomic update. Assumes+-- that the bucket is in-bounds.+type DoAtomicUpdate rep r =+ Space -> [VName] -> [Imp.TExp Int64] -> ImpM rep r Imp.KernelOp ()++-- | The mechanism that will be used for performing the atomic update.+-- Approximates how efficient it will be. Ordered from most to least+-- efficient.+data AtomicUpdate rep r+ = -- | Supported directly by primitive.+ AtomicPrim (DoAtomicUpdate rep r)+ | -- | Can be done by efficient swaps.+ AtomicCAS (DoAtomicUpdate rep r)+ | -- | Requires explicit locking.+ AtomicLocking (Locking -> DoAtomicUpdate rep r)++-- | Is there an atomic t'BinOp' corresponding to this t'BinOp'?+type AtomicBinOp =+ BinOp ->+ Maybe (VName -> VName -> Count Imp.Elements (Imp.TExp Int64) -> Imp.Exp -> Imp.AtomicOp)++-- | Do an atomic update corresponding to a binary operator lambda.+atomicUpdateLocking ::+ AtomicBinOp ->+ Lambda GPUMem ->+ AtomicUpdate GPUMem KernelEnv+atomicUpdateLocking atomicBinOp lam+ | Just ops_and_ts <- lamIsBinOp lam,+ all (\(_, t, _, _) -> primBitSize t `elem` [32, 64]) ops_and_ts =+ primOrCas ops_and_ts $ \space arrs bucket ->+ -- If the operator is a vectorised binary operator on 32/64-bit+ -- values, we can use a particularly efficient+ -- implementation. If the operator has an atomic implementation+ -- we use that, otherwise it is still a binary operator which+ -- can be implemented by atomic compare-and-swap if 32/64 bits.+ forM_ (zip arrs ops_and_ts) $ \(a, (op, t, x, y)) -> do+ -- Common variables.+ old <- dPrim "old" t++ (arr', _a_space, bucket_offset) <- fullyIndexArray a bucket++ case opHasAtomicSupport space (tvVar old) arr' bucket_offset op of+ Just f -> sOp $ f $ Imp.var y t+ Nothing ->+ atomicUpdateCAS space t a (tvVar old) bucket x $+ x <~~ Imp.BinOpExp op (Imp.var x t) (Imp.var y t)+ where+ opHasAtomicSupport space old arr' bucket' bop = do+ let atomic f = Imp.Atomic space . f old arr' bucket'+ atomic <$> atomicBinOp bop++ primOrCas ops+ | all isPrim ops = AtomicPrim+ | otherwise = AtomicCAS++ isPrim (op, _, _, _) = isJust $ atomicBinOp op++-- If the operator functions purely on single 32/64-bit values, we can+-- use an implementation based on CAS, no matter what the operator+-- does.+atomicUpdateLocking _ op+ | [Prim t] <- lambdaReturnType op,+ [xp, _] <- lambdaParams op,+ primBitSize t `elem` [32, 64] = AtomicCAS $ \space [arr] bucket -> do+ old <- dPrim "old" t+ atomicUpdateCAS space t arr (tvVar old) bucket (paramName xp) $+ compileBody' [xp] $ lambdaBody op+atomicUpdateLocking _ op = AtomicLocking $ \locking space arrs bucket -> do+ old <- dPrim "old" int32+ continue <- dPrimVol "continue" Bool true++ -- Correctly index into locks.+ (locks', _locks_space, locks_offset) <-+ fullyIndexArray (lockingArray locking) $ lockingMapping locking bucket++ -- Critical section+ let try_acquire_lock =+ sOp $+ Imp.Atomic space $+ Imp.AtomicCmpXchg+ int32+ (tvVar old)+ locks'+ locks_offset+ (untyped $ lockingIsUnlocked locking)+ (untyped $ lockingToLock locking)+ lock_acquired = tvExp old .==. lockingIsUnlocked locking+ -- Even the releasing is done with an atomic rather than a+ -- simple write, for memory coherency reasons.+ release_lock =+ sOp $+ Imp.Atomic space $+ Imp.AtomicCmpXchg+ int32+ (tvVar old)+ locks'+ locks_offset+ (untyped $ lockingToLock locking)+ (untyped $ lockingToUnlock locking)+ break_loop = continue <-- false++ -- Preparing parameters. It is assumed that the caller has already+ -- filled the arr_params. We copy the current value to the+ -- accumulator parameters.+ --+ -- Note the use of 'everythingVolatile' when reading and writing the+ -- buckets. This was necessary to ensure correct execution on a+ -- newer NVIDIA GPU (RTX 2080). The 'volatile' modifiers likely+ -- make the writes pass through the (SM-local) L1 cache, which is+ -- necessary here, because we are really doing device-wide+ -- synchronisation without atomics (naughty!).+ let (acc_params, _arr_params) = splitAt (length arrs) $ lambdaParams op+ bind_acc_params =+ everythingVolatile $+ sComment "bind lhs" $+ forM_ (zip acc_params arrs) $ \(acc_p, arr) ->+ copyDWIMFix (paramName acc_p) [] (Var arr) bucket++ let op_body =+ sComment "execute operation" $+ compileBody' acc_params $ lambdaBody op++ do_hist =+ everythingVolatile $+ sComment "update global result" $+ zipWithM_ (writeArray bucket) arrs $ map (Var . paramName) acc_params++ fence = case space of+ Space "local" -> sOp $ Imp.MemFence Imp.FenceLocal+ _ -> sOp $ Imp.MemFence Imp.FenceGlobal++ -- While-loop: Try to insert your value+ sWhile (tvExp continue) $ do+ try_acquire_lock+ sWhen lock_acquired $ do+ dLParams acc_params+ bind_acc_params+ op_body+ do_hist+ fence+ release_lock+ break_loop+ fence+ where+ writeArray bucket arr val = copyDWIMFix arr bucket val []++atomicUpdateCAS ::+ Space ->+ PrimType ->+ VName ->+ VName ->+ [Imp.TExp Int64] ->+ VName ->+ InKernelGen () ->+ InKernelGen ()+atomicUpdateCAS space t arr old bucket x do_op = do+ -- Code generation target:+ --+ -- old = d_his[idx];+ -- do {+ -- assumed = old;+ -- x = do_op(assumed, y);+ -- old = atomicCAS(&d_his[idx], assumed, tmp);+ -- } while(assumed != old);+ assumed <- tvVar <$> dPrim "assumed" t+ run_loop <- dPrimV "run_loop" true++ -- XXX: CUDA may generate really bad code if this is not a volatile+ -- read. Unclear why. The later reads are volatile, so maybe+ -- that's it.+ everythingVolatile $ copyDWIMFix old [] (Var arr) bucket++ (arr', _a_space, bucket_offset) <- fullyIndexArray arr bucket++ -- While-loop: Try to insert your value+ let (toBits, fromBits) =+ case t of+ FloatType Float32 ->+ ( \v -> Imp.FunExp "to_bits32" [v] int32,+ \v -> Imp.FunExp "from_bits32" [v] t+ )+ FloatType Float64 ->+ ( \v -> Imp.FunExp "to_bits64" [v] int64,+ \v -> Imp.FunExp "from_bits64" [v] t+ )+ _ -> (id, id)++ int+ | primBitSize t == 32 = int32+ | otherwise = int64++ sWhile (tvExp run_loop) $ do+ assumed <~~ Imp.var old t+ x <~~ Imp.var assumed t+ do_op+ old_bits_v <- newVName "old_bits"+ dPrim_ old_bits_v int+ let old_bits = Imp.var old_bits_v int+ sOp $+ Imp.Atomic space $+ Imp.AtomicCmpXchg+ int+ old_bits_v+ arr'+ bucket_offset+ (toBits (Imp.var assumed t))+ (toBits (Imp.var x t))+ old <~~ fromBits old_bits+ let won = CmpOpExp (CmpEq int) (toBits (Imp.var assumed t)) old_bits+ sWhen (isBool won) (run_loop <-- false)++computeKernelUses ::+ FreeIn a =>+ a ->+ [VName] ->+ CallKernelGen [Imp.KernelUse]+computeKernelUses kernel_body bound_in_kernel = do+ let actually_free = freeIn kernel_body `namesSubtract` namesFromList bound_in_kernel+ -- Compute the variables that we need to pass to the kernel.+ nubOrd <$> readsFromSet actually_free++readsFromSet :: Names -> CallKernelGen [Imp.KernelUse]+readsFromSet free =+ fmap catMaybes $+ forM (namesToList free) $ \var -> do+ t <- lookupType var+ vtable <- getVTable+ case t of+ Array {} -> return Nothing+ Acc {} -> return Nothing+ Mem (Space "local") -> return Nothing+ Mem {} -> return $ Just $ Imp.MemoryUse var+ Prim bt ->+ isConstExp vtable (Imp.var var bt) >>= \case+ Just ce -> return $ Just $ Imp.ConstUse var ce+ Nothing -> return $ Just $ Imp.ScalarUse var bt++isConstExp ::+ VTable GPUMem ->+ Imp.Exp ->+ ImpM rep r op (Maybe Imp.KernelConstExp)+isConstExp vtable size = do+ fname <- askFunction+ let onLeaf (Imp.ScalarVar name) _ = lookupConstExp name+ onLeaf Imp.Index {} _ = Nothing+ lookupConstExp name =+ constExp =<< hasExp =<< M.lookup name vtable+ constExp (Op (Inner (SizeOp (GetSize key _)))) =+ Just $ LeafExp (Imp.SizeConst $ keyWithEntryPoint fname key) int32+ constExp e = primExpFromExp lookupConstExp e+ return $ replaceInPrimExpM onLeaf size+ where+ hasExp (ArrayVar e _) = e+ hasExp (AccVar e _) = e+ hasExp (ScalarVar e _) = e+ hasExp (MemVar e _) = e++computeThreadChunkSize ::+ SplitOrdering ->+ Imp.TExp Int64 ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ TV Int64 ->+ ImpM rep r op ()+computeThreadChunkSize (SplitStrided stride) thread_index elements_per_thread num_elements chunk_var =+ chunk_var+ <-- sMin64+ (Imp.unCount elements_per_thread)+ ((Imp.unCount num_elements - thread_index) `divUp` toInt64Exp stride)+computeThreadChunkSize SplitContiguous thread_index elements_per_thread num_elements chunk_var = do+ starting_point <-+ dPrimV "starting_point" $+ thread_index * Imp.unCount elements_per_thread+ remaining_elements <-+ dPrimV "remaining_elements" $+ Imp.unCount num_elements - tvExp starting_point++ let no_remaining_elements = tvExp remaining_elements .<=. 0+ beyond_bounds = Imp.unCount num_elements .<=. tvExp starting_point++ sIf+ (no_remaining_elements .||. beyond_bounds)+ (chunk_var <-- 0)+ ( sIf+ is_last_thread+ (chunk_var <-- Imp.unCount last_thread_elements)+ (chunk_var <-- Imp.unCount elements_per_thread)+ )+ where+ last_thread_elements =+ num_elements - Imp.elements thread_index * elements_per_thread+ is_last_thread =+ Imp.unCount num_elements+ .<. (thread_index + 1) * Imp.unCount elements_per_thread++kernelInitialisationSimple ::+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ CallKernelGen (KernelConstants, InKernelGen ())+kernelInitialisationSimple (Count num_groups) (Count group_size) = do+ global_tid <- newVName "global_tid"+ local_tid <- newVName "local_tid"+ group_id <- newVName "group_tid"+ wave_size <- newVName "wave_size"+ inner_group_size <- newVName "group_size"+ let constants =+ KernelConstants+ (Imp.vi32 global_tid)+ (Imp.vi32 local_tid)+ (Imp.vi32 group_id)+ global_tid+ local_tid+ group_id+ num_groups+ group_size+ (sExt32 (group_size * num_groups))+ (Imp.vi32 wave_size)+ true+ mempty++ let set_constants = do+ dPrim_ global_tid int32+ dPrim_ local_tid int32+ dPrim_ inner_group_size int64+ dPrim_ wave_size int32+ dPrim_ group_id int32++ sOp (Imp.GetGlobalId global_tid 0)+ sOp (Imp.GetLocalId local_tid 0)+ sOp (Imp.GetLocalSize inner_group_size 0)+ sOp (Imp.GetLockstepWidth wave_size)+ sOp (Imp.GetGroupId group_id 0)++ return (constants, set_constants)++isActive :: [(VName, SubExp)] -> Imp.TExp Bool+isActive limit = case actives of+ [] -> true+ x : xs -> foldl (.&&.) x xs+ where+ (is, ws) = unzip limit+ actives = zipWith active is $ map toInt64Exp ws+ active i = (Imp.vi64 i .<.)++-- | Change every memory block to be in the global address space,+-- except those who are in the local memory space. This only affects+-- generated code - we still need to make sure that the memory is+-- actually present on the device (and dared as variables in the+-- kernel).+makeAllMemoryGlobal :: CallKernelGen a -> CallKernelGen a+makeAllMemoryGlobal =+ localDefaultSpace (Imp.Space "global") . localVTable (M.map globalMemory)+ where+ globalMemory (MemVar _ entry)+ | entryMemSpace entry /= Space "local" =+ MemVar Nothing entry {entryMemSpace = Imp.Space "global"}+ globalMemory entry =+ entry++groupReduce ::+ Imp.TExp Int32 ->+ Lambda GPUMem ->+ [VName] ->+ InKernelGen ()+groupReduce w lam arrs = do+ offset <- dPrim "offset" int32+ groupReduceWithOffset offset w lam arrs++groupReduceWithOffset ::+ TV Int32 ->+ Imp.TExp Int32 ->+ Lambda GPUMem ->+ [VName] ->+ InKernelGen ()+groupReduceWithOffset offset w lam arrs = do+ constants <- kernelConstants <$> askEnv++ let local_tid = kernelLocalThreadId constants+ global_tid = kernelGlobalThreadId constants++ barrier+ | all primType $ lambdaReturnType lam = sOp $ Imp.Barrier Imp.FenceLocal+ | otherwise = sOp $ Imp.Barrier Imp.FenceGlobal++ readReduceArgument param arr+ | Prim _ <- paramType param = do+ let i = local_tid + tvExp offset+ copyDWIMFix (paramName param) [] (Var arr) [sExt64 i]+ | otherwise = do+ let i = global_tid + tvExp offset+ copyDWIMFix (paramName param) [] (Var arr) [sExt64 i]++ writeReduceOpResult param arr+ | Prim _ <- paramType param =+ copyDWIMFix arr [sExt64 local_tid] (Var $ paramName param) []+ | otherwise =+ return ()++ let (reduce_acc_params, reduce_arr_params) = splitAt (length arrs) $ lambdaParams lam++ skip_waves <- dPrimV "skip_waves" (1 :: Imp.TExp Int32)+ dLParams $ lambdaParams lam++ offset <-- (0 :: Imp.TExp Int32)++ comment "participating threads read initial accumulator" $+ sWhen (local_tid .<. w) $+ zipWithM_ readReduceArgument reduce_acc_params arrs++ let do_reduce = do+ comment "read array element" $+ zipWithM_ readReduceArgument reduce_arr_params arrs+ comment "apply reduction operation" $+ compileBody' reduce_acc_params $ lambdaBody lam+ comment "write result of operation" $+ zipWithM_ writeReduceOpResult reduce_acc_params arrs+ in_wave_reduce = everythingVolatile do_reduce++ wave_size = kernelWaveSize constants+ group_size = kernelGroupSize constants+ wave_id = local_tid `quot` wave_size+ in_wave_id = local_tid - wave_id * wave_size+ num_waves = (sExt32 group_size + wave_size - 1) `quot` wave_size+ arg_in_bounds = local_tid + tvExp offset .<. w++ doing_in_wave_reductions =+ tvExp offset .<. wave_size+ apply_in_in_wave_iteration =+ (in_wave_id .&. (2 * tvExp offset - 1)) .==. 0+ in_wave_reductions = do+ offset <-- (1 :: Imp.TExp Int32)+ sWhile doing_in_wave_reductions $ do+ sWhen+ (arg_in_bounds .&&. apply_in_in_wave_iteration)+ in_wave_reduce+ offset <-- tvExp offset * 2++ doing_cross_wave_reductions =+ tvExp skip_waves .<. num_waves+ is_first_thread_in_wave =+ in_wave_id .==. 0+ wave_not_skipped =+ (wave_id .&. (2 * tvExp skip_waves - 1)) .==. 0+ apply_in_cross_wave_iteration =+ arg_in_bounds .&&. is_first_thread_in_wave .&&. wave_not_skipped+ cross_wave_reductions =+ sWhile doing_cross_wave_reductions $ do+ barrier+ offset <-- tvExp skip_waves * wave_size+ sWhen+ apply_in_cross_wave_iteration+ do_reduce+ skip_waves <-- tvExp skip_waves * 2++ in_wave_reductions+ cross_wave_reductions++groupScan ::+ Maybe (Imp.TExp Int32 -> Imp.TExp Int32 -> Imp.TExp Bool) ->+ Imp.TExp Int64 ->+ Imp.TExp Int64 ->+ Lambda GPUMem ->+ [VName] ->+ InKernelGen ()+groupScan seg_flag arrs_full_size w lam arrs = do+ constants <- kernelConstants <$> askEnv+ renamed_lam <- renameLambda lam++ let ltid32 = kernelLocalThreadId constants+ ltid = sExt64 ltid32+ (x_params, y_params) = splitAt (length arrs) $ lambdaParams lam++ dLParams (lambdaParams lam ++ lambdaParams renamed_lam)++ ltid_in_bounds <- dPrimVE "ltid_in_bounds" $ ltid .<. w++ -- The scan works by splitting the group into blocks, which are+ -- scanned separately. Typically, these blocks are smaller than+ -- the lockstep width, which enables barrier-free execution inside+ -- them.+ --+ -- We hardcode the block size here. The only requirement is that+ -- it should not be less than the square root of the group size.+ -- With 32, we will work on groups of size 1024 or smaller, which+ -- fits every device Troels has seen. Still, it would be nicer if+ -- it were a runtime parameter. Some day.+ let block_size = 32+ simd_width = kernelWaveSize constants+ block_id = ltid32 `quot` block_size+ in_block_id = ltid32 - block_id * block_size+ doInBlockScan seg_flag' active =+ inBlockScan+ constants+ seg_flag'+ arrs_full_size+ simd_width+ block_size+ active+ arrs+ barrier+ array_scan = not $ all primType $ lambdaReturnType lam+ barrier+ | array_scan =+ sOp $ Imp.Barrier Imp.FenceGlobal+ | otherwise =+ sOp $ Imp.Barrier Imp.FenceLocal++ group_offset = sExt64 (kernelGroupId constants) * kernelGroupSize constants++ writeBlockResult p arr+ | primType $ paramType p =+ copyDWIM arr [DimFix $ sExt64 block_id] (Var $ paramName p) []+ | otherwise =+ copyDWIM arr [DimFix $ group_offset + sExt64 block_id] (Var $ paramName p) []++ readPrevBlockResult p arr+ | primType $ paramType p =+ copyDWIM (paramName p) [] (Var arr) [DimFix $ sExt64 block_id - 1]+ | otherwise =+ copyDWIM (paramName p) [] (Var arr) [DimFix $ group_offset + sExt64 block_id - 1]++ doInBlockScan seg_flag ltid_in_bounds lam+ barrier++ let is_first_block = block_id .==. 0+ when array_scan $ do+ sComment "save correct values for first block" $+ sWhen is_first_block $+ forM_ (zip x_params arrs) $ \(x, arr) ->+ unless (primType $ paramType x) $+ copyDWIM arr [DimFix $ arrs_full_size + group_offset + sExt64 block_size + ltid] (Var $ paramName x) []++ barrier++ let last_in_block = in_block_id .==. block_size - 1+ sComment "last thread of block 'i' writes its result to offset 'i'" $+ sWhen (last_in_block .&&. ltid_in_bounds) $+ everythingVolatile $+ zipWithM_ writeBlockResult x_params arrs++ barrier++ let first_block_seg_flag = do+ flag_true <- seg_flag+ Just $ \from to ->+ flag_true (from * block_size + block_size -1) (to * block_size + block_size -1)+ comment+ "scan the first block, after which offset 'i' contains carry-in for block 'i+1'"+ $ doInBlockScan first_block_seg_flag (is_first_block .&&. ltid_in_bounds) renamed_lam++ barrier++ when array_scan $ do+ sComment "move correct values for first block back a block" $+ sWhen is_first_block $+ forM_ (zip x_params arrs) $ \(x, arr) ->+ unless (primType $ paramType x) $+ copyDWIM+ arr+ [DimFix $ arrs_full_size + group_offset + ltid]+ (Var arr)+ [DimFix $ arrs_full_size + group_offset + sExt64 block_size + ltid]++ barrier++ let read_carry_in = do+ forM_ (zip x_params y_params) $ \(x, y) ->+ copyDWIM (paramName y) [] (Var (paramName x)) []+ zipWithM_ readPrevBlockResult x_params arrs++ y_to_x = forM_ (zip x_params y_params) $ \(x, y) ->+ when (primType (paramType x)) $+ copyDWIM (paramName x) [] (Var (paramName y)) []++ op_to_x+ | Nothing <- seg_flag =+ compileBody' x_params $ lambdaBody lam+ | Just flag_true <- seg_flag = do+ inactive <-+ dPrimVE "inactive" $ flag_true (block_id * block_size -1) ltid32+ sWhen inactive y_to_x+ when array_scan barrier+ sUnless inactive $ compileBody' x_params $ lambdaBody lam++ write_final_result =+ forM_ (zip x_params arrs) $ \(p, arr) ->+ when (primType $ paramType p) $+ copyDWIM arr [DimFix ltid] (Var $ paramName p) []++ sComment "carry-in for every block except the first" $+ sUnless (is_first_block .||. bNot ltid_in_bounds) $ do+ sComment "read operands" read_carry_in+ sComment "perform operation" op_to_x+ sComment "write final result" write_final_result++ barrier++ sComment "restore correct values for first block" $+ sWhen is_first_block $+ forM_ (zip3 x_params y_params arrs) $ \(x, y, arr) ->+ if primType (paramType y)+ then copyDWIM arr [DimFix ltid] (Var $ paramName y) []+ else copyDWIM (paramName x) [] (Var arr) [DimFix $ arrs_full_size + group_offset + ltid]++ barrier++inBlockScan ::+ KernelConstants ->+ Maybe (Imp.TExp Int32 -> Imp.TExp Int32 -> Imp.TExp Bool) ->+ Imp.TExp Int64 ->+ Imp.TExp Int32 ->+ Imp.TExp Int32 ->+ Imp.TExp Bool ->+ [VName] ->+ InKernelGen () ->+ Lambda GPUMem ->+ InKernelGen ()+inBlockScan constants seg_flag arrs_full_size lockstep_width block_size active arrs barrier scan_lam = everythingVolatile $ do+ skip_threads <- dPrim "skip_threads" int32+ let in_block_thread_active =+ tvExp skip_threads .<=. in_block_id+ actual_params = lambdaParams scan_lam+ (x_params, y_params) =+ splitAt (length actual_params `div` 2) actual_params+ y_to_x =+ forM_ (zip x_params y_params) $ \(x, y) ->+ when (primType (paramType x)) $+ copyDWIM (paramName x) [] (Var (paramName y)) []++ -- Set initial y values+ sComment "read input for in-block scan" $+ sWhen active $ do+ zipWithM_ readInitial y_params arrs+ -- Since the final result is expected to be in x_params, we may+ -- need to copy it there for the first thread in the block.+ sWhen (in_block_id .==. 0) y_to_x++ when array_scan barrier++ let op_to_x+ | Nothing <- seg_flag =+ compileBody' x_params $ lambdaBody scan_lam+ | Just flag_true <- seg_flag = do+ inactive <-+ dPrimVE "inactive" $+ flag_true (ltid32 - tvExp skip_threads) ltid32+ sWhen inactive y_to_x+ when array_scan barrier+ sUnless inactive $ compileBody' x_params $ lambdaBody scan_lam++ maybeBarrier =+ sWhen+ (lockstep_width .<=. tvExp skip_threads)+ barrier++ sComment "in-block scan (hopefully no barriers needed)" $ do+ skip_threads <-- 1+ sWhile (tvExp skip_threads .<. block_size) $ do+ sWhen (in_block_thread_active .&&. active) $ do+ sComment "read operands" $+ zipWithM_ (readParam (sExt64 $ tvExp skip_threads)) x_params arrs+ sComment "perform operation" op_to_x++ maybeBarrier++ sWhen (in_block_thread_active .&&. active) $+ sComment "write result" $+ sequence_ $ zipWith3 writeResult x_params y_params arrs++ maybeBarrier++ skip_threads <-- tvExp skip_threads * 2+ where+ block_id = ltid32 `quot` block_size+ in_block_id = ltid32 - block_id * block_size+ ltid32 = kernelLocalThreadId constants+ ltid = sExt64 ltid32+ gtid = sExt64 $ kernelGlobalThreadId constants+ array_scan = not $ all primType $ lambdaReturnType scan_lam++ readInitial p arr+ | primType $ paramType p =+ copyDWIM (paramName p) [] (Var arr) [DimFix ltid]+ | otherwise =+ copyDWIM (paramName p) [] (Var arr) [DimFix gtid]++ readParam behind p arr+ | primType $ paramType p =+ copyDWIM (paramName p) [] (Var arr) [DimFix $ ltid - behind]+ | otherwise =+ copyDWIM (paramName p) [] (Var arr) [DimFix $ gtid - behind + arrs_full_size]++ writeResult x y arr+ | primType $ paramType x = do+ copyDWIM arr [DimFix ltid] (Var $ paramName x) []+ copyDWIM (paramName y) [] (Var $ paramName x) []+ | otherwise =+ copyDWIM (paramName y) [] (Var $ paramName x) []++computeMapKernelGroups :: Imp.TExp Int64 -> CallKernelGen (Imp.TExp Int64, Imp.TExp Int64)+computeMapKernelGroups kernel_size = do+ group_size <- dPrim "group_size" int64+ fname <- askFunction+ let group_size_key = keyWithEntryPoint fname $ nameFromString $ pretty $ tvVar group_size+ sOp $ Imp.GetSize (tvVar group_size) group_size_key Imp.SizeGroup+ num_groups <- dPrimV "num_groups" $ kernel_size `divUp` tvExp group_size+ return (tvExp num_groups, tvExp group_size)++simpleKernelConstants ::+ Imp.TExp Int64 ->+ String ->+ CallKernelGen (KernelConstants, InKernelGen ())+simpleKernelConstants kernel_size desc = do+ thread_gtid <- newVName $ desc ++ "_gtid"+ thread_ltid <- newVName $ desc ++ "_ltid"+ group_id <- newVName $ desc ++ "_gid"+ (num_groups, group_size) <- computeMapKernelGroups kernel_size+ let set_constants = do+ dPrim_ thread_gtid int32+ dPrim_ thread_ltid int32+ dPrim_ group_id int32+ sOp (Imp.GetGlobalId thread_gtid 0)+ sOp (Imp.GetLocalId thread_ltid 0)+ sOp (Imp.GetGroupId group_id 0)++ return+ ( KernelConstants+ (Imp.vi32 thread_gtid)+ (Imp.vi32 thread_ltid)+ (Imp.vi32 group_id)+ thread_gtid+ thread_ltid+ group_id+ num_groups+ group_size+ (sExt32 (group_size * num_groups))+ 0+ (Imp.vi64 thread_gtid .<. kernel_size)+ mempty,+ set_constants+ )++-- | For many kernels, we may not have enough physical groups to cover+-- the logical iteration space. Some groups thus have to perform+-- double duty; we put an outer loop to accomplish this. The+-- advantage over just launching a bazillion threads is that the cost+-- of memory expansion should be proportional to the number of+-- *physical* threads (hardware parallelism), not the amount of+-- application parallelism.+virtualiseGroups ::+ SegVirt ->+ Imp.TExp Int32 ->+ (Imp.TExp Int32 -> InKernelGen ()) ->+ InKernelGen ()+virtualiseGroups SegVirt required_groups m = do+ constants <- kernelConstants <$> askEnv+ phys_group_id <- dPrim "phys_group_id" int32+ sOp $ Imp.GetGroupId (tvVar phys_group_id) 0+ let iterations =+ (required_groups - tvExp phys_group_id)+ `divUp` sExt32 (kernelNumGroups constants)++ sFor "i" iterations $ \i -> do+ m . tvExp+ =<< dPrimV+ "virt_group_id"+ (tvExp phys_group_id + i * sExt32 (kernelNumGroups constants))+ -- Make sure the virtual group is actually done before we let+ -- another virtual group have its way with it.+ sOp $ Imp.Barrier Imp.FenceGlobal+virtualiseGroups _ _ m = do+ gid <- kernelGroupIdVar . kernelConstants <$> askEnv+ m $ Imp.vi32 gid++sKernelThread ::+ String ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ VName ->+ InKernelGen () ->+ CallKernelGen ()+sKernelThread = sKernel threadOperations kernelGlobalThreadId++sKernelGroup ::+ String ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ VName ->+ InKernelGen () ->+ CallKernelGen ()+sKernelGroup = sKernel groupOperations kernelGroupId++sKernelFailureTolerant ::+ Bool ->+ Operations GPUMem KernelEnv Imp.KernelOp ->+ KernelConstants ->+ Name ->+ InKernelGen () ->+ CallKernelGen ()+sKernelFailureTolerant tol ops constants name m = do+ HostEnv atomics _ locks <- askEnv+ body <- makeAllMemoryGlobal $ subImpM_ (KernelEnv atomics constants locks) ops m+ uses <- computeKernelUses body mempty+ emit $+ Imp.Op $+ Imp.CallKernel+ Imp.Kernel+ { Imp.kernelBody = body,+ Imp.kernelUses = uses,+ Imp.kernelNumGroups = [untyped $ kernelNumGroups constants],+ Imp.kernelGroupSize = [untyped $ kernelGroupSize constants],+ Imp.kernelName = name,+ Imp.kernelFailureTolerant = tol+ }++sKernel ::+ Operations GPUMem KernelEnv Imp.KernelOp ->+ (KernelConstants -> Imp.TExp Int32) ->+ String ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ VName ->+ InKernelGen () ->+ CallKernelGen ()+sKernel ops flatf name num_groups group_size v f = do+ (constants, set_constants) <- kernelInitialisationSimple num_groups group_size+ name' <- nameForFun $ name ++ "_" ++ show (baseTag v)+ sKernelFailureTolerant False ops constants name' $ do+ set_constants+ dPrimV_ v $ flatf constants+ 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)++ case (dest_space, src_space) of+ (ScalarSpace destds _, ScalarSpace srcds _) -> do+ let destslice' =+ replicate (length destslice - length destds) (DimFix 0)+ ++ takeLast (length destds) destslice+ srcslice' =+ replicate (length srcslice - length srcds) (DimFix 0)+ ++ takeLast (length srcds) srcslice+ copyElementWise pt destloc destslice' srcloc srcslice'+ _ -> do+ groupCoverSpace (sliceDims destslice) $ \is ->+ copyElementWise+ pt+ destloc+ (map DimFix $ fixSlice destslice is)+ srcloc+ (map DimFix $ fixSlice srcslice is)+ sOp $ Imp.Barrier Imp.FenceLocal++threadOperations, groupOperations :: Operations GPUMem KernelEnv Imp.KernelOp+threadOperations =+ (defaultOperations compileThreadOp)+ { opsCopyCompiler = copyElementWise,+ opsExpCompiler = compileThreadExp,+ opsStmsCompiler = \_ -> defCompileStms mempty,+ opsAllocCompilers =+ M.fromList [(Space "local", allocLocal)]+ }+groupOperations =+ (defaultOperations compileGroupOp)+ { opsCopyCompiler = copyInGroup,+ opsExpCompiler = compileGroupExp,+ opsStmsCompiler = \_ -> defCompileStms mempty,+ opsAllocCompilers =+ M.fromList [(Space "local", allocLocal)]+ }++-- | Perform a Replicate with a kernel.+sReplicateKernel :: VName -> SubExp -> CallKernelGen ()+sReplicateKernel arr se = do+ t <- subExpType se+ ds <- dropLast (arrayRank t) . arrayDims <$> lookupType arr++ let dims = map toInt64Exp $ ds ++ arrayDims t+ (constants, set_constants) <-+ simpleKernelConstants (product $ map sExt64 dims) "replicate"++ fname <- askFunction+ let name =+ keyWithEntryPoint fname $+ nameFromString $+ "replicate_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)+ is' = unflattenIndex dims $ sExt64 $ kernelGlobalThreadId constants++ sKernelFailureTolerant True threadOperations constants name $ do+ set_constants+ sWhen (kernelThreadActive constants) $+ copyDWIMFix arr is' se $ drop (length ds) is'++replicateName :: PrimType -> String+replicateName bt = "replicate_" ++ pretty bt++replicateForType :: PrimType -> CallKernelGen Name+replicateForType bt = do+ let fname = nameFromString $ "builtin#" <> replicateName bt++ exists <- hasFunction fname+ unless exists $ do+ mem <- newVName "mem"+ num_elems <- newVName "num_elems"+ val <- newVName "val"++ let params =+ [ Imp.MemParam mem (Space "device"),+ Imp.ScalarParam num_elems int32,+ Imp.ScalarParam val bt+ ]+ shape = Shape [Var num_elems]+ function fname [] params $ do+ arr <-+ sArray "arr" bt shape $+ ArrayIn mem $+ IxFun.iota $+ map pe64 $ shapeDims shape+ sReplicateKernel arr $ Var val++ return fname++replicateIsFill :: VName -> SubExp -> CallKernelGen (Maybe (CallKernelGen ()))+replicateIsFill arr v = do+ ArrayEntry (MemLocation arr_mem arr_shape arr_ixfun) _ <- lookupArray arr+ v_t <- subExpType v+ case v_t of+ Prim v_t'+ | IxFun.isLinear arr_ixfun -> return $+ Just $ do+ fname <- replicateForType v_t'+ emit $+ Imp.Call+ []+ fname+ [ Imp.MemArg arr_mem,+ Imp.ExpArg $ untyped $ product $ map toInt64Exp arr_shape,+ Imp.ExpArg $ toExp' v_t' v+ ]+ _ -> return Nothing++-- | Perform a Replicate with a kernel.+sReplicate :: VName -> SubExp -> CallKernelGen ()+sReplicate arr se = do+ -- If the replicate is of a particularly common and simple form+ -- (morally a memset()/fill), then we use a common function.+ is_fill <- replicateIsFill arr se++ case is_fill of+ Just m -> m+ Nothing -> sReplicateKernel arr se++-- | Perform an Iota with a kernel.+sIotaKernel ::+ VName ->+ Imp.TExp Int64 ->+ Imp.Exp ->+ Imp.Exp ->+ IntType ->+ CallKernelGen ()+sIotaKernel arr n x s et = do+ destloc <- entryArrayLocation <$> lookupArray arr+ (constants, set_constants) <- simpleKernelConstants n "iota"++ fname <- askFunction+ let name =+ keyWithEntryPoint fname $+ nameFromString $+ "iota_" ++ pretty et ++ "_"+ ++ show (baseTag $ kernelGlobalThreadIdVar constants)++ sKernelFailureTolerant True threadOperations constants name $ do+ set_constants+ let gtid = sExt64 $ kernelGlobalThreadId constants+ sWhen (kernelThreadActive constants) $ do+ (destmem, destspace, destidx) <- fullyIndexArray' destloc [gtid]++ emit $+ Imp.Write destmem destidx (IntType et) destspace Imp.Nonvolatile $+ BinOpExp+ (Add et OverflowWrap)+ (BinOpExp (Mul et OverflowWrap) (Imp.sExt et $ untyped gtid) s)+ x++iotaName :: IntType -> String+iotaName bt = "iota_" ++ pretty bt++iotaForType :: IntType -> CallKernelGen Name+iotaForType bt = do+ let fname = nameFromString $ "builtin#" <> iotaName bt++ exists <- hasFunction fname+ unless exists $ do+ mem <- newVName "mem"+ n <- newVName "n"+ x <- newVName "x"+ s <- newVName "s"++ let params =+ [ Imp.MemParam mem (Space "device"),+ Imp.ScalarParam n int32,+ Imp.ScalarParam x $ IntType bt,+ Imp.ScalarParam s $ IntType bt+ ]+ shape = Shape [Var n]+ n' = Imp.vi64 n+ x' = Imp.var x $ IntType bt+ s' = Imp.var s $ IntType bt++ function fname [] params $ do+ arr <-+ sArray "arr" (IntType bt) shape $+ ArrayIn mem $+ IxFun.iota $+ map pe64 $ shapeDims shape+ sIotaKernel arr (sExt64 n') x' s' bt++ return fname++-- | Perform an Iota with a kernel.+sIota ::+ VName ->+ Imp.TExp Int64 ->+ Imp.Exp ->+ Imp.Exp ->+ IntType ->+ CallKernelGen ()+sIota arr n x s et = do+ ArrayEntry (MemLocation arr_mem _ arr_ixfun) _ <- lookupArray arr+ if IxFun.isLinear arr_ixfun+ then do+ fname <- iotaForType et+ emit $+ Imp.Call+ []+ fname+ [Imp.MemArg arr_mem, Imp.ExpArg $ untyped n, Imp.ExpArg x, Imp.ExpArg s]+ 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++ (constants, set_constants) <- simpleKernelConstants kernel_size "copy"++ fname <- askFunction+ let name =+ keyWithEntryPoint fname $+ nameFromString $+ "copy_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)++ sKernelFailureTolerant True threadOperations constants name $ do+ set_constants++ let gtid = sExt64 $ kernelGlobalThreadId constants+ dest_is = unflattenIndex shape gtid+ src_is = dest_is++ (_, destspace, destidx) <-+ fullyIndexArray' destloc $ fixSlice destslice dest_is+ (_, srcspace, srcidx) <-+ fullyIndexArray' srcloc $ fixSlice srcslice src_is++ 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+ n <- toInt64Exp . arraySize 0 <$> lookupType what++ constants <- kernelConstants <$> askEnv+ let ltid = sExt64 $ kernelLocalThreadId constants+ offset =+ toInt64Exp per_group_elems+ * sExt64 (kernelGroupId constants)++ -- Avoid loop for the common case where each thread is statically+ -- known to write at most one element.+ localOps threadOperations $+ if toInt64Exp per_group_elems == kernelGroupSize constants+ then+ sWhen (ltid + offset .<. toInt64Exp w) $+ copyDWIMFix (patElemName pe) [ltid + offset] (Var what) [ltid]+ else sFor "i" (n `divUp` kernelGroupSize constants) $ \i -> do+ 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+ let gids = map fst $ unSegSpace space+ out_tile_sizes = map (toInt64Exp . snd) dims+ group_is = zipWith (*) (map Imp.vi64 gids) out_tile_sizes+ local_is <- localThreadIDs $ map snd dims+ is_for_thread <-+ mapM (dPrimV "thread_out_index") $+ zipWith (+) group_is local_is++ 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+ constants <- kernelConstants <$> askEnv++ let gids = map fst $ unSegSpace space+ (dims, group_tiles, reg_tiles) = unzip3 dims_n_tiles+ group_tiles' = map toInt64Exp group_tiles+ reg_tiles' = map toInt64Exp reg_tiles++ -- Which group tile is this group responsible for?+ let group_tile_is = map Imp.vi64 gids++ -- 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++ -- Compute output array slice for the register tile belonging to+ -- this thread.+ let regTileSliceDim (group_tile, group_tile_i) (reg_tile, reg_tile_i) = do+ tile_dim_start <-+ dPrimVE "tile_dim_start" $+ 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)++ localOps threadOperations $+ sLoopNest (Shape reg_tiles) $ \is_in_reg_tile -> do+ let dest_is = fixSlice reg_tile_slices is_in_reg_tile+ 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+ constants <- kernelConstants <$> askEnv+ in_local_memory <- arrayInLocalMemory what+ let gids = map (Imp.vi64 . fst) $ unSegSpace space++ if not in_local_memory+ then+ localOps threadOperations $+ sWhen (kernelLocalThreadId constants .==. 0) $+ copyDWIMFix (patElemName pe) gids what []+ else -- If the result of the group is an array in local memory, we+ -- store it by collective copying among all the threads of the+ -- group. TODO: also do this if the array is in global memory+ -- (but this is a bit more tricky, synchronisation-wise).+ copyDWIMFix (patElemName pe) gids what []+compileGroupResult _ _ WriteReturns {} =+ compilerLimitationS "compileGroupResult: WriteReturns not handled yet."+compileGroupResult _ _ ConcatReturns {} =+ compilerLimitationS "compileGroupResult: ConcatReturns not handled yet."++compileThreadResult ::+ SegSpace ->+ PatElem GPUMem ->+ KernelResult ->+ InKernelGen ()+compileThreadResult _ _ RegTileReturns {} =+ compilerLimitationS "compileThreadResult: RegTileReturns not yet handled."+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+ 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+ 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+ 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 []+compileThreadResult _ _ TileReturns {} =+ compilerBugS "compileThreadResult: TileReturns unhandled."++arrayInLocalMemory :: SubExp -> InKernelGen Bool+arrayInLocalMemory (Var name) = do+ res <- lookupVar name+ case res of+ ArrayVar _ entry ->+ (Space "local" ==) . entryMemSpace+ <$> lookupMemory (memLocationName (entryArrayLocation entry))+ _ -> return False+arrayInLocalMemory Constant {} = return False
+ src/Futhark/CodeGen/ImpGen/GPU/SegHist.hs view
@@ -0,0 +1,1151 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++-- | Our compilation strategy for 'SegHist' is based around avoiding+-- bin conflicts. We do this by splitting the input into chunks, and+-- for each chunk computing a single subhistogram. Then we combine+-- the subhistograms using an ordinary segmented reduction ('SegRed').+--+-- There are some branches around to efficiently handle the case where+-- we use only a single subhistogram (because it's large), so that we+-- respect the asymptotics, and do not copy the destination array.+--+-- We also use a heuristic strategy for computing subhistograms in+-- local memory when possible. Given:+--+-- H: total size of histograms in bytes, including any lock arrays.+--+-- G: group size+--+-- T: number of bytes of local memory each thread can be given without+-- impacting occupancy (determined experimentally, e.g. 32).+--+-- LMAX: maximum amount of local memory per workgroup (hard limit).+--+-- We wish to compute:+--+-- COOP: cooperation level (number of threads per subhistogram)+--+-- LH: number of local memory subhistograms+--+-- We do this as:+--+-- COOP = ceil(H / T)+-- LH = ceil((G*T)/H)+-- if COOP <= G && H <= LMAX then+-- use local memory+-- else+-- use global memory+module Futhark.CodeGen.ImpGen.GPU.SegHist (compileSegHist) where++import Control.Monad.Except+import Data.List (foldl', genericLength, zip4, zip6)+import Data.Maybe+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.CodeGen.ImpGen.GPU.SegRed (compileSegRed')+import Futhark.Construct (fullSliceNum)+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.MonadFreshNames+import Futhark.Pass.ExplicitAllocations ()+import Futhark.Util (chunks, mapAccumLM, maxinum, splitFromEnd, takeLast)+import Futhark.Util.IntegralExp (divUp, quot, rem)+import Prelude hiding (quot, rem)++data SubhistosInfo = SubhistosInfo+ { subhistosArray :: VName,+ subhistosAlloc :: CallKernelGen ()+ }++data SegHistSlug = SegHistSlug+ { slugOp :: HistOp GPUMem,+ slugNumSubhistos :: TV Int64,+ slugSubhistos :: [SubhistosInfo],+ slugAtomicUpdate :: AtomicUpdate GPUMem KernelEnv+ }++histoSpaceUsage ::+ HistOp GPUMem ->+ Imp.Count Imp.Bytes (Imp.TExp Int64)+histoSpaceUsage op =+ sum $+ map+ ( typeSize+ . (`arrayOfRow` histWidth op)+ . (`arrayOfShape` histShape op)+ )+ $ lambdaReturnType $ histOp op++-- | Figure out how much memory is needed per histogram, both+-- segmented and unsegmented,, and compute some other auxiliary+-- information.+computeHistoUsage ::+ SegSpace ->+ HistOp GPUMem ->+ CallKernelGen+ ( Imp.Count Imp.Bytes (Imp.TExp Int64),+ Imp.Count Imp.Bytes (Imp.TExp Int64),+ SegHistSlug+ )+computeHistoUsage space op = do+ let segment_dims = init $ unSegSpace space+ num_segments = length segment_dims++ -- Create names for the intermediate array memory blocks,+ -- memory block sizes, arrays, and number of subhistograms.+ 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++ subhistos_mem <-+ sDeclareMem (baseString dest ++ "_subhistos_mem") (Space "device")++ let subhistos_shape =+ Shape (map snd segment_dims ++ [tvSize num_subhistos])+ <> stripDims num_segments (arrayShape dest_t)+ subhistos_membind =+ ArrayIn subhistos_mem $+ IxFun.iota $+ map pe64 $ shapeDims subhistos_shape+ subhistos <-+ sArray+ (baseString dest ++ "_subhistos")+ (elemType dest_t)+ subhistos_shape+ subhistos_membind++ return $+ SubhistosInfo subhistos $ do+ let unitHistoCase =+ emit $+ Imp.SetMem subhistos_mem (memLocationName dest_mem) $+ Space "device"++ multiHistoCase = do+ let num_elems =+ foldl' (*) (sExt64 $ tvExp num_subhistos) $+ map toInt64Exp $ arrayDims dest_t++ let subhistos_mem_size =+ Imp.bytes $+ Imp.unCount (Imp.elements num_elems `Imp.withElemType` elemType dest_t)++ sAlloc_ subhistos_mem subhistos_mem_size $ Space "device"+ sReplicate subhistos ne+ subhistos_t <- lookupType subhistos+ let slice =+ fullSliceNum (map toInt64Exp $ arrayDims subhistos_t) $+ map (unitSlice 0 . toInt64Exp . snd) segment_dims+ ++ [DimFix 0]+ sUpdate subhistos slice $ Var dest++ sIf (tvExp num_subhistos .==. 1) unitHistoCase multiHistoCase++ let h = histoSpaceUsage op+ segmented_h = h * product (map (Imp.bytes . toInt64Exp) $ init $ segSpaceDims space)++ atomics <- hostAtomics <$> askEnv++ return+ ( h,+ segmented_h,+ SegHistSlug op num_subhistos subhisto_infos $+ atomicUpdateLocking atomics $ histOp op+ )++prepareAtomicUpdateGlobal ::+ Maybe Locking ->+ [VName] ->+ SegHistSlug ->+ CallKernelGen+ ( Maybe Locking,+ [Imp.TExp Int64] -> InKernelGen ()+ )+prepareAtomicUpdateGlobal l dests slug =+ -- We need a separate lock array if the operators are not all of a+ -- particularly simple form that permits pure atomic operations.+ case (l, slugAtomicUpdate slug) of+ (_, AtomicPrim f) -> return (l, f (Space "global") dests)+ (_, AtomicCAS f) -> return (l, f (Space "global") dests)+ (Just l', AtomicLocking f) -> return (l, f l' (Space "global") dests)+ (Nothing, AtomicLocking f) -> do+ -- The number of locks used here is too low, but since we are+ -- currently forced to inline a huge list, I'm keeping it down+ -- for now. Some quick experiments suggested that it has little+ -- impact anyway (maybe the locking case is just too slow).+ --+ -- A fun solution would also be to use a simple hashing+ -- algorithm to ensure good distribution of locks.+ let num_locks = 100151+ dims =+ map toInt64Exp $+ shapeDims (histShape (slugOp slug))+ ++ [ tvSize (slugNumSubhistos slug),+ histWidth (slugOp slug)+ ]+ locks <-+ sStaticArray "hist_locks" (Space "device") int32 $+ Imp.ArrayZeros num_locks+ let l' = Locking locks 0 1 0 (pure . (`rem` fromIntegral num_locks) . flattenIndex dims)+ return (Just l', f l' (Space "global") dests)++-- | Some kernel bodies are not safe (or efficient) to execute+-- multiple times.+data Passage = MustBeSinglePass | MayBeMultiPass deriving (Eq, Ord)++bodyPassage :: KernelBody GPUMem -> Passage+bodyPassage kbody+ | mempty == consumedInKernelBody (aliasAnalyseKernelBody mempty kbody) =+ MayBeMultiPass+ | otherwise =+ MustBeSinglePass++prepareIntermediateArraysGlobal ::+ Passage ->+ Imp.TExp Int32 ->+ Imp.TExp Int64 ->+ [SegHistSlug] ->+ CallKernelGen+ ( Imp.TExp Int32,+ [[Imp.TExp Int64] -> InKernelGen ()]+ )+prepareIntermediateArraysGlobal passage hist_T hist_N slugs = do+ -- The paper formulae assume there is only one histogram, but in our+ -- implementation there can be multiple that have been horisontally+ -- fused. We do a bit of trickery with summings and averages to+ -- pretend there is really only one. For the case of a single+ -- histogram, the actual calculations should be the same as in the+ -- paper.++ -- The sum of all Hs.+ hist_H <- dPrimVE "hist_H" $ sum $ map (toInt64Exp . histWidth . slugOp) slugs++ hist_RF <-+ dPrimVE "hist_RF" $+ sum (map (r64 . toInt64Exp . histRaceFactor . slugOp) slugs)+ / genericLength slugs++ hist_el_size <- dPrimVE "hist_el_size" $ sum $ map slugElAvgSize slugs++ hist_C_max <-+ dPrimVE "hist_C_max" $+ fMin64 (r64 hist_T) $ r64 hist_H / hist_k_ct_min++ hist_M_min <-+ dPrimVE "hist_M_min" $+ sMax32 1 $ sExt32 $ t64 $ r64 hist_T / hist_C_max++ -- Querying L2 cache size is not reliable. Instead we provide a+ -- tunable knob with a hopefully sane default.+ let hist_L2_def = 4 * 1024 * 1024+ hist_L2 <- dPrim "L2_size" int32+ entry <- askFunction+ -- Equivalent to F_L2*L2 in paper.+ sOp $+ Imp.GetSize+ (tvVar hist_L2)+ (keyWithEntryPoint entry $ nameFromString (pretty (tvVar hist_L2)))+ $ Imp.SizeBespoke (nameFromString "L2_for_histogram") hist_L2_def++ let hist_L2_ln_sz = 16 * 4 -- L2 cache line size approximation+ hist_RACE_exp <-+ dPrimVE "hist_RACE_exp" $+ fMax64 1 $+ (hist_k_RF * hist_RF)+ / (hist_L2_ln_sz / r64 hist_el_size)++ hist_S <- dPrim "hist_S" int32++ -- For sparse histograms (H exceeds N) we only want a single chunk.+ sIf+ (hist_N .<. hist_H)+ (hist_S <-- (1 :: Imp.TExp Int32))+ $ hist_S+ <-- case passage of+ MayBeMultiPass ->+ sExt32 $+ (sExt64 hist_M_min * hist_H * sExt64 hist_el_size)+ `divUp` t64 (hist_F_L2 * r64 (tvExp hist_L2) * hist_RACE_exp)+ MustBeSinglePass ->+ 1++ emit $ Imp.DebugPrint "Race expansion factor (RACE^exp)" $ Just $ untyped hist_RACE_exp+ emit $ Imp.DebugPrint "Number of chunks (S)" $ Just $ untyped $ tvExp hist_S++ histograms <-+ snd+ <$> mapAccumLM+ (onOp (tvExp hist_L2) hist_M_min (tvExp hist_S) hist_RACE_exp)+ Nothing+ slugs++ return (tvExp hist_S, histograms)+ where+ hist_k_ct_min = 2 -- Chosen experimentally+ hist_k_RF = 0.75 -- Chosen experimentally+ hist_F_L2 = 0.4 -- Chosen experimentally+ r64 = isF64 . ConvOpExp (SIToFP Int32 Float64) . untyped+ t64 = isInt64 . ConvOpExp (FPToSI Float64 Int64) . untyped++ -- "Average element size" as computed by a formula that also takes+ -- locking into account.+ slugElAvgSize slug@(SegHistSlug op _ _ do_op) =+ case do_op of+ AtomicLocking {} ->+ slugElSize slug `quot` (1 + genericLength (lambdaReturnType (histOp op)))+ _ ->+ slugElSize slug `quot` genericLength (lambdaReturnType (histOp op))++ -- "Average element size" as computed by a formula that also takes+ -- locking into account.+ slugElSize (SegHistSlug op _ _ do_op) =+ case do_op of+ AtomicLocking {} ->+ sExt32 $+ unCount $+ sum $+ map (typeSize . (`arrayOfShape` histShape op)) $+ Prim int32 : lambdaReturnType (histOp op)+ _ ->+ sExt32 $+ unCount $+ sum $+ map (typeSize . (`arrayOfShape` histShape op)) $+ lambdaReturnType (histOp op)++ onOp hist_L2 hist_M_min hist_S hist_RACE_exp l slug = do+ let SegHistSlug op num_subhistos subhisto_info do_op = slug+ hist_H = toInt64Exp $ histWidth op++ hist_H_chk <- dPrimVE "hist_H_chk" $ hist_H `divUp` sExt64 hist_S++ emit $ Imp.DebugPrint "Chunk size (H_chk)" $ Just $ untyped hist_H_chk++ hist_k_max <-+ dPrimVE "hist_k_max" $+ fMin64+ (hist_F_L2 * (r64 hist_L2 / r64 (slugElSize slug)) * hist_RACE_exp)+ (r64 hist_N)+ / r64 hist_T++ hist_u <- dPrimVE "hist_u" $+ case do_op of+ AtomicPrim {} -> 2+ _ -> 1++ hist_C <-+ dPrimVE "hist_C" $+ fMin64 (r64 hist_T) $ r64 (hist_u * hist_H_chk) / hist_k_max++ -- Number of subhistograms per result histogram.+ hist_M <- dPrimVE "hist_M" $+ case slugAtomicUpdate slug of+ AtomicPrim {} -> 1+ _ -> sMax32 hist_M_min $ sExt32 $ t64 $ r64 hist_T / hist_C++ emit $ Imp.DebugPrint "Elements/thread in L2 cache (k_max)" $ Just $ untyped hist_k_max+ emit $ Imp.DebugPrint "Multiplication degree (M)" $ Just $ untyped hist_M+ emit $ Imp.DebugPrint "Cooperation level (C)" $ Just $ untyped hist_C++ -- num_subhistos is the variable we use to communicate back.+ num_subhistos <-- sExt64 hist_M++ -- Initialise sub-histograms.+ --+ -- If hist_M is 1, then we just reuse the original+ -- 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++ sub_mem <-+ fmap memLocationName $+ entryArrayLocation+ <$> lookupArray (subhistosArray info)++ let unitHistoCase =+ emit $+ Imp.SetMem sub_mem (memLocationName dest_mem) $+ Space "device"++ multiHistoCase = subhistosAlloc info++ sIf (hist_M .==. 1) unitHistoCase multiHistoCase++ return $ subhistosArray info++ (l', do_op') <- prepareAtomicUpdateGlobal l dests slug++ return (l', do_op')++histKernelGlobalPass ::+ [PatElem GPUMem] ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ SegSpace ->+ [SegHistSlug] ->+ KernelBody GPUMem ->+ [[Imp.TExp Int64] -> InKernelGen ()] ->+ Imp.TExp Int32 ->+ Imp.TExp Int32 ->+ CallKernelGen ()+histKernelGlobalPass map_pes num_groups group_size space slugs kbody histograms hist_S chk_i = do+ let (space_is, space_sizes) = unzip $ unSegSpace space+ space_sizes_64 = map (sExt64 . toInt64Exp) space_sizes+ total_w_64 = product space_sizes_64++ hist_H_chks <- forM (map (histWidth . slugOp) slugs) $ \w ->+ dPrimVE "hist_H_chk" $ toInt64Exp w `divUp` sExt64 hist_S++ sKernelThread "seghist_global" num_groups group_size (segFlat space) $ do+ constants <- kernelConstants <$> askEnv++ -- Compute subhistogram index for each thread, per histogram.+ subhisto_inds <- forM slugs $ \slug ->+ dPrimVE "subhisto_ind" $+ kernelGlobalThreadId constants+ `quot` ( kernelNumThreads constants+ `divUp` sExt32 (tvExp (slugNumSubhistos slug))+ )++ -- Loop over flat offsets into the input and output. The+ -- calculation is done with 64-bit integers to avoid overflow,+ -- but the final unflattened segment indexes are 32 bit.+ let gtid = sExt64 $ kernelGlobalThreadId constants+ num_threads = sExt64 $ kernelNumThreads constants+ kernelLoop gtid num_threads total_w_64 $ \offset -> do+ -- Construct segment indices.+ zipWithM_ dPrimV_ space_is $+ map sExt32 $ unflattenIndex space_sizes_64 offset++ -- We execute the bucket function once and update each histogram serially.+ -- We apply the bucket function if j=offset+ltid is less than+ -- num_elements. This also involves writing to the mapout+ -- arrays.+ let input_in_bounds = offset .<. total_w_64++ sWhen input_in_bounds $+ compileStms mempty (kernelBodyStms kbody) $ do+ let (red_res, map_res) = splitFromEnd (length map_pes) $ kernelBodyResult kbody++ sComment "save map-out results" $+ forM_ (zip map_pes map_res) $ \(pe, res) ->+ copyDWIMFix+ (patElemName pe)+ (map (Imp.vi64 . fst) $ unSegSpace space)+ (kernelResultSubExp res)+ []++ let (buckets, vs) = splitAt (length slugs) red_res+ perOp = chunks $ map (length . histDest . slugOp) slugs++ sComment "perform atomic updates" $+ forM_ (zip6 (map slugOp slugs) histograms buckets (perOp vs) subhisto_inds hist_H_chks) $+ \( HistOp dest_w _ _ _ shape lam,+ do_op,+ bucket,+ vs',+ subhisto_ind,+ hist_H_chk+ ) -> do+ let chk_beg = sExt64 chk_i * hist_H_chk+ bucket' = toInt64Exp $ kernelResultSubExp bucket+ dest_w' = toInt64Exp dest_w+ bucket_in_bounds =+ chk_beg .<=. bucket'+ .&&. bucket' .<. (chk_beg + hist_H_chk)+ .&&. bucket' .<. dest_w'+ vs_params = takeLast (length vs') $ lambdaParams lam++ sWhen bucket_in_bounds $ do+ let bucket_is =+ map Imp.vi64 (init space_is)+ ++ [sExt64 subhisto_ind, bucket']+ dLParams $ lambdaParams lam+ sLoopNest shape $ \is -> do+ forM_ (zip vs_params vs') $ \(p, res) ->+ copyDWIMFix (paramName p) [] (kernelResultSubExp res) is+ do_op (bucket_is ++ is)++histKernelGlobal ::+ [PatElem GPUMem] ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ [SegHistSlug] ->+ KernelBody GPUMem ->+ CallKernelGen ()+histKernelGlobal map_pes num_groups group_size space slugs kbody = do+ let num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size+ let (_space_is, space_sizes) = unzip $ unSegSpace space+ num_threads = sExt32 $ unCount num_groups' * unCount group_size'++ emit $ Imp.DebugPrint "## Using global memory" Nothing++ (hist_S, histograms) <-+ prepareIntermediateArraysGlobal+ (bodyPassage kbody)+ num_threads+ (toInt64Exp $ last space_sizes)+ slugs++ sFor "chk_i" hist_S $ \chk_i ->+ histKernelGlobalPass+ map_pes+ num_groups'+ group_size'+ space+ slugs+ kbody+ histograms+ hist_S+ chk_i++type InitLocalHistograms =+ [ ( [VName],+ SubExp ->+ InKernelGen+ ( [VName],+ [Imp.TExp Int64] -> InKernelGen ()+ )+ )+ ]++prepareIntermediateArraysLocal ::+ TV Int32 ->+ Count NumGroups (Imp.TExp Int64) ->+ SegSpace ->+ [SegHistSlug] ->+ CallKernelGen InitLocalHistograms+prepareIntermediateArraysLocal num_subhistos_per_group groups_per_segment space slugs = do+ num_segments <-+ dPrimVE "num_segments" $+ product $ map (toInt64Exp . snd) $ init $ unSegSpace space+ mapM (onOp num_segments) slugs+ where+ onOp num_segments (SegHistSlug op num_subhistos subhisto_info do_op) = do+ num_subhistos <-- sExt64 (unCount groups_per_segment) * num_segments++ emit $+ Imp.DebugPrint "Number of subhistograms in global memory" $+ Just $ untyped $ tvExp num_subhistos++ mk_op <-+ case do_op of+ AtomicPrim f -> return $ const $ return f+ AtomicCAS f -> return $ const $ return f+ AtomicLocking f -> return $ \hist_H_chk -> do+ let lock_shape =+ Shape $+ tvSize num_subhistos_per_group :+ shapeDims (histShape op)+ ++ [hist_H_chk]++ let dims = map toInt64Exp $ shapeDims lock_shape++ locks <- sAllocArray "locks" int32 lock_shape $ Space "local"++ sComment "All locks start out unlocked" $+ groupCoverSpace dims $ \is ->+ copyDWIMFix locks is (intConst Int32 0) []++ return $ f $ Locking locks 0 1 0 id++ -- Initialise local-memory sub-histograms. These are+ -- represented as two-dimensional arrays.+ let init_local_subhistos hist_H_chk = do+ local_subhistos <-+ forM (histType op) $ \t -> do+ let sub_local_shape =+ Shape [tvSize num_subhistos_per_group]+ <> (arrayShape t `setOuterDim` hist_H_chk)+ sAllocArray+ "subhistogram_local"+ (elemType t)+ sub_local_shape+ (Space "local")++ do_op' <- mk_op hist_H_chk++ return (local_subhistos, do_op' (Space "local") local_subhistos)++ -- Initialise global-memory sub-histograms.+ glob_subhistos <- forM subhisto_info $ \info -> do+ subhistosAlloc info+ return $ subhistosArray info++ return (glob_subhistos, init_local_subhistos)++histKernelLocalPass ::+ TV Int32 ->+ Count NumGroups (Imp.TExp Int64) ->+ [PatElem GPUMem] ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ SegSpace ->+ [SegHistSlug] ->+ KernelBody GPUMem ->+ InitLocalHistograms ->+ Imp.TExp Int32 ->+ Imp.TExp Int32 ->+ CallKernelGen ()+histKernelLocalPass+ num_subhistos_per_group_var+ groups_per_segment+ map_pes+ num_groups+ group_size+ space+ slugs+ kbody+ init_histograms+ hist_S+ chk_i = do+ let (space_is, space_sizes) = unzip $ unSegSpace space+ segment_is = init space_is+ segment_dims = init space_sizes+ (i_in_segment, segment_size) = last $ unSegSpace space+ num_subhistos_per_group = tvExp num_subhistos_per_group_var+ segment_size' = toInt64Exp segment_size++ num_segments <-+ dPrimVE "num_segments" $+ product $ map toInt64Exp segment_dims++ hist_H_chks <- forM (map (histWidth . slugOp) slugs) $ \w ->+ dPrimV "hist_H_chk" $ toInt64Exp w `divUp` sExt64 hist_S++ histo_sizes <- forM (zip slugs hist_H_chks) $ \(slug, hist_H_chk) -> do+ let histo_dims =+ tvExp hist_H_chk :+ map toInt64Exp (shapeDims (histShape (slugOp slug)))+ histo_size <-+ dPrimVE "histo_size" $ product histo_dims+ let group_hists_size =+ sExt64 num_subhistos_per_group * histo_size+ init_per_thread <-+ dPrimVE "init_per_thread" $ sExt32 $ group_hists_size `divUp` unCount group_size+ return (histo_dims, histo_size, init_per_thread)++ sKernelThread "seghist_local" num_groups group_size (segFlat space) $+ virtualiseGroups SegVirt (sExt32 $ unCount groups_per_segment * num_segments) $ \group_id -> do+ constants <- kernelConstants <$> askEnv++ flat_segment_id <- dPrimVE "flat_segment_id" $ group_id `quot` sExt32 (unCount groups_per_segment)+ gid_in_segment <- dPrimVE "gid_in_segment" $ group_id `rem` sExt32 (unCount groups_per_segment)+ -- This pgtid is kind of a "virtualised physical" gtid - not the+ -- same thing as the gtid used for the SegHist itself.+ pgtid_in_segment <-+ dPrimVE "pgtid_in_segment" $+ gid_in_segment * sExt32 (kernelGroupSize constants)+ + kernelLocalThreadId constants+ threads_per_segment <-+ dPrimVE "threads_per_segment" $+ sExt32 $ unCount groups_per_segment * kernelGroupSize constants++ -- Set segment indices.+ zipWithM_ dPrimV_ segment_is $+ unflattenIndex (map toInt64Exp segment_dims) $ sExt64 flat_segment_id++ histograms <- forM (zip init_histograms hist_H_chks) $+ \((glob_subhistos, init_local_subhistos), hist_H_chk) -> do+ (local_subhistos, do_op) <- init_local_subhistos $ Var $ tvVar hist_H_chk+ return (zip glob_subhistos local_subhistos, hist_H_chk, do_op)++ -- Find index of local subhistograms updated by this thread. We+ -- try to ensure, as much as possible, that threads in the same+ -- warp use different subhistograms, to avoid conflicts.+ thread_local_subhisto_i <-+ dPrimVE "thread_local_subhisto_i" $+ kernelLocalThreadId constants `rem` num_subhistos_per_group++ let onSlugs f =+ forM_ (zip3 slugs histograms histo_sizes) $+ \(slug, (dests, hist_H_chk, _), (histo_dims, histo_size, init_per_thread)) ->+ f slug dests (tvExp hist_H_chk) histo_dims histo_size init_per_thread++ let onAllHistograms f =+ onSlugs $ \slug dests hist_H_chk histo_dims histo_size init_per_thread -> do+ let group_hists_size = num_subhistos_per_group * sExt32 histo_size++ forM_ (zip dests (histNeutral $ slugOp slug)) $+ \((dest_global, dest_local), ne) ->+ sFor "local_i" init_per_thread $ \i -> do+ j <-+ dPrimVE "j" $+ i * sExt32 (kernelGroupSize constants)+ + kernelLocalThreadId constants+ j_offset <-+ dPrimVE "j_offset" $+ num_subhistos_per_group * sExt32 histo_size * gid_in_segment + j++ local_subhisto_i <- dPrimVE "local_subhisto_i" $ j `quot` sExt32 histo_size+ let local_bucket_is = unflattenIndex histo_dims $ sExt64 $ j `rem` sExt32 histo_size+ global_bucket_is =+ head local_bucket_is + sExt64 chk_i * hist_H_chk :+ tail local_bucket_is+ global_subhisto_i <- dPrimVE "global_subhisto_i" $ j_offset `quot` sExt32 histo_size++ sWhen (j .<. group_hists_size) $+ f+ dest_local+ dest_global+ (slugOp slug)+ ne+ local_subhisto_i+ global_subhisto_i+ local_bucket_is+ global_bucket_is++ sComment "initialize histograms in local memory" $+ onAllHistograms $ \dest_local dest_global op ne local_subhisto_i global_subhisto_i local_bucket_is global_bucket_is ->+ sComment "First subhistogram is initialised from global memory; others with neutral element." $ do+ let global_is = map Imp.vi64 segment_is ++ [0] ++ global_bucket_is+ local_is = sExt64 local_subhisto_i : local_bucket_is+ sIf+ (global_subhisto_i .==. 0)+ (copyDWIMFix dest_local local_is (Var dest_global) global_is)+ ( sLoopNest (histShape op) $ \is ->+ copyDWIMFix dest_local (local_is ++ is) ne []+ )++ sOp $ Imp.Barrier Imp.FenceLocal++ kernelLoop pgtid_in_segment threads_per_segment (sExt32 segment_size') $ \ie -> do+ dPrimV_ i_in_segment ie++ -- We execute the bucket function once and update each histogram+ -- serially. This also involves writing to the mapout arrays if+ -- this is the first chunk.++ compileStms mempty (kernelBodyStms kbody) $ do+ let (red_res, map_res) =+ splitFromEnd (length map_pes) $+ map kernelResultSubExp $ kernelBodyResult kbody+ (buckets, vs) = splitAt (length slugs) red_res+ perOp = chunks $ map (length . histDest . slugOp) slugs++ sWhen (chk_i .==. 0) $+ sComment "save map-out results" $+ forM_ (zip map_pes map_res) $ \(pe, se) ->+ copyDWIMFix+ (patElemName pe)+ (map Imp.vi64 space_is)+ se+ []++ forM_ (zip4 (map slugOp slugs) histograms buckets (perOp vs)) $+ \( HistOp dest_w _ _ _ shape lam,+ (_, hist_H_chk, do_op),+ bucket,+ vs'+ ) -> do+ let chk_beg = sExt64 chk_i * tvExp hist_H_chk+ bucket' = toInt64Exp bucket+ dest_w' = toInt64Exp dest_w+ bucket_in_bounds =+ bucket' .<. dest_w'+ .&&. chk_beg .<=. bucket'+ .&&. bucket' .<. (chk_beg + tvExp hist_H_chk)+ bucket_is = [sExt64 thread_local_subhisto_i, bucket' - chk_beg]+ vs_params = takeLast (length vs') $ lambdaParams lam++ sComment "perform atomic updates" $+ sWhen bucket_in_bounds $ do+ dLParams $ lambdaParams lam+ sLoopNest shape $ \is -> do+ forM_ (zip vs_params vs') $ \(p, v) ->+ copyDWIMFix (paramName p) [] v is+ do_op (bucket_is ++ is)++ sOp $ Imp.ErrorSync Imp.FenceGlobal++ sComment "Compact the multiple local memory subhistograms to result in global memory" $+ onSlugs $ \slug dests hist_H_chk histo_dims _histo_size bins_per_thread -> do+ trunc_H <-+ dPrimV "trunc_H" $+ sMin64 hist_H_chk $+ toInt64Exp (histWidth (slugOp slug))+ - sExt64 chk_i * head histo_dims+ let trunc_histo_dims =+ tvExp trunc_H :+ map toInt64Exp (shapeDims (histShape (slugOp slug)))+ trunc_histo_size <- dPrimVE "histo_size" $ sExt32 $ product trunc_histo_dims++ sFor "local_i" bins_per_thread $ \i -> do+ j <-+ dPrimVE "j" $+ i * sExt32 (kernelGroupSize constants)+ + kernelLocalThreadId constants+ sWhen (j .<. trunc_histo_size) $ do+ -- We are responsible for compacting the flat bin 'j', which+ -- we immediately unflatten.+ let local_bucket_is = unflattenIndex histo_dims $ sExt64 j+ global_bucket_is =+ head local_bucket_is + sExt64 chk_i * hist_H_chk :+ tail local_bucket_is+ dLParams $ lambdaParams $ histOp $ slugOp slug+ let (global_dests, local_dests) = unzip dests+ (xparams, yparams) =+ splitAt (length local_dests) $+ lambdaParams $ histOp $ slugOp slug++ sComment "Read values from subhistogram 0." $+ forM_ (zip xparams local_dests) $ \(xp, subhisto) ->+ copyDWIMFix+ (paramName xp)+ []+ (Var subhisto)+ (0 : local_bucket_is)++ sComment "Accumulate based on values in other subhistograms." $+ sFor "subhisto_id" (num_subhistos_per_group - 1) $ \subhisto_id -> do+ forM_ (zip yparams local_dests) $ \(yp, subhisto) ->+ copyDWIMFix+ (paramName yp)+ []+ (Var subhisto)+ (sExt64 subhisto_id + 1 : local_bucket_is)+ compileBody' xparams $ lambdaBody $ histOp $ slugOp slug++ sComment "Put final bucket value in global memory." $ do+ let global_is =+ map Imp.vi64 segment_is+ ++ [sExt64 group_id `rem` unCount groups_per_segment]+ ++ global_bucket_is+ forM_ (zip xparams global_dests) $ \(xp, global_dest) ->+ copyDWIMFix global_dest global_is (Var $ paramName xp) []++histKernelLocal ::+ TV Int32 ->+ Count NumGroups (Imp.TExp Int64) ->+ [PatElem GPUMem] ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ Imp.TExp Int32 ->+ [SegHistSlug] ->+ KernelBody GPUMem ->+ CallKernelGen ()+histKernelLocal num_subhistos_per_group_var groups_per_segment map_pes num_groups group_size space hist_S slugs kbody = do+ let num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size+ num_subhistos_per_group = tvExp num_subhistos_per_group_var++ emit $+ Imp.DebugPrint "Number of local subhistograms per group" $+ Just $ untyped num_subhistos_per_group++ init_histograms <-+ prepareIntermediateArraysLocal num_subhistos_per_group_var groups_per_segment space slugs++ sFor "chk_i" hist_S $ \chk_i ->+ histKernelLocalPass+ num_subhistos_per_group_var+ groups_per_segment+ map_pes+ num_groups'+ group_size'+ space+ slugs+ kbody+ init_histograms+ hist_S+ chk_i++-- | The maximum number of passes we are willing to accept for this+-- kind of atomic update.+slugMaxLocalMemPasses :: SegHistSlug -> Int+slugMaxLocalMemPasses slug =+ case slugAtomicUpdate slug of+ AtomicPrim _ -> 3+ AtomicCAS _ -> 4+ AtomicLocking _ -> 6++localMemoryCase ::+ [PatElem GPUMem] ->+ Imp.TExp Int32 ->+ SegSpace ->+ Imp.TExp Int64 ->+ Imp.TExp Int64 ->+ Imp.TExp Int64 ->+ Imp.TExp Int32 ->+ [SegHistSlug] ->+ KernelBody GPUMem ->+ CallKernelGen (Imp.TExp Bool, CallKernelGen ())+localMemoryCase map_pes hist_T space hist_H hist_el_size hist_N _ slugs kbody = do+ let space_sizes = segSpaceDims space+ segment_dims = init space_sizes+ segmented = not $ null segment_dims++ hist_L <- dPrim "hist_L" int32+ sOp $ Imp.GetSizeMax (tvVar hist_L) Imp.SizeLocalMemory++ max_group_size <- dPrim "max_group_size" int32+ sOp $ Imp.GetSizeMax (tvVar max_group_size) Imp.SizeGroup+ let group_size = Imp.Count $ Var $ tvVar max_group_size+ num_groups <-+ fmap (Imp.Count . tvSize) $+ dPrimV "num_groups" $+ sExt64 hist_T `divUp` toInt64Exp (unCount group_size)+ let num_groups' = toInt64Exp <$> num_groups+ group_size' = toInt64Exp <$> group_size++ let r64 = isF64 . ConvOpExp (SIToFP Int64 Float64) . untyped+ t64 = isInt64 . ConvOpExp (FPToSI Float64 Int64) . untyped++ -- M approximation.+ hist_m' <-+ dPrimVE "hist_m_prime" $+ r64+ ( sMin64+ (sExt64 (tvExp hist_L `quot` hist_el_size))+ (hist_N `divUp` sExt64 (unCount num_groups'))+ )+ / r64 hist_H++ let hist_B = unCount group_size'++ -- M in the paper, but not adjusted for asymptotic efficiency.+ hist_M0 <-+ dPrimVE "hist_M0" $+ sMax64 1 $ sMin64 (t64 hist_m') hist_B++ -- Minimal sequential chunking factor.+ let q_small = 2++ -- The number of segments/histograms produced..+ hist_Nout <- dPrimVE "hist_Nout" $ product $ map toInt64Exp segment_dims++ hist_Nin <- dPrimVE "hist_Nin" $ toInt64Exp $ last space_sizes++ -- Maximum M for work efficiency.+ work_asymp_M_max <-+ if segmented+ then do+ hist_T_hist_min <-+ dPrimVE "hist_T_hist_min" $+ sExt32 $+ sMin64 (sExt64 hist_Nin * sExt64 hist_Nout) (sExt64 hist_T)+ `divUp` sExt64 hist_Nout++ -- Number of groups, rounded up.+ let r = hist_T_hist_min `divUp` sExt32 hist_B++ dPrimVE "work_asymp_M_max" $ hist_Nin `quot` (sExt64 r * hist_H)+ else+ dPrimVE "work_asymp_M_max" $+ (hist_Nout * hist_N)+ `quot` ( (q_small * unCount num_groups' * hist_H)+ `quot` genericLength slugs+ )++ -- Number of subhistograms per result histogram.+ hist_M <- dPrimV "hist_M" $ sExt32 $ sMin64 hist_M0 work_asymp_M_max++ -- hist_M may be zero (which we'll check for below), but we need it+ -- for some divisions first, so crudely make a nonzero form.+ let hist_M_nonzero = sMax32 1 $ tvExp hist_M++ -- "Cooperation factor" - the number of threads cooperatively+ -- working on the same (sub)histogram.+ hist_C <-+ dPrimVE "hist_C" $+ hist_B `divUp` sExt64 hist_M_nonzero++ emit $ Imp.DebugPrint "local hist_M0" $ Just $ untyped hist_M0+ emit $ Imp.DebugPrint "local work asymp M max" $ Just $ untyped work_asymp_M_max+ emit $ Imp.DebugPrint "local C" $ Just $ untyped hist_C+ emit $ Imp.DebugPrint "local B" $ Just $ untyped hist_B+ emit $ Imp.DebugPrint "local M" $ Just $ untyped $ tvExp hist_M+ emit $+ Imp.DebugPrint "local memory needed" $+ Just $ untyped $ hist_H * hist_el_size * sExt64 (tvExp hist_M)++ -- local_mem_needed is what we need to keep a single bucket in local+ -- memory - this is an absolute minimum. We can fit anything else+ -- by doing multiple passes, although more than a few is+ -- (heuristically) not efficient.+ local_mem_needed <-+ dPrimVE "local_mem_needed" $+ hist_el_size * sExt64 (tvExp hist_M)+ hist_S <-+ dPrimVE "hist_S" $+ sExt32 $+ (hist_H * local_mem_needed) `divUp` tvExp hist_L+ let max_S = case bodyPassage kbody of+ MustBeSinglePass -> 1+ MayBeMultiPass -> fromIntegral $ maxinum $ map slugMaxLocalMemPasses slugs++ groups_per_segment <-+ if segmented+ then+ fmap Count $+ dPrimVE "groups_per_segment" $ unCount num_groups' `divUp` hist_Nout+ else pure num_groups'++ -- We only use local memory if the number of updates per histogram+ -- at least matches the histogram size, as otherwise it is not+ -- asymptotically efficient. This mostly matters for the segmented+ -- case.+ let pick_local =+ hist_Nin .>=. hist_H+ .&&. (local_mem_needed .<=. tvExp hist_L)+ .&&. (hist_S .<=. max_S)+ .&&. hist_C .<=. hist_B+ .&&. tvExp hist_M .>. 0++ run = do+ emit $ Imp.DebugPrint "## Using local memory" Nothing+ emit $ Imp.DebugPrint "Histogram size (H)" $ Just $ untyped hist_H+ emit $ Imp.DebugPrint "Multiplication degree (M)" $ Just $ untyped $ tvExp hist_M+ emit $ Imp.DebugPrint "Cooperation level (C)" $ Just $ untyped hist_C+ emit $ Imp.DebugPrint "Number of chunks (S)" $ Just $ untyped hist_S+ when segmented $+ emit $ Imp.DebugPrint "Groups per segment" $ Just $ untyped $ unCount groups_per_segment+ histKernelLocal+ hist_M+ groups_per_segment+ map_pes+ num_groups+ group_size+ space+ hist_S+ slugs+ kbody++ return (pick_local, run)++-- | Generate code for a segmented histogram called from the host.+compileSegHist ::+ Pattern GPUMem ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ [HistOp GPUMem] ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegHist (Pattern _ 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+ -- are always in global memory, but their number may vary).+ let num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size+ dims = map toInt64Exp $ segSpaceDims space++ num_red_res = length ops + sum (map (length . histNeutral) ops)+ (all_red_pes, map_pes) = splitAt num_red_res pes+ segment_size = last dims++ (op_hs, op_seg_hs, slugs) <- unzip3 <$> mapM (computeHistoUsage space) ops+ h <- dPrimVE "h" $ Imp.unCount $ sum op_hs+ seg_h <- dPrimVE "seg_h" $ Imp.unCount $ sum op_seg_hs++ -- Check for emptyness to avoid division-by-zero.+ sUnless (seg_h .==. 0) $ do+ -- Maximum group size (or actual, in this case).+ let hist_B = unCount group_size'++ -- Size of a histogram.+ hist_H <- dPrimVE "hist_H" $ sum $ map (toInt64Exp . histWidth) ops++ -- Size of a single histogram element. Actually the weighted+ -- average of histogram elements in cases where we have more than+ -- one histogram operation, plus any locks.+ let lockSize slug = case slugAtomicUpdate slug of+ AtomicLocking {} -> Just $ primByteSize int32+ _ -> Nothing+ hist_el_size <-+ dPrimVE "hist_el_size" $+ foldl' (+) (h `divUp` hist_H) $+ mapMaybe lockSize slugs++ -- Input elements contributing to each histogram.+ hist_N <- dPrimVE "hist_N" segment_size++ -- Compute RF as the average RF over all the histograms.+ hist_RF <-+ dPrimVE "hist_RF" $+ sExt32 $+ sum (map (toInt64Exp . histRaceFactor . slugOp) slugs)+ `quot` genericLength slugs++ let hist_T = sExt32 $ unCount num_groups' * unCount group_size'+ emit $ Imp.DebugPrint "\n# SegHist" Nothing+ emit $ Imp.DebugPrint "Number of threads (T)" $ Just $ untyped hist_T+ emit $ Imp.DebugPrint "Desired group size (B)" $ Just $ untyped hist_B+ emit $ Imp.DebugPrint "Histogram size (H)" $ Just $ untyped hist_H+ emit $ Imp.DebugPrint "Input elements per histogram (N)" $ Just $ untyped hist_N+ emit $+ Imp.DebugPrint "Number of segments" $+ Just $ untyped $ product $ map (toInt64Exp . snd) segment_dims+ emit $ Imp.DebugPrint "Histogram element size (el_size)" $ Just $ untyped hist_el_size+ emit $ Imp.DebugPrint "Race factor (RF)" $ Just $ untyped hist_RF+ emit $ Imp.DebugPrint "Memory per set of subhistograms per segment" $ Just $ untyped h+ emit $ Imp.DebugPrint "Memory per set of subhistograms times segments" $ Just $ untyped seg_h++ (use_local_memory, run_in_local_memory) <-+ localMemoryCase map_pes hist_T space hist_H hist_el_size hist_N hist_RF slugs kbody++ sIf use_local_memory run_in_local_memory $+ histKernelGlobal map_pes num_groups group_size space slugs kbody++ let pes_per_op = chunks (map (length . histDest) ops) all_red_pes++ forM_ (zip3 slugs pes_per_op ops) $ \(slug, red_pes, op) -> do+ let num_histos = slugNumSubhistos slug+ subhistos = map subhistosArray $ slugSubhistos slug++ let unitHistoCase =+ -- This is OK because the memory blocks are at least as+ -- large as the ones we are supposed to use for the result.+ forM_ (zip red_pes subhistos) $ \(pe, subhisto) -> do+ pe_mem <-+ memLocationName . entryArrayLocation+ <$> lookupArray (patElemName pe)+ subhisto_mem <-+ memLocationName . entryArrayLocation+ <$> lookupArray subhisto+ emit $ Imp.SetMem pe_mem subhisto_mem $ Space "device"++ sIf (tvExp num_histos .==. 1) unitHistoCase $ do+ -- For the segmented reduction, we keep the segment dimensions+ -- unchanged. To this, we add two dimensions: one over the number+ -- of buckets, and one over the number of subhistograms. This+ -- inner dimension is the one that is collapsed in the reduction.+ let num_buckets = histWidth op++ bucket_id <- newVName "bucket_id"+ subhistogram_id <- newVName "subhistogram_id"+ vector_ids <-+ mapM (const $ newVName "vector_id") $+ shapeDims $ histShape op++ flat_gtid <- newVName "flat_gtid"++ let lvl = SegThread num_groups group_size SegVirt+ segred_space =+ SegSpace flat_gtid $+ segment_dims+ ++ [(bucket_id, num_buckets)]+ ++ zip vector_ids (shapeDims $ histShape op)+ ++ [(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 ->+ red_cont $+ flip map subhistos $ \subhisto ->+ ( Var subhisto,+ map Imp.vi64 $+ map fst segment_dims ++ [subhistogram_id, bucket_id] ++ vector_ids+ )++ emit $ Imp.DebugPrint "" Nothing+ where+ segment_dims = init $ unSegSpace space
+ src/Futhark/CodeGen/ImpGen/GPU/SegMap.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | Code generation for 'SegMap' is quite straightforward. The only+-- trick is virtualisation in case the physical number of threads is+-- not sufficient to cover the logical thread space. This is handled+-- by having actual workgroups run a loop to imitate multiple workgroups.+module Futhark.CodeGen.ImpGen.GPU.SegMap (compileSegMap) where++import Control.Monad.Except+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.IR.GPUMem+import Futhark.Util.IntegralExp (divUp)+import Prelude hiding (quot, rem)++-- | Compile 'SegMap' instance code.+compileSegMap ::+ Pattern GPUMem ->+ SegLevel ->+ SegSpace ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegMap pat lvl space kbody = do+ let (is, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ num_groups' = toInt64Exp <$> segNumGroups lvl+ group_size' = toInt64Exp <$> segGroupSize lvl++ emit $ Imp.DebugPrint "\n# SegMap" Nothing+ case lvl of+ SegThread {} -> do+ let virt_num_groups =+ sExt32 $ product dims' `divUp` unCount group_size'+ sKernelThread "segmap" num_groups' group_size' (segFlat space) $+ virtualiseGroups (segVirt lvl) virt_num_groups $ \group_id -> do+ local_tid <- kernelLocalThreadId . kernelConstants <$> askEnv++ global_tid <-+ dPrimVE "global_tid" $+ sExt64 group_id * sExt64 (unCount group_size')+ + sExt64 local_tid++ dIndexSpace (zip is dims') global_tid++ sWhen (isActive $ unSegSpace space) $+ compileStms mempty (kernelBodyStms kbody) $+ zipWithM_ (compileThreadResult space) (patternElements pat) $+ kernelBodyResult kbody+ SegGroup {} ->+ sKernelGroup "segmap_intragroup" num_groups' group_size' (segFlat space) $ do+ let virt_num_groups = sExt32 $ product dims'+ precomputeSegOpIDs (kernelBodyStms kbody) $+ virtualiseGroups (segVirt lvl) virt_num_groups $ \group_id -> do+ dIndexSpace (zip is dims') $ sExt64 group_id++ compileStms mempty (kernelBodyStms kbody) $+ zipWithM_ (compileGroupResult space) (patternElements pat) $+ kernelBodyResult kbody+ emit $ Imp.DebugPrint "" Nothing
+ src/Futhark/CodeGen/ImpGen/GPU/SegRed.hs view
@@ -0,0 +1,842 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | We generate code for non-segmented/single-segment SegRed using+-- the basic approach outlined in the paper "Design and GPGPU+-- Performance of Futhark’s Redomap Construct" (ARRAY '16). The main+-- deviations are:+--+-- * While we still use two-phase reduction, we use only a single+-- kernel, with the final workgroup to write a result (tracked via+-- an atomic counter) performing the final reduction as well.+--+-- * Instead of depending on storage layout transformations to handle+-- non-commutative reductions efficiently, we slide a+-- @groupsize@-sized window over the input, and perform a parallel+-- reduction for each window. This sacrifices the notion of+-- efficient sequentialisation, but is sometimes faster and+-- definitely simpler and more predictable (and uses less auxiliary+-- storage).+--+-- For segmented reductions we use the approach from "Strategies for+-- Regular Segmented Reductions on GPU" (FHPC '17). This involves+-- having two different strategies, and dynamically deciding which one+-- to use based on the number of segments and segment size. We use the+-- (static) @group_size@ to decide which of the following two+-- strategies to choose:+--+-- * Large: uses one or more groups to process a single segment. If+-- multiple groups are used per segment, the intermediate reduction+-- results must be recursively reduced, until there is only a single+-- value per segment.+--+-- Each thread /can/ read multiple elements, which will greatly+-- increase performance; however, if the reduction is+-- non-commutative we will have to use a less efficient traversal+-- (with interim group-wide reductions) to enable coalesced memory+-- accesses, just as in the non-segmented case.+--+-- * Small: is used to let each group process *multiple* segments+-- within a group. We will only use this approach when we can+-- process at least two segments within a single group. In those+-- cases, we would allocate a /whole/ group per segment with the+-- large strategy, but at most 50% of the threads in the group would+-- have any element to read, which becomes highly inefficient.+module Futhark.CodeGen.ImpGen.GPU.SegRed+ ( compileSegRed,+ compileSegRed',+ DoSegBody,+ )+where++import Control.Monad.Except+import Data.List (genericLength, zip7)+import Data.Maybe+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.Error+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.Transform.Rename+import Futhark.Util (chunks)+import Futhark.Util.IntegralExp (divUp, quot, rem)+import Prelude hiding (quot, rem)++-- | The maximum number of operators we support in a single SegRed.+-- This limit arises out of the static allocation of counters.+maxNumOps :: Int32+maxNumOps = 10++-- | Code generation for the body of the SegRed, taking a continuation+-- for saving the results of the body. The results should be+-- represented as a pairing of a t'SubExp' along with a list of+-- indexes into that t'SubExp' for reading the result.+type DoSegBody = ([(SubExp, [Imp.TExp Int64])] -> InKernelGen ()) -> InKernelGen ()++-- | Compile 'SegRed' instance to host-level code with calls to+-- various kernels.+compileSegRed ::+ Pattern GPUMem ->+ SegLevel ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegRed pat lvl space reds body =+ compileSegRed' pat lvl space reds $ \red_cont ->+ compileStms mempty (kernelBodyStms body) $ do+ let (red_res, map_res) = splitAt (segBinOpResults reds) $ kernelBodyResult body++ sComment "save map-out results" $ do+ let map_arrs = drop (segBinOpResults reds) $ patternElements 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 ->+ SegLevel ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ DoSegBody ->+ CallKernelGen ()+compileSegRed' pat lvl space reds body+ | genericLength reds > maxNumOps =+ compilerLimitationS $+ "compileSegRed': at most " ++ show maxNumOps ++ " reduction operators are supported."+ | [(_, Constant (IntValue (Int64Value 1))), _] <- unSegSpace space =+ nonsegmentedReduction pat num_groups group_size space reds body+ | otherwise = do+ let group_size' = toInt64Exp $ unCount group_size+ segment_size = toInt64Exp $ last $ segSpaceDims space+ use_small_segments = segment_size * 2 .<. group_size'+ sIf+ use_small_segments+ (smallSegmentsReduction pat num_groups group_size space reds body)+ (largeSegmentsReduction pat num_groups group_size space reds body)+ where+ num_groups = segNumGroups lvl+ group_size = segGroupSize lvl++-- | Prepare intermediate arrays for the reduction. Prim-typed+-- arguments go in local memory (so we need to do the allocation of+-- those arrays inside the kernel), while array-typed arguments go in+-- global memory. Allocations for the former have already been+-- performed. This policy is baked into how the allocations are done+-- in ExplicitAllocations.+intermediateArrays ::+ Count GroupSize SubExp ->+ SubExp ->+ SegBinOp GPUMem ->+ InKernelGen [VName]+intermediateArrays (Count group_size) num_threads (SegBinOp _ red_op nes _) = do+ let red_op_params = lambdaParams red_op+ (red_acc_params, _) = splitAt (length nes) red_op_params+ forM red_acc_params $ \p ->+ case paramDec p of+ MemArray pt shape _ (ArrayIn mem _) -> do+ let shape' = Shape [num_threads] <> shape+ sArray "red_arr" pt shape' $+ ArrayIn mem $ IxFun.iota $ map pe64 $ shapeDims shape'+ _ -> do+ let pt = elemType $ paramType p+ shape = Shape [group_size]+ sAllocArray "red_arr" pt shape $ Space "local"++-- | Arrays for storing group results.+--+-- The group-result arrays have an extra dimension because they are+-- also used for keeping vectorised accumulators for first-stage+-- reduction, if necessary. If necessary, this dimension has size+-- group_size, and otherwise 1. When actually storing group results,+-- the first index is set to 0.+groupResultArrays ::+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ [SegBinOp GPUMem] ->+ CallKernelGen [[VName]]+groupResultArrays (Count virt_num_groups) (Count group_size) reds =+ forM reds $ \(SegBinOp _ lam _ shape) ->+ forM (lambdaReturnType lam) $ \t -> do+ let pt = elemType t+ extra_dim+ | primType t = intConst Int64 1+ | otherwise = group_size+ full_shape = Shape [extra_dim, virt_num_groups] <> shape <> arrayShape t+ -- Move the groupsize dimension last to ensure coalesced+ -- memory access.+ perm = [1 .. shapeRank full_shape -1] ++ [0]+ sAllocArrayPerm "segred_tmp" pt full_shape (Space "device") perm++nonsegmentedReduction ::+ Pattern GPUMem ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ DoSegBody ->+ CallKernelGen ()+nonsegmentedReduction segred_pat num_groups group_size space reds body = do+ let (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size+ global_tid = Imp.vi64 $ segFlat space+ w = last dims'++ counter <-+ sStaticArray "counter" (Space "device") int32 $+ Imp.ArrayValues $ replicate (fromIntegral maxNumOps) $ IntValue $ Int32Value 0++ reds_group_res_arrs <- groupResultArrays num_groups group_size reds++ num_threads <-+ dPrimV "num_threads" $+ unCount num_groups' * unCount group_size'++ emit $ Imp.DebugPrint "\n# SegRed" Nothing++ sKernelThread "segred_nonseg" num_groups' group_size' (segFlat space) $ do+ constants <- kernelConstants <$> askEnv+ sync_arr <- sAllocArray "sync_arr" Bool (Shape [intConst Int32 1]) $ Space "local"+ reds_arrs <- mapM (intermediateArrays group_size (tvSize num_threads)) reds++ -- Since this is the nonsegmented case, all outer segment IDs must+ -- necessarily be 0.+ forM_ gtids $ \v -> dPrimV_ v (0 :: Imp.TExp Int64)++ let num_elements = Imp.elements w+ elems_per_thread =+ num_elements+ `divUp` Imp.elements (sExt64 (kernelNumThreads constants))++ slugs <-+ mapM (segBinOpSlug (kernelLocalThreadId constants) (kernelGroupId constants)) $+ zip3 reds reds_arrs reds_group_res_arrs+ reds_op_renamed <-+ reductionStageOne+ constants+ (zip gtids dims')+ num_elements+ global_tid+ elems_per_thread+ (tvVar num_threads)+ slugs+ body++ let segred_pes =+ chunks (map (length . segBinOpNeutral) reds) $+ patternElements 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+ reductionStageTwo+ constants+ pes+ (kernelGroupId constants)+ 0+ [0]+ 0+ (sExt64 $ kernelNumGroups constants)+ slug+ red_x_params+ red_y_params+ red_op_renamed+ nes+ 1+ counter+ (fromInteger i)+ sync_arr+ group_res_arrs+ red_arrs++ emit $ Imp.DebugPrint "" Nothing++smallSegmentsReduction ::+ Pattern GPUMem ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ DoSegBody ->+ CallKernelGen ()+smallSegmentsReduction (Pattern _ segred_pes) num_groups group_size space reds body = do+ let (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ segment_size = last dims'++ -- Careful to avoid division by zero now.+ segment_size_nonzero <-+ dPrimVE "segment_size_nonzero" $ sMax64 1 segment_size++ let num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size+ num_threads <- dPrimV "num_threads" $ unCount num_groups' * unCount group_size'+ let num_segments = product $ init dims'+ segments_per_group = unCount group_size' `quot` segment_size_nonzero+ required_groups = sExt32 $ num_segments `divUp` segments_per_group++ emit $ Imp.DebugPrint "\n# SegRed-small" Nothing+ emit $ Imp.DebugPrint "num_segments" $ Just $ untyped num_segments+ emit $ Imp.DebugPrint "segment_size" $ Just $ untyped segment_size+ emit $ Imp.DebugPrint "segments_per_group" $ Just $ untyped segments_per_group+ emit $ Imp.DebugPrint "required_groups" $ Just $ untyped required_groups++ sKernelThread "segred_small" num_groups' group_size' (segFlat space) $ do+ constants <- kernelConstants <$> askEnv+ reds_arrs <- mapM (intermediateArrays group_size (Var $ tvVar num_threads)) reds++ -- We probably do not have enough actual workgroups to cover the+ -- entire iteration space. Some groups thus have to perform double+ -- duty; we put an outer loop to accomplish this.+ virtualiseGroups SegVirt required_groups $ \group_id' -> do+ -- Compute the 'n' input indices. The outer 'n-1' correspond to+ -- the segment ID, and are computed from the group id. The inner+ -- is computed from the local thread id, and may be out-of-bounds.+ let ltid = sExt64 $ kernelLocalThreadId constants+ segment_index =+ (ltid `quot` segment_size_nonzero)+ + (sExt64 group_id' * sExt64 segments_per_group)+ index_within_segment = ltid `rem` segment_size++ dIndexSpace (zip (init gtids) (init dims')) segment_index+ dPrimV_ (last gtids) index_within_segment++ let out_of_bounds =+ forM_ (zip reds reds_arrs) $ \(SegBinOp _ _ nes _, red_arrs) ->+ forM_ (zip red_arrs nes) $ \(arr, ne) ->+ copyDWIMFix arr [ltid] ne []++ in_bounds =+ body $ \red_res ->+ sComment "save results to be reduced" $ do+ let red_dests = zip (concat reds_arrs) $ repeat [ltid]+ forM_ (zip red_dests red_res) $ \((d, d_is), (res, res_is)) ->+ copyDWIMFix d d_is res res_is++ sComment "apply map function if in bounds" $+ sIf+ ( segment_size .>. 0+ .&&. isActive (init $ zip gtids dims)+ .&&. ltid .<. segment_size * segments_per_group+ )+ in_bounds+ out_of_bounds++ sOp $ Imp.ErrorSync Imp.FenceLocal -- Also implicitly barrier.+ let crossesSegment from to =+ (sExt64 to - sExt64 from) .>. (sExt64 to `rem` segment_size)+ sWhen (segment_size .>. 0) $+ sComment "perform segmented scan to imitate reduction" $+ forM_ (zip reds reds_arrs) $ \(SegBinOp _ red_op _ _, red_arrs) ->+ groupScan+ (Just crossesSegment)+ (sExt64 $ tvExp num_threads)+ (segment_size * segments_per_group)+ red_op+ red_arrs++ sOp $ Imp.Barrier Imp.FenceLocal++ sComment "save final values of segments" $+ sWhen+ ( sExt64 group_id' * segments_per_group + sExt64 ltid .<. num_segments+ .&&. ltid .<. segments_per_group+ )+ $ forM_ (zip segred_pes (concat reds_arrs)) $ \(pe, arr) -> do+ -- Figure out which segment result this thread should write...+ let flat_segment_index =+ sExt64 group_id' * segments_per_group + sExt64 ltid+ gtids' =+ unflattenIndex (init dims') flat_segment_index+ copyDWIMFix+ (patElemName pe)+ gtids'+ (Var arr)+ [(ltid + 1) * segment_size_nonzero - 1]++ -- Finally another barrier, because we will be writing to the+ -- local memory array first thing in the next iteration.+ sOp $ Imp.Barrier Imp.FenceLocal++ emit $ Imp.DebugPrint "" Nothing++largeSegmentsReduction ::+ Pattern GPUMem ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ DoSegBody ->+ CallKernelGen ()+largeSegmentsReduction segred_pat num_groups group_size space reds body = do+ let (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ num_segments = product $ init dims'+ segment_size = last dims'+ num_groups' = fmap toInt64Exp num_groups+ group_size' = fmap toInt64Exp group_size++ (groups_per_segment, elems_per_thread) <-+ groupsPerSegmentAndElementsPerThread+ segment_size+ num_segments+ num_groups'+ group_size'+ virt_num_groups <-+ dPrimV "virt_num_groups" $+ groups_per_segment * num_segments++ num_threads <-+ dPrimV "num_threads" $+ unCount num_groups' * unCount group_size'++ threads_per_segment <-+ dPrimV "threads_per_segment" $+ groups_per_segment * unCount group_size'++ emit $ Imp.DebugPrint "\n# SegRed-large" Nothing+ emit $ Imp.DebugPrint "num_segments" $ Just $ untyped num_segments+ emit $ Imp.DebugPrint "segment_size" $ Just $ untyped segment_size+ emit $ Imp.DebugPrint "virt_num_groups" $ Just $ untyped $ tvExp virt_num_groups+ emit $ Imp.DebugPrint "num_groups" $ Just $ untyped $ Imp.unCount num_groups'+ emit $ Imp.DebugPrint "group_size" $ Just $ untyped $ Imp.unCount group_size'+ emit $ Imp.DebugPrint "elems_per_thread" $ Just $ untyped $ Imp.unCount elems_per_thread+ emit $ Imp.DebugPrint "groups_per_segment" $ Just $ untyped groups_per_segment++ reds_group_res_arrs <- groupResultArrays (Count (tvSize virt_num_groups)) group_size reds++ -- In principle we should have a counter for every segment. Since+ -- the number of segments is a dynamic quantity, we would have to+ -- allocate and zero out an array here, which is expensive.+ -- However, we exploit the fact that the number of segments being+ -- reduced at any point in time is limited by the number of+ -- workgroups. If we bound the number of workgroups, we can get away+ -- with using that many counters. FIXME: Is this limit checked+ -- anywhere? There are other places in the compiler that will fail+ -- if the group count exceeds the maximum group size, which is at+ -- most 1024 anyway.+ let num_counters = fromIntegral maxNumOps * 1024+ counter <-+ sStaticArray "counter" (Space "device") int32 $+ Imp.ArrayZeros num_counters++ sKernelThread "segred_large" num_groups' group_size' (segFlat space) $ do+ constants <- kernelConstants <$> askEnv+ reds_arrs <- mapM (intermediateArrays group_size (tvSize num_threads)) reds+ sync_arr <- sAllocArray "sync_arr" Bool (Shape [intConst Int32 1]) $ Space "local"++ -- We probably do not have enough actual workgroups to cover the+ -- entire iteration space. Some groups thus have to perform double+ -- duty; we put an outer loop to accomplish this.+ virtualiseGroups SegVirt (sExt32 (tvExp virt_num_groups)) $ \group_id -> do+ let segment_gtids = init gtids+ w = last dims+ local_tid = kernelLocalThreadId constants++ flat_segment_id <-+ dPrimVE "flat_segment_id" $+ group_id `quot` sExt32 groups_per_segment++ global_tid <-+ dPrimVE "global_tid" $+ (sExt64 group_id * sExt64 (unCount group_size') + sExt64 local_tid)+ `rem` (sExt64 (unCount group_size') * groups_per_segment)++ let first_group_for_segment = sExt64 flat_segment_id * groups_per_segment+ dIndexSpace (zip segment_gtids (init dims')) $sExt64 flat_segment_id+ dPrim_ (last gtids) int64+ let num_elements = Imp.elements $ toInt64Exp w++ slugs <-+ mapM (segBinOpSlug local_tid group_id) $+ zip3 reds reds_arrs reds_group_res_arrs+ reds_op_renamed <-+ reductionStageOne+ constants+ (zip gtids dims')+ num_elements+ global_tid+ elems_per_thread+ (tvVar threads_per_segment)+ slugs+ body++ let segred_pes =+ chunks (map (length . segBinOpNeutral) reds) $+ patternElements segred_pat++ multiple_groups_per_segment =+ 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+ reductionStageTwo+ constants+ pes+ group_id+ flat_segment_id+ (map Imp.vi64 segment_gtids)+ (sExt64 first_group_for_segment)+ groups_per_segment+ slug+ red_x_params+ red_y_params+ red_op_renamed+ nes+ (fromIntegral num_counters)+ counter+ (fromInteger i)+ sync_arr+ group_res_arrs+ red_arrs++ one_group_per_segment =+ comment "first thread in group saves final result to memory" $+ forM_ (zip slugs segred_pes) $ \(slug, pes) ->+ sWhen (local_tid .==. 0) $+ forM_ (zip pes (slugAccs slug)) $ \(v, (acc, acc_is)) ->+ copyDWIMFix (patElemName v) (map Imp.vi64 segment_gtids) (Var acc) acc_is++ sIf (groups_per_segment .==. 1) one_group_per_segment multiple_groups_per_segment++ emit $ Imp.DebugPrint "" Nothing++-- Careful to avoid division by zero here. We have at least one group+-- per segment.+groupsPerSegmentAndElementsPerThread ::+ Imp.TExp Int64 ->+ Imp.TExp Int64 ->+ Count NumGroups (Imp.TExp Int64) ->+ Count GroupSize (Imp.TExp Int64) ->+ CallKernelGen+ ( Imp.TExp Int64,+ Imp.Count Imp.Elements (Imp.TExp Int64)+ )+groupsPerSegmentAndElementsPerThread segment_size num_segments num_groups_hint group_size = do+ groups_per_segment <-+ dPrimVE "groups_per_segment" $+ unCount num_groups_hint `divUp` sMax64 1 num_segments+ elements_per_thread <-+ dPrimVE "elements_per_thread" $+ segment_size `divUp` (unCount group_size * groups_per_segment)+ return (groups_per_segment, Imp.elements elements_per_thread)++-- | A SegBinOp with auxiliary information.+data SegBinOpSlug = SegBinOpSlug+ { slugOp :: SegBinOp GPUMem,+ -- | The arrays used for computing the intra-group reduction+ -- (either local or global memory).+ slugArrs :: [VName],+ -- | Places to store accumulator in stage 1 reduction.+ slugAccs :: [(VName, [Imp.TExp Int64])]+ }++slugBody :: SegBinOpSlug -> Body GPUMem+slugBody = lambdaBody . segBinOpLambda . slugOp++slugParams :: SegBinOpSlug -> [LParam GPUMem]+slugParams = lambdaParams . segBinOpLambda . slugOp++slugNeutral :: SegBinOpSlug -> [SubExp]+slugNeutral = segBinOpNeutral . slugOp++slugShape :: SegBinOpSlug -> Shape+slugShape = segBinOpShape . slugOp++slugsComm :: [SegBinOpSlug] -> Commutativity+slugsComm = mconcat . map (segBinOpComm . slugOp)++accParams, nextParams :: SegBinOpSlug -> [LParam GPUMem]+accParams slug = take (length (slugNeutral slug)) $ slugParams slug+nextParams slug = drop (length (slugNeutral slug)) $ slugParams slug++segBinOpSlug :: Imp.TExp Int32 -> Imp.TExp Int32 -> (SegBinOp GPUMem, [VName], [VName]) -> InKernelGen SegBinOpSlug+segBinOpSlug local_tid group_id (op, group_res_arrs, param_arrs) =+ SegBinOpSlug op group_res_arrs+ <$> zipWithM mkAcc (lambdaParams (segBinOpLambda op)) param_arrs+ where+ mkAcc p param_arr+ | Prim t <- paramType p,+ shapeRank (segBinOpShape op) == 0 = do+ acc <- dPrim (baseString (paramName p) <> "_acc") t+ return (tvVar acc, [])+ | otherwise =+ return (param_arr, [sExt64 local_tid, sExt64 group_id])++reductionStageZero ::+ KernelConstants ->+ [(VName, Imp.TExp Int64)] ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ Imp.TExp Int64 ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ VName ->+ [SegBinOpSlug] ->+ DoSegBody ->+ InKernelGen ([Lambda GPUMem], InKernelGen ())+reductionStageZero constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body = do+ let (gtids, _dims) = unzip ispace+ gtid = mkTV (last gtids) int64+ local_tid = sExt64 $ kernelLocalThreadId constants++ -- Figure out how many elements this thread should process.+ chunk_size <- dPrim "chunk_size" int64+ let ordering = case slugsComm slugs of+ Commutative -> SplitStrided $ Var threads_per_segment+ Noncommutative -> SplitContiguous+ computeThreadChunkSize ordering (sExt64 global_tid) elems_per_thread num_elements chunk_size++ dScope Nothing $ scopeOfLParams $ concatMap slugParams slugs++ sComment "neutral-initialise the accumulators" $+ forM_ slugs $ \slug ->+ forM_ (zip (slugAccs slug) (slugNeutral slug)) $ \((acc, acc_is), ne) ->+ sLoopNest (slugShape slug) $ \vec_is ->+ copyDWIMFix acc (acc_is ++ vec_is) ne []++ slugs_op_renamed <- mapM (renameLambda . segBinOpLambda . slugOp) slugs++ let doTheReduction =+ forM_ (zip slugs_op_renamed slugs) $ \(slug_op_renamed, slug) ->+ sLoopNest (slugShape slug) $ \vec_is -> do+ comment "to reduce current chunk, first store our result in memory" $ do+ forM_ (zip (slugParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->+ copyDWIMFix (paramName p) [] (Var acc) (acc_is ++ vec_is)++ forM_ (zip (slugArrs slug) (slugParams slug)) $ \(arr, p) ->+ when (primType $ paramType p) $+ copyDWIMFix arr [local_tid] (Var $ paramName p) []++ sOp $ Imp.ErrorSync Imp.FenceLocal -- Also implicitly barrier.+ groupReduce (sExt32 (kernelGroupSize constants)) slug_op_renamed (slugArrs slug)++ sOp $ Imp.Barrier Imp.FenceLocal++ sComment "first thread saves the result in accumulator" $+ sWhen (local_tid .==. 0) $+ forM_ (zip (slugAccs slug) (lambdaParams slug_op_renamed)) $ \((acc, acc_is), p) ->+ copyDWIMFix acc (acc_is ++ vec_is) (Var $ paramName p) []++ -- If this is a non-commutative reduction, each thread must run the+ -- loop the same number of iterations, because we will be performing+ -- a group-wide reduction in there.+ let comm = slugsComm slugs+ (bound, check_bounds) =+ case comm of+ Commutative -> (tvExp chunk_size, id)+ Noncommutative ->+ ( Imp.unCount elems_per_thread,+ sWhen (tvExp gtid .<. Imp.unCount num_elements)+ )++ sFor "i" bound $ \i -> do+ gtid+ <-- case comm of+ Commutative ->+ global_tid + Imp.vi64 threads_per_segment * i+ Noncommutative ->+ let index_in_segment = global_tid `quot` kernelGroupSize constants+ in sExt64 local_tid+ + (index_in_segment * Imp.unCount elems_per_thread + i)+ * kernelGroupSize constants++ check_bounds $+ sComment "apply map function" $+ body $ \all_red_res -> do+ let slugs_res = chunks (map (length . slugNeutral) slugs) all_red_res++ forM_ (zip slugs slugs_res) $ \(slug, red_res) ->+ sLoopNest (slugShape slug) $ \vec_is -> do+ sComment "load accumulator" $+ forM_ (zip (accParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->+ copyDWIMFix (paramName p) [] (Var acc) (acc_is ++ vec_is)+ sComment "load new values" $+ forM_ (zip (nextParams slug) red_res) $ \(p, (res, res_is)) ->+ copyDWIMFix (paramName p) [] res (res_is ++ vec_is)+ sComment "apply reduction operator" $+ compileStms mempty (bodyStms $ slugBody slug) $+ sComment "store in accumulator" $+ forM_+ ( zip+ (slugAccs slug)+ (bodyResult $ slugBody slug)+ )+ $ \((acc, acc_is), se) ->+ copyDWIMFix acc (acc_is ++ vec_is) se []++ case comm of+ Noncommutative -> do+ doTheReduction+ sComment "first thread keeps accumulator; others reset to neutral element" $ do+ let reset_to_neutral =+ forM_ slugs $ \slug ->+ forM_ (zip (slugAccs slug) (slugNeutral slug)) $ \((acc, acc_is), ne) ->+ sLoopNest (slugShape slug) $ \vec_is ->+ copyDWIMFix acc (acc_is ++ vec_is) ne []+ sUnless (local_tid .==. 0) reset_to_neutral+ _ -> return ()++ return (slugs_op_renamed, doTheReduction)++reductionStageOne ::+ KernelConstants ->+ [(VName, Imp.TExp Int64)] ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ Imp.TExp Int64 ->+ Imp.Count Imp.Elements (Imp.TExp Int64) ->+ VName ->+ [SegBinOpSlug] ->+ DoSegBody ->+ InKernelGen [Lambda GPUMem]+reductionStageOne constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body = do+ (slugs_op_renamed, doTheReduction) <-+ reductionStageZero constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body++ case slugsComm slugs of+ Noncommutative ->+ forM_ slugs $ \slug ->+ forM_ (zip (accParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->+ copyDWIMFix (paramName p) [] (Var acc) acc_is+ _ -> doTheReduction++ return slugs_op_renamed++reductionStageTwo ::+ KernelConstants ->+ [PatElem GPUMem] ->+ Imp.TExp Int32 ->+ Imp.TExp Int32 ->+ [Imp.TExp Int64] ->+ Imp.TExp Int64 ->+ Imp.TExp Int64 ->+ SegBinOpSlug ->+ [LParam GPUMem] ->+ [LParam GPUMem] ->+ Lambda GPUMem ->+ [SubExp] ->+ Imp.TExp Int32 ->+ VName ->+ Imp.TExp Int32 ->+ VName ->+ [VName] ->+ [VName] ->+ InKernelGen ()+reductionStageTwo+ constants+ segred_pes+ group_id+ flat_segment_id+ segment_gtids+ first_group_for_segment+ groups_per_segment+ slug+ red_x_params+ red_y_params+ red_op_renamed+ nes+ num_counters+ counter+ counter_i+ sync_arr+ group_res_arrs+ red_arrs = do+ let local_tid = kernelLocalThreadId constants+ group_size = kernelGroupSize constants+ old_counter <- dPrim "old_counter" int32+ (counter_mem, _, counter_offset) <-+ fullyIndexArray+ counter+ [ sExt64 $+ counter_i * num_counters+ + flat_segment_id `rem` num_counters+ ]+ comment "first thread in group saves group result to global memory" $+ sWhen (local_tid .==. 0) $ do+ forM_ (take (length nes) $ zip group_res_arrs (slugAccs slug)) $ \(v, (acc, acc_is)) ->+ copyDWIMFix v [0, sExt64 group_id] (Var acc) acc_is+ sOp $ Imp.MemFence Imp.FenceGlobal+ -- Increment the counter, thus stating that our result is+ -- available.+ sOp $+ Imp.Atomic DefaultSpace $+ Imp.AtomicAdd+ Int32+ (tvVar old_counter)+ counter_mem+ counter_offset+ $ untyped (1 :: Imp.TExp Int32)+ -- Now check if we were the last group to write our result. If+ -- so, it is our responsibility to produce the final result.+ sWrite sync_arr [0] $ untyped $ tvExp old_counter .==. groups_per_segment - 1++ sOp $ Imp.Barrier Imp.FenceGlobal++ is_last_group <- dPrim "is_last_group" Bool+ copyDWIMFix (tvVar is_last_group) [] (Var sync_arr) [0]+ sWhen (tvExp is_last_group) $ do+ -- The final group has written its result (and it was+ -- us!), so read in all the group results and perform the+ -- final stage of the reduction. But first, we reset the+ -- counter so it is ready for next time. This is done+ -- with an atomic to avoid warnings about write/write+ -- races in oclgrind.+ sWhen (local_tid .==. 0) $+ sOp $+ Imp.Atomic DefaultSpace $+ Imp.AtomicAdd Int32 (tvVar old_counter) counter_mem counter_offset $+ untyped $ negate groups_per_segment++ sLoopNest (slugShape slug) $ \vec_is -> do+ -- There is no guarantee that the number of workgroups for the+ -- segment is less than the workgroup size, so each thread may+ -- have to read multiple elements. We do this in a sequential+ -- way that may induce non-coalesced accesses, but the total+ -- number of accesses should be tiny here.+ comment "read in the per-group-results" $ do+ read_per_thread <-+ dPrimVE "read_per_thread" $+ groups_per_segment `divUp` sExt64 group_size++ forM_ (zip red_x_params nes) $ \(p, ne) ->+ copyDWIMFix (paramName p) [] ne []++ sFor "i" read_per_thread $ \i -> do+ group_res_id <-+ dPrimVE "group_res_id" $+ sExt64 local_tid * read_per_thread + i+ index_of_group_res <-+ dPrimVE "index_of_group_res" $+ first_group_for_segment + group_res_id++ sWhen (group_res_id .<. groups_per_segment) $ do+ forM_ (zip red_y_params group_res_arrs) $+ \(p, group_res_arr) ->+ copyDWIMFix+ (paramName p)+ []+ (Var group_res_arr)+ ([0, index_of_group_res] ++ vec_is)++ compileStms mempty (bodyStms $ slugBody slug) $+ forM_ (zip red_x_params (bodyResult $ slugBody slug)) $ \(p, se) ->+ copyDWIMFix (paramName p) [] se []++ forM_ (zip red_x_params red_arrs) $ \(p, arr) ->+ when (primType $ paramType p) $+ copyDWIMFix arr [sExt64 local_tid] (Var $ paramName p) []++ sOp $ Imp.Barrier Imp.FenceLocal++ sComment "reduce the per-group results" $ do+ groupReduce (sExt32 group_size) red_op_renamed red_arrs++ sComment "and back to memory with the final result" $+ sWhen (local_tid .==. 0) $+ forM_ (zip segred_pes $ lambdaParams red_op_renamed) $ \(pe, p) ->+ copyDWIMFix+ (patElemName pe)+ (segment_gtids ++ vec_is)+ (Var $ paramName p)+ []
+ src/Futhark/CodeGen/ImpGen/GPU/SegScan.hs view
@@ -0,0 +1,68 @@+-- | Code generation for 'SegScan'. Dispatches to either a+-- single-pass or two-pass implementation, depending on the nature of+-- the scan and the chosen abckend.+module Futhark.CodeGen.ImpGen.GPU.SegScan (compileSegScan) where++import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen hiding (compileProg)+import Futhark.CodeGen.ImpGen.GPU.Base+import qualified Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass as SinglePass+import qualified Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass as TwoPass+import Futhark.IR.GPUMem++-- The single-pass scan does not support multiple operators, so jam+-- them together here.+combineScans :: [SegBinOp GPUMem] -> SegBinOp GPUMem+combineScans ops =+ SegBinOp+ { segBinOpComm = mconcat (map segBinOpComm ops),+ segBinOpLambda = lam',+ segBinOpNeutral = concatMap segBinOpNeutral ops,+ segBinOpShape = mempty -- Assumed+ }+ where+ lams = map segBinOpLambda ops+ xParams lam = take (length (lambdaReturnType lam)) (lambdaParams lam)+ yParams lam = drop (length (lambdaReturnType lam)) (lambdaParams lam)+ lam' =+ Lambda+ { lambdaParams = concatMap xParams lams ++ concatMap yParams lams,+ lambdaReturnType = concatMap lambdaReturnType lams,+ lambdaBody =+ Body+ ()+ (mconcat (map (bodyStms . lambdaBody) lams))+ (concatMap (bodyResult . lambdaBody) lams)+ }++canBeSinglePass :: SegSpace -> [SegBinOp GPUMem] -> Maybe (SegBinOp GPUMem)+canBeSinglePass space ops+ | [_] <- unSegSpace space,+ all ok ops =+ Just $ combineScans ops+ | otherwise =+ Nothing+ where+ ok op =+ segBinOpShape op == mempty+ && all primType (lambdaReturnType (segBinOpLambda op))++-- | Compile 'SegScan' instance to host-level code with calls to+-- various kernels.+compileSegScan ::+ Pattern GPUMem ->+ SegLevel ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegScan pat lvl space scans kbody = sWhen (0 .<. n) $ do+ emit $ Imp.DebugPrint "\n# SegScan" Nothing+ target <- hostTarget <$> askEnv+ case target of+ CUDA+ | Just scan' <- canBeSinglePass space scans ->+ SinglePass.compileSegScan pat lvl space scan' kbody+ _ -> TwoPass.compileSegScan pat lvl space scans kbody+ where+ n = product $ map toInt64Exp $ segSpaceDims space
+ src/Futhark/CodeGen/ImpGen/GPU/SegScan/SinglePass.hs view
@@ -0,0 +1,565 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | Code generation for segmented and non-segmented scans. Uses a+-- fast single-pass algorithm, but which only works on NVIDIA GPUs and+-- with some constraints on the operator. We use this when we can.+module Futhark.CodeGen.ImpGen.GPU.SegScan.SinglePass (compileSegScan) where++import Control.Monad.Except+import Data.List (zip4)+import Data.Maybe+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.Transform.Rename+import Futhark.Util (takeLast)+import Futhark.Util.IntegralExp (IntegralExp (mod, rem), divUp, quot)+import Prelude hiding (mod, quot, rem)++xParams, yParams :: SegBinOp GPUMem -> [LParam GPUMem]+xParams scan =+ take (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))+yParams scan =+ drop (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))++alignTo :: IntegralExp a => a -> a -> a+alignTo x a = (x `divUp` a) * a++createLocalArrays ::+ Count GroupSize SubExp ->+ SubExp ->+ [PrimType] ->+ InKernelGen (VName, [VName], [VName], VName, VName, [VName])+createLocalArrays (Count groupSize) m types = do+ let groupSizeE = toInt64Exp groupSize+ workSize = toInt64Exp m * groupSizeE+ prefixArraysSize =+ foldl (\acc tySize -> alignTo acc tySize + tySize * groupSizeE) 0 $+ map primByteSize types+ maxTransposedArraySize =+ foldl1 sMax64 $ map (\ty -> workSize * primByteSize ty) types++ warpSize :: Num a => a+ warpSize = 32+ maxWarpExchangeSize =+ foldl (\acc tySize -> alignTo acc tySize + tySize * fromInteger warpSize) 0 $+ map primByteSize types+ maxLookbackSize = maxWarpExchangeSize + warpSize+ size = Imp.bytes $ maxLookbackSize `sMax64` prefixArraysSize `sMax64` maxTransposedArraySize++ varTE :: TV Int64 -> TPrimExp Int64 VName+ varTE = le64 . tvVar++ byteOffsets <-+ mapM (fmap varTE . dPrimV "byte_offsets") $+ scanl (\off tySize -> alignTo off tySize + toInt64Exp groupSize * tySize) 0 $+ map primByteSize types++ warpByteOffsets <-+ mapM (fmap varTE . dPrimV "warp_byte_offset") $+ scanl (\off tySize -> alignTo off tySize + warpSize * tySize) warpSize $+ map primByteSize types++ sComment "Allocate reused shared memeory" $ return ()++ localMem <- sAlloc "local_mem" size (Space "local")+ transposeArrayLength <- dPrimV "trans_arr_len" workSize++ sharedId <- sArrayInMem "shared_id" int32 (Shape [constant (1 :: Int32)]) localMem+ sharedReadOffset <- sArrayInMem "shared_read_offset" int32 (Shape [constant (1 :: Int32)]) localMem++ transposedArrays <-+ forM types $ \ty ->+ sArrayInMem+ "local_transpose_arr"+ ty+ (Shape [tvSize transposeArrayLength])+ localMem++ prefixArrays <-+ forM (zip byteOffsets types) $ \(off, ty) -> do+ let off' = off `quot` primByteSize ty+ sArray+ "local_prefix_arr"+ ty+ (Shape [groupSize])+ $ ArrayIn localMem $ IxFun.iotaOffset off' [pe64 groupSize]++ warpscan <- sArrayInMem "warpscan" int8 (Shape [constant (warpSize :: Int64)]) localMem+ warpExchanges <-+ forM (zip warpByteOffsets types) $ \(off, ty) -> do+ let off' = off `quot` primByteSize ty+ sArray+ "warp_exchange"+ ty+ (Shape [constant (warpSize :: Int64)])+ $ ArrayIn localMem $ IxFun.iotaOffset off' [warpSize]++ return (sharedId, transposedArrays, prefixArrays, sharedReadOffset, warpscan, warpExchanges)++-- | Compile 'SegScan' instance to host-level code with calls to a+-- single-pass kernel.+compileSegScan ::+ Pattern GPUMem ->+ SegLevel ->+ SegSpace ->+ SegBinOp GPUMem ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegScan pat lvl space scanOp kbody = do+ let Pattern _ all_pes = pat+ group_size = toInt64Exp <$> segGroupSize lvl+ n = product $ map toInt64Exp $ segSpaceDims space+ num_groups = Count (n `divUp` (unCount group_size * m))+ num_threads = unCount num_groups * unCount group_size+ (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ segmented = length dims' > 1+ not_segmented_e = if segmented then false else true+ segment_size = last dims'+ scanOpNe = segBinOpNeutral scanOp+ tys = map (\(Prim pt) -> pt) $ lambdaReturnType $ segBinOpLambda scanOp++ statusX, statusA, statusP :: Num a => a+ statusX = 0+ statusA = 1+ statusP = 2+ makeStatusUsed flag used = tvExp flag .|. (tvExp used .<<. 2)+ unmakeStatusUsed :: TV Int8 -> TV Int8 -> TV Int8 -> InKernelGen ()+ unmakeStatusUsed flagUsed flag used = do+ used <-- tvExp flagUsed .>>. 2+ flag <-- tvExp flagUsed .&. 3++ sumT :: Integer+ maxT :: Integer+ sumT = foldl (\bytes typ -> bytes + primByteSize typ) 0 tys+ primByteSize' = max 4 . primByteSize+ sumT' = foldl (\bytes typ -> bytes + primByteSize' typ) 0 tys `div` 4+ maxT = maximum (map primByteSize tys)+ -- TODO: Make these constants dynamic by querying device+ -- RTX 2080 Ti constants (CC 7.5)+ k_reg = 64+ k_mem = 48 --12*4+ mem_constraint = max k_mem sumT `div` maxT+ reg_constraint = (k_reg -1 - sumT') `div` (2 * sumT' + 3)+ m :: Num a => a+ m = fromIntegral $ max 1 $ min mem_constraint reg_constraint++ -- Allocate the shared memory for output component+ numThreads <- dPrimV "numThreads" num_threads+ numGroups <- dPrimV "numGroups" $ unCount num_groups++ globalId <- sStaticArray "id_counter" (Space "device") int32 $ Imp.ArrayZeros 1+ statusFlags <- sAllocArray "status_flags" int8 (Shape [tvSize numGroups]) (Space "device")+ (aggregateArrays, incprefixArrays) <-+ fmap unzip $+ forM tys $ \ty ->+ (,) <$> sAllocArray "aggregates" ty (Shape [tvSize numGroups]) (Space "device")+ <*> sAllocArray "incprefixes" ty (Shape [tvSize numGroups]) (Space "device")++ sReplicate statusFlags $ intConst Int8 statusX++ sKernelThread "segscan" num_groups group_size (segFlat space) $ do+ constants <- kernelConstants <$> askEnv++ (sharedId, transposedArrays, prefixArrays, sharedReadOffset, warpscan, exchanges) <-+ createLocalArrays (segGroupSize lvl) (intConst Int64 m) tys++ dynamicId <- dPrim "dynamic_id" int32+ sWhen (kernelLocalThreadId constants .==. 0) $ do+ (globalIdMem, _, globalIdOff) <- fullyIndexArray globalId [0]+ sOp $+ Imp.Atomic DefaultSpace $+ Imp.AtomicAdd+ Int32+ (tvVar dynamicId)+ globalIdMem+ (Count $ unCount globalIdOff)+ (untyped (1 :: Imp.TExp Int32))+ copyDWIMFix sharedId [0] (tvSize dynamicId) []++ let localBarrier = Imp.Barrier Imp.FenceLocal+ localFence = Imp.MemFence Imp.FenceLocal+ globalFence = Imp.MemFence Imp.FenceGlobal++ sOp localBarrier+ copyDWIMFix (tvVar dynamicId) [] (Var sharedId) [0]+ sOp localBarrier++ blockOff <-+ dPrimV "blockOff" $+ sExt64 (tvExp dynamicId) * m * kernelGroupSize constants+ sgmIdx <- dPrimVE "sgm_idx" $ tvExp blockOff `mod` segment_size+ boundary <-+ dPrimVE "boundary" $+ sExt32 $ sMin64 (m * unCount group_size) (segment_size - sgmIdx)+ segsize_compact <-+ dPrimVE "segsize_compact" $+ sExt32 $ sMin64 (m * unCount group_size) segment_size+ privateArrays <-+ forM tys $ \ty ->+ sAllocArray+ "private"+ ty+ (Shape [intConst Int64 m])+ (ScalarSpace [intConst Int64 m] ty)++ sComment "Load and map" $+ sFor "i" m $ \i -> do+ -- The map's input index+ phys_tid <-+ dPrimVE "phys_tid" $+ tvExp blockOff + sExt64 (kernelLocalThreadId constants)+ + i * kernelGroupSize constants+ dIndexSpace (zip gtids dims') phys_tid+ -- Perform the map+ let in_bounds =+ compileStms mempty (kernelBodyStms kbody) $ do+ let (all_scan_res, map_res) = splitAt (segBinOpResults [scanOp]) $ kernelBodyResult kbody++ -- Write map results to their global memory destinations+ forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(dest, src) ->+ copyDWIMFix (patElemName dest) (map Imp.vi64 gtids) (kernelResultSubExp src) []++ -- Write to-scan results to private memory.+ forM_ (zip privateArrays $ map kernelResultSubExp all_scan_res) $ \(dest, src) ->+ copyDWIMFix dest [i] src []++ out_of_bounds =+ forM_ (zip privateArrays scanOpNe) $ \(dest, ne) ->+ copyDWIMFix dest [i] ne []++ sIf (phys_tid .<. n) in_bounds out_of_bounds++ sComment "Transpose scan inputs" $ do+ forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do+ sOp localBarrier+ sFor "i" m $ \i -> do+ sharedIdx <-+ dPrimVE "sharedIdx" $+ sExt64 (kernelLocalThreadId constants)+ + i * kernelGroupSize constants+ copyDWIMFix trans [sharedIdx] (Var priv) [i]+ sOp localBarrier+ sFor "i" m $ \i -> do+ sharedIdx <- dPrimV "sharedIdx" $ kernelLocalThreadId constants * m + i+ copyDWIMFix priv [sExt64 i] (Var trans) [sExt64 $ tvExp sharedIdx]+ sOp localBarrier++ sComment "Per thread scan" $ do+ -- We don't need to touch the first element, so only m-1+ -- iterations here.+ globalIdx <-+ dPrimVE "gidx" $+ (kernelLocalThreadId constants * m) + 1+ sFor "i" (m -1) $ \i -> do+ let xs = map paramName $ xParams scanOp+ ys = map paramName $ yParams scanOp+ -- determine if start of segment+ new_sgm <-+ if segmented+ then dPrimVE "new_sgm" $ (globalIdx + sExt32 i - boundary) `mod` segsize_compact .==. 0+ else pure false+ -- skip scan of first element in segment+ sUnless new_sgm $ do+ forM_ (zip privateArrays $ zip3 xs ys tys) $ \(src, (x, y, ty)) -> do+ dPrim_ x ty+ dPrim_ y ty+ copyDWIMFix x [] (Var src) [i]+ copyDWIMFix y [] (Var src) [i + 1]++ compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scanOp) $+ forM_ (zip privateArrays $ bodyResult $ lambdaBody $ segBinOpLambda scanOp) $ \(dest, res) ->+ copyDWIMFix dest [i + 1] res []++ sComment "Publish results in shared memory" $ do+ forM_ (zip prefixArrays privateArrays) $ \(dest, src) ->+ copyDWIMFix dest [sExt64 $ kernelLocalThreadId constants] (Var src) [m - 1]+ sOp localBarrier++ let crossesSegment = do+ guard segmented+ Just $ \from to ->+ let from' = (from + 1) * m - 1+ to' = (to + 1) * m - 1+ in (to' - from') .>. (to' + segsize_compact - boundary) `mod` segsize_compact++ scanOp' <- renameLambda $ segBinOpLambda scanOp++ accs <- mapM (dPrim "acc") tys+ sComment "Scan results (with warp scan)" $ do+ groupScan+ crossesSegment+ (tvExp numThreads)+ (kernelGroupSize constants)+ scanOp'+ prefixArrays++ sOp localBarrier++ let firstThread acc prefixes =+ copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelGroupSize constants) - 1]+ notFirstThread acc prefixes =+ copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelLocalThreadId constants) - 1]+ sIf+ (kernelLocalThreadId constants .==. 0)+ (zipWithM_ firstThread accs prefixArrays)+ (zipWithM_ notFirstThread accs prefixArrays)++ sOp localBarrier++ prefixes <- forM (zip scanOpNe tys) $ \(ne, ty) ->+ dPrimV "prefix" $ TPrimExp $ toExp' ty ne+ blockNewSgm <- dPrimVE "block_new_sgm" $ sgmIdx .==. 0+ sComment "Perform lookback" $ do+ sWhen (blockNewSgm .&&. kernelLocalThreadId constants .==. 0) $ do+ everythingVolatile $+ forM_ (zip incprefixArrays accs) $ \(incprefixArray, acc) ->+ copyDWIMFix incprefixArray [tvExp dynamicId] (tvSize acc) []+ sOp globalFence+ everythingVolatile $+ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []+ forM_ (zip scanOpNe accs) $ \(ne, acc) ->+ copyDWIMFix (tvVar acc) [] ne []+ -- end sWhen++ let warpSize = kernelWaveSize constants+ sWhen (bNot blockNewSgm .&&. kernelLocalThreadId constants .<. warpSize) $ do+ sWhen (kernelLocalThreadId constants .==. 0) $ do+ sIf+ (not_segmented_e .||. boundary .==. sExt32 (unCount group_size * m))+ ( do+ everythingVolatile $+ forM_ (zip aggregateArrays accs) $ \(aggregateArray, acc) ->+ copyDWIMFix aggregateArray [tvExp dynamicId] (tvSize acc) []+ sOp globalFence+ everythingVolatile $+ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusA) []+ )+ ( do+ everythingVolatile $+ forM_ (zip incprefixArrays accs) $ \(incprefixArray, acc) ->+ copyDWIMFix incprefixArray [tvExp dynamicId] (tvSize acc) []+ sOp globalFence+ everythingVolatile $+ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []+ )+ copyDWIMFix warpscan [0] (Var statusFlags) [tvExp dynamicId - 1]+ -- sWhen+ sOp localFence++ status <- dPrim "status" int8 :: InKernelGen (TV Int8)+ copyDWIMFix (tvVar status) [] (Var warpscan) [0]++ sIf+ (tvExp status .==. statusP)+ ( sWhen (kernelLocalThreadId constants .==. 0) $+ everythingVolatile $+ forM_ (zip prefixes incprefixArrays) $ \(prefix, incprefixArray) ->+ copyDWIMFix (tvVar prefix) [] (Var incprefixArray) [tvExp dynamicId - 1]+ )+ ( do+ readOffset <-+ dPrimV "readOffset" $+ sExt32 $ tvExp dynamicId - sExt64 (kernelWaveSize constants)+ let loopStop = warpSize * (-1)+ sameSegment readIdx+ | segmented =+ let startIdx = sExt64 (tvExp readIdx + 1) * kernelGroupSize constants * m - 1+ in tvExp blockOff - startIdx .<=. sgmIdx+ | otherwise = true+ sWhile (tvExp readOffset .>. loopStop) $ do+ readI <- dPrimV "read_i" $ tvExp readOffset + kernelLocalThreadId constants+ aggrs <- forM (zip scanOpNe tys) $ \(ne, ty) ->+ dPrimV "aggr" $ TPrimExp $ toExp' ty ne+ flag <- dPrimV "flag" statusX+ used <- dPrimV "used" 0+ everythingVolatile . sWhen (tvExp readI .>=. 0) $ do+ sIf+ (sameSegment readI)+ ( do+ copyDWIMFix (tvVar flag) [] (Var statusFlags) [sExt64 $ tvExp readI]+ sIf+ (tvExp flag .==. statusP)+ ( forM_ (zip incprefixArrays aggrs) $ \(incprefix, aggr) ->+ copyDWIMFix (tvVar aggr) [] (Var incprefix) [sExt64 $ tvExp readI]+ )+ ( sWhen (tvExp flag .==. statusA) $ do+ forM_ (zip aggrs aggregateArrays) $ \(aggr, aggregate) ->+ copyDWIMFix (tvVar aggr) [] (Var aggregate) [sExt64 $ tvExp readI]+ used <-- 1+ )+ )+ (copyDWIMFix (tvVar flag) [] (intConst Int8 statusP) [])+ -- end sIf+ -- end sWhen+ forM_ (zip exchanges aggrs) $ \(exchange, aggr) ->+ copyDWIMFix exchange [sExt64 $ kernelLocalThreadId constants] (tvSize aggr) []+ tmp <- dPrimV "tmp" $ makeStatusUsed flag used+ copyDWIMFix warpscan [sExt64 $ kernelLocalThreadId constants] (tvSize tmp) []+ sOp localFence++ (warpscanMem, warpscanSpace, warpscanOff) <-+ fullyIndexArray warpscan [sExt64 warpSize - 1]+ flag <-- TPrimExp (Imp.index warpscanMem warpscanOff int8 warpscanSpace Imp.Volatile)+ sWhen (kernelLocalThreadId constants .==. 0) $ do+ -- TODO: This is a single-threaded reduce+ sIf+ (bNot $ tvExp flag .==. statusP)+ ( do+ scanOp'' <- renameLambda scanOp'+ let (agg1s, agg2s) = splitAt (length tys) $ map paramName $ lambdaParams scanOp''++ forM_ (zip3 agg1s scanOpNe tys) $ \(agg1, ne, ty) ->+ dPrimV_ agg1 $ TPrimExp $ toExp' ty ne+ zipWithM_ dPrim_ agg2s tys++ flag1 <- dPrimV "flag1" statusX+ flag2 <- dPrim "flag2" int8+ used1 <- dPrimV "used1" 0+ used2 <- dPrim "used2" int8+ sFor "i" warpSize $ \i -> do+ copyDWIMFix (tvVar flag2) [] (Var warpscan) [sExt64 i]+ unmakeStatusUsed flag2 flag2 used2+ forM_ (zip agg2s exchanges) $ \(agg2, exchange) ->+ copyDWIMFix agg2 [] (Var exchange) [sExt64 i]+ sIf+ (bNot $ tvExp flag2 .==. statusA)+ ( do+ flag1 <-- tvExp flag2+ used1 <-- tvExp used2+ forM_ (zip3 agg1s tys agg2s) $ \(agg1, ty, agg2) ->+ agg1 <~~ toExp' ty (Var agg2)+ )+ ( do+ used1 <-- tvExp used1 + tvExp used2+ compileStms mempty (bodyStms $ lambdaBody scanOp'') $+ forM_ (zip3 agg1s tys $ bodyResult $ lambdaBody scanOp'') $+ \(agg1, ty, res) -> agg1 <~~ toExp' ty res+ )+ flag <-- tvExp flag1+ used <-- tvExp used1+ forM_ (zip3 aggrs tys agg1s) $ \(aggr, ty, agg1) ->+ tvVar aggr <~~ toExp' ty (Var agg1)+ )+ -- else+ ( forM_ (zip aggrs exchanges) $ \(aggr, exchange) ->+ copyDWIMFix (tvVar aggr) [] (Var exchange) [sExt64 warpSize - 1]+ )+ -- end sIf+ sIf+ (tvExp flag .==. statusP)+ (readOffset <-- loopStop)+ (readOffset <-- tvExp readOffset - zExt32 (tvExp used))+ copyDWIMFix sharedReadOffset [0] (tvSize readOffset) []+ scanOp''' <- renameLambda scanOp'+ let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scanOp'''+ 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''') $+ \(prefix, ty, res) -> prefix <-- TPrimExp (toExp' ty res)+ -- end sWhen+ sOp localFence+ copyDWIMFix (tvVar readOffset) [] (Var sharedReadOffset) [0]+ )+ -- end sWhile+ -- end sIf+ sWhen (kernelLocalThreadId constants .==. 0) $ do+ scanOp'''' <- renameLambda scanOp'+ let xs = map paramName $ take (length tys) $ lambdaParams scanOp''''+ ys = map paramName $ drop (length tys) $ lambdaParams scanOp''''+ sWhen (boundary .==. sExt32 (unCount group_size * m)) $ do+ forM_ (zip xs prefixes) $ \(x, prefix) -> dPrimV_ x $ tvExp prefix+ forM_ (zip ys accs) $ \(y, acc) -> dPrimV_ y $ tvExp acc+ compileStms mempty (bodyStms $ lambdaBody scanOp'''') $+ everythingVolatile $+ forM_ (zip incprefixArrays $ bodyResult $ lambdaBody scanOp'''') $+ \(incprefixArray, res) -> copyDWIMFix incprefixArray [tvExp dynamicId] res []+ sOp globalFence+ everythingVolatile $ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []+ forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->+ copyDWIMFix exchange [0] (tvSize prefix) []+ forM_ (zip3 accs tys scanOpNe) $ \(acc, ty, ne) ->+ tvVar acc <~~ toExp' ty ne+ -- end sWhen+ -- end sWhen++ sWhen (bNot $ tvExp dynamicId .==. 0) $ do+ sOp localBarrier+ forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->+ copyDWIMFix (tvVar prefix) [] (Var exchange) [0]+ sOp localBarrier+ -- end sWhen+ -- end sComment++ scanOp''''' <- renameLambda scanOp'+ scanOp'''''' <- renameLambda scanOp'++ sComment "Distribute results" $ do+ let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scanOp'''''+ (xs', ys') = splitAt (length tys) $ map paramName $ lambdaParams scanOp''''''++ forM_ (zip4 (zip prefixes accs) (zip xs xs') (zip ys ys') tys) $+ \((prefix, acc), (x, x'), (y, y'), ty) -> do+ dPrim_ x ty+ dPrim_ y ty+ dPrimV_ x' $ tvExp prefix+ dPrimV_ y' $ tvExp acc++ sIf+ (kernelLocalThreadId constants * m .<. boundary .&&. bNot blockNewSgm)+ ( compileStms mempty (bodyStms $ lambdaBody scanOp'''''') $+ forM_ (zip3 xs tys $ bodyResult $ lambdaBody scanOp'''''') $+ \(x, ty, res) -> x <~~ toExp' ty res+ )+ (forM_ (zip xs accs) $ \(x, acc) -> copyDWIMFix x [] (Var $ tvVar acc) [])+ -- calculate where previous thread stopped, to determine number of+ -- elements left before new segment.+ stop <-+ dPrimVE "stopping_point" $+ segsize_compact - (kernelLocalThreadId constants * m - 1 + segsize_compact - boundary) `rem` segsize_compact+ sFor "i" m $ \i -> do+ sWhen (sExt32 i .<. stop - 1) $ do+ forM_ (zip privateArrays ys) $ \(src, y) ->+ -- 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''''') $+ \(dest, res) ->+ copyDWIMFix dest [i] res []++ sComment "Transpose scan output" $ do+ forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do+ sOp localBarrier+ sFor "i" m $ \i -> do+ sharedIdx <-+ dPrimV "sharedIdx" $+ sExt64 (kernelLocalThreadId constants * m) + i+ copyDWIMFix trans [tvExp sharedIdx] (Var priv) [i]+ sOp localBarrier+ sFor "i" m $ \i -> do+ sharedIdx <-+ dPrimV "sharedIdx" $+ kernelLocalThreadId constants+ + sExt32 (kernelGroupSize constants * i)+ copyDWIMFix priv [i] (Var trans) [sExt64 $ tvExp sharedIdx]+ sOp localBarrier++ sComment "Write block scan results to global memory" $+ sFor "i" m $ \i -> do+ flat_idx <-+ dPrimVE "flat_idx" $+ tvExp blockOff + kernelGroupSize constants * i+ + sExt64 (kernelLocalThreadId constants)+ dIndexSpace (zip gtids dims') flat_idx+ sWhen (flat_idx .<. n) $ do+ forM_ (zip (map patElemName all_pes) privateArrays) $ \(dest, src) ->+ copyDWIMFix dest (map Imp.vi64 gtids) (Var src) [i]++ sComment "If this is the last block, reset the dynamicId" $+ sWhen (tvExp dynamicId .==. unCount num_groups - 1) $+ copyDWIMFix globalId [0] (constant (0 :: Int32)) []
+ src/Futhark/CodeGen/ImpGen/GPU/SegScan/TwoPass.hs view
@@ -0,0 +1,506 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | Code generation for segmented and non-segmented scans. Uses a+-- fairly inefficient two-pass algorithm, but can handle anything.+module Futhark.CodeGen.ImpGen.GPU.SegScan.TwoPass (compileSegScan) where++import Control.Monad.Except+import Control.Monad.State+import Data.List (delete, find, foldl', zip4)+import Data.Maybe+import qualified Futhark.CodeGen.ImpCode.GPU as Imp+import Futhark.CodeGen.ImpGen+import Futhark.CodeGen.ImpGen.GPU.Base+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.Transform.Rename+import Futhark.Util (takeLast)+import Futhark.Util.IntegralExp (divUp, quot, rem)+import Prelude hiding (quot, rem)++-- Aggressively try to reuse memory for different SegBinOps, because+-- we will run them sequentially after another.+makeLocalArrays ::+ Count GroupSize SubExp ->+ SubExp ->+ [SegBinOp GPUMem] ->+ InKernelGen [[VName]]+makeLocalArrays (Count group_size) num_threads scans = do+ (arrs, mems_and_sizes) <- runStateT (mapM onScan scans) mempty+ let maxSize sizes = Imp.bytes $ foldl' sMax64 1 $ map Imp.unCount sizes+ forM_ mems_and_sizes $ \(sizes, mem) ->+ sAlloc_ mem (maxSize sizes) (Space "local")+ return arrs+ where+ onScan (SegBinOp _ scan_op nes _) = do+ let (scan_x_params, _scan_y_params) =+ splitAt (length nes) $ lambdaParams scan_op+ (arrs, used_mems) <- fmap unzip $+ forM scan_x_params $ \p ->+ case paramDec p of+ MemArray pt shape _ (ArrayIn mem _) -> do+ let shape' = Shape [num_threads] <> shape+ arr <-+ lift $+ sArray "scan_arr" pt shape' $+ ArrayIn mem $ IxFun.iota $ map pe64 $ shapeDims shape'+ return (arr, [])+ _ -> do+ let pt = elemType $ paramType p+ shape = Shape [group_size]+ (sizes, mem') <- getMem pt shape+ arr <- lift $ sArrayInMem "scan_arr" pt shape mem'+ return (arr, [(sizes, mem')])+ modify (<> concat used_mems)+ return arrs++ getMem pt shape = do+ let size = typeSize $ Array pt shape NoUniqueness+ mems <- get+ case (find ((size `elem`) . fst) mems, mems) of+ (Just mem, _) -> do+ modify $ delete mem+ return mem+ (Nothing, (size', mem) : mems') -> do+ put mems'+ return (size : size', mem)+ (Nothing, []) -> do+ mem <- lift $ sDeclareMem "scan_arr_mem" $ Space "local"+ return ([size], mem)++type CrossesSegment = Maybe (Imp.TExp Int64 -> Imp.TExp Int64 -> Imp.TExp Bool)++localArrayIndex :: KernelConstants -> Type -> Imp.TExp Int64+localArrayIndex constants t =+ if primType t+ then sExt64 (kernelLocalThreadId constants)+ else sExt64 (kernelGlobalThreadId constants)++barrierFor :: Lambda GPUMem -> (Bool, Imp.Fence, InKernelGen ())+barrierFor scan_op = (array_scan, fence, sOp $ Imp.Barrier fence)+ where+ array_scan = not $ all primType $ lambdaReturnType scan_op+ fence+ | array_scan = Imp.FenceGlobal+ | otherwise = Imp.FenceLocal++xParams, yParams :: SegBinOp GPUMem -> [LParam GPUMem]+xParams scan =+ take (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))+yParams scan =+ drop (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))++writeToScanValues ::+ [VName] ->+ ([PatElem GPUMem], SegBinOp GPUMem, [KernelResult]) ->+ InKernelGen ()+writeToScanValues gtids (pes, scan, scan_res)+ | shapeRank (segBinOpShape scan) > 0 =+ forM_ (zip pes scan_res) $ \(pe, res) ->+ copyDWIMFix+ (patElemName pe)+ (map Imp.vi64 gtids)+ (kernelResultSubExp res)+ []+ | otherwise =+ forM_ (zip (yParams scan) scan_res) $ \(p, res) ->+ copyDWIMFix (paramName p) [] (kernelResultSubExp res) []++readToScanValues ::+ [Imp.TExp Int64] ->+ [PatElem GPUMem] ->+ SegBinOp GPUMem ->+ InKernelGen ()+readToScanValues is pes scan+ | shapeRank (segBinOpShape scan) > 0 =+ forM_ (zip (yParams scan) pes) $ \(p, pe) ->+ copyDWIMFix (paramName p) [] (Var (patElemName pe)) is+ | otherwise =+ return ()++readCarries ::+ Imp.TExp Int64 ->+ [Imp.TExp Int64] ->+ [Imp.TExp Int64] ->+ [PatElem GPUMem] ->+ SegBinOp GPUMem ->+ InKernelGen ()+readCarries chunk_offset dims' vec_is pes scan+ | shapeRank (segBinOpShape scan) > 0 = do+ ltid <- kernelLocalThreadId . kernelConstants <$> askEnv+ -- We may have to reload the carries from the output of the+ -- previous chunk.+ sIf+ (chunk_offset .>. 0 .&&. ltid .==. 0)+ ( do+ let is = unflattenIndex dims' $ chunk_offset - 1+ forM_ (zip (xParams scan) pes) $ \(p, pe) ->+ copyDWIMFix (paramName p) [] (Var (patElemName pe)) (is ++ vec_is)+ )+ ( forM_ (zip (xParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->+ copyDWIMFix (paramName p) [] ne []+ )+ | otherwise =+ return ()++-- | Produce partially scanned intervals; one per workgroup.+scanStage1 ::+ Pattern 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+ 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'++ let (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims+ let num_elements = product dims'+ elems_per_thread = num_elements `divUp` sExt64 (tvExp num_threads)+ elems_per_group = unCount group_size' * elems_per_thread++ let crossesSegment =+ case reverse dims' of+ segment_size : _ : _ -> Just $ \from to ->+ (to - from) .>. (to `rem` segment_size)+ _ -> Nothing++ sKernelThread "scan_stage1" num_groups' group_size' (segFlat space) $ do+ constants <- kernelConstants <$> askEnv+ all_local_arrs <- makeLocalArrays group_size (tvSize num_threads) scans++ -- The variables from scan_op will be used for the carry and such+ -- in the big chunking loop.+ forM_ scans $ \scan -> do+ dScope Nothing $ scopeOfLParams $ lambdaParams $ segBinOpLambda scan+ forM_ (zip (xParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->+ copyDWIMFix (paramName p) [] ne []++ sFor "j" elems_per_thread $ \j -> do+ chunk_offset <-+ dPrimV "chunk_offset" $+ sExt64 (kernelGroupSize constants) * j+ + sExt64 (kernelGroupId constants) * elems_per_group+ flat_idx <-+ dPrimV "flat_idx" $+ tvExp chunk_offset + sExt64 (kernelLocalThreadId constants)+ -- Construct segment indices.+ zipWithM_ dPrimV_ gtids $ unflattenIndex dims' $ tvExp flat_idx++ let per_scan_pes = segBinOpChunks scans all_pes++ in_bounds =+ foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'++ when_in_bounds = compileStms mempty (kernelBodyStms kbody) $ do+ let (all_scan_res, map_res) =+ splitAt (segBinOpResults scans) $ kernelBodyResult kbody+ per_scan_res =+ segBinOpChunks scans all_scan_res++ sComment "write to-scan values to parameters" $+ mapM_ (writeToScanValues gtids) $+ zip3 per_scan_pes scans per_scan_res++ sComment "write mapped values results to global memory" $+ forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(pe, se) ->+ copyDWIMFix+ (patElemName pe)+ (map Imp.vi64 gtids)+ (kernelResultSubExp se)+ []++ sComment "threads in bounds read input" $+ sWhen in_bounds when_in_bounds++ forM_ (zip3 per_scan_pes scans all_local_arrs) $+ \(pes, scan@(SegBinOp _ scan_op nes vec_shape), local_arrs) ->+ sComment "do one intra-group scan operation" $ do+ let rets = lambdaReturnType scan_op+ scan_x_params = xParams scan+ (array_scan, fence, barrier) = barrierFor scan_op++ when array_scan barrier++ sLoopNest vec_shape $ \vec_is -> do+ sComment "maybe restore some to-scan values to parameters, or read neutral" $+ sIf+ in_bounds+ ( do+ readToScanValues (map Imp.vi64 gtids ++ vec_is) pes scan+ readCarries (tvExp chunk_offset) dims' vec_is pes scan+ )+ ( forM_ (zip (yParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->+ copyDWIMFix (paramName p) [] ne []+ )++ sComment "combine with carry and write to local memory" $+ compileStms mempty (bodyStms $ lambdaBody scan_op) $+ forM_ (zip3 rets local_arrs (bodyResult $ lambdaBody scan_op)) $+ \(t, arr, se) ->+ copyDWIMFix arr [localArrayIndex constants t] se []++ let crossesSegment' = do+ f <- crossesSegment+ Just $ \from to ->+ let from' = sExt64 from + tvExp chunk_offset+ to' = sExt64 to + tvExp chunk_offset+ in f from' to'++ sOp $ Imp.ErrorSync fence++ -- We need to avoid parameter name clashes.+ scan_op_renamed <- renameLambda scan_op+ groupScan+ crossesSegment'+ (sExt64 $ tvExp num_threads)+ (sExt64 $ kernelGroupSize constants)+ scan_op_renamed+ local_arrs++ sComment "threads in bounds write partial scan result" $+ sWhen in_bounds $+ forM_ (zip3 rets pes local_arrs) $ \(t, pe, arr) ->+ copyDWIMFix+ (patElemName pe)+ (map Imp.vi64 gtids ++ vec_is)+ (Var arr)+ [localArrayIndex constants t]++ barrier++ let load_carry =+ forM_ (zip local_arrs scan_x_params) $ \(arr, p) ->+ copyDWIMFix+ (paramName p)+ []+ (Var arr)+ [ if primType $ paramType p+ then sExt64 (kernelGroupSize constants) - 1+ else+ (sExt64 (kernelGroupId constants) + 1)+ * sExt64 (kernelGroupSize constants) - 1+ ]+ load_neutral =+ forM_ (zip nes scan_x_params) $ \(ne, p) ->+ copyDWIMFix (paramName p) [] ne []++ sComment "first thread reads last element as carry-in for next iteration" $ do+ crosses_segment <- dPrimVE "crosses_segment" $+ case crossesSegment of+ Nothing -> false+ Just f ->+ f+ ( tvExp chunk_offset+ + sExt64 (kernelGroupSize constants) -1+ )+ ( tvExp chunk_offset+ + sExt64 (kernelGroupSize constants)+ )+ should_load_carry <-+ dPrimVE "should_load_carry" $+ kernelLocalThreadId constants .==. 0 .&&. bNot crosses_segment+ sWhen should_load_carry load_carry+ when array_scan barrier+ sUnless should_load_carry load_neutral++ barrier++ return (num_threads, elems_per_group, crossesSegment)++scanStage2 ::+ Pattern GPUMem ->+ TV Int32 ->+ Imp.TExp Int64 ->+ Count NumGroups SubExp ->+ CrossesSegment ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ CallKernelGen ()+scanStage2 (Pattern _ all_pes) stage1_num_threads elems_per_group num_groups crossesSegment space scans = do+ let (gtids, dims) = unzip $ unSegSpace space+ dims' = map toInt64Exp dims++ -- Our group size is the number of groups for the stage 1 kernel.+ let group_size = Count $ unCount num_groups+ group_size' = fmap toInt64Exp group_size++ let crossesSegment' = do+ f <- crossesSegment+ Just $ \from to ->+ f+ ((sExt64 from + 1) * elems_per_group - 1)+ ((sExt64 to + 1) * elems_per_group - 1)++ sKernelThread "scan_stage2" 1 group_size' (segFlat space) $ do+ constants <- kernelConstants <$> askEnv+ per_scan_local_arrs <- makeLocalArrays group_size (tvSize stage1_num_threads) scans+ let per_scan_rets = map (lambdaReturnType . segBinOpLambda) scans+ per_scan_pes = segBinOpChunks scans all_pes++ flat_idx <-+ dPrimV "flat_idx" $+ (sExt64 (kernelLocalThreadId constants) + 1) * elems_per_group - 1+ -- Construct segment indices.+ zipWithM_ dPrimV_ gtids $ unflattenIndex dims' $ tvExp flat_idx++ forM_ (zip4 scans per_scan_local_arrs per_scan_rets per_scan_pes) $+ \(SegBinOp _ scan_op nes vec_shape, local_arrs, rets, pes) ->+ sLoopNest vec_shape $ \vec_is -> do+ let glob_is = map Imp.vi64 gtids ++ vec_is++ in_bounds =+ foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'++ when_in_bounds = forM_ (zip3 rets local_arrs pes) $ \(t, arr, pe) ->+ copyDWIMFix+ arr+ [localArrayIndex constants t]+ (Var $ patElemName pe)+ glob_is++ when_out_of_bounds = forM_ (zip3 rets local_arrs nes) $ \(t, arr, ne) ->+ copyDWIMFix arr [localArrayIndex constants t] ne []+ (_, _, barrier) =+ barrierFor scan_op++ sComment "threads in bound read carries; others get neutral element" $+ sIf in_bounds when_in_bounds when_out_of_bounds++ barrier++ groupScan+ crossesSegment'+ (sExt64 $ tvExp stage1_num_threads)+ (sExt64 $ kernelGroupSize constants)+ scan_op+ local_arrs++ sComment "threads in bounds write scanned carries" $+ sWhen in_bounds $+ forM_ (zip3 rets pes local_arrs) $ \(t, pe, arr) ->+ copyDWIMFix+ (patElemName pe)+ glob_is+ (Var arr)+ [localArrayIndex constants t]++scanStage3 ::+ Pattern GPUMem ->+ Count NumGroups SubExp ->+ Count GroupSize SubExp ->+ Imp.TExp Int64 ->+ CrossesSegment ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ CallKernelGen ()+scanStage3 (Pattern _ 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+ dims' = map toInt64Exp dims+ required_groups <-+ dPrimVE "required_groups" $+ sExt32 $ product dims' `divUp` sExt64 (unCount group_size')++ sKernelThread "scan_stage3" num_groups' group_size' (segFlat space) $+ virtualiseGroups SegVirt required_groups $ \virt_group_id -> do+ constants <- kernelConstants <$> askEnv++ -- Compute our logical index.+ flat_idx <-+ dPrimVE "flat_idx" $+ sExt64 virt_group_id * sExt64 (unCount group_size')+ + sExt64 (kernelLocalThreadId constants)+ zipWithM_ dPrimV_ gtids $ unflattenIndex dims' flat_idx++ -- Figure out which group this element was originally in.+ orig_group <- dPrimV "orig_group" $ flat_idx `quot` elems_per_group+ -- Then the index of the carry-in of the preceding group.+ carry_in_flat_idx <-+ dPrimV "carry_in_flat_idx" $+ tvExp orig_group * elems_per_group - 1+ -- Figure out the logical index of the carry-in.+ let carry_in_idx = unflattenIndex dims' $ tvExp carry_in_flat_idx++ -- Apply the carry if we are not in the scan results for the first+ -- group, and are not the last element in such a group (because+ -- then the carry was updated in stage 2), and we are not crossing+ -- a segment boundary.+ let in_bounds =+ foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'+ crosses_segment =+ fromMaybe false $+ crossesSegment+ <*> pure (tvExp carry_in_flat_idx)+ <*> pure flat_idx+ is_a_carry = flat_idx .==. (tvExp orig_group + 1) * elems_per_group - 1+ no_carry_in = tvExp orig_group .==. 0 .||. is_a_carry .||. crosses_segment++ let per_scan_pes = segBinOpChunks scans all_pes+ sWhen in_bounds $+ sUnless no_carry_in $+ forM_ (zip per_scan_pes scans) $+ \(pes, SegBinOp _ scan_op nes vec_shape) -> do+ dScope Nothing $ scopeOfLParams $ lambdaParams scan_op+ let (scan_x_params, scan_y_params) =+ splitAt (length nes) $ lambdaParams scan_op++ sLoopNest vec_shape $ \vec_is -> do+ forM_ (zip scan_x_params pes) $ \(p, pe) ->+ copyDWIMFix+ (paramName p)+ []+ (Var $ patElemName pe)+ (carry_in_idx ++ vec_is)++ forM_ (zip scan_y_params pes) $ \(p, pe) ->+ copyDWIMFix+ (paramName p)+ []+ (Var $ patElemName pe)+ (map Imp.vi64 gtids ++ vec_is)++ compileBody' scan_x_params $ lambdaBody scan_op++ forM_ (zip scan_x_params pes) $ \(p, pe) ->+ copyDWIMFix+ (patElemName pe)+ (map Imp.vi64 gtids ++ vec_is)+ (Var $ paramName p)+ []++-- | Compile 'SegScan' instance to host-level code with calls to+-- various kernels.+compileSegScan ::+ Pattern GPUMem ->+ SegLevel ->+ SegSpace ->+ [SegBinOp GPUMem] ->+ KernelBody GPUMem ->+ CallKernelGen ()+compileSegScan pat lvl space scans kbody = do+ -- Since stage 2 involves a group size equal to the number of groups+ -- used for stage 1, we have to cap this number to the maximum group+ -- size.+ stage1_max_num_groups <- dPrim "stage1_max_num_groups" int64+ sOp $ Imp.GetSizeMax (tvVar stage1_max_num_groups) SizeGroup++ stage1_num_groups <-+ fmap (Imp.Count . tvSize) $+ dPrimV "stage1_num_groups" $+ sMin64 (tvExp stage1_max_num_groups) $+ toInt64Exp $ Imp.unCount $ segNumGroups lvl++ (stage1_num_threads, elems_per_group, crossesSegment) <-+ scanStage1 pat stage1_num_groups (segGroupSize lvl) space scans kbody++ emit $ Imp.DebugPrint "elems_per_group" $ Just $ untyped elems_per_group++ scanStage2 pat stage1_num_threads elems_per_group stage1_num_groups crossesSegment space scans+ scanStage3 pat (segNumGroups lvl) (segGroupSize lvl) elems_per_group crossesSegment space scans
+ src/Futhark/CodeGen/ImpGen/GPU/ToOpenCL.hs view
@@ -0,0 +1,888 @@+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}++-- | This module defines a translation from imperative code with+-- kernels to imperative code with OpenCL calls.+module Futhark.CodeGen.ImpGen.GPU.ToOpenCL+ ( kernelsToOpenCL,+ kernelsToCUDA,+ )+where++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 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.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 qualified Language.C.Quote.OpenCL as C+import qualified Language.C.Syntax as C++kernelsToCUDA, kernelsToOpenCL :: ImpGPU.Program -> ImpOpenCL.Program+kernelsToCUDA = translateGPU TargetCUDA+kernelsToOpenCL = translateGPU TargetOpenCL++-- | Translate a kernels-program to an OpenCL-program.+translateGPU ::+ KernelTarget ->+ ImpGPU.Program ->+ ImpOpenCL.Program+translateGPU target prog =+ let ( prog',+ ToOpenCL kernels device_funs used_types sizes failures+ ) =+ (`runState` initialOpenCL) . (`runReaderT` defFuns prog) $ do+ let ImpGPU.Definitions+ (ImpGPU.Constants ps consts)+ (ImpGPU.Functions funs) = prog+ consts' <- traverse (onHostOp target) consts+ funs' <- forM funs $ \(fname, fun) ->+ (fname,) <$> traverse (onHostOp target) fun++ return $+ ImpOpenCL.Definitions+ (ImpOpenCL.Constants ps consts')+ (ImpOpenCL.Functions funs')++ (device_prototypes, device_defs) = unzip $ M.elems device_funs+ kernels' = M.map fst kernels+ 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+ ]+ in ImpOpenCL.Program+ opencl_code+ opencl_prelude+ kernels'+ (S.toList used_types)+ (cleanSizes sizes)+ failures+ prog'+ where+ genPrelude TargetOpenCL = genOpenClPrelude+ genPrelude TargetCUDA = const genCUDAPrelude++-- | Due to simplifications after kernel extraction, some threshold+-- parameters may contain KernelPaths that reference threshold+-- parameters that no longer exist. We remove these here.+cleanSizes :: M.Map Name SizeClass -> M.Map Name SizeClass+cleanSizes m = M.map clean m+ where+ known = M.keys m+ clean (SizeThreshold path def) =+ SizeThreshold (filter ((`elem` known) . fst) path) def+ clean s = s++pointerQuals :: Monad m => String -> m [C.TypeQual]+pointerQuals "global" = return [C.ctyquals|__global|]+pointerQuals "local" = return [C.ctyquals|__local|]+pointerQuals "private" = return [C.ctyquals|__private|]+pointerQuals "constant" = return [C.ctyquals|__constant|]+pointerQuals "write_only" = return [C.ctyquals|__write_only|]+pointerQuals "read_only" = return [C.ctyquals|__read_only|]+pointerQuals "kernel" = return [C.ctyquals|__kernel|]+pointerQuals s = error $ "'" ++ s ++ "' is not an OpenCL kernel address space."++-- In-kernel name and per-workgroup size in bytes.+type LocalMemoryUse = (VName, Count Bytes Exp)++data KernelState = KernelState+ { kernelLocalMemory :: [LocalMemoryUse],+ kernelFailures :: [FailureMsg],+ kernelNextSync :: Int,+ -- | Has a potential failure occurred sine the last+ -- ErrorSync?+ kernelSyncPending :: Bool,+ kernelHasBarriers :: Bool+ }++newKernelState :: [FailureMsg] -> KernelState+newKernelState failures = KernelState mempty failures 0 False False++errorLabel :: KernelState -> String+errorLabel = ("error_" ++) . show . kernelNextSync++data ToOpenCL = ToOpenCL+ { clGPU :: M.Map KernelName (KernelSafety, C.Func),+ clDevFuns :: M.Map Name (C.Definition, C.Func),+ clUsedTypes :: S.Set PrimType,+ clSizes :: M.Map Name SizeClass,+ clFailures :: [FailureMsg]+ }++initialOpenCL :: ToOpenCL+initialOpenCL = ToOpenCL mempty mempty mempty mempty mempty++type AllFunctions = ImpGPU.Functions ImpGPU.HostOp++lookupFunction :: Name -> AllFunctions -> Maybe ImpGPU.Function+lookupFunction fname (ImpGPU.Functions fs) = lookup fname fs++type OnKernelM = ReaderT AllFunctions (State ToOpenCL)++addSize :: Name -> SizeClass -> OnKernelM ()+addSize key sclass =+ modify $ \s -> s {clSizes = M.insert key sclass $ clSizes s}++onHostOp :: KernelTarget -> HostOp -> OnKernelM OpenCL+onHostOp target (CallKernel k) = onKernel target k+onHostOp _ (ImpGPU.GetSize v key size_class) = do+ addSize key size_class+ return $ ImpOpenCL.GetSize v key+onHostOp _ (ImpGPU.CmpSizeLe v key size_class x) = do+ addSize key size_class+ return $ ImpOpenCL.CmpSizeLe v key x+onHostOp _ (ImpGPU.GetSizeMax v size_class) =+ return $ ImpOpenCL.GetSizeMax v size_class++genGPUCode ::+ OpsMode ->+ KernelCode ->+ [FailureMsg] ->+ GC.CompilerM KernelOp KernelState a ->+ (a, GC.CompilerState KernelState)+genGPUCode mode body failures =+ GC.runCompilerM+ (inKernelOperations mode body)+ blankNameSource+ (newKernelState failures)++-- Compilation of a device function that is not not invoked from the+-- host, but is invoked by (perhaps multiple) kernels.+generateDeviceFun :: Name -> ImpGPU.Function -> OnKernelM ()+generateDeviceFun fname host_func = do+ -- Functions are a priori always considered host-level, so we have+ -- to convert them to device code. This is where most of our+ -- limitations on device-side functions (no arrays, no parallelism)+ -- comes from.+ let device_func = fmap toDevice host_func+ when (any memParam $ functionInput host_func) bad++ failures <- gets clFailures++ let params =+ [ [C.cparam|__global int *global_failure|],+ [C.cparam|__global typename int64_t *global_failure_args|]+ ]+ (func, cstate) =+ genGPUCode FunMode (functionBody device_func) failures $+ GC.compileFun mempty params (fname, device_func)+ kstate = GC.compUserState cstate++ modify $ \s ->+ s+ { clUsedTypes = typesInCode (functionBody device_func) <> clUsedTypes s,+ clDevFuns = M.insert fname func $ clDevFuns s,+ clFailures = kernelFailures kstate+ }++ -- Important to do this after the 'modify' call, so we propagate the+ -- right clFailures.+ void $ ensureDeviceFuns $ functionBody device_func+ where+ toDevice :: HostOp -> KernelOp+ toDevice _ = bad++ memParam MemParam {} = True+ memParam ScalarParam {} = False++ bad = compilerLimitationS "Cannot generate GPU functions that use arrays."++-- Ensure that this device function is available, but don't regenerate+-- it if it already exists.+ensureDeviceFun :: Name -> ImpGPU.Function -> OnKernelM ()+ensureDeviceFun fname host_func = do+ exists <- gets $ M.member fname . clDevFuns+ unless exists $ generateDeviceFun fname host_func++ensureDeviceFuns :: ImpGPU.KernelCode -> OnKernelM [Name]+ensureDeviceFuns code = do+ let called = calledFuncs code+ fmap catMaybes $+ forM (S.toList called) $ \fname -> do+ def <- asks $ lookupFunction fname+ case def of+ Just func -> do+ ensureDeviceFun fname func+ return $ Just fname+ Nothing -> return Nothing++onKernel :: KernelTarget -> Kernel -> OnKernelM OpenCL+onKernel target kernel = do+ called <- ensureDeviceFuns $ kernelBody kernel++ -- Crucial that this is done after 'ensureDeviceFuns', as the device+ -- functions may themselves define failure points.+ failures <- gets clFailures++ let (kernel_body, cstate) =+ genGPUCode KernelMode (kernelBody kernel) failures $+ GC.blockScope $ GC.compileCode $ kernelBody kernel+ kstate = GC.compUserState cstate++ use_params = mapMaybe useAsParam $ kernelUses kernel++ (local_memory_args, local_memory_params, local_memory_init) =+ unzip3 $+ flip evalState (blankNameSource :: VNameSource) $+ mapM (prepareLocalMemory target) $ kernelLocalMemory kstate++ -- CUDA has very strict restrictions on the number of blocks+ -- permitted along the 'y' and 'z' dimensions of the grid+ -- (1<<16). To work around this, we are going to dynamically+ -- permute the block dimensions to move the largest one to the+ -- 'x' dimension, which has a higher limit (1<<31). This means+ -- we need to extend the kernel with extra parameters that+ -- contain information about this permutation, but we only do+ -- this for multidimensional kernels (at the time of this+ -- writing, only transposes). The corresponding arguments are+ -- added automatically in CCUDA.hs.+ (perm_params, block_dim_init) =+ case (target, num_groups) of+ (TargetCUDA, [_, _, _]) ->+ ( [ [C.cparam|const int block_dim0|],+ [C.cparam|const int block_dim1|],+ [C.cparam|const int block_dim2|]+ ],+ mempty+ )+ _ ->+ ( mempty,+ [ [C.citem|const int block_dim0 = 0;|],+ [C.citem|const int block_dim1 = 1;|],+ [C.citem|const int block_dim2 = 2;|]+ ]+ )++ (const_defs, const_undefs) = unzip $ mapMaybe constDef $ kernelUses kernel++ let (safety, error_init)+ -- We conservatively assume that any called function can fail.+ | not $ null called =+ (SafetyFull, [])+ | length (kernelFailures kstate) == length failures =+ if kernelFailureTolerant kernel+ then (SafetyNone, [])+ else -- No possible failures in this kernel, so if we make+ -- it past an initial check, then we are good to go.++ ( SafetyCheap,+ [C.citems|if (*global_failure >= 0) { return; }|]+ )+ | otherwise =+ if not (kernelHasBarriers kstate)+ then+ ( SafetyFull,+ [C.citems|if (*global_failure >= 0) { return; }|]+ )+ else+ ( SafetyFull,+ [C.citems|+ volatile __local bool local_failure;+ if (failure_is_an_option) {+ int failed = *global_failure >= 0;+ if (failed) {+ return;+ }+ }+ // All threads write this value - it looks like CUDA has a compiler bug otherwise.+ local_failure = false;+ barrier(CLK_LOCAL_MEM_FENCE);+ |]+ )++ failure_params =+ [ [C.cparam|__global int *global_failure|],+ [C.cparam|int failure_is_an_option|],+ [C.cparam|__global typename int64_t *global_failure_args|]+ ]++ params =+ perm_params+ ++ take (numFailureParams safety) failure_params+ ++ catMaybes local_memory_params+ ++ use_params++ kernel_fun =+ [C.cfun|__kernel void $id:name ($params:params) {+ $items:const_defs+ $items:block_dim_init+ $items:local_memory_init+ $items:error_init+ $items:kernel_body++ $id:(errorLabel kstate): return;++ $items:const_undefs+ }|]+ modify $ \s ->+ s+ { clGPU = M.insert name (safety, kernel_fun) $ clGPU s,+ clUsedTypes = typesInKernel kernel <> clUsedTypes s,+ clFailures = kernelFailures kstate+ }++ -- The argument corresponding to the global_failure parameters is+ -- added automatically later.+ let args =+ catMaybes local_memory_args+ ++ kernelArgs kernel++ return $ LaunchKernel safety name args num_groups group_size+ where+ name = kernelName kernel+ num_groups = kernelNumGroups kernel+ group_size = kernelGroupSize kernel++ prepareLocalMemory TargetOpenCL (mem, size) = do+ mem_aligned <- newVName $ baseString mem ++ "_aligned"+ 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;|]+ )+ 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];|]+ )++useAsParam :: KernelUse -> Maybe C.Param+useAsParam (ScalarUse name bt) =+ let ctp = case bt of+ -- OpenCL does not permit bool as a kernel parameter type.+ Bool -> [C.cty|unsigned char|]+ Unit -> [C.cty|unsigned char|]+ _ -> GC.primTypeToCType bt+ in Just [C.cparam|$ty:ctp $id:name|]+useAsParam (MemoryUse name) =+ Just [C.cparam|__global unsigned char *$id:name|]+useAsParam ConstUse {} =+ Nothing++-- Constants are #defined as macros. Since a constant name in one+-- kernel might potentially (although unlikely) also be used for+-- something else in another kernel, we #undef them after the kernel.+constDef :: KernelUse -> Maybe (C.BlockItem, C.BlockItem)+constDef (ConstUse v e) =+ Just+ ( [C.citem|$escstm:def|],+ [C.citem|$escstm:undef|]+ )+ where+ e' = compilePrimExp e+ def = "#define " ++ pretty (C.toIdent v mempty) ++ " (" ++ prettyOneLine e' ++ ")"+ undef = "#undef " ++ pretty (C.toIdent v mempty)+constDef _ = Nothing++openClCode :: [C.Func] -> String+openClCode kernels =+ pretty [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 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. */+__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")++typedef char int8_t;+typedef short int16_t;+typedef int int32_t;+typedef long int64_t;++typedef uchar uint8_t;+typedef ushort uint16_t;+typedef uint uint32_t;+typedef ulong uint64_t;++// 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")+static inline void mem_fence_global() {+ asm("membar.gl;");+}+$esc:("#else")+static inline void mem_fence_global() {+ mem_fence(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);+}+$esc:("#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|]]+ where+ uses_float64 = FloatType Float64 `S.member` ts++genCUDAPrelude :: [C.Definition]+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")++typedef char int8_t;+typedef short int16_t;+typedef int int32_t;+typedef long long int64_t;+typedef unsigned char uint8_t;+typedef unsigned short uint16_t;+typedef unsigned int uint32_t;+typedef unsigned long long uint64_t;+typedef uint8_t uchar;+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")++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;+ case 2: d = block_dim2; break;+ }+ switch (d) {+ case 0: return blockIdx.x;+ case 1: return blockIdx.y;+ case 2: return blockIdx.z;+ default: return 0;+ }+}+$esc:("#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)+{+ switch (d) {+ case 0: d = block_dim0; break;+ case 1: d = block_dim1; break;+ case 2: d = block_dim2; break;+ }+ switch(d) {+ case 0: return gridDim.x;+ case 1: return gridDim.y;+ case 2: return gridDim.z;+ default: return 0;+ }+}+$esc:("#define get_num_groups(d) get_num_groups_fn(block_dim0, block_dim1, block_dim2, d)")++static inline int get_local_id(int d)+{+ switch (d) {+ case 0: return threadIdx.x;+ case 1: return threadIdx.y;+ case 2: return threadIdx.z;+ default: return 0;+ }+}++static inline int get_local_size(int d)+{+ switch (d) {+ case 0: return blockDim.x;+ case 1: return blockDim.y;+ case 2: return blockDim.z;+ default: return 0;+ }+}++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)")++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)+{+ __syncthreads();+}+static inline void mem_fence_local() {+ __threadfence_block();+}+static inline void mem_fence_global() {+ __threadfence();+}++$esc:("#define NAN (0.0/0.0)")+$esc:("#define INFINITY (1.0/0.0)")+extern volatile __shared__ char shared_mem[];+|]++compilePrimExp :: PrimExp KernelConst -> C.Exp+compilePrimExp e = runIdentity $ GC.compilePrimExp compileKernelConst e+ where+ compileKernelConst (SizeConst key) =+ return [C.cexp|$id:(zEncodeString (pretty key))|]++kernelArgs :: Kernel -> [KernelArg]+kernelArgs = mapMaybe useToArg . kernelUses+ where+ useToArg (MemoryUse mem) = Just $ MemKArg mem+ useToArg (ScalarUse v bt) = Just $ ValueKArg (LeafExp (ScalarVar v) bt) bt+ useToArg ConstUse {} = Nothing++nextErrorLabel :: GC.CompilerM KernelOp KernelState String+nextErrorLabel =+ errorLabel <$> GC.getUserState++incErrorLabel :: GC.CompilerM KernelOp KernelState ()+incErrorLabel =+ GC.modifyUserState $ \s -> s {kernelNextSync = kernelNextSync s + 1}++pendingError :: Bool -> GC.CompilerM KernelOp KernelState ()+pendingError b =+ GC.modifyUserState $ \s -> s {kernelSyncPending = b}++hasCommunication :: ImpGPU.KernelCode -> Bool+hasCommunication = any communicates+ where+ communicates ErrorSync {} = True+ communicates Barrier {} = True+ communicates _ = False++-- Whether we are generating code for a kernel or a device function.+-- This has minor effects, such as exactly how failures are+-- propagated.+data OpsMode = KernelMode | FunMode deriving (Eq)++inKernelOperations ::+ OpsMode ->+ ImpGPU.KernelCode ->+ GC.Operations KernelOp KernelState+inKernelOperations mode body =+ GC.Operations+ { GC.opsCompiler = kernelOps,+ GC.opsMemoryType = kernelMemoryType,+ GC.opsWriteScalar = kernelWriteScalar,+ GC.opsReadScalar = kernelReadScalar,+ GC.opsAllocate = cannotAllocate,+ GC.opsDeallocate = cannotDeallocate,+ GC.opsCopy = copyInKernel,+ GC.opsStaticArray = noStaticArrays,+ GC.opsFatMemory = False,+ GC.opsError = errorInKernel,+ GC.opsCall = callInKernel,+ GC.opsCritical = mempty+ }+ where+ has_communication = hasCommunication body++ fence FenceLocal = [C.cexp|CLK_LOCAL_MEM_FENCE|]+ fence FenceGlobal = [C.cexp|CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE|]++ kernelOps :: GC.OpCompiler KernelOp KernelState+ kernelOps (GetGroupId v i) =+ GC.stm [C.cstm|$id:v = get_group_id($int:i);|]+ kernelOps (GetLocalId v i) =+ GC.stm [C.cstm|$id:v = get_local_id($int:i);|]+ kernelOps (GetLocalSize v i) =+ GC.stm [C.cstm|$id:v = get_local_size($int:i);|]+ kernelOps (GetGlobalId v i) =+ GC.stm [C.cstm|$id:v = get_global_id($int:i);|]+ kernelOps (GetGlobalSize v i) =+ GC.stm [C.cstm|$id:v = get_global_size($int:i);|]+ kernelOps (GetLockstepWidth v) =+ GC.stm [C.cstm|$id:v = LOCKSTEP_WIDTH;|]+ kernelOps (Barrier f) = do+ GC.stm [C.cstm|barrier($exp:(fence f));|]+ GC.modifyUserState $ \s -> s {kernelHasBarriers = True}+ kernelOps (MemFence FenceLocal) =+ GC.stm [C.cstm|mem_fence_local();|]+ kernelOps (MemFence FenceGlobal) =+ GC.stm [C.cstm|mem_fence_global();|]+ kernelOps (LocalAlloc name size) = do+ 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';|]+ kernelOps (ErrorSync f) = do+ label <- nextErrorLabel+ pending <- kernelSyncPending <$> GC.getUserState+ when pending $ do+ pendingError False+ GC.stm [C.cstm|$id:label: barrier($exp:(fence f));|]+ GC.stm [C.cstm|if (local_failure) { return; }|]+ GC.stm [C.cstm|barrier(CLK_LOCAL_MEM_FENCE);|] -- intentional+ GC.modifyUserState $ \s -> s {kernelHasBarriers = True}+ incErrorLabel+ kernelOps (Atomic space aop) = atomicOps space aop++ atomicCast s t = do+ let volatile = [C.ctyquals|volatile|]+ quals <- case s of+ Space sid -> pointerQuals sid+ _ -> pointerQuals "global"+ return [C.cty|$tyquals:(volatile++quals) $ty:t|]++ atomicSpace (Space sid) = sid+ atomicSpace _ = "global"++ doAtomic s t old arr ind val op ty = do+ ind' <- GC.compileExp $ untyped $ unCount ind+ val' <- GC.compileExp val+ cast <- atomicCast s ty+ GC.stm [C.cstm|$id:old = $id:op'(&(($ty:cast *)$id:arr)[$exp:ind'], ($ty:ty) $exp:val');|]+ where+ op' = op ++ "_" ++ pretty t ++ "_" ++ atomicSpace s++ doAtomicCmpXchg s t old arr ind cmp val ty = do+ ind' <- GC.compileExp $ untyped $ unCount ind+ cmp' <- GC.compileExp cmp+ val' <- GC.compileExp val+ cast <- atomicCast s ty+ GC.stm [C.cstm|$id:old = $id:op(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:cmp', $exp:val');|]+ where+ op = "atomic_cmpxchg_" ++ pretty t ++ "_" ++ atomicSpace s+ doAtomicXchg s t old arr ind val ty = do+ cast <- atomicCast s ty+ ind' <- GC.compileExp $ untyped $ unCount ind+ val' <- GC.compileExp val+ GC.stm [C.cstm|$id:old = $id:op(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:val');|]+ where+ op = "atomic_chg_" ++ pretty t ++ "_" ++ atomicSpace s+ -- First the 64-bit operations.+ atomicOps s (AtomicAdd Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_add" [C.cty|typename int64_t|]+ atomicOps s (AtomicFAdd Float64 old arr ind val) =+ doAtomic s Float64 old arr ind val "atomic_fadd" [C.cty|double|]+ atomicOps s (AtomicSMax Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_smax" [C.cty|typename int64_t|]+ atomicOps s (AtomicSMin Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_smin" [C.cty|typename int64_t|]+ atomicOps s (AtomicUMax Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_umax" [C.cty|unsigned int64_t|]+ atomicOps s (AtomicUMin Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_umin" [C.cty|unsigned int64_t|]+ atomicOps s (AtomicAnd Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_and" [C.cty|typename int64_t|]+ atomicOps s (AtomicOr Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_or" [C.cty|typename int64_t|]+ atomicOps s (AtomicXor Int64 old arr ind val) =+ doAtomic s Int64 old arr ind val "atomic_xor" [C.cty|typename int64_t|]+ atomicOps s (AtomicCmpXchg (IntType Int64) old arr ind cmp val) =+ doAtomicCmpXchg s (IntType Int64) old arr ind cmp val [C.cty|typename int64_t|]+ atomicOps s (AtomicXchg (IntType Int64) old arr ind val) =+ doAtomicXchg s (IntType Int64) old arr ind val [C.cty|typename int64_t|]+ --+ 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 (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) =+ doAtomic s t old arr ind val "atomic_smin" [C.cty|int|]+ atomicOps s (AtomicUMax t old arr ind val) =+ doAtomic s t old arr ind val "atomic_umax" [C.cty|unsigned int|]+ atomicOps s (AtomicUMin t old arr ind val) =+ doAtomic s t old arr ind val "atomic_umin" [C.cty|unsigned int|]+ atomicOps s (AtomicAnd t old arr ind val) =+ doAtomic s t old arr ind val "atomic_and" [C.cty|int|]+ atomicOps s (AtomicOr t old arr ind val) =+ doAtomic s t old arr ind val "atomic_or" [C.cty|int|]+ atomicOps s (AtomicXor t old arr ind val) =+ doAtomic s t old arr ind val "atomic_xor" [C.cty|int|]+ atomicOps s (AtomicCmpXchg t old arr ind cmp val) =+ doAtomicCmpXchg s t old arr ind cmp val [C.cty|int|]+ atomicOps s (AtomicXchg t old arr ind val) =+ doAtomicXchg s t old arr ind val [C.cty|int|]++ cannotAllocate :: GC.Allocate KernelOp KernelState+ cannotAllocate _ =+ error "Cannot allocate memory in kernel"++ cannotDeallocate :: GC.Deallocate KernelOp KernelState+ cannotDeallocate _ _ =+ error "Cannot deallocate memory in kernel"++ copyInKernel :: GC.Copy KernelOp KernelState+ copyInKernel _ _ _ _ _ _ _ =+ error "Cannot bulk copy in kernel."++ noStaticArrays :: GC.StaticArray KernelOp KernelState+ noStaticArrays _ _ _ _ =+ error "Cannot create static array in kernel."++ kernelMemoryType space = do+ quals <- pointerQuals space+ return [C.cty|$tyquals:quals $ty:defaultMemBlockType|]++ kernelWriteScalar =+ GC.writeScalarPointerWithQuals pointerQuals++ kernelReadScalar =+ GC.readScalarPointerWithQuals pointerQuals++ whatNext = do+ label <- nextErrorLabel+ pendingError True+ return $+ if has_communication+ then [C.citems|local_failure = true; goto $id:label;|]+ else+ if mode == FunMode+ then [C.citems|return 1;|]+ else [C.citems|return;|]++ callInKernel dests fname args+ | isBuiltInFunction fname =+ GC.opsCall GC.defaultOperations dests fname args+ | otherwise = do+ let out_args = [[C.cexp|&$id:d|] | d <- dests]+ args' =+ [C.cexp|global_failure|] :+ [C.cexp|global_failure_args|] :+ out_args ++ args++ what_next <- whatNext++ GC.item [C.citem|if ($id:(funName fname)($args:args') != 0) { $items:what_next; }|]++ errorInKernel msg@(ErrorMsg parts) backtrace = do+ n <- length . kernelFailures <$> GC.getUserState+ GC.modifyUserState $ \s ->+ s {kernelFailures = kernelFailures s ++ [FailureMsg msg backtrace]}+ let setArgs _ [] = return []+ setArgs i (ErrorString {} : parts') = setArgs i parts'+ setArgs i (ErrorInt32 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++ GC.stm+ [C.cstm|{ if (atomic_cmpxchg_i32_global(global_failure, -1, $int:n) == -1)+ { $stms:argstms; }+ $items:what_next+ }|]++--- Checking requirements++typesInKernel :: Kernel -> S.Set PrimType+typesInKernel kernel = typesInCode $ kernelBody kernel++typesInCode :: ImpGPU.KernelCode -> S.Set PrimType+typesInCode Skip = mempty+typesInCode (c1 :>>: c2) = typesInCode c1 <> typesInCode c2+typesInCode (For _ e c) = typesInExp e <> typesInCode c+typesInCode (While (TPrimExp e) c) = typesInExp e <> typesInCode c+typesInCode DeclareMem {} = mempty+typesInCode (DeclareScalar _ _ t) = S.singleton t+typesInCode (DeclareArray _ _ t _) = S.singleton t+typesInCode (Allocate _ (Count (TPrimExp e)) _) = typesInExp e+typesInCode Free {} = mempty+typesInCode+ ( Copy+ _+ (Count (TPrimExp e1))+ _+ _+ (Count (TPrimExp e2))+ _+ (Count (TPrimExp e3))+ ) =+ typesInExp e1 <> typesInExp e2 <> typesInExp e3+typesInCode (Write _ (Count (TPrimExp e1)) t _ _ e2) =+ typesInExp e1 <> S.singleton t <> typesInExp e2+typesInCode (SetScalar _ e) = typesInExp e+typesInCode SetMem {} = mempty+typesInCode (Call _ _ es) = mconcat $ map typesInArg es+ where+ typesInArg MemArg {} = mempty+ typesInArg (ExpArg e) = typesInExp e+typesInCode (If (TPrimExp e) c1 c2) =+ typesInExp e <> typesInCode c1 <> typesInCode c2+typesInCode (Assert e _ _) = typesInExp e+typesInCode (Comment _ c) = typesInCode c+typesInCode (DebugPrint _ v) = maybe mempty typesInExp v+typesInCode Op {} = mempty++typesInExp :: Exp -> S.Set PrimType+typesInExp (ValueExp v) = S.singleton $ primValueType v+typesInExp (BinOpExp _ e1 e2) = typesInExp e1 <> typesInExp e2+typesInExp (CmpOpExp _ e1 e2) = typesInExp e1 <> typesInExp e2+typesInExp (ConvOpExp op e) = S.fromList [from, to] <> typesInExp e+ where+ (from, to) = convOpType op+typesInExp (UnOpExp _ e) = typesInExp e+typesInExp (FunExp _ args t) = S.singleton t <> mconcat (map typesInExp args)+typesInExp (LeafExp (Index _ (Count (TPrimExp e)) t _ _) _) = S.singleton t <> typesInExp e+typesInExp (LeafExp ScalarVar {} _) = mempty
+ src/Futhark/CodeGen/ImpGen/GPU/Transpose.hs view
@@ -0,0 +1,386 @@+-- | Carefully optimised implementations of GPU transpositions.+-- Written in ImpCode so we can compile it to both CUDA and OpenCL.+module Futhark.CodeGen.ImpGen.GPU.Transpose+ ( TransposeType (..),+ TransposeArgs,+ mapTransposeKernel,+ )+where++import Futhark.CodeGen.ImpCode.GPU+import Futhark.IR.Prop.Types+import Futhark.Util.IntegralExp (divUp, quot, rem)+import Prelude hiding (quot, rem)++-- | Which form of transposition to generate code for.+data TransposeType+ = TransposeNormal+ | TransposeLowWidth+ | TransposeLowHeight+ | -- | For small arrays that do not+ -- benefit from coalescing.+ TransposeSmall+ deriving (Eq, Ord, Show)++-- | The types of the arguments accepted by a transposition function.+type TransposeArgs =+ ( VName,+ TExp Int32,+ VName,+ TExp Int32,+ TExp Int32,+ TExp Int32,+ TExp Int32,+ TExp Int32,+ TExp Int32,+ VName+ )++elemsPerThread :: TExp Int32+elemsPerThread = 4++mapTranspose :: TExp Int32 -> TransposeArgs -> PrimType -> TransposeType -> KernelCode+mapTranspose block_dim args t kind =+ case kind of+ TransposeSmall ->+ mconcat+ [ get_ids,+ dec our_array_offset $ vi32 get_global_id_0 `quot` (height * width) * (height * width),+ dec x_index $ (vi32 get_global_id_0 `rem` (height * width)) `quot` height,+ dec y_index $ vi32 get_global_id_0 `rem` height,+ dec odata_offset $+ (basic_odata_offset `quot` primByteSize t) + vi32 our_array_offset,+ dec idata_offset $+ (basic_idata_offset `quot` primByteSize t) + vi32 our_array_offset,+ dec index_in $ vi32 y_index * width + vi32 x_index,+ dec index_out $ vi32 x_index * height + vi32 y_index,+ when+ (vi32 get_global_id_0 .<. width * height * num_arrays)+ ( Write odata (elements $ sExt64 $ vi32 odata_offset + vi32 index_out) t (Space "global") Nonvolatile $+ index idata (elements $ sExt64 $ vi32 idata_offset + vi32 index_in) t (Space "global") Nonvolatile+ )+ ]+ TransposeLowWidth ->+ mkTranspose $+ lowDimBody+ (vi32 get_group_id_0 * block_dim + (vi32 get_local_id_0 `quot` muly))+ ( vi32 get_group_id_1 * block_dim * muly + vi32 get_local_id_1+ + (vi32 get_local_id_0 `rem` muly) * block_dim+ )+ ( vi32 get_group_id_1 * block_dim * muly + vi32 get_local_id_0+ + (vi32 get_local_id_1 `rem` muly) * block_dim+ )+ (vi32 get_group_id_0 * block_dim + (vi32 get_local_id_1 `quot` muly))+ TransposeLowHeight ->+ mkTranspose $+ lowDimBody+ ( vi32 get_group_id_0 * block_dim * mulx + vi32 get_local_id_0+ + (vi32 get_local_id_1 `rem` mulx) * block_dim+ )+ (vi32 get_group_id_1 * block_dim + (vi32 get_local_id_1 `quot` mulx))+ (vi32 get_group_id_1 * block_dim + (vi32 get_local_id_0 `quot` mulx))+ ( vi32 get_group_id_0 * block_dim * mulx + vi32 get_local_id_1+ + (vi32 get_local_id_0 `rem` mulx) * block_dim+ )+ TransposeNormal ->+ mkTranspose $+ mconcat+ [ dec x_index $ vi32 get_global_id_0,+ dec y_index $ vi32 get_group_id_1 * tile_dim + vi32 get_local_id_1,+ when (vi32 x_index .<. width) $+ For j (untyped elemsPerThread) $+ let i = vi32 j * (tile_dim `quot` elemsPerThread)+ in mconcat+ [ dec index_in $ (vi32 y_index + i) * width + vi32 x_index,+ when (vi32 y_index + i .<. height) $+ Write+ block+ ( elements $+ sExt64 $+ (vi32 get_local_id_1 + i) * (tile_dim + 1)+ + vi32 get_local_id_0+ )+ t+ (Space "local")+ Nonvolatile+ $ index+ idata+ (elements $ sExt64 $ vi32 idata_offset + vi32 index_in)+ t+ (Space "global")+ Nonvolatile+ ],+ Op $ Barrier FenceLocal,+ SetScalar x_index $ untyped $ vi32 get_group_id_1 * tile_dim + vi32 get_local_id_0,+ SetScalar y_index $ untyped $ vi32 get_group_id_0 * tile_dim + vi32 get_local_id_1,+ when (vi32 x_index .<. height) $+ For j (untyped elemsPerThread) $+ let i = vi32 j * (tile_dim `quot` elemsPerThread)+ in mconcat+ [ dec index_out $ (vi32 y_index + i) * height + vi32 x_index,+ when (vi32 y_index + i .<. width) $+ Write+ odata+ (elements $ sExt64 $ vi32 odata_offset + vi32 index_out)+ t+ (Space "global")+ Nonvolatile+ $ index+ block+ ( elements $+ sExt64 $+ vi32 get_local_id_0 * (tile_dim + 1) + vi32 get_local_id_1 + i+ )+ t+ (Space "local")+ Nonvolatile+ ]+ ]+ where+ dec v (TPrimExp e) =+ DeclareScalar v Nonvolatile (primExpType e) <> SetScalar v e+ tile_dim = 2 * block_dim++ when a b = If a b mempty++ ( odata,+ basic_odata_offset,+ idata,+ basic_idata_offset,+ width,+ height,+ mulx,+ muly,+ num_arrays,+ block+ ) = args++ -- Be extremely careful when editing this list to ensure that+ -- the names match up. Also, be careful that the tags on+ -- these names do not conflict with the tags of the+ -- surrounding code. We accomplish the latter by using very+ -- low tags (normal variables start at least in the low+ -- hundreds).+ [ our_array_offset,+ x_index,+ y_index,+ odata_offset,+ idata_offset,+ index_in,+ index_out,+ get_global_id_0,+ get_local_id_0,+ get_local_id_1,+ get_group_id_0,+ get_group_id_1,+ get_group_id_2,+ j+ ] =+ zipWith (flip VName) [30 ..] $+ map+ nameFromString+ [ "our_array_offset",+ "x_index",+ "y_index",+ "odata_offset",+ "idata_offset",+ "index_in",+ "index_out",+ "get_global_id_0",+ "get_local_id_0",+ "get_local_id_1",+ "get_group_id_0",+ "get_group_id_1",+ "get_group_id_2",+ "j"+ ]++ get_ids =+ mconcat+ [ DeclareScalar get_global_id_0 Nonvolatile int32,+ Op $ GetGlobalId get_global_id_0 0,+ DeclareScalar get_local_id_0 Nonvolatile int32,+ Op $ GetLocalId get_local_id_0 0,+ DeclareScalar get_local_id_1 Nonvolatile int32,+ Op $ GetLocalId get_local_id_1 1,+ DeclareScalar get_group_id_0 Nonvolatile int32,+ Op $ GetGroupId get_group_id_0 0,+ DeclareScalar get_group_id_1 Nonvolatile int32,+ Op $ GetGroupId get_group_id_1 1,+ DeclareScalar get_group_id_2 Nonvolatile int32,+ Op $ GetGroupId get_group_id_2 2+ ]++ mkTranspose body =+ mconcat+ [ get_ids,+ dec our_array_offset $ vi32 get_group_id_2 * width * height,+ dec odata_offset $+ (basic_odata_offset `quot` primByteSize t) + vi32 our_array_offset,+ dec idata_offset $+ (basic_idata_offset `quot` primByteSize t) + vi32 our_array_offset,+ body+ ]++ lowDimBody x_in_index y_in_index x_out_index y_out_index =+ mconcat+ [ dec x_index x_in_index,+ dec y_index y_in_index,+ dec index_in $ vi32 y_index * width + vi32 x_index,+ when (vi32 x_index .<. width .&&. vi32 y_index .<. height) $+ Write+ block+ (elements $ sExt64 $ vi32 get_local_id_1 * (block_dim + 1) + vi32 get_local_id_0)+ t+ (Space "local")+ Nonvolatile+ $ index+ idata+ (elements $ sExt64 $ vi32 idata_offset + vi32 index_in)+ t+ (Space "global")+ Nonvolatile,+ Op $ Barrier FenceLocal,+ SetScalar x_index $ untyped x_out_index,+ SetScalar y_index $ untyped y_out_index,+ dec index_out $ vi32 y_index * height + vi32 x_index,+ when (vi32 x_index .<. height .&&. vi32 y_index .<. width) $+ Write+ odata+ (elements $ sExt64 (vi32 odata_offset + vi32 index_out))+ t+ (Space "global")+ Nonvolatile+ $ index+ block+ (elements $ sExt64 $ vi32 get_local_id_0 * (block_dim + 1) + vi32 get_local_id_1)+ t+ (Space "local")+ Nonvolatile+ ]++-- | Generate a transpose kernel. There is special support to handle+-- input arrays with low width, low height, or both.+--+-- Normally when transposing a @[2][n]@ array we would use a @FUT_BLOCK_DIM x+-- FUT_BLOCK_DIM@ group to process a @[2][FUT_BLOCK_DIM]@ slice of the input+-- array. This would mean that many of the threads in a group would be inactive.+-- We try to remedy this by using a special kernel that will process a larger+-- part of the input, by using more complex indexing. In our example, we could+-- use all threads in a group if we are processing @(2/FUT_BLOCK_DIM)@ as large+-- a slice of each rows per group. The variable @mulx@ contains this factor for+-- the kernel to handle input arrays with low height.+--+-- See issue #308 on GitHub for more details.+--+-- These kernels are optimized to ensure all global reads and writes+-- are coalesced, and to avoid bank conflicts in shared memory. Each+-- thread group transposes a 2D tile of block_dim*2 by block_dim*2+-- elements. The size of a thread group is block_dim/2 by+-- block_dim*2, meaning that each thread will process 4 elements in a+-- 2D tile. The shared memory array containing the 2D tile consists+-- of block_dim*2 by block_dim*2+1 elements. Padding each row with+-- an additional element prevents bank conflicts from occuring when+-- the tile is accessed column-wise.+mapTransposeKernel ::+ String ->+ Integer ->+ TransposeArgs ->+ PrimType ->+ TransposeType ->+ Kernel+mapTransposeKernel desc block_dim_int args t kind =+ Kernel+ { kernelBody =+ DeclareMem block (Space "local")+ <> Op (LocalAlloc block block_size)+ <> mapTranspose block_dim args t kind,+ kernelUses = uses,+ kernelNumGroups = map untyped num_groups,+ kernelGroupSize = map untyped group_size,+ kernelName = nameFromString name,+ kernelFailureTolerant = True+ }+ where+ pad2DBytes k = k * (k + 1) * primByteSize t+ block_size =+ bytes $+ case kind of+ TransposeSmall -> 1 :: TExp Int64+ -- Not used, but AMD's OpenCL+ -- does not like zero-size+ -- local memory.+ TransposeNormal -> fromInteger $ pad2DBytes $ 2 * block_dim_int+ TransposeLowWidth -> fromInteger $ pad2DBytes block_dim_int+ TransposeLowHeight -> fromInteger $ pad2DBytes block_dim_int+ block_dim = fromInteger block_dim_int :: TExp Int32++ ( odata,+ basic_odata_offset,+ idata,+ basic_idata_offset,+ width,+ height,+ mulx,+ muly,+ num_arrays,+ block+ ) = args++ (num_groups, group_size) =+ case kind of+ TransposeSmall ->+ ( [(num_arrays * width * height) `divUp` (block_dim * block_dim)],+ [block_dim * block_dim]+ )+ TransposeLowWidth ->+ lowDimKernelAndGroupSize block_dim num_arrays width $ height `divUp` muly+ TransposeLowHeight ->+ lowDimKernelAndGroupSize block_dim num_arrays (width `divUp` mulx) height+ TransposeNormal ->+ let actual_dim = block_dim * 2+ in ( [ width `divUp` actual_dim,+ height `divUp` actual_dim,+ num_arrays+ ],+ [actual_dim, actual_dim `quot` elemsPerThread, 1]+ )++ uses =+ map+ (`ScalarUse` int32)+ ( namesToList $+ mconcat $+ map+ freeIn+ [ basic_odata_offset,+ basic_idata_offset,+ num_arrays,+ width,+ height,+ mulx,+ muly+ ]+ )+ ++ map MemoryUse [odata, idata]++ name =+ case kind of+ TransposeSmall -> desc ++ "_small"+ TransposeLowHeight -> desc ++ "_low_height"+ TransposeLowWidth -> desc ++ "_low_width"+ TransposeNormal -> desc++lowDimKernelAndGroupSize ::+ TExp Int32 ->+ TExp Int32 ->+ TExp Int32 ->+ TExp Int32 ->+ ([TExp Int32], [TExp Int32])+lowDimKernelAndGroupSize block_dim num_arrays x_elems y_elems =+ ( [ x_elems `divUp` block_dim,+ y_elems `divUp` block_dim,+ num_arrays+ ],+ [block_dim, block_dim, 1]+ )
− src/Futhark/CodeGen/ImpGen/Kernels.hs
@@ -1,431 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}---- | Compile a 'KernelsMem' program to imperative code with kernels.--- This is mostly (but not entirely) the same process no matter if we--- are targeting OpenCL or CUDA. The important distinctions (the host--- level code) are introduced later.-module Futhark.CodeGen.ImpGen.Kernels- ( compileProgOpenCL,- compileProgCUDA,- Warnings,- )-where--import Control.Monad.Except-import Data.Bifunctor (second)-import Data.List (foldl')-import qualified Data.Map as M-import Data.Maybe-import Futhark.CodeGen.ImpCode.Kernels (bytes)-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen hiding (compileProg)-import qualified Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.CodeGen.ImpGen.Kernels.SegHist-import Futhark.CodeGen.ImpGen.Kernels.SegMap-import Futhark.CodeGen.ImpGen.Kernels.SegRed-import Futhark.CodeGen.ImpGen.Kernels.SegScan-import Futhark.CodeGen.ImpGen.Kernels.Transpose-import Futhark.CodeGen.SetDefaultSpace-import Futhark.Error-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.MonadFreshNames-import Futhark.Util.IntegralExp (IntegralExp, divUp, quot, rem)-import Prelude hiding (quot, rem)--callKernelOperations :: Operations KernelsMem HostEnv Imp.HostOp-callKernelOperations =- Operations- { opsExpCompiler = expCompiler,- opsCopyCompiler = callKernelCopy,- opsOpCompiler = opCompiler,- opsStmsCompiler = defCompileStms,- opsAllocCompilers = mempty- }--openclAtomics, cudaAtomics :: AtomicBinOp-(openclAtomics, cudaAtomics) = (flip lookup opencl, flip lookup cuda)- where- opencl64 =- [ (Add Int64 OverflowUndef, Imp.AtomicAdd Int64),- (SMax Int64, Imp.AtomicSMax Int64),- (SMin Int64, Imp.AtomicSMin Int64),- (UMax Int64, Imp.AtomicUMax Int64),- (UMin Int64, Imp.AtomicUMin Int64),- (And Int64, Imp.AtomicAnd Int64),- (Or Int64, Imp.AtomicOr Int64),- (Xor Int64, Imp.AtomicXor Int64)- ]- opencl32 =- [ (Add Int32 OverflowUndef, Imp.AtomicAdd Int32),- (SMax Int32, Imp.AtomicSMax Int32),- (SMin Int32, Imp.AtomicSMin Int32),- (UMax Int32, Imp.AtomicUMax Int32),- (UMin Int32, Imp.AtomicUMin Int32),- (And Int32, Imp.AtomicAnd Int32),- (Or Int32, Imp.AtomicOr Int32),- (Xor Int32, Imp.AtomicXor Int32)- ]- opencl = opencl32 ++ opencl64- cuda =- opencl- ++ [ (FAdd Float32, Imp.AtomicFAdd Float32),- (FAdd Float64, Imp.AtomicFAdd Float64)- ]--compileProg ::- MonadFreshNames m =>- HostEnv ->- Prog KernelsMem ->- m (Warnings, Imp.Program)-compileProg env prog =- second (setDefaultSpace (Imp.Space "device"))- <$> Futhark.CodeGen.ImpGen.compileProg env callKernelOperations (Imp.Space "device") prog---- | Compile a 'KernelsMem' program to low-level parallel code, with--- either CUDA or OpenCL characteristics.-compileProgOpenCL,- compileProgCUDA ::- MonadFreshNames m => Prog KernelsMem -> m (Warnings, Imp.Program)-compileProgOpenCL = compileProg $ HostEnv openclAtomics OpenCL mempty-compileProgCUDA = compileProg $ HostEnv cudaAtomics CUDA mempty--opCompiler ::- Pattern KernelsMem ->- Op KernelsMem ->- CallKernelGen ()-opCompiler dest (Alloc e space) =- compileAlloc dest e space-opCompiler (Pattern _ [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- 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))) =- sOp $ Imp.GetSizeMax (patElemName pe) size_class-opCompiler (Pattern _ [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 $- Imp.GetSize (tvVar max_num_groups) (keyWithEntryPoint fname max_num_groups_key) $- sizeClassWithEntryPoint fname SizeNumGroups-- -- If 'w' is small, we launch fewer groups than we normally would.- -- We don't want any idle groups.- --- -- The calculations are done with 64-bit integers to avoid overflow- -- issues.- let num_groups_maybe_zero =- sMin64 (toInt64Exp w64 `divUp` toInt64Exp group_size) $- sExt64 (tvExp max_num_groups)- -- We also don't want zero groups.- let num_groups = sMax64 1 num_groups_maybe_zero- mkTV (patElemName pe) int32 <-- sExt32 num_groups-opCompiler dest (Inner (SegOp op)) =- segOpCompiler dest op-opCompiler pat e =- compilerBugS $- "opCompiler: Invalid pattern\n "- ++ pretty pat- ++ "\nfor expression\n "- ++ pretty e--sizeClassWithEntryPoint :: Maybe Name -> Imp.SizeClass -> Imp.SizeClass-sizeClassWithEntryPoint fname (Imp.SizeThreshold path def) =- Imp.SizeThreshold (map f path) def- where- f (name, x) = (keyWithEntryPoint fname name, x)-sizeClassWithEntryPoint _ size_class = size_class--segOpCompiler ::- Pattern KernelsMem ->- SegOp SegLevel KernelsMem ->- CallKernelGen ()-segOpCompiler pat (SegMap lvl space _ kbody) =- compileSegMap pat lvl space kbody-segOpCompiler pat (SegRed lvl@SegThread {} space reds _ kbody) =- compileSegRed pat lvl space reds kbody-segOpCompiler pat (SegScan lvl@SegThread {} space scans _ kbody) =- compileSegScan pat lvl space scans kbody-segOpCompiler pat (SegHist (SegThread num_groups group_size _) space ops _ kbody) =- compileSegHist pat num_groups group_size space ops kbody-segOpCompiler pat segop =- compilerBugS $ "segOpCompiler: unexpected " ++ pretty (segLevel segop) ++ " for rhs of pattern " ++ pretty pat---- Create boolean expression that checks whether all kernels in the--- enclosed code do not use more local memory than we have available.--- We look at *all* the kernels here, even those that might be--- otherwise protected by their own multi-versioning branches deeper--- down. Currently the compiler will not generate multi-versioning--- that makes this a problem, but it might in the future.-checkLocalMemoryReqs :: Imp.Code -> CallKernelGen (Maybe (Imp.TExp Bool))-checkLocalMemoryReqs code = do- scope <- askScope- let alloc_sizes = map (sum . map alignedSize . localAllocSizes . Imp.kernelBody) $ getKernels code-- -- If any of the sizes involve a variable that is not known at this- -- point, then we cannot check the requirements.- if any (`M.notMember` scope) (namesToList $ freeIn alloc_sizes)- then return Nothing- else do- local_memory_capacity :: TV Int32 <- dPrim "local_memory_capacity" int32- sOp $ Imp.GetSizeMax (tvVar local_memory_capacity) SizeLocalMemory-- let local_memory_capacity_64 =- sExt64 $ tvExp local_memory_capacity- fits size =- unCount size .<=. local_memory_capacity_64- return $ Just $ foldl' (.&&.) true (map fits alloc_sizes)- where- getKernels = foldMap getKernel- getKernel (Imp.CallKernel k) = [k]- getKernel _ = []-- localAllocSizes = foldMap localAllocSize- localAllocSize (Imp.LocalAlloc _ size) = [size]- localAllocSize _ = []-- -- These allocations will actually be padded to an 8-byte aligned- -- size, so we should take that into account when checking whether- -- they fit.- alignedSize x = x + ((8 - (x `rem` 8)) `rem` 8)--withAcc ::- Pattern KernelsMem ->- [(Shape, [VName], Maybe (Lambda KernelsMem, [SubExp]))] ->- Lambda KernelsMem ->- CallKernelGen ()-withAcc pat inputs lam = do- atomics <- hostAtomics <$> askEnv- locksForInputs atomics $ zip accs inputs- where- accs = map paramName $ lambdaParams lam- locksForInputs _ [] =- defCompileExp pat $ WithAcc inputs lam- locksForInputs atomics ((c, (_, _, op)) : inputs')- | Just (op_lam, _) <- op,- AtomicLocking _ <- atomicUpdateLocking atomics op_lam = do- let num_locks = 100151- locks_arr <-- sStaticArray "withacc_locks" (Space "device") int32 $- Imp.ArrayZeros num_locks- let locks = Locks locks_arr num_locks- extend env = env {hostLocks = M.insert c locks $ hostLocks env}- localEnv extend $ locksForInputs atomics inputs'- | otherwise =- locksForInputs atomics inputs'--expCompiler :: ExpCompiler KernelsMem HostEnv Imp.HostOp--- We generate a simple kernel for itoa and replicate.-expCompiler (Pattern _ [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)) =- sReplicate (patElemName pe) se--- Allocation in the "local" space is just a placeholder.-expCompiler _ (Op (Alloc _ (Space "local"))) =- return ()-expCompiler pat (WithAcc inputs lam) =- withAcc pat inputs lam--- This is a multi-versioning If created by incremental flattening.--- We need to augment the conditional with a check that any local--- memory requirements in tbranch are compatible with the hardware.--- We do not check anything for fbranch, as we assume that it will--- always be safe (and what would we do if none of the branches would--- work?).-expCompiler dest (If cond tbranch fbranch (IfDec _ IfEquiv)) = do- tcode <- collect $ compileBody dest tbranch- fcode <- collect $ compileBody dest fbranch- check <- checkLocalMemoryReqs tcode- emit $ case check of- Nothing -> fcode- Just ok -> Imp.If (ok .&&. toBoolExp cond) tcode fcode-expCompiler dest e =- defCompileExp dest e--callKernelCopy :: CopyCompiler KernelsMem 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--mapTransposeForType :: PrimType -> CallKernelGen Name-mapTransposeForType bt = do- let fname = nameFromString $ "builtin#" <> mapTransposeName bt-- exists <- hasFunction fname- unless exists $ emitFunction fname $ mapTransposeFunction bt-- return fname--mapTransposeName :: PrimType -> String-mapTransposeName bt = "gpu_map_transpose_" ++ pretty bt--mapTransposeFunction :: PrimType -> Imp.Function-mapTransposeFunction bt =- Imp.Function Nothing [] params transpose_code [] []- where- params =- [ memparam destmem,- intparam destoffset,- memparam srcmem,- intparam srcoffset,- intparam num_arrays,- intparam x,- intparam y- ]-- space = Space "device"- memparam v = Imp.MemParam v space- intparam v = Imp.ScalarParam v $ IntType Int32-- [ destmem,- destoffset,- srcmem,- srcoffset,- num_arrays,- x,- y,- mulx,- muly,- block- ] =- zipWith- (VName . nameFromString)- [ "destmem",- "destoffset",- "srcmem",- "srcoffset",- "num_arrays",- "x_elems",- "y_elems",- -- The following is only used for low width/height- -- transpose kernels- "mulx",- "muly",- "block"- ]- [0 ..]-- block_dim_int = 16-- block_dim :: IntegralExp a => a- block_dim = 16-- -- When an input array has either width==1 or height==1, performing a- -- transpose will be the same as performing a copy.- can_use_copy =- let onearr = Imp.vi32 num_arrays .==. 1- height_is_one = Imp.vi32 y .==. 1- width_is_one = Imp.vi32 x .==. 1- in onearr .&&. (width_is_one .||. height_is_one)-- transpose_code =- Imp.If input_is_empty mempty $- mconcat- [ Imp.DeclareScalar muly Imp.Nonvolatile (IntType Int32),- Imp.SetScalar muly $ untyped $ block_dim `quot` Imp.vi32 x,- Imp.DeclareScalar mulx Imp.Nonvolatile (IntType Int32),- Imp.SetScalar mulx $ untyped $ block_dim `quot` Imp.vi32 y,- Imp.If can_use_copy copy_code $- Imp.If should_use_lowwidth (callTransposeKernel TransposeLowWidth) $- Imp.If should_use_lowheight (callTransposeKernel TransposeLowHeight) $- Imp.If should_use_small (callTransposeKernel TransposeSmall) $- callTransposeKernel TransposeNormal- ]-- input_is_empty =- Imp.vi32 num_arrays .==. 0 .||. Imp.vi32 x .==. 0 .||. Imp.vi32 y .==. 0-- should_use_small =- Imp.vi32 x .<=. (block_dim `quot` 2)- .&&. Imp.vi32 y .<=. (block_dim `quot` 2)-- should_use_lowwidth =- Imp.vi32 x .<=. (block_dim `quot` 2)- .&&. block_dim .<. Imp.vi32 y-- should_use_lowheight =- Imp.vi32 y .<=. (block_dim `quot` 2)- .&&. block_dim .<. Imp.vi32 x-- copy_code =- let num_bytes = sExt64 $ Imp.vi32 x * Imp.vi32 y * primByteSize bt- in Imp.Copy- destmem- (Imp.Count $ sExt64 $ Imp.vi32 destoffset)- space- srcmem- (Imp.Count $ sExt64 $ Imp.vi32 srcoffset)- space- (Imp.Count num_bytes)-- callTransposeKernel =- Imp.Op . Imp.CallKernel- . mapTransposeKernel- (mapTransposeName bt)- block_dim_int- ( destmem,- Imp.vi32 destoffset,- srcmem,- Imp.vi32 srcoffset,- Imp.vi32 x,- Imp.vi32 y,- Imp.vi32 mulx,- Imp.vi32 muly,- Imp.vi32 num_arrays,- block- )- bt
− src/Futhark/CodeGen/ImpGen/Kernels/Base.hs
@@ -1,1803 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TypeFamilies #-}--module Futhark.CodeGen.ImpGen.Kernels.Base- ( KernelConstants (..),- keyWithEntryPoint,- CallKernelGen,- InKernelGen,- Locks (..),- HostEnv (..),- Target (..),- KernelEnv (..),- computeThreadChunkSize,- groupReduce,- groupScan,- isActive,- sKernelThread,- sKernelGroup,- sReplicate,- sIota,- sCopy,- compileThreadResult,- compileGroupResult,- virtualiseGroups,- groupLoop,- kernelLoop,- groupCoverSpace,- precomputeSegOpIDs,- atomicUpdateLocking,- AtomicBinOp,- Locking (..),- AtomicUpdate (..),- DoAtomicUpdate,- )-where--import Control.Monad.Except-import Data.List (elemIndex, find, zip4)-import qualified Data.Map.Strict as M-import Data.Maybe-import qualified Data.Set as S-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.Error-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.MonadFreshNames-import Futhark.Transform.Rename-import Futhark.Util (chunks, dropLast, mapAccumLM, maybeNth, nubOrd, takeLast)-import Futhark.Util.IntegralExp (divUp, quot, rem)-import Prelude hiding (quot, rem)---- | Which target are we ultimately generating code for? While most--- of the kernels code is the same, there are some cases where we--- generate special code based on the ultimate low-level API we are--- targeting.-data Target = CUDA | OpenCL---- | Information about the locks available for accumulators.-data Locks = Locks- { locksArray :: VName,- locksCount :: Int- }--data HostEnv = HostEnv- { hostAtomics :: AtomicBinOp,- hostTarget :: Target,- hostLocks :: M.Map VName Locks- }--data KernelEnv = KernelEnv- { kernelAtomics :: AtomicBinOp,- kernelConstants :: KernelConstants,- kernelLocks :: M.Map VName Locks- }--type CallKernelGen = ImpM KernelsMem HostEnv Imp.HostOp--type InKernelGen = ImpM KernelsMem KernelEnv Imp.KernelOp--data KernelConstants = KernelConstants- { kernelGlobalThreadId :: Imp.TExp Int32,- kernelLocalThreadId :: Imp.TExp Int32,- kernelGroupId :: Imp.TExp Int32,- kernelGlobalThreadIdVar :: VName,- kernelLocalThreadIdVar :: VName,- kernelGroupIdVar :: VName,- kernelNumGroups :: Imp.TExp Int64,- kernelGroupSize :: Imp.TExp Int64,- kernelNumThreads :: Imp.TExp Int32,- kernelWaveSize :: Imp.TExp Int32,- kernelThreadActive :: Imp.TExp Bool,- -- | A mapping from dimensions of nested SegOps to already- -- computed local thread IDs.- kernelLocalIdMap :: M.Map [SubExp] [Imp.TExp Int32]- }--segOpSizes :: Stms KernelsMem -> S.Set [SubExp]-segOpSizes = onStms- where- onStms = foldMap (onExp . stmExp)- onExp (Op (Inner (SegOp op))) =- S.singleton $ map snd $ unSegSpace $ segSpace op- onExp (If _ tbranch fbranch _) =- onStms (bodyStms tbranch) <> onStms (bodyStms fbranch)- onExp (DoLoop _ _ _ body) =- onStms (bodyStms body)- onExp _ = mempty--precomputeSegOpIDs :: Stms KernelsMem -> InKernelGen a -> InKernelGen a-precomputeSegOpIDs stms m = do- ltid <- kernelLocalThreadId . kernelConstants <$> askEnv- new_ids <- M.fromList <$> mapM (mkMap ltid) (S.toList (segOpSizes stms))- let f env =- env- { kernelConstants =- (kernelConstants env) {kernelLocalIdMap = new_ids}- }- 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')--keyWithEntryPoint :: Maybe Name -> Name -> Name-keyWithEntryPoint fname key =- nameFromString $ maybe "" ((++ ".") . nameToString) fname ++ nameToString key--allocLocal :: AllocCompiler KernelsMem r Imp.KernelOp-allocLocal mem size =- sOp $ Imp.LocalAlloc mem size--kernelAlloc ::- Pattern KernelsMem ->- SubExp ->- Space ->- InKernelGen ()-kernelAlloc (Pattern _ [_]) _ 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") =- allocLocal (patElemName mem) $ Imp.bytes $ toInt64Exp size-kernelAlloc (Pattern _ [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 KernelsMem ->- SplitOrdering ->- w ->- i ->- elems_per_thread ->- ImpM lore r op ()-splitSpace (Pattern [] [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- computeThreadChunkSize o i' elems_per_thread' num_elements (mkTV (patElemName size) int64)-splitSpace pat _ _ _ _ =- error $ "Invalid target for splitSpace: " ++ pretty pat--updateAcc :: VName -> [SubExp] -> [SubExp] -> InKernelGen ()-updateAcc acc is vs = sComment "UpdateAcc" $ do- -- 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) $- case op of- Nothing ->- forM_ (zip arrs vs) $ \(arr, v) -> copyDWIMFix arr is' v []- Just lam -> do- dLParams $ lambdaParams lam- let (_x_params, y_params) =- splitAt (length vs) $ map paramName $ lambdaParams lam- forM_ (zip y_params vs) $ \(yp, v) -> copyDWIM yp [] v []- atomics <- kernelAtomics <$> askEnv- case atomicUpdateLocking atomics lam of- AtomicPrim f -> f space arrs is'- AtomicCAS f -> f space arrs is'- AtomicLocking f -> do- c_locks <- M.lookup c . kernelLocks <$> askEnv- case c_locks of- Just (Locks locks num_locks) -> do- let locking =- Locking locks 0 1 0 $- pure . (`rem` fromIntegral num_locks) . flattenIndex dims- f locking space arrs is'- Nothing ->- error $ "Missing locks for " ++ pretty acc--compileThreadExp :: ExpCompiler KernelsMem KernelEnv Imp.KernelOp-compileThreadExp (Pattern _ [dest]) (BasicOp (ArrayLit es _)) =- forM_ (zip [0 ..] es) $ \(i, e) ->- copyDWIMFix (patElemName dest) [fromIntegral (i :: Int64)] e []-compileThreadExp _ (BasicOp (UpdateAcc acc is vs)) =- updateAcc acc is vs-compileThreadExp dest e =- defCompileExp dest e---- | Assign iterations of a for-loop to all threads in the kernel.--- The passed-in function is invoked with the (symbolic) iteration.--- 'threadOperations' will be in effect in the body. For--- multidimensional loops, use 'groupCoverSpace'.-kernelLoop ::- IntExp t =>- Imp.TExp t ->- Imp.TExp t ->- Imp.TExp t ->- (Imp.TExp t -> InKernelGen ()) ->- InKernelGen ()-kernelLoop tid num_threads n f =- localOps threadOperations $- if n == num_threads- then f tid- else do- -- Compute how many elements this thread is responsible for.- -- Formula: (n - tid) / num_threads (rounded up).- let elems_for_this = (n - tid) `divUp` num_threads-- sFor "i" elems_for_this $ \i -> f $ i * num_threads + tid---- | Assign iterations of a for-loop to threads in the workgroup. The--- passed-in function is invoked with the (symbolic) iteration. For--- multidimensional loops, use 'groupCoverSpace'.-groupLoop ::- Imp.TExp Int64 ->- (Imp.TExp Int64 -> InKernelGen ()) ->- InKernelGen ()-groupLoop n f = do- constants <- kernelConstants <$> askEnv- kernelLoop- (sExt64 $ kernelLocalThreadId constants)- (kernelGroupSize constants)- n- f---- | Iterate collectively though a multidimensional space, such that--- all threads in the group participate. The passed-in function is--- invoked with a (symbolic) point in the index space.-groupCoverSpace ::- [Imp.TExp Int64] ->- ([Imp.TExp Int64] -> InKernelGen ()) ->- InKernelGen ()-groupCoverSpace ds f =- groupLoop (product ds) $ f . unflattenIndex ds--compileGroupExp :: ExpCompiler KernelsMem KernelEnv Imp.KernelOp--- The static arrays stuff does not work inside kernels.-compileGroupExp (Pattern _ [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- 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- n' <- toExp n- e' <- toExp e- s' <- toExp s- groupLoop (TPrimExp n') $ \i' -> do- x <-- dPrimV "x" $- TPrimExp $- BinOpExp (Add it OverflowUndef) e' $- BinOpExp (Mul it OverflowUndef) (untyped i') s'- copyDWIMFix (patElemName dest) [i'] (Var (tvVar x)) []- sOp $ Imp.Barrier Imp.FenceLocal---- When generating code for a scalar in-place update, we must make--- 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))- | null $ sliceDims slice = do- sOp $ Imp.Barrier Imp.FenceLocal- ltid <- kernelLocalThreadId . kernelConstants <$> askEnv- sWhen (ltid .==. 0) $- copyDWIM (patElemName pe) (map (fmap toInt64Exp) slice) se []- sOp $ Imp.Barrier Imp.FenceLocal-compileGroupExp dest e =- defCompileExp dest e--sanityCheckLevel :: SegLevel -> InKernelGen ()-sanityCheckLevel SegThread {} = return ()-sanityCheckLevel SegGroup {} =- error "compileGroupOp: unexpected group-level SegOp."--localThreadIDs :: [SubExp] -> InKernelGen [Imp.TExp Int64]-localThreadIDs dims = do- ltid <- sExt64 . kernelLocalThreadId . kernelConstants <$> askEnv- let dims' = map toInt64Exp dims- maybe (unflattenIndex dims' ltid) (map sExt64)- . M.lookup dims- . kernelLocalIdMap- . kernelConstants- <$> askEnv--compileGroupSpace :: SegLevel -> SegSpace -> InKernelGen ()-compileGroupSpace lvl space = do- sanityCheckLevel lvl- let (ltids, dims) = unzip $ unSegSpace space- zipWithM_ dPrimV_ ltids =<< localThreadIDs dims- ltid <- kernelLocalThreadId . kernelConstants <$> askEnv- dPrimV_ (segFlat space) ltid---- Construct the necessary lock arrays for an intra-group histogram.-prepareIntraGroupSegHist ::- Count GroupSize SubExp ->- [HistOp KernelsMem] ->- InKernelGen [[Imp.TExp Int64] -> InKernelGen ()]-prepareIntraGroupSegHist group_size =- fmap snd . mapAccumLM onOp Nothing- where- onOp l op = do- constants <- kernelConstants <$> askEnv- atomicBinOp <- kernelAtomics <$> askEnv-- let local_subhistos = histDest op-- case (l, atomicUpdateLocking atomicBinOp $ histOp op) of- (_, AtomicPrim f) -> return (l, f (Space "local") local_subhistos)- (_, AtomicCAS f) -> return (l, f (Space "local") local_subhistos)- (Just l', AtomicLocking f) -> return (l, f l' (Space "local") local_subhistos)- (Nothing, AtomicLocking f) -> do- locks <- newVName "locks"-- let num_locks = toInt64Exp $ unCount group_size- dims = map toInt64Exp $ shapeDims (histShape op) ++ [histWidth op]- l' = Locking locks 0 1 0 (pure . (`rem` num_locks) . flattenIndex dims)- locks_t = Array int32 (Shape [unCount group_size]) NoUniqueness-- locks_mem <- sAlloc "locks_mem" (typeSize locks_t) $ Space "local"- dArray locks int32 (arrayShape locks_t) $- ArrayIn locks_mem $- IxFun.iota $- map pe64 $ arrayDims locks_t-- sComment "All locks start out unlocked" $- groupCoverSpace [kernelGroupSize constants] $ \is ->- copyDWIMFix locks is (intConst Int32 0) []-- return (Just l', f l' (Space "local") local_subhistos)--whenActive :: SegLevel -> SegSpace -> InKernelGen () -> InKernelGen ()-whenActive lvl space m- | SegNoVirtFull <- segVirt lvl = m- | otherwise = do- group_size <- kernelGroupSize . kernelConstants <$> askEnv- -- XXX: the following check is too naive - we should also handle- -- the multi-dimensional case.- if [group_size] == map (toInt64Exp . snd) (unSegSpace space)- then m- else sWhen (isActive $ unSegSpace space) m--compileGroupOp :: OpCompiler KernelsMem KernelEnv Imp.KernelOp-compileGroupOp pat (Alloc size space) =- kernelAlloc pat size space-compileGroupOp pat (Inner (SizeOp (SplitSpace o w i elems_per_thread))) =- splitSpace pat o w i elems_per_thread-compileGroupOp pat (Inner (SegOp (SegMap lvl space _ body))) = do- void $ compileGroupSpace lvl space-- whenActive lvl space $- localOps threadOperations $- compileStms mempty (kernelBodyStms body) $- zipWithM_ (compileThreadResult space) (patternElements pat) $- kernelBodyResult body-- sOp $ Imp.ErrorSync Imp.FenceLocal-compileGroupOp pat (Inner (SegOp (SegScan lvl space scans _ body))) = do- compileGroupSpace lvl space- let (ltids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims-- whenActive lvl space $- compileStms mempty (kernelBodyStms body) $- forM_ (zip (patternNames pat) $ kernelBodyResult body) $ \(dest, res) ->- copyDWIMFix- dest- (map Imp.vi64 ltids)- (kernelResultSubExp res)- []-- sOp $ Imp.ErrorSync Imp.FenceLocal-- let segment_size = last dims'- crossesSegment from to =- (sExt64 to - sExt64 from) .>. (sExt64 to `rem` segment_size)-- -- groupScan needs to treat the scan output as a one-dimensional- -- array of scan elements, so we invent some new flattened arrays- -- here. XXX: this assumes that the original index function is just- -- 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)- let pe_t = typeOf pe- arr_dims = Var (tvVar dims_flat) : drop (length dims') (arrayDims pe_t)- sArray- (baseString (patElemName pe) ++ "_flat")- (elemType pe_t)- (Shape arr_dims)- $ ArrayIn mem $ IxFun.iota $ map pe64 arr_dims-- num_scan_results = sum $ map (length . segBinOpNeutral) scans-- arrs_flat <- mapM flattened $ take num_scan_results $ patternElements pat-- forM_ scans $ \scan -> do- let scan_op = segBinOpLambda scan- groupScan (Just crossesSegment) (product dims') (product dims') scan_op arrs_flat-compileGroupOp pat (Inner (SegOp (SegRed lvl space ops _ body))) = do- compileGroupSpace lvl space-- let (ltids, dims) = unzip $ unSegSpace space- (red_pes, map_pes) =- splitAt (segBinOpResults ops) $ patternElements pat-- dims' = map toInt64Exp dims-- mkTempArr t =- sAllocArray "red_arr" (elemType t) (Shape dims <> arrayShape t) $ Space "local"-- tmp_arrs <- mapM mkTempArr $ concatMap (lambdaReturnType . segBinOpLambda) ops- let tmps_for_ops = chunks (map (length . segBinOpNeutral) ops) tmp_arrs-- whenActive lvl space $- compileStms mempty (kernelBodyStms body) $ do- let (red_res, map_res) =- splitAt (segBinOpResults ops) $ kernelBodyResult body- forM_ (zip tmp_arrs red_res) $ \(dest, res) ->- copyDWIMFix dest (map Imp.vi64 ltids) (kernelResultSubExp res) []- zipWithM_ (compileThreadResult space) map_pes map_res-- sOp $ Imp.ErrorSync Imp.FenceLocal-- case dims' of- -- Nonsegmented case (or rather, a single segment) - this we can- -- handle directly with a group-level reduction.- [dim'] -> do- forM_ (zip ops tmps_for_ops) $ \(op, tmps) ->- groupReduce (sExt32 dim') (segBinOpLambda op) tmps-- sOp $ Imp.ErrorSync Imp.FenceLocal-- forM_ (zip red_pes tmp_arrs) $ \(pe, arr) ->- copyDWIMFix (patElemName pe) [] (Var arr) [0]- _ -> do- -- Segmented intra-group reductions are turned into (regular)- -- segmented scans. It is possible that this can be done- -- better, but at least this approach is simple.-- -- groupScan operates on flattened arrays. This does not- -- involve copying anything; merely playing with the index- -- function.- dims_flat <- dPrimV "dims_flat" $ product dims'- let flatten arr = do- ArrayEntry arr_loc pt <- lookupArray arr- let flat_shape =- Shape $- Var (tvVar dims_flat) :- drop (length ltids) (memLocationShape arr_loc)- sArray "red_arr_flat" pt flat_shape $- ArrayIn (memLocationName arr_loc) $- IxFun.iota $ map pe64 $ shapeDims flat_shape-- let segment_size = last dims'- crossesSegment from to =- (sExt64 to - sExt64 from) .>. (sExt64 to `rem` sExt64 segment_size)-- forM_ (zip ops tmps_for_ops) $ \(op, tmps) -> do- tmps_flat <- mapM flatten tmps- groupScan- (Just crossesSegment)- (product dims')- (product dims')- (segBinOpLambda op)- tmps_flat-- sOp $ Imp.ErrorSync Imp.FenceLocal-- forM_ (zip red_pes tmp_arrs) $ \(pe, arr) ->- copyDWIM- (patElemName pe)- []- (Var arr)- (map (unitSlice 0) (init dims') ++ [DimFix $ last dims' -1])-- sOp $ Imp.Barrier Imp.FenceLocal-compileGroupOp pat (Inner (SegOp (SegHist lvl space ops _ kbody))) = do- compileGroupSpace lvl space- let ltids = map fst $ unSegSpace space-- -- We don't need the red_pes, because it is guaranteed by our type- -- rules that they occupy the same memory as the destinations for- -- the ops.- let num_red_res = length ops + sum (map (length . histNeutral) ops)- (_red_pes, map_pes) =- splitAt num_red_res $ patternElements pat-- ops' <- prepareIntraGroupSegHist (segGroupSize lvl) ops-- -- Ensure that all locks have been initialised.- sOp $ Imp.Barrier Imp.FenceLocal-- whenActive lvl space $- compileStms mempty (kernelBodyStms kbody) $ do- let (red_res, map_res) = splitAt num_red_res $ kernelBodyResult kbody- (red_is, red_vs) = splitAt (length ops) $ map kernelResultSubExp red_res- zipWithM_ (compileThreadResult space) map_pes map_res-- let vs_per_op = chunks (map (length . histDest) ops) red_vs-- forM_ (zip4 red_is vs_per_op ops' ops) $- \(bin, op_vs, do_op, HistOp dest_w _ _ _ shape lam) -> do- let bin' = toInt64Exp bin- dest_w' = toInt64Exp dest_w- bin_in_bounds = 0 .<=. bin' .&&. bin' .<. dest_w'- bin_is = map Imp.vi64 (init ltids) ++ [bin']- vs_params = takeLast (length op_vs) $ lambdaParams lam-- sComment "perform atomic updates" $- sWhen bin_in_bounds $ do- dLParams $ lambdaParams lam- sLoopNest shape $ \is -> do- forM_ (zip vs_params op_vs) $ \(p, v) ->- copyDWIMFix (paramName p) [] v is- do_op (bin_is ++ is)-- sOp $ Imp.ErrorSync Imp.FenceLocal-compileGroupOp pat _ =- compilerBugS $ "compileGroupOp: cannot compile rhs of binding " ++ pretty pat--compileThreadOp :: OpCompiler KernelsMem KernelEnv Imp.KernelOp-compileThreadOp pat (Alloc size space) =- kernelAlloc pat size space-compileThreadOp pat (Inner (SizeOp (SplitSpace o w i elems_per_thread))) =- splitSpace pat o w i elems_per_thread-compileThreadOp pat _ =- compilerBugS $ "compileThreadOp: cannot compile rhs of binding " ++ pretty pat---- | Locking strategy used for an atomic update.-data Locking = Locking- { -- | Array containing the lock.- lockingArray :: VName,- -- | Value for us to consider the lock free.- lockingIsUnlocked :: Imp.TExp Int32,- -- | What to write when we lock it.- lockingToLock :: Imp.TExp Int32,- -- | What to write when we unlock it.- lockingToUnlock :: Imp.TExp Int32,- -- | A transformation from the logical lock index to the- -- physical position in the array. This can also be used- -- to make the lock array smaller.- lockingMapping :: [Imp.TExp Int64] -> [Imp.TExp Int64]- }---- | A function for generating code for an atomic update. Assumes--- that the bucket is in-bounds.-type DoAtomicUpdate lore r =- Space -> [VName] -> [Imp.TExp Int64] -> ImpM lore r Imp.KernelOp ()---- | The mechanism that will be used for performing the atomic update.--- Approximates how efficient it will be. Ordered from most to least--- efficient.-data AtomicUpdate lore r- = -- | Supported directly by primitive.- AtomicPrim (DoAtomicUpdate lore r)- | -- | Can be done by efficient swaps.- AtomicCAS (DoAtomicUpdate lore r)- | -- | Requires explicit locking.- AtomicLocking (Locking -> DoAtomicUpdate lore r)---- | Is there an atomic t'BinOp' corresponding to this t'BinOp'?-type AtomicBinOp =- BinOp ->- Maybe (VName -> VName -> Count Imp.Elements (Imp.TExp Int64) -> Imp.Exp -> Imp.AtomicOp)---- | Do an atomic update corresponding to a binary operator lambda.-atomicUpdateLocking ::- AtomicBinOp ->- Lambda KernelsMem ->- AtomicUpdate KernelsMem KernelEnv-atomicUpdateLocking atomicBinOp lam- | Just ops_and_ts <- splitOp lam,- all (\(_, t, _, _) -> primBitSize t `elem` [32, 64]) ops_and_ts =- primOrCas ops_and_ts $ \space arrs bucket ->- -- If the operator is a vectorised binary operator on 32/64-bit- -- values, we can use a particularly efficient- -- implementation. If the operator has an atomic implementation- -- we use that, otherwise it is still a binary operator which- -- can be implemented by atomic compare-and-swap if 32/64 bits.- forM_ (zip arrs ops_and_ts) $ \(a, (op, t, x, y)) -> do- -- Common variables.- old <- dPrim "old" t-- (arr', _a_space, bucket_offset) <- fullyIndexArray a bucket-- case opHasAtomicSupport space (tvVar old) arr' bucket_offset op of- Just f -> sOp $ f $ Imp.var y t- Nothing ->- atomicUpdateCAS space t a (tvVar old) bucket x $- x <~~ Imp.BinOpExp op (Imp.var x t) (Imp.var y t)- where- opHasAtomicSupport space old arr' bucket' bop = do- let atomic f = Imp.Atomic space . f old arr' bucket'- atomic <$> atomicBinOp bop-- primOrCas ops- | all isPrim ops = AtomicPrim- | otherwise = AtomicCAS-- isPrim (op, _, _, _) = isJust $ atomicBinOp op---- If the operator functions purely on single 32/64-bit values, we can--- use an implementation based on CAS, no matter what the operator--- does.-atomicUpdateLocking _ op- | [Prim t] <- lambdaReturnType op,- [xp, _] <- lambdaParams op,- primBitSize t `elem` [32, 64] = AtomicCAS $ \space [arr] bucket -> do- old <- dPrim "old" t- atomicUpdateCAS space t arr (tvVar old) bucket (paramName xp) $- compileBody' [xp] $ lambdaBody op-atomicUpdateLocking _ op = AtomicLocking $ \locking space arrs bucket -> do- old <- dPrim "old" int32- continue <- dPrimVol "continue" Bool true-- -- Correctly index into locks.- (locks', _locks_space, locks_offset) <-- fullyIndexArray (lockingArray locking) $ lockingMapping locking bucket-- -- Critical section- let try_acquire_lock =- sOp $- Imp.Atomic space $- Imp.AtomicCmpXchg- int32- (tvVar old)- locks'- locks_offset- (untyped $ lockingIsUnlocked locking)- (untyped $ lockingToLock locking)- lock_acquired = tvExp old .==. lockingIsUnlocked locking- -- Even the releasing is done with an atomic rather than a- -- simple write, for memory coherency reasons.- release_lock =- sOp $- Imp.Atomic space $- Imp.AtomicCmpXchg- int32- (tvVar old)- locks'- locks_offset- (untyped $ lockingToLock locking)- (untyped $ lockingToUnlock locking)- break_loop = continue <-- false-- -- Preparing parameters. It is assumed that the caller has already- -- filled the arr_params. We copy the current value to the- -- accumulator parameters.- --- -- Note the use of 'everythingVolatile' when reading and writing the- -- buckets. This was necessary to ensure correct execution on a- -- newer NVIDIA GPU (RTX 2080). The 'volatile' modifiers likely- -- make the writes pass through the (SM-local) L1 cache, which is- -- necessary here, because we are really doing device-wide- -- synchronisation without atomics (naughty!).- let (acc_params, _arr_params) = splitAt (length arrs) $ lambdaParams op- bind_acc_params =- everythingVolatile $- sComment "bind lhs" $- forM_ (zip acc_params arrs) $ \(acc_p, arr) ->- copyDWIMFix (paramName acc_p) [] (Var arr) bucket-- let op_body =- sComment "execute operation" $- compileBody' acc_params $ lambdaBody op-- do_hist =- everythingVolatile $- sComment "update global result" $- zipWithM_ (writeArray bucket) arrs $ map (Var . paramName) acc_params-- fence = case space of- Space "local" -> sOp $ Imp.MemFence Imp.FenceLocal- _ -> sOp $ Imp.MemFence Imp.FenceGlobal-- -- While-loop: Try to insert your value- sWhile (tvExp continue) $ do- try_acquire_lock- sWhen lock_acquired $ do- dLParams acc_params- bind_acc_params- op_body- do_hist- fence- release_lock- break_loop- fence- where- writeArray bucket arr val = copyDWIMFix arr bucket val []--atomicUpdateCAS ::- Space ->- PrimType ->- VName ->- VName ->- [Imp.TExp Int64] ->- VName ->- InKernelGen () ->- InKernelGen ()-atomicUpdateCAS space t arr old bucket x do_op = do- -- Code generation target:- --- -- old = d_his[idx];- -- do {- -- assumed = old;- -- x = do_op(assumed, y);- -- old = atomicCAS(&d_his[idx], assumed, tmp);- -- } while(assumed != old);- assumed <- tvVar <$> dPrim "assumed" t- run_loop <- dPrimV "run_loop" true-- -- XXX: CUDA may generate really bad code if this is not a volatile- -- read. Unclear why. The later reads are volatile, so maybe- -- that's it.- everythingVolatile $ copyDWIMFix old [] (Var arr) bucket-- (arr', _a_space, bucket_offset) <- fullyIndexArray arr bucket-- -- While-loop: Try to insert your value- let (toBits, fromBits) =- case t of- FloatType Float32 ->- ( \v -> Imp.FunExp "to_bits32" [v] int32,- \v -> Imp.FunExp "from_bits32" [v] t- )- FloatType Float64 ->- ( \v -> Imp.FunExp "to_bits64" [v] int64,- \v -> Imp.FunExp "from_bits64" [v] t- )- _ -> (id, id)-- int- | primBitSize t == 32 = int32- | otherwise = int64-- sWhile (tvExp run_loop) $ do- assumed <~~ Imp.var old t- x <~~ Imp.var assumed t- do_op- old_bits_v <- newVName "old_bits"- dPrim_ old_bits_v int- let old_bits = Imp.var old_bits_v int- sOp $- Imp.Atomic space $- Imp.AtomicCmpXchg- int- old_bits_v- arr'- bucket_offset- (toBits (Imp.var assumed t))- (toBits (Imp.var x t))- old <~~ fromBits old_bits- let won = CmpOpExp (CmpEq int) (toBits (Imp.var assumed t)) old_bits- sWhen (isBool won) (run_loop <-- false)---- | Horizontally fission a lambda that models a binary operator.-splitOp :: ASTLore lore => Lambda lore -> Maybe [(BinOp, PrimType, VName, VName)]-splitOp 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) $- stmsToList $ bodyStms $ lambdaBody lam- i <- Var res `elemIndex` bodyResult (lambdaBody lam)- xp <- maybeNth i $ lambdaParams lam- yp <- maybeNth (n + i) $ lambdaParams lam- guard $ paramName xp == x- guard $ paramName yp == y- Prim t <- Just $ patElemType pe- return (op, t, paramName xp, paramName yp)- splitStm _ = Nothing--computeKernelUses ::- FreeIn a =>- a ->- [VName] ->- CallKernelGen [Imp.KernelUse]-computeKernelUses kernel_body bound_in_kernel = do- let actually_free = freeIn kernel_body `namesSubtract` namesFromList bound_in_kernel- -- Compute the variables that we need to pass to the kernel.- nubOrd <$> readsFromSet actually_free--readsFromSet :: Names -> CallKernelGen [Imp.KernelUse]-readsFromSet free =- fmap catMaybes $- forM (namesToList free) $ \var -> do- t <- lookupType var- vtable <- getVTable- case t of- Array {} -> return Nothing- Acc {} -> return Nothing- Mem (Space "local") -> return Nothing- Mem {} -> return $ Just $ Imp.MemoryUse var- Prim bt ->- isConstExp vtable (Imp.var var bt) >>= \case- Just ce -> return $ Just $ Imp.ConstUse var ce- Nothing -> return $ Just $ Imp.ScalarUse var bt--isConstExp ::- VTable KernelsMem ->- Imp.Exp ->- ImpM lore r op (Maybe Imp.KernelConstExp)-isConstExp vtable size = do- fname <- askFunction- let onLeaf (Imp.ScalarVar name) _ = lookupConstExp name- onLeaf Imp.Index {} _ = Nothing- lookupConstExp name =- constExp =<< hasExp =<< M.lookup name vtable- constExp (Op (Inner (SizeOp (GetSize key _)))) =- Just $ LeafExp (Imp.SizeConst $ keyWithEntryPoint fname key) int32- constExp e = primExpFromExp lookupConstExp e- return $ replaceInPrimExpM onLeaf size- where- hasExp (ArrayVar e _) = e- hasExp (AccVar e _) = e- hasExp (ScalarVar e _) = e- hasExp (MemVar e _) = e--computeThreadChunkSize ::- SplitOrdering ->- Imp.TExp Int64 ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- TV Int64 ->- ImpM lore r op ()-computeThreadChunkSize (SplitStrided stride) thread_index elements_per_thread num_elements chunk_var =- chunk_var- <-- sMin64- (Imp.unCount elements_per_thread)- ((Imp.unCount num_elements - thread_index) `divUp` toInt64Exp stride)-computeThreadChunkSize SplitContiguous thread_index elements_per_thread num_elements chunk_var = do- starting_point <-- dPrimV "starting_point" $- thread_index * Imp.unCount elements_per_thread- remaining_elements <-- dPrimV "remaining_elements" $- Imp.unCount num_elements - tvExp starting_point-- let no_remaining_elements = tvExp remaining_elements .<=. 0- beyond_bounds = Imp.unCount num_elements .<=. tvExp starting_point-- sIf- (no_remaining_elements .||. beyond_bounds)- (chunk_var <-- 0)- ( sIf- is_last_thread- (chunk_var <-- Imp.unCount last_thread_elements)- (chunk_var <-- Imp.unCount elements_per_thread)- )- where- last_thread_elements =- num_elements - Imp.elements thread_index * elements_per_thread- is_last_thread =- Imp.unCount num_elements- .<. (thread_index + 1) * Imp.unCount elements_per_thread--kernelInitialisationSimple ::- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- CallKernelGen (KernelConstants, InKernelGen ())-kernelInitialisationSimple (Count num_groups) (Count group_size) = do- global_tid <- newVName "global_tid"- local_tid <- newVName "local_tid"- group_id <- newVName "group_tid"- wave_size <- newVName "wave_size"- inner_group_size <- newVName "group_size"- let constants =- KernelConstants- (Imp.vi32 global_tid)- (Imp.vi32 local_tid)- (Imp.vi32 group_id)- global_tid- local_tid- group_id- num_groups- group_size- (sExt32 (group_size * num_groups))- (Imp.vi32 wave_size)- true- mempty-- let set_constants = do- dPrim_ global_tid int32- dPrim_ local_tid int32- dPrim_ inner_group_size int64- dPrim_ wave_size int32- dPrim_ group_id int32-- sOp (Imp.GetGlobalId global_tid 0)- sOp (Imp.GetLocalId local_tid 0)- sOp (Imp.GetLocalSize inner_group_size 0)- sOp (Imp.GetLockstepWidth wave_size)- sOp (Imp.GetGroupId group_id 0)-- return (constants, set_constants)--isActive :: [(VName, SubExp)] -> Imp.TExp Bool-isActive limit = case actives of- [] -> true- x : xs -> foldl (.&&.) x xs- where- (is, ws) = unzip limit- actives = zipWith active is $ map toInt64Exp ws- active i = (Imp.vi64 i .<.)---- | Change every memory block to be in the global address space,--- except those who are in the local memory space. This only affects--- generated code - we still need to make sure that the memory is--- actually present on the device (and dared as variables in the--- kernel).-makeAllMemoryGlobal :: CallKernelGen a -> CallKernelGen a-makeAllMemoryGlobal =- localDefaultSpace (Imp.Space "global") . localVTable (M.map globalMemory)- where- globalMemory (MemVar _ entry)- | entryMemSpace entry /= Space "local" =- MemVar Nothing entry {entryMemSpace = Imp.Space "global"}- globalMemory entry =- entry--groupReduce ::- Imp.TExp Int32 ->- Lambda KernelsMem ->- [VName] ->- InKernelGen ()-groupReduce w lam arrs = do- offset <- dPrim "offset" int32- groupReduceWithOffset offset w lam arrs--groupReduceWithOffset ::- TV Int32 ->- Imp.TExp Int32 ->- Lambda KernelsMem ->- [VName] ->- InKernelGen ()-groupReduceWithOffset offset w lam arrs = do- constants <- kernelConstants <$> askEnv-- let local_tid = kernelLocalThreadId constants- global_tid = kernelGlobalThreadId constants-- barrier- | all primType $ lambdaReturnType lam = sOp $ Imp.Barrier Imp.FenceLocal- | otherwise = sOp $ Imp.Barrier Imp.FenceGlobal-- readReduceArgument param arr- | Prim _ <- paramType param = do- let i = local_tid + tvExp offset- copyDWIMFix (paramName param) [] (Var arr) [sExt64 i]- | otherwise = do- let i = global_tid + tvExp offset- copyDWIMFix (paramName param) [] (Var arr) [sExt64 i]-- writeReduceOpResult param arr- | Prim _ <- paramType param =- copyDWIMFix arr [sExt64 local_tid] (Var $ paramName param) []- | otherwise =- return ()-- let (reduce_acc_params, reduce_arr_params) = splitAt (length arrs) $ lambdaParams lam-- skip_waves <- dPrimV "skip_waves" (1 :: Imp.TExp Int32)- dLParams $ lambdaParams lam-- offset <-- (0 :: Imp.TExp Int32)-- comment "participating threads read initial accumulator" $- sWhen (local_tid .<. w) $- zipWithM_ readReduceArgument reduce_acc_params arrs-- let do_reduce = do- comment "read array element" $- zipWithM_ readReduceArgument reduce_arr_params arrs- comment "apply reduction operation" $- compileBody' reduce_acc_params $ lambdaBody lam- comment "write result of operation" $- zipWithM_ writeReduceOpResult reduce_acc_params arrs- in_wave_reduce = everythingVolatile do_reduce-- wave_size = kernelWaveSize constants- group_size = kernelGroupSize constants- wave_id = local_tid `quot` wave_size- in_wave_id = local_tid - wave_id * wave_size- num_waves = (sExt32 group_size + wave_size - 1) `quot` wave_size- arg_in_bounds = local_tid + tvExp offset .<. w-- doing_in_wave_reductions =- tvExp offset .<. wave_size- apply_in_in_wave_iteration =- (in_wave_id .&. (2 * tvExp offset - 1)) .==. 0- in_wave_reductions = do- offset <-- (1 :: Imp.TExp Int32)- sWhile doing_in_wave_reductions $ do- sWhen- (arg_in_bounds .&&. apply_in_in_wave_iteration)- in_wave_reduce- offset <-- tvExp offset * 2-- doing_cross_wave_reductions =- tvExp skip_waves .<. num_waves- is_first_thread_in_wave =- in_wave_id .==. 0- wave_not_skipped =- (wave_id .&. (2 * tvExp skip_waves - 1)) .==. 0- apply_in_cross_wave_iteration =- arg_in_bounds .&&. is_first_thread_in_wave .&&. wave_not_skipped- cross_wave_reductions =- sWhile doing_cross_wave_reductions $ do- barrier- offset <-- tvExp skip_waves * wave_size- sWhen- apply_in_cross_wave_iteration- do_reduce- skip_waves <-- tvExp skip_waves * 2-- in_wave_reductions- cross_wave_reductions--groupScan ::- Maybe (Imp.TExp Int32 -> Imp.TExp Int32 -> Imp.TExp Bool) ->- Imp.TExp Int64 ->- Imp.TExp Int64 ->- Lambda KernelsMem ->- [VName] ->- InKernelGen ()-groupScan seg_flag arrs_full_size w lam arrs = do- constants <- kernelConstants <$> askEnv- renamed_lam <- renameLambda lam-- let ltid32 = kernelLocalThreadId constants- ltid = sExt64 ltid32- (x_params, y_params) = splitAt (length arrs) $ lambdaParams lam-- dLParams (lambdaParams lam ++ lambdaParams renamed_lam)-- ltid_in_bounds <- dPrimVE "ltid_in_bounds" $ ltid .<. w-- -- The scan works by splitting the group into blocks, which are- -- scanned separately. Typically, these blocks are smaller than- -- the lockstep width, which enables barrier-free execution inside- -- them.- --- -- We hardcode the block size here. The only requirement is that- -- it should not be less than the square root of the group size.- -- With 32, we will work on groups of size 1024 or smaller, which- -- fits every device Troels has seen. Still, it would be nicer if- -- it were a runtime parameter. Some day.- let block_size = 32- simd_width = kernelWaveSize constants- block_id = ltid32 `quot` block_size- in_block_id = ltid32 - block_id * block_size- doInBlockScan seg_flag' active =- inBlockScan- constants- seg_flag'- arrs_full_size- simd_width- block_size- active- arrs- barrier- array_scan = not $ all primType $ lambdaReturnType lam- barrier- | array_scan =- sOp $ Imp.Barrier Imp.FenceGlobal- | otherwise =- sOp $ Imp.Barrier Imp.FenceLocal-- group_offset = sExt64 (kernelGroupId constants) * kernelGroupSize constants-- writeBlockResult p arr- | primType $ paramType p =- copyDWIM arr [DimFix $ sExt64 block_id] (Var $ paramName p) []- | otherwise =- copyDWIM arr [DimFix $ group_offset + sExt64 block_id] (Var $ paramName p) []-- readPrevBlockResult p arr- | primType $ paramType p =- copyDWIM (paramName p) [] (Var arr) [DimFix $ sExt64 block_id - 1]- | otherwise =- copyDWIM (paramName p) [] (Var arr) [DimFix $ group_offset + sExt64 block_id - 1]-- doInBlockScan seg_flag ltid_in_bounds lam- barrier-- let is_first_block = block_id .==. 0- when array_scan $ do- sComment "save correct values for first block" $- sWhen is_first_block $- forM_ (zip x_params arrs) $ \(x, arr) ->- unless (primType $ paramType x) $- copyDWIM arr [DimFix $ arrs_full_size + group_offset + sExt64 block_size + ltid] (Var $ paramName x) []-- barrier-- let last_in_block = in_block_id .==. block_size - 1- sComment "last thread of block 'i' writes its result to offset 'i'" $- sWhen (last_in_block .&&. ltid_in_bounds) $- everythingVolatile $- zipWithM_ writeBlockResult x_params arrs-- barrier-- let first_block_seg_flag = do- flag_true <- seg_flag- Just $ \from to ->- flag_true (from * block_size + block_size -1) (to * block_size + block_size -1)- comment- "scan the first block, after which offset 'i' contains carry-in for block 'i+1'"- $ doInBlockScan first_block_seg_flag (is_first_block .&&. ltid_in_bounds) renamed_lam-- barrier-- when array_scan $ do- sComment "move correct values for first block back a block" $- sWhen is_first_block $- forM_ (zip x_params arrs) $ \(x, arr) ->- unless (primType $ paramType x) $- copyDWIM- arr- [DimFix $ arrs_full_size + group_offset + ltid]- (Var arr)- [DimFix $ arrs_full_size + group_offset + sExt64 block_size + ltid]-- barrier-- let read_carry_in = do- forM_ (zip x_params y_params) $ \(x, y) ->- copyDWIM (paramName y) [] (Var (paramName x)) []- zipWithM_ readPrevBlockResult x_params arrs-- y_to_x = forM_ (zip x_params y_params) $ \(x, y) ->- when (primType (paramType x)) $- copyDWIM (paramName x) [] (Var (paramName y)) []-- op_to_x- | Nothing <- seg_flag =- compileBody' x_params $ lambdaBody lam- | Just flag_true <- seg_flag = do- inactive <-- dPrimVE "inactive" $ flag_true (block_id * block_size -1) ltid32- sWhen inactive y_to_x- when array_scan barrier- sUnless inactive $ compileBody' x_params $ lambdaBody lam-- write_final_result =- forM_ (zip x_params arrs) $ \(p, arr) ->- when (primType $ paramType p) $- copyDWIM arr [DimFix ltid] (Var $ paramName p) []-- sComment "carry-in for every block except the first" $- sUnless (is_first_block .||. bNot ltid_in_bounds) $ do- sComment "read operands" read_carry_in- sComment "perform operation" op_to_x- sComment "write final result" write_final_result-- barrier-- sComment "restore correct values for first block" $- sWhen is_first_block $- forM_ (zip3 x_params y_params arrs) $ \(x, y, arr) ->- if primType (paramType y)- then copyDWIM arr [DimFix ltid] (Var $ paramName y) []- else copyDWIM (paramName x) [] (Var arr) [DimFix $ arrs_full_size + group_offset + ltid]-- barrier--inBlockScan ::- KernelConstants ->- Maybe (Imp.TExp Int32 -> Imp.TExp Int32 -> Imp.TExp Bool) ->- Imp.TExp Int64 ->- Imp.TExp Int32 ->- Imp.TExp Int32 ->- Imp.TExp Bool ->- [VName] ->- InKernelGen () ->- Lambda KernelsMem ->- InKernelGen ()-inBlockScan constants seg_flag arrs_full_size lockstep_width block_size active arrs barrier scan_lam = everythingVolatile $ do- skip_threads <- dPrim "skip_threads" int32- let in_block_thread_active =- tvExp skip_threads .<=. in_block_id- actual_params = lambdaParams scan_lam- (x_params, y_params) =- splitAt (length actual_params `div` 2) actual_params- y_to_x =- forM_ (zip x_params y_params) $ \(x, y) ->- when (primType (paramType x)) $- copyDWIM (paramName x) [] (Var (paramName y)) []-- -- Set initial y values- sComment "read input for in-block scan" $- sWhen active $ do- zipWithM_ readInitial y_params arrs- -- Since the final result is expected to be in x_params, we may- -- need to copy it there for the first thread in the block.- sWhen (in_block_id .==. 0) y_to_x-- when array_scan barrier-- let op_to_x- | Nothing <- seg_flag =- compileBody' x_params $ lambdaBody scan_lam- | Just flag_true <- seg_flag = do- inactive <-- dPrimVE "inactive" $- flag_true (ltid32 - tvExp skip_threads) ltid32- sWhen inactive y_to_x- when array_scan barrier- sUnless inactive $ compileBody' x_params $ lambdaBody scan_lam-- maybeBarrier =- sWhen- (lockstep_width .<=. tvExp skip_threads)- barrier-- sComment "in-block scan (hopefully no barriers needed)" $ do- skip_threads <-- 1- sWhile (tvExp skip_threads .<. block_size) $ do- sWhen (in_block_thread_active .&&. active) $ do- sComment "read operands" $- zipWithM_ (readParam (sExt64 $ tvExp skip_threads)) x_params arrs- sComment "perform operation" op_to_x-- maybeBarrier-- sWhen (in_block_thread_active .&&. active) $- sComment "write result" $- sequence_ $ zipWith3 writeResult x_params y_params arrs-- maybeBarrier-- skip_threads <-- tvExp skip_threads * 2- where- block_id = ltid32 `quot` block_size- in_block_id = ltid32 - block_id * block_size- ltid32 = kernelLocalThreadId constants- ltid = sExt64 ltid32- gtid = sExt64 $ kernelGlobalThreadId constants- array_scan = not $ all primType $ lambdaReturnType scan_lam-- readInitial p arr- | primType $ paramType p =- copyDWIM (paramName p) [] (Var arr) [DimFix ltid]- | otherwise =- copyDWIM (paramName p) [] (Var arr) [DimFix gtid]-- readParam behind p arr- | primType $ paramType p =- copyDWIM (paramName p) [] (Var arr) [DimFix $ ltid - behind]- | otherwise =- copyDWIM (paramName p) [] (Var arr) [DimFix $ gtid - behind + arrs_full_size]-- writeResult x y arr- | primType $ paramType x = do- copyDWIM arr [DimFix ltid] (Var $ paramName x) []- copyDWIM (paramName y) [] (Var $ paramName x) []- | otherwise =- copyDWIM (paramName y) [] (Var $ paramName x) []--computeMapKernelGroups :: Imp.TExp Int64 -> CallKernelGen (Imp.TExp Int64, Imp.TExp Int64)-computeMapKernelGroups kernel_size = do- group_size <- dPrim "group_size" int64- fname <- askFunction- let group_size_key = keyWithEntryPoint fname $ nameFromString $ pretty $ tvVar group_size- sOp $ Imp.GetSize (tvVar group_size) group_size_key Imp.SizeGroup- num_groups <- dPrimV "num_groups" $ kernel_size `divUp` tvExp group_size- return (tvExp num_groups, tvExp group_size)--simpleKernelConstants ::- Imp.TExp Int64 ->- String ->- CallKernelGen (KernelConstants, InKernelGen ())-simpleKernelConstants kernel_size desc = do- thread_gtid <- newVName $ desc ++ "_gtid"- thread_ltid <- newVName $ desc ++ "_ltid"- group_id <- newVName $ desc ++ "_gid"- (num_groups, group_size) <- computeMapKernelGroups kernel_size- let set_constants = do- dPrim_ thread_gtid int32- dPrim_ thread_ltid int32- dPrim_ group_id int32- sOp (Imp.GetGlobalId thread_gtid 0)- sOp (Imp.GetLocalId thread_ltid 0)- sOp (Imp.GetGroupId group_id 0)-- return- ( KernelConstants- (Imp.vi32 thread_gtid)- (Imp.vi32 thread_ltid)- (Imp.vi32 group_id)- thread_gtid- thread_ltid- group_id- num_groups- group_size- (sExt32 (group_size * num_groups))- 0- (Imp.vi64 thread_gtid .<. kernel_size)- mempty,- set_constants- )---- | For many kernels, we may not have enough physical groups to cover--- the logical iteration space. Some groups thus have to perform--- double duty; we put an outer loop to accomplish this. The--- advantage over just launching a bazillion threads is that the cost--- of memory expansion should be proportional to the number of--- *physical* threads (hardware parallelism), not the amount of--- application parallelism.-virtualiseGroups ::- SegVirt ->- Imp.TExp Int32 ->- (Imp.TExp Int32 -> InKernelGen ()) ->- InKernelGen ()-virtualiseGroups SegVirt required_groups m = do- constants <- kernelConstants <$> askEnv- phys_group_id <- dPrim "phys_group_id" int32- sOp $ Imp.GetGroupId (tvVar phys_group_id) 0- let iterations =- (required_groups - tvExp phys_group_id)- `divUp` sExt32 (kernelNumGroups constants)-- sFor "i" iterations $ \i -> do- m . tvExp- =<< dPrimV- "virt_group_id"- (tvExp phys_group_id + i * sExt32 (kernelNumGroups constants))- -- Make sure the virtual group is actually done before we let- -- another virtual group have its way with it.- sOp $ Imp.Barrier Imp.FenceGlobal-virtualiseGroups _ _ m = do- gid <- kernelGroupIdVar . kernelConstants <$> askEnv- m $ Imp.vi32 gid--sKernelThread ::- String ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- VName ->- InKernelGen () ->- CallKernelGen ()-sKernelThread = sKernel threadOperations kernelGlobalThreadId--sKernelGroup ::- String ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- VName ->- InKernelGen () ->- CallKernelGen ()-sKernelGroup = sKernel groupOperations kernelGroupId--sKernelFailureTolerant ::- Bool ->- Operations KernelsMem KernelEnv Imp.KernelOp ->- KernelConstants ->- Name ->- InKernelGen () ->- CallKernelGen ()-sKernelFailureTolerant tol ops constants name m = do- HostEnv atomics _ locks <- askEnv- body <- makeAllMemoryGlobal $ subImpM_ (KernelEnv atomics constants locks) ops m- uses <- computeKernelUses body mempty- emit $- Imp.Op $- Imp.CallKernel- Imp.Kernel- { Imp.kernelBody = body,- Imp.kernelUses = uses,- Imp.kernelNumGroups = [untyped $ kernelNumGroups constants],- Imp.kernelGroupSize = [untyped $ kernelGroupSize constants],- Imp.kernelName = name,- Imp.kernelFailureTolerant = tol- }--sKernel ::- Operations KernelsMem KernelEnv Imp.KernelOp ->- (KernelConstants -> Imp.TExp Int32) ->- String ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- VName ->- InKernelGen () ->- CallKernelGen ()-sKernel ops flatf name num_groups group_size v f = do- (constants, set_constants) <- kernelInitialisationSimple num_groups group_size- name' <- nameForFun $ name ++ "_" ++ show (baseTag v)- sKernelFailureTolerant False ops constants name' $ do- set_constants- dPrimV_ v $ flatf constants- f--copyInGroup :: CopyCompiler KernelsMem KernelEnv Imp.KernelOp-copyInGroup pt destloc destslice srcloc srcslice = do- dest_space <- entryMemSpace <$> lookupMemory (memLocationName destloc)- src_space <- entryMemSpace <$> lookupMemory (memLocationName srcloc)-- case (dest_space, src_space) of- (ScalarSpace destds _, ScalarSpace srcds _) -> do- let destslice' =- replicate (length destslice - length destds) (DimFix 0)- ++ takeLast (length destds) destslice- srcslice' =- replicate (length srcslice - length srcds) (DimFix 0)- ++ takeLast (length srcds) srcslice- copyElementWise pt destloc destslice' srcloc srcslice'- _ -> do- groupCoverSpace (sliceDims destslice) $ \is ->- copyElementWise- pt- destloc- (map DimFix $ fixSlice destslice is)- srcloc- (map DimFix $ fixSlice srcslice is)- sOp $ Imp.Barrier Imp.FenceLocal--threadOperations, groupOperations :: Operations KernelsMem KernelEnv Imp.KernelOp-threadOperations =- (defaultOperations compileThreadOp)- { opsCopyCompiler = copyElementWise,- opsExpCompiler = compileThreadExp,- opsStmsCompiler = \_ -> defCompileStms mempty,- opsAllocCompilers =- M.fromList [(Space "local", allocLocal)]- }-groupOperations =- (defaultOperations compileGroupOp)- { opsCopyCompiler = copyInGroup,- opsExpCompiler = compileGroupExp,- opsStmsCompiler = \_ -> defCompileStms mempty,- opsAllocCompilers =- M.fromList [(Space "local", allocLocal)]- }---- | Perform a Replicate with a kernel.-sReplicateKernel :: VName -> SubExp -> CallKernelGen ()-sReplicateKernel arr se = do- t <- subExpType se- ds <- dropLast (arrayRank t) . arrayDims <$> lookupType arr-- let dims = map toInt64Exp $ ds ++ arrayDims t- (constants, set_constants) <-- simpleKernelConstants (product $ map sExt64 dims) "replicate"-- fname <- askFunction- let name =- keyWithEntryPoint fname $- nameFromString $- "replicate_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)- is' = unflattenIndex dims $ sExt64 $ kernelGlobalThreadId constants-- sKernelFailureTolerant True threadOperations constants name $ do- set_constants- sWhen (kernelThreadActive constants) $- copyDWIMFix arr is' se $ drop (length ds) is'--replicateName :: PrimType -> String-replicateName bt = "replicate_" ++ pretty bt--replicateForType :: PrimType -> CallKernelGen Name-replicateForType bt = do- let fname = nameFromString $ "builtin#" <> replicateName bt-- exists <- hasFunction fname- unless exists $ do- mem <- newVName "mem"- num_elems <- newVName "num_elems"- val <- newVName "val"-- let params =- [ Imp.MemParam mem (Space "device"),- Imp.ScalarParam num_elems int32,- Imp.ScalarParam val bt- ]- shape = Shape [Var num_elems]- function fname [] params $ do- arr <-- sArray "arr" bt shape $- ArrayIn mem $- IxFun.iota $- map pe64 $ shapeDims shape- sReplicateKernel arr $ Var val-- return fname--replicateIsFill :: VName -> SubExp -> CallKernelGen (Maybe (CallKernelGen ()))-replicateIsFill arr v = do- ArrayEntry (MemLocation arr_mem arr_shape arr_ixfun) _ <- lookupArray arr- v_t <- subExpType v- case v_t of- Prim v_t'- | IxFun.isLinear arr_ixfun -> return $- Just $ do- fname <- replicateForType v_t'- emit $- Imp.Call- []- fname- [ Imp.MemArg arr_mem,- Imp.ExpArg $ untyped $ product $ map toInt64Exp arr_shape,- Imp.ExpArg $ toExp' v_t' v- ]- _ -> return Nothing---- | Perform a Replicate with a kernel.-sReplicate :: VName -> SubExp -> CallKernelGen ()-sReplicate arr se = do- -- If the replicate is of a particularly common and simple form- -- (morally a memset()/fill), then we use a common function.- is_fill <- replicateIsFill arr se-- case is_fill of- Just m -> m- Nothing -> sReplicateKernel arr se---- | Perform an Iota with a kernel.-sIotaKernel ::- VName ->- Imp.TExp Int64 ->- Imp.Exp ->- Imp.Exp ->- IntType ->- CallKernelGen ()-sIotaKernel arr n x s et = do- destloc <- entryArrayLocation <$> lookupArray arr- (constants, set_constants) <- simpleKernelConstants n "iota"-- fname <- askFunction- let name =- keyWithEntryPoint fname $- nameFromString $- "iota_" ++ pretty et ++ "_"- ++ show (baseTag $ kernelGlobalThreadIdVar constants)-- sKernelFailureTolerant True threadOperations constants name $ do- set_constants- let gtid = sExt64 $ kernelGlobalThreadId constants- sWhen (kernelThreadActive constants) $ do- (destmem, destspace, destidx) <- fullyIndexArray' destloc [gtid]-- emit $- Imp.Write destmem destidx (IntType et) destspace Imp.Nonvolatile $- BinOpExp- (Add et OverflowWrap)- (BinOpExp (Mul et OverflowWrap) (Imp.sExt et $ untyped gtid) s)- x--iotaName :: IntType -> String-iotaName bt = "iota_" ++ pretty bt--iotaForType :: IntType -> CallKernelGen Name-iotaForType bt = do- let fname = nameFromString $ "builtin#" <> iotaName bt-- exists <- hasFunction fname- unless exists $ do- mem <- newVName "mem"- n <- newVName "n"- x <- newVName "x"- s <- newVName "s"-- let params =- [ Imp.MemParam mem (Space "device"),- Imp.ScalarParam n int32,- Imp.ScalarParam x $ IntType bt,- Imp.ScalarParam s $ IntType bt- ]- shape = Shape [Var n]- n' = Imp.vi64 n- x' = Imp.var x $ IntType bt- s' = Imp.var s $ IntType bt-- function fname [] params $ do- arr <-- sArray "arr" (IntType bt) shape $- ArrayIn mem $- IxFun.iota $- map pe64 $ shapeDims shape- sIotaKernel arr (sExt64 n') x' s' bt-- return fname---- | Perform an Iota with a kernel.-sIota ::- VName ->- Imp.TExp Int64 ->- Imp.Exp ->- Imp.Exp ->- IntType ->- CallKernelGen ()-sIota arr n x s et = do- ArrayEntry (MemLocation arr_mem _ arr_ixfun) _ <- lookupArray arr- if IxFun.isLinear arr_ixfun- then do- fname <- iotaForType et- emit $- Imp.Call- []- fname- [Imp.MemArg arr_mem, Imp.ExpArg $ untyped n, Imp.ExpArg x, Imp.ExpArg s]- else sIotaKernel arr n x s et--sCopy :: CopyCompiler KernelsMem 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-- (constants, set_constants) <- simpleKernelConstants kernel_size "copy"-- fname <- askFunction- let name =- keyWithEntryPoint fname $- nameFromString $- "copy_" ++ show (baseTag $ kernelGlobalThreadIdVar constants)-- sKernelFailureTolerant True threadOperations constants name $ do- set_constants-- let gtid = sExt64 $ kernelGlobalThreadId constants- dest_is = unflattenIndex shape gtid- src_is = dest_is-- (_, destspace, destidx) <-- fullyIndexArray' destloc $ fixSlice destslice dest_is- (_, srcspace, srcidx) <-- fullyIndexArray' srcloc $ fixSlice srcslice src_is-- sWhen (gtid .<. kernel_size) $- emit $- Imp.Write destmem destidx bt destspace Imp.Nonvolatile $- Imp.index srcmem srcidx bt srcspace Imp.Nonvolatile--compileGroupResult ::- SegSpace ->- PatElem KernelsMem ->- KernelResult ->- InKernelGen ()-compileGroupResult _ pe (TileReturns [(w, per_group_elems)] what) = do- n <- toInt64Exp . arraySize 0 <$> lookupType what-- constants <- kernelConstants <$> askEnv- let ltid = sExt64 $ kernelLocalThreadId constants- offset =- toInt64Exp per_group_elems- * sExt64 (kernelGroupId constants)-- -- Avoid loop for the common case where each thread is statically- -- known to write at most one element.- localOps threadOperations $- if toInt64Exp per_group_elems == kernelGroupSize constants- then- sWhen (ltid + offset .<. toInt64Exp w) $- copyDWIMFix (patElemName pe) [ltid + offset] (Var what) [ltid]- else sFor "i" (n `divUp` kernelGroupSize constants) $ \i -> do- 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- let gids = map fst $ unSegSpace space- out_tile_sizes = map (toInt64Exp . snd) dims- group_is = zipWith (*) (map Imp.vi64 gids) out_tile_sizes- local_is <- localThreadIDs $ map snd dims- is_for_thread <-- mapM (dPrimV "thread_out_index") $- zipWith (+) group_is local_is-- 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- constants <- kernelConstants <$> askEnv-- let gids = map fst $ unSegSpace space- (dims, group_tiles, reg_tiles) = unzip3 dims_n_tiles- group_tiles' = map toInt64Exp group_tiles- reg_tiles' = map toInt64Exp reg_tiles-- -- Which group tile is this group responsible for?- let group_tile_is = map Imp.vi64 gids-- -- 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-- -- Compute output array slice for the register tile belonging to- -- this thread.- let regTileSliceDim (group_tile, group_tile_i) (reg_tile, reg_tile_i) = do- tile_dim_start <-- dPrimVE "tile_dim_start" $- 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)-- localOps threadOperations $- sLoopNest (Shape reg_tiles) $ \is_in_reg_tile -> do- let dest_is = fixSlice reg_tile_slices is_in_reg_tile- 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- constants <- kernelConstants <$> askEnv- in_local_memory <- arrayInLocalMemory what- let gids = map (Imp.vi64 . fst) $ unSegSpace space-- if not in_local_memory- then- localOps threadOperations $- sWhen (kernelLocalThreadId constants .==. 0) $- copyDWIMFix (patElemName pe) gids what []- else -- If the result of the group is an array in local memory, we- -- store it by collective copying among all the threads of the- -- group. TODO: also do this if the array is in global memory- -- (but this is a bit more tricky, synchronisation-wise).- copyDWIMFix (patElemName pe) gids what []-compileGroupResult _ _ WriteReturns {} =- compilerLimitationS "compileGroupResult: WriteReturns not handled yet."-compileGroupResult _ _ ConcatReturns {} =- compilerLimitationS "compileGroupResult: ConcatReturns not handled yet."--compileThreadResult ::- SegSpace ->- PatElem KernelsMem ->- KernelResult ->- InKernelGen ()-compileThreadResult _ _ RegTileReturns {} =- compilerLimitationS "compileThreadResult: RegTileReturns not yet handled."-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- 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- 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- 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 []-compileThreadResult _ _ TileReturns {} =- compilerBugS "compileThreadResult: TileReturns unhandled."--arrayInLocalMemory :: SubExp -> InKernelGen Bool-arrayInLocalMemory (Var name) = do- res <- lookupVar name- case res of- ArrayVar _ entry ->- (Space "local" ==) . entryMemSpace- <$> lookupMemory (memLocationName (entryArrayLocation entry))- _ -> return False-arrayInLocalMemory Constant {} = return False
− src/Futhark/CodeGen/ImpGen/Kernels/SegHist.hs
@@ -1,1151 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies #-}---- | Our compilation strategy for 'SegHist' is based around avoiding--- bin conflicts. We do this by splitting the input into chunks, and--- for each chunk computing a single subhistogram. Then we combine--- the subhistograms using an ordinary segmented reduction ('SegRed').------ There are some branches around to efficiently handle the case where--- we use only a single subhistogram (because it's large), so that we--- respect the asymptotics, and do not copy the destination array.------ We also use a heuristic strategy for computing subhistograms in--- local memory when possible. Given:------ H: total size of histograms in bytes, including any lock arrays.------ G: group size------ T: number of bytes of local memory each thread can be given without--- impacting occupancy (determined experimentally, e.g. 32).------ LMAX: maximum amount of local memory per workgroup (hard limit).------ We wish to compute:------ COOP: cooperation level (number of threads per subhistogram)------ LH: number of local memory subhistograms------ We do this as:------ COOP = ceil(H / T)--- LH = ceil((G*T)/H)--- if COOP <= G && H <= LMAX then--- use local memory--- else--- use global memory-module Futhark.CodeGen.ImpGen.Kernels.SegHist (compileSegHist) where--import Control.Monad.Except-import Data.List (foldl', genericLength, zip4, zip6)-import Data.Maybe-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.CodeGen.ImpGen.Kernels.SegRed (compileSegRed')-import Futhark.Construct (fullSliceNum)-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.MonadFreshNames-import Futhark.Pass.ExplicitAllocations ()-import Futhark.Util (chunks, mapAccumLM, maxinum, splitFromEnd, takeLast)-import Futhark.Util.IntegralExp (divUp, quot, rem)-import Prelude hiding (quot, rem)--data SubhistosInfo = SubhistosInfo- { subhistosArray :: VName,- subhistosAlloc :: CallKernelGen ()- }--data SegHistSlug = SegHistSlug- { slugOp :: HistOp KernelsMem,- slugNumSubhistos :: TV Int64,- slugSubhistos :: [SubhistosInfo],- slugAtomicUpdate :: AtomicUpdate KernelsMem KernelEnv- }--histoSpaceUsage ::- HistOp KernelsMem ->- Imp.Count Imp.Bytes (Imp.TExp Int64)-histoSpaceUsage op =- sum $- map- ( typeSize- . (`arrayOfRow` histWidth op)- . (`arrayOfShape` histShape op)- )- $ lambdaReturnType $ histOp op---- | Figure out how much memory is needed per histogram, both--- segmented and unsegmented,, and compute some other auxiliary--- information.-computeHistoUsage ::- SegSpace ->- HistOp KernelsMem ->- CallKernelGen- ( Imp.Count Imp.Bytes (Imp.TExp Int64),- Imp.Count Imp.Bytes (Imp.TExp Int64),- SegHistSlug- )-computeHistoUsage space op = do- let segment_dims = init $ unSegSpace space- num_segments = length segment_dims-- -- Create names for the intermediate array memory blocks,- -- memory block sizes, arrays, and number of subhistograms.- 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-- subhistos_mem <-- sDeclareMem (baseString dest ++ "_subhistos_mem") (Space "device")-- let subhistos_shape =- Shape (map snd segment_dims ++ [tvSize num_subhistos])- <> stripDims num_segments (arrayShape dest_t)- subhistos_membind =- ArrayIn subhistos_mem $- IxFun.iota $- map pe64 $ shapeDims subhistos_shape- subhistos <-- sArray- (baseString dest ++ "_subhistos")- (elemType dest_t)- subhistos_shape- subhistos_membind-- return $- SubhistosInfo subhistos $ do- let unitHistoCase =- emit $- Imp.SetMem subhistos_mem (memLocationName dest_mem) $- Space "device"-- multiHistoCase = do- let num_elems =- foldl' (*) (sExt64 $ tvExp num_subhistos) $- map toInt64Exp $ arrayDims dest_t-- let subhistos_mem_size =- Imp.bytes $- Imp.unCount (Imp.elements num_elems `Imp.withElemType` elemType dest_t)-- sAlloc_ subhistos_mem subhistos_mem_size $ Space "device"- sReplicate subhistos ne- subhistos_t <- lookupType subhistos- let slice =- fullSliceNum (map toInt64Exp $ arrayDims subhistos_t) $- map (unitSlice 0 . toInt64Exp . snd) segment_dims- ++ [DimFix 0]- sUpdate subhistos slice $ Var dest-- sIf (tvExp num_subhistos .==. 1) unitHistoCase multiHistoCase-- let h = histoSpaceUsage op- segmented_h = h * product (map (Imp.bytes . toInt64Exp) $ init $ segSpaceDims space)-- atomics <- hostAtomics <$> askEnv-- return- ( h,- segmented_h,- SegHistSlug op num_subhistos subhisto_infos $- atomicUpdateLocking atomics $ histOp op- )--prepareAtomicUpdateGlobal ::- Maybe Locking ->- [VName] ->- SegHistSlug ->- CallKernelGen- ( Maybe Locking,- [Imp.TExp Int64] -> InKernelGen ()- )-prepareAtomicUpdateGlobal l dests slug =- -- We need a separate lock array if the operators are not all of a- -- particularly simple form that permits pure atomic operations.- case (l, slugAtomicUpdate slug) of- (_, AtomicPrim f) -> return (l, f (Space "global") dests)- (_, AtomicCAS f) -> return (l, f (Space "global") dests)- (Just l', AtomicLocking f) -> return (l, f l' (Space "global") dests)- (Nothing, AtomicLocking f) -> do- -- The number of locks used here is too low, but since we are- -- currently forced to inline a huge list, I'm keeping it down- -- for now. Some quick experiments suggested that it has little- -- impact anyway (maybe the locking case is just too slow).- --- -- A fun solution would also be to use a simple hashing- -- algorithm to ensure good distribution of locks.- let num_locks = 100151- dims =- map toInt64Exp $- shapeDims (histShape (slugOp slug))- ++ [ tvSize (slugNumSubhistos slug),- histWidth (slugOp slug)- ]- locks <-- sStaticArray "hist_locks" (Space "device") int32 $- Imp.ArrayZeros num_locks- let l' = Locking locks 0 1 0 (pure . (`rem` fromIntegral num_locks) . flattenIndex dims)- return (Just l', f l' (Space "global") dests)---- | Some kernel bodies are not safe (or efficient) to execute--- multiple times.-data Passage = MustBeSinglePass | MayBeMultiPass deriving (Eq, Ord)--bodyPassage :: KernelBody KernelsMem -> Passage-bodyPassage kbody- | mempty == consumedInKernelBody (aliasAnalyseKernelBody mempty kbody) =- MayBeMultiPass- | otherwise =- MustBeSinglePass--prepareIntermediateArraysGlobal ::- Passage ->- Imp.TExp Int32 ->- Imp.TExp Int64 ->- [SegHistSlug] ->- CallKernelGen- ( Imp.TExp Int32,- [[Imp.TExp Int64] -> InKernelGen ()]- )-prepareIntermediateArraysGlobal passage hist_T hist_N slugs = do- -- The paper formulae assume there is only one histogram, but in our- -- implementation there can be multiple that have been horisontally- -- fused. We do a bit of trickery with summings and averages to- -- pretend there is really only one. For the case of a single- -- histogram, the actual calculations should be the same as in the- -- paper.-- -- The sum of all Hs.- hist_H <- dPrimVE "hist_H" $ sum $ map (toInt64Exp . histWidth . slugOp) slugs-- hist_RF <-- dPrimVE "hist_RF" $- sum (map (r64 . toInt64Exp . histRaceFactor . slugOp) slugs)- / genericLength slugs-- hist_el_size <- dPrimVE "hist_el_size" $ sum $ map slugElAvgSize slugs-- hist_C_max <-- dPrimVE "hist_C_max" $- fMin64 (r64 hist_T) $ r64 hist_H / hist_k_ct_min-- hist_M_min <-- dPrimVE "hist_M_min" $- sMax32 1 $ sExt32 $ t64 $ r64 hist_T / hist_C_max-- -- Querying L2 cache size is not reliable. Instead we provide a- -- tunable knob with a hopefully sane default.- let hist_L2_def = 4 * 1024 * 1024- hist_L2 <- dPrim "L2_size" int32- entry <- askFunction- -- Equivalent to F_L2*L2 in paper.- sOp $- Imp.GetSize- (tvVar hist_L2)- (keyWithEntryPoint entry $ nameFromString (pretty (tvVar hist_L2)))- $ Imp.SizeBespoke (nameFromString "L2_for_histogram") hist_L2_def-- let hist_L2_ln_sz = 16 * 4 -- L2 cache line size approximation- hist_RACE_exp <-- dPrimVE "hist_RACE_exp" $- fMax64 1 $- (hist_k_RF * hist_RF)- / (hist_L2_ln_sz / r64 hist_el_size)-- hist_S <- dPrim "hist_S" int32-- -- For sparse histograms (H exceeds N) we only want a single chunk.- sIf- (hist_N .<. hist_H)- (hist_S <-- (1 :: Imp.TExp Int32))- $ hist_S- <-- case passage of- MayBeMultiPass ->- sExt32 $- (sExt64 hist_M_min * hist_H * sExt64 hist_el_size)- `divUp` t64 (hist_F_L2 * r64 (tvExp hist_L2) * hist_RACE_exp)- MustBeSinglePass ->- 1-- emit $ Imp.DebugPrint "Race expansion factor (RACE^exp)" $ Just $ untyped hist_RACE_exp- emit $ Imp.DebugPrint "Number of chunks (S)" $ Just $ untyped $ tvExp hist_S-- histograms <-- snd- <$> mapAccumLM- (onOp (tvExp hist_L2) hist_M_min (tvExp hist_S) hist_RACE_exp)- Nothing- slugs-- return (tvExp hist_S, histograms)- where- hist_k_ct_min = 2 -- Chosen experimentally- hist_k_RF = 0.75 -- Chosen experimentally- hist_F_L2 = 0.4 -- Chosen experimentally- r64 = isF64 . ConvOpExp (SIToFP Int32 Float64) . untyped- t64 = isInt64 . ConvOpExp (FPToSI Float64 Int64) . untyped-- -- "Average element size" as computed by a formula that also takes- -- locking into account.- slugElAvgSize slug@(SegHistSlug op _ _ do_op) =- case do_op of- AtomicLocking {} ->- slugElSize slug `quot` (1 + genericLength (lambdaReturnType (histOp op)))- _ ->- slugElSize slug `quot` genericLength (lambdaReturnType (histOp op))-- -- "Average element size" as computed by a formula that also takes- -- locking into account.- slugElSize (SegHistSlug op _ _ do_op) =- case do_op of- AtomicLocking {} ->- sExt32 $- unCount $- sum $- map (typeSize . (`arrayOfShape` histShape op)) $- Prim int32 : lambdaReturnType (histOp op)- _ ->- sExt32 $- unCount $- sum $- map (typeSize . (`arrayOfShape` histShape op)) $- lambdaReturnType (histOp op)-- onOp hist_L2 hist_M_min hist_S hist_RACE_exp l slug = do- let SegHistSlug op num_subhistos subhisto_info do_op = slug- hist_H = toInt64Exp $ histWidth op-- hist_H_chk <- dPrimVE "hist_H_chk" $ hist_H `divUp` sExt64 hist_S-- emit $ Imp.DebugPrint "Chunk size (H_chk)" $ Just $ untyped hist_H_chk-- hist_k_max <-- dPrimVE "hist_k_max" $- fMin64- (hist_F_L2 * (r64 hist_L2 / r64 (slugElSize slug)) * hist_RACE_exp)- (r64 hist_N)- / r64 hist_T-- hist_u <- dPrimVE "hist_u" $- case do_op of- AtomicPrim {} -> 2- _ -> 1-- hist_C <-- dPrimVE "hist_C" $- fMin64 (r64 hist_T) $ r64 (hist_u * hist_H_chk) / hist_k_max-- -- Number of subhistograms per result histogram.- hist_M <- dPrimVE "hist_M" $- case slugAtomicUpdate slug of- AtomicPrim {} -> 1- _ -> sMax32 hist_M_min $ sExt32 $ t64 $ r64 hist_T / hist_C-- emit $ Imp.DebugPrint "Elements/thread in L2 cache (k_max)" $ Just $ untyped hist_k_max- emit $ Imp.DebugPrint "Multiplication degree (M)" $ Just $ untyped hist_M- emit $ Imp.DebugPrint "Cooperation level (C)" $ Just $ untyped hist_C-- -- num_subhistos is the variable we use to communicate back.- num_subhistos <-- sExt64 hist_M-- -- Initialise sub-histograms.- --- -- If hist_M is 1, then we just reuse the original- -- 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-- sub_mem <-- fmap memLocationName $- entryArrayLocation- <$> lookupArray (subhistosArray info)-- let unitHistoCase =- emit $- Imp.SetMem sub_mem (memLocationName dest_mem) $- Space "device"-- multiHistoCase = subhistosAlloc info-- sIf (hist_M .==. 1) unitHistoCase multiHistoCase-- return $ subhistosArray info-- (l', do_op') <- prepareAtomicUpdateGlobal l dests slug-- return (l', do_op')--histKernelGlobalPass ::- [PatElem KernelsMem] ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- SegSpace ->- [SegHistSlug] ->- KernelBody KernelsMem ->- [[Imp.TExp Int64] -> InKernelGen ()] ->- Imp.TExp Int32 ->- Imp.TExp Int32 ->- CallKernelGen ()-histKernelGlobalPass map_pes num_groups group_size space slugs kbody histograms hist_S chk_i = do- let (space_is, space_sizes) = unzip $ unSegSpace space- space_sizes_64 = map (sExt64 . toInt64Exp) space_sizes- total_w_64 = product space_sizes_64-- hist_H_chks <- forM (map (histWidth . slugOp) slugs) $ \w ->- dPrimVE "hist_H_chk" $ toInt64Exp w `divUp` sExt64 hist_S-- sKernelThread "seghist_global" num_groups group_size (segFlat space) $ do- constants <- kernelConstants <$> askEnv-- -- Compute subhistogram index for each thread, per histogram.- subhisto_inds <- forM slugs $ \slug ->- dPrimVE "subhisto_ind" $- kernelGlobalThreadId constants- `quot` ( kernelNumThreads constants- `divUp` sExt32 (tvExp (slugNumSubhistos slug))- )-- -- Loop over flat offsets into the input and output. The- -- calculation is done with 64-bit integers to avoid overflow,- -- but the final unflattened segment indexes are 32 bit.- let gtid = sExt64 $ kernelGlobalThreadId constants- num_threads = sExt64 $ kernelNumThreads constants- kernelLoop gtid num_threads total_w_64 $ \offset -> do- -- Construct segment indices.- zipWithM_ dPrimV_ space_is $- map sExt32 $ unflattenIndex space_sizes_64 offset-- -- We execute the bucket function once and update each histogram serially.- -- We apply the bucket function if j=offset+ltid is less than- -- num_elements. This also involves writing to the mapout- -- arrays.- let input_in_bounds = offset .<. total_w_64-- sWhen input_in_bounds $- compileStms mempty (kernelBodyStms kbody) $ do- let (red_res, map_res) = splitFromEnd (length map_pes) $ kernelBodyResult kbody-- sComment "save map-out results" $- forM_ (zip map_pes map_res) $ \(pe, res) ->- copyDWIMFix- (patElemName pe)- (map (Imp.vi64 . fst) $ unSegSpace space)- (kernelResultSubExp res)- []-- let (buckets, vs) = splitAt (length slugs) red_res- perOp = chunks $ map (length . histDest . slugOp) slugs-- sComment "perform atomic updates" $- forM_ (zip6 (map slugOp slugs) histograms buckets (perOp vs) subhisto_inds hist_H_chks) $- \( HistOp dest_w _ _ _ shape lam,- do_op,- bucket,- vs',- subhisto_ind,- hist_H_chk- ) -> do- let chk_beg = sExt64 chk_i * hist_H_chk- bucket' = toInt64Exp $ kernelResultSubExp bucket- dest_w' = toInt64Exp dest_w- bucket_in_bounds =- chk_beg .<=. bucket'- .&&. bucket' .<. (chk_beg + hist_H_chk)- .&&. bucket' .<. dest_w'- vs_params = takeLast (length vs') $ lambdaParams lam-- sWhen bucket_in_bounds $ do- let bucket_is =- map Imp.vi64 (init space_is)- ++ [sExt64 subhisto_ind, bucket']- dLParams $ lambdaParams lam- sLoopNest shape $ \is -> do- forM_ (zip vs_params vs') $ \(p, res) ->- copyDWIMFix (paramName p) [] (kernelResultSubExp res) is- do_op (bucket_is ++ is)--histKernelGlobal ::- [PatElem KernelsMem] ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [SegHistSlug] ->- KernelBody KernelsMem ->- CallKernelGen ()-histKernelGlobal map_pes num_groups group_size space slugs kbody = do- let num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size- let (_space_is, space_sizes) = unzip $ unSegSpace space- num_threads = sExt32 $ unCount num_groups' * unCount group_size'-- emit $ Imp.DebugPrint "## Using global memory" Nothing-- (hist_S, histograms) <-- prepareIntermediateArraysGlobal- (bodyPassage kbody)- num_threads- (toInt64Exp $ last space_sizes)- slugs-- sFor "chk_i" hist_S $ \chk_i ->- histKernelGlobalPass- map_pes- num_groups'- group_size'- space- slugs- kbody- histograms- hist_S- chk_i--type InitLocalHistograms =- [ ( [VName],- SubExp ->- InKernelGen- ( [VName],- [Imp.TExp Int64] -> InKernelGen ()- )- )- ]--prepareIntermediateArraysLocal ::- TV Int32 ->- Count NumGroups (Imp.TExp Int64) ->- SegSpace ->- [SegHistSlug] ->- CallKernelGen InitLocalHistograms-prepareIntermediateArraysLocal num_subhistos_per_group groups_per_segment space slugs = do- num_segments <-- dPrimVE "num_segments" $- product $ map (toInt64Exp . snd) $ init $ unSegSpace space- mapM (onOp num_segments) slugs- where- onOp num_segments (SegHistSlug op num_subhistos subhisto_info do_op) = do- num_subhistos <-- sExt64 (unCount groups_per_segment) * num_segments-- emit $- Imp.DebugPrint "Number of subhistograms in global memory" $- Just $ untyped $ tvExp num_subhistos-- mk_op <-- case do_op of- AtomicPrim f -> return $ const $ return f- AtomicCAS f -> return $ const $ return f- AtomicLocking f -> return $ \hist_H_chk -> do- let lock_shape =- Shape $- tvSize num_subhistos_per_group :- shapeDims (histShape op)- ++ [hist_H_chk]-- let dims = map toInt64Exp $ shapeDims lock_shape-- locks <- sAllocArray "locks" int32 lock_shape $ Space "local"-- sComment "All locks start out unlocked" $- groupCoverSpace dims $ \is ->- copyDWIMFix locks is (intConst Int32 0) []-- return $ f $ Locking locks 0 1 0 id-- -- Initialise local-memory sub-histograms. These are- -- represented as two-dimensional arrays.- let init_local_subhistos hist_H_chk = do- local_subhistos <-- forM (histType op) $ \t -> do- let sub_local_shape =- Shape [tvSize num_subhistos_per_group]- <> (arrayShape t `setOuterDim` hist_H_chk)- sAllocArray- "subhistogram_local"- (elemType t)- sub_local_shape- (Space "local")-- do_op' <- mk_op hist_H_chk-- return (local_subhistos, do_op' (Space "local") local_subhistos)-- -- Initialise global-memory sub-histograms.- glob_subhistos <- forM subhisto_info $ \info -> do- subhistosAlloc info- return $ subhistosArray info-- return (glob_subhistos, init_local_subhistos)--histKernelLocalPass ::- TV Int32 ->- Count NumGroups (Imp.TExp Int64) ->- [PatElem KernelsMem] ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- SegSpace ->- [SegHistSlug] ->- KernelBody KernelsMem ->- InitLocalHistograms ->- Imp.TExp Int32 ->- Imp.TExp Int32 ->- CallKernelGen ()-histKernelLocalPass- num_subhistos_per_group_var- groups_per_segment- map_pes- num_groups- group_size- space- slugs- kbody- init_histograms- hist_S- chk_i = do- let (space_is, space_sizes) = unzip $ unSegSpace space- segment_is = init space_is- segment_dims = init space_sizes- (i_in_segment, segment_size) = last $ unSegSpace space- num_subhistos_per_group = tvExp num_subhistos_per_group_var- segment_size' = toInt64Exp segment_size-- num_segments <-- dPrimVE "num_segments" $- product $ map toInt64Exp segment_dims-- hist_H_chks <- forM (map (histWidth . slugOp) slugs) $ \w ->- dPrimV "hist_H_chk" $ toInt64Exp w `divUp` sExt64 hist_S-- histo_sizes <- forM (zip slugs hist_H_chks) $ \(slug, hist_H_chk) -> do- let histo_dims =- tvExp hist_H_chk :- map toInt64Exp (shapeDims (histShape (slugOp slug)))- histo_size <-- dPrimVE "histo_size" $ product histo_dims- let group_hists_size =- sExt64 num_subhistos_per_group * histo_size- init_per_thread <-- dPrimVE "init_per_thread" $ sExt32 $ group_hists_size `divUp` unCount group_size- return (histo_dims, histo_size, init_per_thread)-- sKernelThread "seghist_local" num_groups group_size (segFlat space) $- virtualiseGroups SegVirt (sExt32 $ unCount groups_per_segment * num_segments) $ \group_id -> do- constants <- kernelConstants <$> askEnv-- flat_segment_id <- dPrimVE "flat_segment_id" $ group_id `quot` sExt32 (unCount groups_per_segment)- gid_in_segment <- dPrimVE "gid_in_segment" $ group_id `rem` sExt32 (unCount groups_per_segment)- -- This pgtid is kind of a "virtualised physical" gtid - not the- -- same thing as the gtid used for the SegHist itself.- pgtid_in_segment <-- dPrimVE "pgtid_in_segment" $- gid_in_segment * sExt32 (kernelGroupSize constants)- + kernelLocalThreadId constants- threads_per_segment <-- dPrimVE "threads_per_segment" $- sExt32 $ unCount groups_per_segment * kernelGroupSize constants-- -- Set segment indices.- zipWithM_ dPrimV_ segment_is $- unflattenIndex (map toInt64Exp segment_dims) $ sExt64 flat_segment_id-- histograms <- forM (zip init_histograms hist_H_chks) $- \((glob_subhistos, init_local_subhistos), hist_H_chk) -> do- (local_subhistos, do_op) <- init_local_subhistos $ Var $ tvVar hist_H_chk- return (zip glob_subhistos local_subhistos, hist_H_chk, do_op)-- -- Find index of local subhistograms updated by this thread. We- -- try to ensure, as much as possible, that threads in the same- -- warp use different subhistograms, to avoid conflicts.- thread_local_subhisto_i <-- dPrimVE "thread_local_subhisto_i" $- kernelLocalThreadId constants `rem` num_subhistos_per_group-- let onSlugs f =- forM_ (zip3 slugs histograms histo_sizes) $- \(slug, (dests, hist_H_chk, _), (histo_dims, histo_size, init_per_thread)) ->- f slug dests (tvExp hist_H_chk) histo_dims histo_size init_per_thread-- let onAllHistograms f =- onSlugs $ \slug dests hist_H_chk histo_dims histo_size init_per_thread -> do- let group_hists_size = num_subhistos_per_group * sExt32 histo_size-- forM_ (zip dests (histNeutral $ slugOp slug)) $- \((dest_global, dest_local), ne) ->- sFor "local_i" init_per_thread $ \i -> do- j <-- dPrimVE "j" $- i * sExt32 (kernelGroupSize constants)- + kernelLocalThreadId constants- j_offset <-- dPrimVE "j_offset" $- num_subhistos_per_group * sExt32 histo_size * gid_in_segment + j-- local_subhisto_i <- dPrimVE "local_subhisto_i" $ j `quot` sExt32 histo_size- let local_bucket_is = unflattenIndex histo_dims $ sExt64 $ j `rem` sExt32 histo_size- global_bucket_is =- head local_bucket_is + sExt64 chk_i * hist_H_chk :- tail local_bucket_is- global_subhisto_i <- dPrimVE "global_subhisto_i" $ j_offset `quot` sExt32 histo_size-- sWhen (j .<. group_hists_size) $- f- dest_local- dest_global- (slugOp slug)- ne- local_subhisto_i- global_subhisto_i- local_bucket_is- global_bucket_is-- sComment "initialize histograms in local memory" $- onAllHistograms $ \dest_local dest_global op ne local_subhisto_i global_subhisto_i local_bucket_is global_bucket_is ->- sComment "First subhistogram is initialised from global memory; others with neutral element." $ do- let global_is = map Imp.vi64 segment_is ++ [0] ++ global_bucket_is- local_is = sExt64 local_subhisto_i : local_bucket_is- sIf- (global_subhisto_i .==. 0)- (copyDWIMFix dest_local local_is (Var dest_global) global_is)- ( sLoopNest (histShape op) $ \is ->- copyDWIMFix dest_local (local_is ++ is) ne []- )-- sOp $ Imp.Barrier Imp.FenceLocal-- kernelLoop pgtid_in_segment threads_per_segment (sExt32 segment_size') $ \ie -> do- dPrimV_ i_in_segment ie-- -- We execute the bucket function once and update each histogram- -- serially. This also involves writing to the mapout arrays if- -- this is the first chunk.-- compileStms mempty (kernelBodyStms kbody) $ do- let (red_res, map_res) =- splitFromEnd (length map_pes) $- map kernelResultSubExp $ kernelBodyResult kbody- (buckets, vs) = splitAt (length slugs) red_res- perOp = chunks $ map (length . histDest . slugOp) slugs-- sWhen (chk_i .==. 0) $- sComment "save map-out results" $- forM_ (zip map_pes map_res) $ \(pe, se) ->- copyDWIMFix- (patElemName pe)- (map Imp.vi64 space_is)- se- []-- forM_ (zip4 (map slugOp slugs) histograms buckets (perOp vs)) $- \( HistOp dest_w _ _ _ shape lam,- (_, hist_H_chk, do_op),- bucket,- vs'- ) -> do- let chk_beg = sExt64 chk_i * tvExp hist_H_chk- bucket' = toInt64Exp bucket- dest_w' = toInt64Exp dest_w- bucket_in_bounds =- bucket' .<. dest_w'- .&&. chk_beg .<=. bucket'- .&&. bucket' .<. (chk_beg + tvExp hist_H_chk)- bucket_is = [sExt64 thread_local_subhisto_i, bucket' - chk_beg]- vs_params = takeLast (length vs') $ lambdaParams lam-- sComment "perform atomic updates" $- sWhen bucket_in_bounds $ do- dLParams $ lambdaParams lam- sLoopNest shape $ \is -> do- forM_ (zip vs_params vs') $ \(p, v) ->- copyDWIMFix (paramName p) [] v is- do_op (bucket_is ++ is)-- sOp $ Imp.ErrorSync Imp.FenceGlobal-- sComment "Compact the multiple local memory subhistograms to result in global memory" $- onSlugs $ \slug dests hist_H_chk histo_dims _histo_size bins_per_thread -> do- trunc_H <-- dPrimV "trunc_H" $- sMin64 hist_H_chk $- toInt64Exp (histWidth (slugOp slug))- - sExt64 chk_i * head histo_dims- let trunc_histo_dims =- tvExp trunc_H :- map toInt64Exp (shapeDims (histShape (slugOp slug)))- trunc_histo_size <- dPrimVE "histo_size" $ sExt32 $ product trunc_histo_dims-- sFor "local_i" bins_per_thread $ \i -> do- j <-- dPrimVE "j" $- i * sExt32 (kernelGroupSize constants)- + kernelLocalThreadId constants- sWhen (j .<. trunc_histo_size) $ do- -- We are responsible for compacting the flat bin 'j', which- -- we immediately unflatten.- let local_bucket_is = unflattenIndex histo_dims $ sExt64 j- global_bucket_is =- head local_bucket_is + sExt64 chk_i * hist_H_chk :- tail local_bucket_is- dLParams $ lambdaParams $ histOp $ slugOp slug- let (global_dests, local_dests) = unzip dests- (xparams, yparams) =- splitAt (length local_dests) $- lambdaParams $ histOp $ slugOp slug-- sComment "Read values from subhistogram 0." $- forM_ (zip xparams local_dests) $ \(xp, subhisto) ->- copyDWIMFix- (paramName xp)- []- (Var subhisto)- (0 : local_bucket_is)-- sComment "Accumulate based on values in other subhistograms." $- sFor "subhisto_id" (num_subhistos_per_group - 1) $ \subhisto_id -> do- forM_ (zip yparams local_dests) $ \(yp, subhisto) ->- copyDWIMFix- (paramName yp)- []- (Var subhisto)- (sExt64 subhisto_id + 1 : local_bucket_is)- compileBody' xparams $ lambdaBody $ histOp $ slugOp slug-- sComment "Put final bucket value in global memory." $ do- let global_is =- map Imp.vi64 segment_is- ++ [sExt64 group_id `rem` unCount groups_per_segment]- ++ global_bucket_is- forM_ (zip xparams global_dests) $ \(xp, global_dest) ->- copyDWIMFix global_dest global_is (Var $ paramName xp) []--histKernelLocal ::- TV Int32 ->- Count NumGroups (Imp.TExp Int64) ->- [PatElem KernelsMem] ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- Imp.TExp Int32 ->- [SegHistSlug] ->- KernelBody KernelsMem ->- CallKernelGen ()-histKernelLocal num_subhistos_per_group_var groups_per_segment map_pes num_groups group_size space hist_S slugs kbody = do- let num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size- num_subhistos_per_group = tvExp num_subhistos_per_group_var-- emit $- Imp.DebugPrint "Number of local subhistograms per group" $- Just $ untyped num_subhistos_per_group-- init_histograms <-- prepareIntermediateArraysLocal num_subhistos_per_group_var groups_per_segment space slugs-- sFor "chk_i" hist_S $ \chk_i ->- histKernelLocalPass- num_subhistos_per_group_var- groups_per_segment- map_pes- num_groups'- group_size'- space- slugs- kbody- init_histograms- hist_S- chk_i---- | The maximum number of passes we are willing to accept for this--- kind of atomic update.-slugMaxLocalMemPasses :: SegHistSlug -> Int-slugMaxLocalMemPasses slug =- case slugAtomicUpdate slug of- AtomicPrim _ -> 3- AtomicCAS _ -> 4- AtomicLocking _ -> 6--localMemoryCase ::- [PatElem KernelsMem] ->- Imp.TExp Int32 ->- SegSpace ->- Imp.TExp Int64 ->- Imp.TExp Int64 ->- Imp.TExp Int64 ->- Imp.TExp Int32 ->- [SegHistSlug] ->- KernelBody KernelsMem ->- CallKernelGen (Imp.TExp Bool, CallKernelGen ())-localMemoryCase map_pes hist_T space hist_H hist_el_size hist_N _ slugs kbody = do- let space_sizes = segSpaceDims space- segment_dims = init space_sizes- segmented = not $ null segment_dims-- hist_L <- dPrim "hist_L" int32- sOp $ Imp.GetSizeMax (tvVar hist_L) Imp.SizeLocalMemory-- max_group_size <- dPrim "max_group_size" int32- sOp $ Imp.GetSizeMax (tvVar max_group_size) Imp.SizeGroup- let group_size = Imp.Count $ Var $ tvVar max_group_size- num_groups <-- fmap (Imp.Count . tvSize) $- dPrimV "num_groups" $- sExt64 hist_T `divUp` toInt64Exp (unCount group_size)- let num_groups' = toInt64Exp <$> num_groups- group_size' = toInt64Exp <$> group_size-- let r64 = isF64 . ConvOpExp (SIToFP Int64 Float64) . untyped- t64 = isInt64 . ConvOpExp (FPToSI Float64 Int64) . untyped-- -- M approximation.- hist_m' <-- dPrimVE "hist_m_prime" $- r64- ( sMin64- (sExt64 (tvExp hist_L `quot` hist_el_size))- (hist_N `divUp` sExt64 (unCount num_groups'))- )- / r64 hist_H-- let hist_B = unCount group_size'-- -- M in the paper, but not adjusted for asymptotic efficiency.- hist_M0 <-- dPrimVE "hist_M0" $- sMax64 1 $ sMin64 (t64 hist_m') hist_B-- -- Minimal sequential chunking factor.- let q_small = 2-- -- The number of segments/histograms produced..- hist_Nout <- dPrimVE "hist_Nout" $ product $ map toInt64Exp segment_dims-- hist_Nin <- dPrimVE "hist_Nin" $ toInt64Exp $ last space_sizes-- -- Maximum M for work efficiency.- work_asymp_M_max <-- if segmented- then do- hist_T_hist_min <-- dPrimVE "hist_T_hist_min" $- sExt32 $- sMin64 (sExt64 hist_Nin * sExt64 hist_Nout) (sExt64 hist_T)- `divUp` sExt64 hist_Nout-- -- Number of groups, rounded up.- let r = hist_T_hist_min `divUp` sExt32 hist_B-- dPrimVE "work_asymp_M_max" $ hist_Nin `quot` (sExt64 r * hist_H)- else- dPrimVE "work_asymp_M_max" $- (hist_Nout * hist_N)- `quot` ( (q_small * unCount num_groups' * hist_H)- `quot` genericLength slugs- )-- -- Number of subhistograms per result histogram.- hist_M <- dPrimV "hist_M" $ sExt32 $ sMin64 hist_M0 work_asymp_M_max-- -- hist_M may be zero (which we'll check for below), but we need it- -- for some divisions first, so crudely make a nonzero form.- let hist_M_nonzero = sMax32 1 $ tvExp hist_M-- -- "Cooperation factor" - the number of threads cooperatively- -- working on the same (sub)histogram.- hist_C <-- dPrimVE "hist_C" $- hist_B `divUp` sExt64 hist_M_nonzero-- emit $ Imp.DebugPrint "local hist_M0" $ Just $ untyped hist_M0- emit $ Imp.DebugPrint "local work asymp M max" $ Just $ untyped work_asymp_M_max- emit $ Imp.DebugPrint "local C" $ Just $ untyped hist_C- emit $ Imp.DebugPrint "local B" $ Just $ untyped hist_B- emit $ Imp.DebugPrint "local M" $ Just $ untyped $ tvExp hist_M- emit $- Imp.DebugPrint "local memory needed" $- Just $ untyped $ hist_H * hist_el_size * sExt64 (tvExp hist_M)-- -- local_mem_needed is what we need to keep a single bucket in local- -- memory - this is an absolute minimum. We can fit anything else- -- by doing multiple passes, although more than a few is- -- (heuristically) not efficient.- local_mem_needed <-- dPrimVE "local_mem_needed" $- hist_el_size * sExt64 (tvExp hist_M)- hist_S <-- dPrimVE "hist_S" $- sExt32 $- (hist_H * local_mem_needed) `divUp` tvExp hist_L- let max_S = case bodyPassage kbody of- MustBeSinglePass -> 1- MayBeMultiPass -> fromIntegral $ maxinum $ map slugMaxLocalMemPasses slugs-- groups_per_segment <-- if segmented- then- fmap Count $- dPrimVE "groups_per_segment" $ unCount num_groups' `divUp` hist_Nout- else pure num_groups'-- -- We only use local memory if the number of updates per histogram- -- at least matches the histogram size, as otherwise it is not- -- asymptotically efficient. This mostly matters for the segmented- -- case.- let pick_local =- hist_Nin .>=. hist_H- .&&. (local_mem_needed .<=. tvExp hist_L)- .&&. (hist_S .<=. max_S)- .&&. hist_C .<=. hist_B- .&&. tvExp hist_M .>. 0-- run = do- emit $ Imp.DebugPrint "## Using local memory" Nothing- emit $ Imp.DebugPrint "Histogram size (H)" $ Just $ untyped hist_H- emit $ Imp.DebugPrint "Multiplication degree (M)" $ Just $ untyped $ tvExp hist_M- emit $ Imp.DebugPrint "Cooperation level (C)" $ Just $ untyped hist_C- emit $ Imp.DebugPrint "Number of chunks (S)" $ Just $ untyped hist_S- when segmented $- emit $ Imp.DebugPrint "Groups per segment" $ Just $ untyped $ unCount groups_per_segment- histKernelLocal- hist_M- groups_per_segment- map_pes- num_groups- group_size- space- hist_S- slugs- kbody-- return (pick_local, run)---- | Generate code for a segmented histogram called from the host.-compileSegHist ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [HistOp KernelsMem] ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegHist (Pattern _ 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- -- are always in global memory, but their number may vary).- let num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size- dims = map toInt64Exp $ segSpaceDims space-- num_red_res = length ops + sum (map (length . histNeutral) ops)- (all_red_pes, map_pes) = splitAt num_red_res pes- segment_size = last dims-- (op_hs, op_seg_hs, slugs) <- unzip3 <$> mapM (computeHistoUsage space) ops- h <- dPrimVE "h" $ Imp.unCount $ sum op_hs- seg_h <- dPrimVE "seg_h" $ Imp.unCount $ sum op_seg_hs-- -- Check for emptyness to avoid division-by-zero.- sUnless (seg_h .==. 0) $ do- -- Maximum group size (or actual, in this case).- let hist_B = unCount group_size'-- -- Size of a histogram.- hist_H <- dPrimVE "hist_H" $ sum $ map (toInt64Exp . histWidth) ops-- -- Size of a single histogram element. Actually the weighted- -- average of histogram elements in cases where we have more than- -- one histogram operation, plus any locks.- let lockSize slug = case slugAtomicUpdate slug of- AtomicLocking {} -> Just $ primByteSize int32- _ -> Nothing- hist_el_size <-- dPrimVE "hist_el_size" $- foldl' (+) (h `divUp` hist_H) $- mapMaybe lockSize slugs-- -- Input elements contributing to each histogram.- hist_N <- dPrimVE "hist_N" segment_size-- -- Compute RF as the average RF over all the histograms.- hist_RF <-- dPrimVE "hist_RF" $- sExt32 $- sum (map (toInt64Exp . histRaceFactor . slugOp) slugs)- `quot` genericLength slugs-- let hist_T = sExt32 $ unCount num_groups' * unCount group_size'- emit $ Imp.DebugPrint "\n# SegHist" Nothing- emit $ Imp.DebugPrint "Number of threads (T)" $ Just $ untyped hist_T- emit $ Imp.DebugPrint "Desired group size (B)" $ Just $ untyped hist_B- emit $ Imp.DebugPrint "Histogram size (H)" $ Just $ untyped hist_H- emit $ Imp.DebugPrint "Input elements per histogram (N)" $ Just $ untyped hist_N- emit $- Imp.DebugPrint "Number of segments" $- Just $ untyped $ product $ map (toInt64Exp . snd) segment_dims- emit $ Imp.DebugPrint "Histogram element size (el_size)" $ Just $ untyped hist_el_size- emit $ Imp.DebugPrint "Race factor (RF)" $ Just $ untyped hist_RF- emit $ Imp.DebugPrint "Memory per set of subhistograms per segment" $ Just $ untyped h- emit $ Imp.DebugPrint "Memory per set of subhistograms times segments" $ Just $ untyped seg_h-- (use_local_memory, run_in_local_memory) <-- localMemoryCase map_pes hist_T space hist_H hist_el_size hist_N hist_RF slugs kbody-- sIf use_local_memory run_in_local_memory $- histKernelGlobal map_pes num_groups group_size space slugs kbody-- let pes_per_op = chunks (map (length . histDest) ops) all_red_pes-- forM_ (zip3 slugs pes_per_op ops) $ \(slug, red_pes, op) -> do- let num_histos = slugNumSubhistos slug- subhistos = map subhistosArray $ slugSubhistos slug-- let unitHistoCase =- -- This is OK because the memory blocks are at least as- -- large as the ones we are supposed to use for the result.- forM_ (zip red_pes subhistos) $ \(pe, subhisto) -> do- pe_mem <-- memLocationName . entryArrayLocation- <$> lookupArray (patElemName pe)- subhisto_mem <-- memLocationName . entryArrayLocation- <$> lookupArray subhisto- emit $ Imp.SetMem pe_mem subhisto_mem $ Space "device"-- sIf (tvExp num_histos .==. 1) unitHistoCase $ do- -- For the segmented reduction, we keep the segment dimensions- -- unchanged. To this, we add two dimensions: one over the number- -- of buckets, and one over the number of subhistograms. This- -- inner dimension is the one that is collapsed in the reduction.- let num_buckets = histWidth op-- bucket_id <- newVName "bucket_id"- subhistogram_id <- newVName "subhistogram_id"- vector_ids <-- mapM (const $ newVName "vector_id") $- shapeDims $ histShape op-- flat_gtid <- newVName "flat_gtid"-- let lvl = SegThread num_groups group_size SegVirt- segred_space =- SegSpace flat_gtid $- segment_dims- ++ [(bucket_id, num_buckets)]- ++ zip vector_ids (shapeDims $ histShape op)- ++ [(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 ->- red_cont $- flip map subhistos $ \subhisto ->- ( Var subhisto,- map Imp.vi64 $- map fst segment_dims ++ [subhistogram_id, bucket_id] ++ vector_ids- )-- emit $ Imp.DebugPrint "" Nothing- where- segment_dims = init $ unSegSpace space
− src/Futhark/CodeGen/ImpGen/Kernels/SegMap.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | Code generation for 'SegMap' is quite straightforward. The only--- trick is virtualisation in case the physical number of threads is--- not sufficient to cover the logical thread space. This is handled--- by having actual workgroups run a loop to imitate multiple workgroups.-module Futhark.CodeGen.ImpGen.Kernels.SegMap (compileSegMap) where--import Control.Monad.Except-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.IR.KernelsMem-import Futhark.Util.IntegralExp (divUp)-import Prelude hiding (quot, rem)---- | Compile 'SegMap' instance code.-compileSegMap ::- Pattern KernelsMem ->- SegLevel ->- SegSpace ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegMap pat lvl space kbody = do- let (is, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims- num_groups' = toInt64Exp <$> segNumGroups lvl- group_size' = toInt64Exp <$> segGroupSize lvl-- emit $ Imp.DebugPrint "\n# SegMap" Nothing- case lvl of- SegThread {} -> do- let virt_num_groups =- sExt32 $ product dims' `divUp` unCount group_size'- sKernelThread "segmap" num_groups' group_size' (segFlat space) $- virtualiseGroups (segVirt lvl) virt_num_groups $ \group_id -> do- local_tid <- kernelLocalThreadId . kernelConstants <$> askEnv-- global_tid <-- dPrimVE "global_tid" $- sExt64 group_id * sExt64 (unCount group_size')- + sExt64 local_tid-- dIndexSpace (zip is dims') global_tid-- sWhen (isActive $ unSegSpace space) $- compileStms mempty (kernelBodyStms kbody) $- zipWithM_ (compileThreadResult space) (patternElements pat) $- kernelBodyResult kbody- SegGroup {} ->- sKernelGroup "segmap_intragroup" num_groups' group_size' (segFlat space) $ do- let virt_num_groups = sExt32 $ product dims'- precomputeSegOpIDs (kernelBodyStms kbody) $- virtualiseGroups (segVirt lvl) virt_num_groups $ \group_id -> do- dIndexSpace (zip is dims') $ sExt64 group_id-- compileStms mempty (kernelBodyStms kbody) $- zipWithM_ (compileGroupResult space) (patternElements pat) $- kernelBodyResult kbody- emit $ Imp.DebugPrint "" Nothing
− src/Futhark/CodeGen/ImpGen/Kernels/SegRed.hs
@@ -1,838 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | We generate code for non-segmented/single-segment SegRed using--- the basic approach outlined in the paper "Design and GPGPU--- Performance of Futhark’s Redomap Construct" (ARRAY '16). The main--- deviations are:------ * While we still use two-phase reduction, we use only a single--- kernel, with the final workgroup to write a result (tracked via--- an atomic counter) performing the final reduction as well.------ * Instead of depending on storage layout transformations to handle--- non-commutative reductions efficiently, we slide a--- @groupsize@-sized window over the input, and perform a parallel--- reduction for each window. This sacrifices the notion of--- efficient sequentialisation, but is sometimes faster and--- definitely simpler and more predictable (and uses less auxiliary--- storage).------ For segmented reductions we use the approach from "Strategies for--- Regular Segmented Reductions on GPU" (FHPC '17). This involves--- having two different strategies, and dynamically deciding which one--- to use based on the number of segments and segment size. We use the--- (static) @group_size@ to decide which of the following two--- strategies to choose:------ * Large: uses one or more groups to process a single segment. If--- multiple groups are used per segment, the intermediate reduction--- results must be recursively reduced, until there is only a single--- value per segment.------ Each thread /can/ read multiple elements, which will greatly--- increase performance; however, if the reduction is--- non-commutative we will have to use a less efficient traversal--- (with interim group-wide reductions) to enable coalesced memory--- accesses, just as in the non-segmented case.------ * Small: is used to let each group process *multiple* segments--- within a group. We will only use this approach when we can--- process at least two segments within a single group. In those--- cases, we would allocate a /whole/ group per segment with the--- large strategy, but at most 50% of the threads in the group would--- have any element to read, which becomes highly inefficient.-module Futhark.CodeGen.ImpGen.Kernels.SegRed- ( compileSegRed,- compileSegRed',- DoSegBody,- )-where--import Control.Monad.Except-import Data.List (genericLength, zip7)-import Data.Maybe-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.Error-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.Transform.Rename-import Futhark.Util (chunks)-import Futhark.Util.IntegralExp (divUp, quot, rem)-import Prelude hiding (quot, rem)---- | The maximum number of operators we support in a single SegRed.--- This limit arises out of the static allocation of counters.-maxNumOps :: Int32-maxNumOps = 10---- | Code generation for the body of the SegRed, taking a continuation--- for saving the results of the body. The results should be--- represented as a pairing of a t'SubExp' along with a list of--- indexes into that t'SubExp' for reading the result.-type DoSegBody = ([(SubExp, [Imp.TExp Int64])] -> InKernelGen ()) -> InKernelGen ()---- | Compile 'SegRed' instance to host-level code with calls to--- various kernels.-compileSegRed ::- Pattern KernelsMem ->- SegLevel ->- SegSpace ->- [SegBinOp KernelsMem] ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegRed pat lvl space reds body =- compileSegRed' pat lvl space reds $ \red_cont ->- compileStms mempty (kernelBodyStms body) $ do- let (red_res, map_res) = splitAt (segBinOpResults reds) $ kernelBodyResult body-- sComment "save map-out results" $ do- let map_arrs = drop (segBinOpResults reds) $ patternElements 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 KernelsMem ->- SegLevel ->- SegSpace ->- [SegBinOp KernelsMem] ->- DoSegBody ->- CallKernelGen ()-compileSegRed' pat lvl space reds body- | genericLength reds > maxNumOps =- compilerLimitationS $- "compileSegRed': at most " ++ show maxNumOps ++ " reduction operators are supported."- | [(_, Constant (IntValue (Int64Value 1))), _] <- unSegSpace space =- nonsegmentedReduction pat num_groups group_size space reds body- | otherwise = do- let group_size' = toInt64Exp $ unCount group_size- segment_size = toInt64Exp $ last $ segSpaceDims space- use_small_segments = segment_size * 2 .<. group_size'- sIf- use_small_segments- (smallSegmentsReduction pat num_groups group_size space reds body)- (largeSegmentsReduction pat num_groups group_size space reds body)- where- num_groups = segNumGroups lvl- group_size = segGroupSize lvl---- | Prepare intermediate arrays for the reduction. Prim-typed--- arguments go in local memory (so we need to do the allocation of--- those arrays inside the kernel), while array-typed arguments go in--- global memory. Allocations for the former have already been--- performed. This policy is baked into how the allocations are done--- in ExplicitAllocations.-intermediateArrays ::- Count GroupSize SubExp ->- SubExp ->- SegBinOp KernelsMem ->- InKernelGen [VName]-intermediateArrays (Count group_size) num_threads (SegBinOp _ red_op nes _) = do- let red_op_params = lambdaParams red_op- (red_acc_params, _) = splitAt (length nes) red_op_params- forM red_acc_params $ \p ->- case paramDec p of- MemArray pt shape _ (ArrayIn mem _) -> do- let shape' = Shape [num_threads] <> shape- sArray "red_arr" pt shape' $- ArrayIn mem $ IxFun.iota $ map pe64 $ shapeDims shape'- _ -> do- let pt = elemType $ paramType p- shape = Shape [group_size]- sAllocArray "red_arr" pt shape $ Space "local"---- | Arrays for storing group results.------ The group-result arrays have an extra dimension (of size groupsize)--- because they are also used for keeping vectorised accumulators for--- first-stage reduction, if necessary. When actually storing group--- results, the first index is set to 0.-groupResultArrays ::- Count NumGroups SubExp ->- Count GroupSize SubExp ->- [SegBinOp KernelsMem] ->- CallKernelGen [[VName]]-groupResultArrays (Count virt_num_groups) (Count group_size) reds =- forM reds $ \(SegBinOp _ lam _ shape) ->- forM (lambdaReturnType lam) $ \t -> do- let pt = elemType t- full_shape = Shape [group_size, virt_num_groups] <> shape <> arrayShape t- -- Move the groupsize dimension last to ensure coalesced- -- memory access.- perm = [1 .. shapeRank full_shape -1] ++ [0]- sAllocArrayPerm "group_res_arr" pt full_shape (Space "device") perm--nonsegmentedReduction ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [SegBinOp KernelsMem] ->- DoSegBody ->- CallKernelGen ()-nonsegmentedReduction segred_pat num_groups group_size space reds body = do- let (gtids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims- num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size- global_tid = Imp.vi64 $ segFlat space- w = last dims'-- counter <-- sStaticArray "counter" (Space "device") int32 $- Imp.ArrayValues $ replicate (fromIntegral maxNumOps) $ IntValue $ Int32Value 0-- reds_group_res_arrs <- groupResultArrays num_groups group_size reds-- num_threads <-- dPrimV "num_threads" $- unCount num_groups' * unCount group_size'-- emit $ Imp.DebugPrint "\n# SegRed" Nothing-- sKernelThread "segred_nonseg" num_groups' group_size' (segFlat space) $ do- constants <- kernelConstants <$> askEnv- sync_arr <- sAllocArray "sync_arr" Bool (Shape [intConst Int32 1]) $ Space "local"- reds_arrs <- mapM (intermediateArrays group_size (tvSize num_threads)) reds-- -- Since this is the nonsegmented case, all outer segment IDs must- -- necessarily be 0.- forM_ gtids $ \v -> dPrimV_ v (0 :: Imp.TExp Int64)-- let num_elements = Imp.elements w- elems_per_thread =- num_elements- `divUp` Imp.elements (sExt64 (kernelNumThreads constants))-- slugs <-- mapM (segBinOpSlug (kernelLocalThreadId constants) (kernelGroupId constants)) $- zip3 reds reds_arrs reds_group_res_arrs- reds_op_renamed <-- reductionStageOne- constants- (zip gtids dims')- num_elements- global_tid- elems_per_thread- (tvVar num_threads)- slugs- body-- let segred_pes =- chunks (map (length . segBinOpNeutral) reds) $- patternElements 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- reductionStageTwo- constants- pes- (kernelGroupId constants)- 0- [0]- 0- (sExt64 $ kernelNumGroups constants)- slug- red_x_params- red_y_params- red_op_renamed- nes- 1- counter- (fromInteger i)- sync_arr- group_res_arrs- red_arrs-- emit $ Imp.DebugPrint "" Nothing--smallSegmentsReduction ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [SegBinOp KernelsMem] ->- DoSegBody ->- CallKernelGen ()-smallSegmentsReduction (Pattern _ segred_pes) num_groups group_size space reds body = do- let (gtids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims- segment_size = last dims'-- -- Careful to avoid division by zero now.- segment_size_nonzero <-- dPrimVE "segment_size_nonzero" $ sMax64 1 segment_size-- let num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size- num_threads <- dPrimV "num_threads" $ unCount num_groups' * unCount group_size'- let num_segments = product $ init dims'- segments_per_group = unCount group_size' `quot` segment_size_nonzero- required_groups = sExt32 $ num_segments `divUp` segments_per_group-- emit $ Imp.DebugPrint "\n# SegRed-small" Nothing- emit $ Imp.DebugPrint "num_segments" $ Just $ untyped num_segments- emit $ Imp.DebugPrint "segment_size" $ Just $ untyped segment_size- emit $ Imp.DebugPrint "segments_per_group" $ Just $ untyped segments_per_group- emit $ Imp.DebugPrint "required_groups" $ Just $ untyped required_groups-- sKernelThread "segred_small" num_groups' group_size' (segFlat space) $ do- constants <- kernelConstants <$> askEnv- reds_arrs <- mapM (intermediateArrays group_size (Var $ tvVar num_threads)) reds-- -- We probably do not have enough actual workgroups to cover the- -- entire iteration space. Some groups thus have to perform double- -- duty; we put an outer loop to accomplish this.- virtualiseGroups SegVirt required_groups $ \group_id' -> do- -- Compute the 'n' input indices. The outer 'n-1' correspond to- -- the segment ID, and are computed from the group id. The inner- -- is computed from the local thread id, and may be out-of-bounds.- let ltid = sExt64 $ kernelLocalThreadId constants- segment_index =- (ltid `quot` segment_size_nonzero)- + (sExt64 group_id' * sExt64 segments_per_group)- index_within_segment = ltid `rem` segment_size-- dIndexSpace (zip (init gtids) (init dims')) segment_index- dPrimV_ (last gtids) index_within_segment-- let out_of_bounds =- forM_ (zip reds reds_arrs) $ \(SegBinOp _ _ nes _, red_arrs) ->- forM_ (zip red_arrs nes) $ \(arr, ne) ->- copyDWIMFix arr [ltid] ne []-- in_bounds =- body $ \red_res ->- sComment "save results to be reduced" $ do- let red_dests = zip (concat reds_arrs) $ repeat [ltid]- forM_ (zip red_dests red_res) $ \((d, d_is), (res, res_is)) ->- copyDWIMFix d d_is res res_is-- sComment "apply map function if in bounds" $- sIf- ( segment_size .>. 0- .&&. isActive (init $ zip gtids dims)- .&&. ltid .<. segment_size * segments_per_group- )- in_bounds- out_of_bounds-- sOp $ Imp.ErrorSync Imp.FenceLocal -- Also implicitly barrier.- let crossesSegment from to =- (sExt64 to - sExt64 from) .>. (sExt64 to `rem` segment_size)- sWhen (segment_size .>. 0) $- sComment "perform segmented scan to imitate reduction" $- forM_ (zip reds reds_arrs) $ \(SegBinOp _ red_op _ _, red_arrs) ->- groupScan- (Just crossesSegment)- (sExt64 $ tvExp num_threads)- (segment_size * segments_per_group)- red_op- red_arrs-- sOp $ Imp.Barrier Imp.FenceLocal-- sComment "save final values of segments" $- sWhen- ( sExt64 group_id' * segments_per_group + sExt64 ltid .<. num_segments- .&&. ltid .<. segments_per_group- )- $ forM_ (zip segred_pes (concat reds_arrs)) $ \(pe, arr) -> do- -- Figure out which segment result this thread should write...- let flat_segment_index =- sExt64 group_id' * segments_per_group + sExt64 ltid- gtids' =- unflattenIndex (init dims') flat_segment_index- copyDWIMFix- (patElemName pe)- gtids'- (Var arr)- [(ltid + 1) * segment_size_nonzero - 1]-- -- Finally another barrier, because we will be writing to the- -- local memory array first thing in the next iteration.- sOp $ Imp.Barrier Imp.FenceLocal-- emit $ Imp.DebugPrint "" Nothing--largeSegmentsReduction ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [SegBinOp KernelsMem] ->- DoSegBody ->- CallKernelGen ()-largeSegmentsReduction segred_pat num_groups group_size space reds body = do- let (gtids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims- num_segments = product $ init dims'- segment_size = last dims'- num_groups' = fmap toInt64Exp num_groups- group_size' = fmap toInt64Exp group_size-- (groups_per_segment, elems_per_thread) <-- groupsPerSegmentAndElementsPerThread- segment_size- num_segments- num_groups'- group_size'- virt_num_groups <-- dPrimV "virt_num_groups" $- groups_per_segment * num_segments-- num_threads <-- dPrimV "num_threads" $- unCount num_groups' * unCount group_size'-- threads_per_segment <-- dPrimV "threads_per_segment" $- groups_per_segment * unCount group_size'-- emit $ Imp.DebugPrint "\n# SegRed-large" Nothing- emit $ Imp.DebugPrint "num_segments" $ Just $ untyped num_segments- emit $ Imp.DebugPrint "segment_size" $ Just $ untyped segment_size- emit $ Imp.DebugPrint "virt_num_groups" $ Just $ untyped $ tvExp virt_num_groups- emit $ Imp.DebugPrint "num_groups" $ Just $ untyped $ Imp.unCount num_groups'- emit $ Imp.DebugPrint "group_size" $ Just $ untyped $ Imp.unCount group_size'- emit $ Imp.DebugPrint "elems_per_thread" $ Just $ untyped $ Imp.unCount elems_per_thread- emit $ Imp.DebugPrint "groups_per_segment" $ Just $ untyped groups_per_segment-- reds_group_res_arrs <- groupResultArrays (Count (tvSize virt_num_groups)) group_size reds-- -- In principle we should have a counter for every segment. Since- -- the number of segments is a dynamic quantity, we would have to- -- allocate and zero out an array here, which is expensive.- -- However, we exploit the fact that the number of segments being- -- reduced at any point in time is limited by the number of- -- workgroups. If we bound the number of workgroups, we can get away- -- with using that many counters. FIXME: Is this limit checked- -- anywhere? There are other places in the compiler that will fail- -- if the group count exceeds the maximum group size, which is at- -- most 1024 anyway.- let num_counters = fromIntegral maxNumOps * 1024- counter <-- sStaticArray "counter" (Space "device") int32 $- Imp.ArrayZeros num_counters-- sKernelThread "segred_large" num_groups' group_size' (segFlat space) $ do- constants <- kernelConstants <$> askEnv- reds_arrs <- mapM (intermediateArrays group_size (tvSize num_threads)) reds- sync_arr <- sAllocArray "sync_arr" Bool (Shape [intConst Int32 1]) $ Space "local"-- -- We probably do not have enough actual workgroups to cover the- -- entire iteration space. Some groups thus have to perform double- -- duty; we put an outer loop to accomplish this.- virtualiseGroups SegVirt (sExt32 (tvExp virt_num_groups)) $ \group_id -> do- let segment_gtids = init gtids- w = last dims- local_tid = kernelLocalThreadId constants-- flat_segment_id <-- dPrimVE "flat_segment_id" $- group_id `quot` sExt32 groups_per_segment-- global_tid <-- dPrimVE "global_tid" $- (sExt64 group_id * sExt64 (unCount group_size') + sExt64 local_tid)- `rem` (sExt64 (unCount group_size') * groups_per_segment)-- let first_group_for_segment = sExt64 flat_segment_id * groups_per_segment- dIndexSpace (zip segment_gtids (init dims')) $sExt64 flat_segment_id- dPrim_ (last gtids) int64- let num_elements = Imp.elements $ toInt64Exp w-- slugs <-- mapM (segBinOpSlug local_tid group_id) $- zip3 reds reds_arrs reds_group_res_arrs- reds_op_renamed <-- reductionStageOne- constants- (zip gtids dims')- num_elements- global_tid- elems_per_thread- (tvVar threads_per_segment)- slugs- body-- let segred_pes =- chunks (map (length . segBinOpNeutral) reds) $- patternElements segred_pat-- multiple_groups_per_segment =- 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- reductionStageTwo- constants- pes- group_id- flat_segment_id- (map Imp.vi64 segment_gtids)- (sExt64 first_group_for_segment)- groups_per_segment- slug- red_x_params- red_y_params- red_op_renamed- nes- (fromIntegral num_counters)- counter- (fromInteger i)- sync_arr- group_res_arrs- red_arrs-- one_group_per_segment =- comment "first thread in group saves final result to memory" $- forM_ (zip slugs segred_pes) $ \(slug, pes) ->- sWhen (local_tid .==. 0) $- forM_ (zip pes (slugAccs slug)) $ \(v, (acc, acc_is)) ->- copyDWIMFix (patElemName v) (map Imp.vi64 segment_gtids) (Var acc) acc_is-- sIf (groups_per_segment .==. 1) one_group_per_segment multiple_groups_per_segment-- emit $ Imp.DebugPrint "" Nothing---- Careful to avoid division by zero here. We have at least one group--- per segment.-groupsPerSegmentAndElementsPerThread ::- Imp.TExp Int64 ->- Imp.TExp Int64 ->- Count NumGroups (Imp.TExp Int64) ->- Count GroupSize (Imp.TExp Int64) ->- CallKernelGen- ( Imp.TExp Int64,- Imp.Count Imp.Elements (Imp.TExp Int64)- )-groupsPerSegmentAndElementsPerThread segment_size num_segments num_groups_hint group_size = do- groups_per_segment <-- dPrimVE "groups_per_segment" $- unCount num_groups_hint `divUp` sMax64 1 num_segments- elements_per_thread <-- dPrimVE "elements_per_thread" $- segment_size `divUp` (unCount group_size * groups_per_segment)- return (groups_per_segment, Imp.elements elements_per_thread)---- | A SegBinOp with auxiliary information.-data SegBinOpSlug = SegBinOpSlug- { slugOp :: SegBinOp KernelsMem,- -- | The arrays used for computing the intra-group reduction- -- (either local or global memory).- slugArrs :: [VName],- -- | Places to store accumulator in stage 1 reduction.- slugAccs :: [(VName, [Imp.TExp Int64])]- }--slugBody :: SegBinOpSlug -> Body KernelsMem-slugBody = lambdaBody . segBinOpLambda . slugOp--slugParams :: SegBinOpSlug -> [LParam KernelsMem]-slugParams = lambdaParams . segBinOpLambda . slugOp--slugNeutral :: SegBinOpSlug -> [SubExp]-slugNeutral = segBinOpNeutral . slugOp--slugShape :: SegBinOpSlug -> Shape-slugShape = segBinOpShape . slugOp--slugsComm :: [SegBinOpSlug] -> Commutativity-slugsComm = mconcat . map (segBinOpComm . slugOp)--accParams, nextParams :: SegBinOpSlug -> [LParam KernelsMem]-accParams slug = take (length (slugNeutral slug)) $ slugParams slug-nextParams slug = drop (length (slugNeutral slug)) $ slugParams slug--segBinOpSlug :: Imp.TExp Int32 -> Imp.TExp Int32 -> (SegBinOp KernelsMem, [VName], [VName]) -> InKernelGen SegBinOpSlug-segBinOpSlug local_tid group_id (op, group_res_arrs, param_arrs) =- SegBinOpSlug op group_res_arrs- <$> zipWithM mkAcc (lambdaParams (segBinOpLambda op)) param_arrs- where- mkAcc p param_arr- | Prim t <- paramType p,- shapeRank (segBinOpShape op) == 0 = do- acc <- dPrim (baseString (paramName p) <> "_acc") t- return (tvVar acc, [])- | otherwise =- return (param_arr, [sExt64 local_tid, sExt64 group_id])--reductionStageZero ::- KernelConstants ->- [(VName, Imp.TExp Int64)] ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- Imp.TExp Int64 ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- VName ->- [SegBinOpSlug] ->- DoSegBody ->- InKernelGen ([Lambda KernelsMem], InKernelGen ())-reductionStageZero constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body = do- let (gtids, _dims) = unzip ispace- gtid = mkTV (last gtids) int64- local_tid = sExt64 $ kernelLocalThreadId constants-- -- Figure out how many elements this thread should process.- chunk_size <- dPrim "chunk_size" int64- let ordering = case slugsComm slugs of- Commutative -> SplitStrided $ Var threads_per_segment- Noncommutative -> SplitContiguous- computeThreadChunkSize ordering (sExt64 global_tid) elems_per_thread num_elements chunk_size-- dScope Nothing $ scopeOfLParams $ concatMap slugParams slugs-- sComment "neutral-initialise the accumulators" $- forM_ slugs $ \slug ->- forM_ (zip (slugAccs slug) (slugNeutral slug)) $ \((acc, acc_is), ne) ->- sLoopNest (slugShape slug) $ \vec_is ->- copyDWIMFix acc (acc_is ++ vec_is) ne []-- slugs_op_renamed <- mapM (renameLambda . segBinOpLambda . slugOp) slugs-- let doTheReduction =- forM_ (zip slugs_op_renamed slugs) $ \(slug_op_renamed, slug) ->- sLoopNest (slugShape slug) $ \vec_is -> do- comment "to reduce current chunk, first store our result in memory" $ do- forM_ (zip (slugParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->- copyDWIMFix (paramName p) [] (Var acc) (acc_is ++ vec_is)-- forM_ (zip (slugArrs slug) (slugParams slug)) $ \(arr, p) ->- when (primType $ paramType p) $- copyDWIMFix arr [local_tid] (Var $ paramName p) []-- sOp $ Imp.ErrorSync Imp.FenceLocal -- Also implicitly barrier.- groupReduce (sExt32 (kernelGroupSize constants)) slug_op_renamed (slugArrs slug)-- sOp $ Imp.Barrier Imp.FenceLocal-- sComment "first thread saves the result in accumulator" $- sWhen (local_tid .==. 0) $- forM_ (zip (slugAccs slug) (lambdaParams slug_op_renamed)) $ \((acc, acc_is), p) ->- copyDWIMFix acc (acc_is ++ vec_is) (Var $ paramName p) []-- -- If this is a non-commutative reduction, each thread must run the- -- loop the same number of iterations, because we will be performing- -- a group-wide reduction in there.- let comm = slugsComm slugs- (bound, check_bounds) =- case comm of- Commutative -> (tvExp chunk_size, id)- Noncommutative ->- ( Imp.unCount elems_per_thread,- sWhen (tvExp gtid .<. Imp.unCount num_elements)- )-- sFor "i" bound $ \i -> do- gtid- <-- case comm of- Commutative ->- global_tid + Imp.vi64 threads_per_segment * i- Noncommutative ->- let index_in_segment = global_tid `quot` kernelGroupSize constants- in sExt64 local_tid- + (index_in_segment * Imp.unCount elems_per_thread + i)- * kernelGroupSize constants-- check_bounds $- sComment "apply map function" $- body $ \all_red_res -> do- let slugs_res = chunks (map (length . slugNeutral) slugs) all_red_res-- forM_ (zip slugs slugs_res) $ \(slug, red_res) ->- sLoopNest (slugShape slug) $ \vec_is -> do- sComment "load accumulator" $- forM_ (zip (accParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->- copyDWIMFix (paramName p) [] (Var acc) (acc_is ++ vec_is)- sComment "load new values" $- forM_ (zip (nextParams slug) red_res) $ \(p, (res, res_is)) ->- copyDWIMFix (paramName p) [] res (res_is ++ vec_is)- sComment "apply reduction operator" $- compileStms mempty (bodyStms $ slugBody slug) $- sComment "store in accumulator" $- forM_- ( zip- (slugAccs slug)- (bodyResult $ slugBody slug)- )- $ \((acc, acc_is), se) ->- copyDWIMFix acc (acc_is ++ vec_is) se []-- case comm of- Noncommutative -> do- doTheReduction- sComment "first thread keeps accumulator; others reset to neutral element" $ do- let reset_to_neutral =- forM_ slugs $ \slug ->- forM_ (zip (slugAccs slug) (slugNeutral slug)) $ \((acc, acc_is), ne) ->- sLoopNest (slugShape slug) $ \vec_is ->- copyDWIMFix acc (acc_is ++ vec_is) ne []- sUnless (local_tid .==. 0) reset_to_neutral- _ -> return ()-- return (slugs_op_renamed, doTheReduction)--reductionStageOne ::- KernelConstants ->- [(VName, Imp.TExp Int64)] ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- Imp.TExp Int64 ->- Imp.Count Imp.Elements (Imp.TExp Int64) ->- VName ->- [SegBinOpSlug] ->- DoSegBody ->- InKernelGen [Lambda KernelsMem]-reductionStageOne constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body = do- (slugs_op_renamed, doTheReduction) <-- reductionStageZero constants ispace num_elements global_tid elems_per_thread threads_per_segment slugs body-- case slugsComm slugs of- Noncommutative ->- forM_ slugs $ \slug ->- forM_ (zip (accParams slug) (slugAccs slug)) $ \(p, (acc, acc_is)) ->- copyDWIMFix (paramName p) [] (Var acc) acc_is- _ -> doTheReduction-- return slugs_op_renamed--reductionStageTwo ::- KernelConstants ->- [PatElem KernelsMem] ->- Imp.TExp Int32 ->- Imp.TExp Int32 ->- [Imp.TExp Int64] ->- Imp.TExp Int64 ->- Imp.TExp Int64 ->- SegBinOpSlug ->- [LParam KernelsMem] ->- [LParam KernelsMem] ->- Lambda KernelsMem ->- [SubExp] ->- Imp.TExp Int32 ->- VName ->- Imp.TExp Int32 ->- VName ->- [VName] ->- [VName] ->- InKernelGen ()-reductionStageTwo- constants- segred_pes- group_id- flat_segment_id- segment_gtids- first_group_for_segment- groups_per_segment- slug- red_x_params- red_y_params- red_op_renamed- nes- num_counters- counter- counter_i- sync_arr- group_res_arrs- red_arrs = do- let local_tid = kernelLocalThreadId constants- group_size = kernelGroupSize constants- old_counter <- dPrim "old_counter" int32- (counter_mem, _, counter_offset) <-- fullyIndexArray- counter- [ sExt64 $- counter_i * num_counters- + flat_segment_id `rem` num_counters- ]- comment "first thread in group saves group result to global memory" $- sWhen (local_tid .==. 0) $ do- forM_ (take (length nes) $ zip group_res_arrs (slugAccs slug)) $ \(v, (acc, acc_is)) ->- copyDWIMFix v [0, sExt64 group_id] (Var acc) acc_is- sOp $ Imp.MemFence Imp.FenceGlobal- -- Increment the counter, thus stating that our result is- -- available.- sOp $- Imp.Atomic DefaultSpace $- Imp.AtomicAdd- Int32- (tvVar old_counter)- counter_mem- counter_offset- $ untyped (1 :: Imp.TExp Int32)- -- Now check if we were the last group to write our result. If- -- so, it is our responsibility to produce the final result.- sWrite sync_arr [0] $ untyped $ tvExp old_counter .==. groups_per_segment - 1-- sOp $ Imp.Barrier Imp.FenceGlobal-- is_last_group <- dPrim "is_last_group" Bool- copyDWIMFix (tvVar is_last_group) [] (Var sync_arr) [0]- sWhen (tvExp is_last_group) $ do- -- The final group has written its result (and it was- -- us!), so read in all the group results and perform the- -- final stage of the reduction. But first, we reset the- -- counter so it is ready for next time. This is done- -- with an atomic to avoid warnings about write/write- -- races in oclgrind.- sWhen (local_tid .==. 0) $- sOp $- Imp.Atomic DefaultSpace $- Imp.AtomicAdd Int32 (tvVar old_counter) counter_mem counter_offset $- untyped $ negate groups_per_segment-- sLoopNest (slugShape slug) $ \vec_is -> do- -- There is no guarantee that the number of workgroups for the- -- segment is less than the workgroup size, so each thread may- -- have to read multiple elements. We do this in a sequential- -- way that may induce non-coalesced accesses, but the total- -- number of accesses should be tiny here.- comment "read in the per-group-results" $ do- read_per_thread <-- dPrimVE "read_per_thread" $- groups_per_segment `divUp` sExt64 group_size-- forM_ (zip red_x_params nes) $ \(p, ne) ->- copyDWIMFix (paramName p) [] ne []-- sFor "i" read_per_thread $ \i -> do- group_res_id <-- dPrimVE "group_res_id" $- sExt64 local_tid * read_per_thread + i- index_of_group_res <-- dPrimVE "index_of_group_res" $- first_group_for_segment + group_res_id-- sWhen (group_res_id .<. groups_per_segment) $ do- forM_ (zip red_y_params group_res_arrs) $- \(p, group_res_arr) ->- copyDWIMFix- (paramName p)- []- (Var group_res_arr)- ([0, index_of_group_res] ++ vec_is)-- compileStms mempty (bodyStms $ slugBody slug) $- forM_ (zip red_x_params (bodyResult $ slugBody slug)) $ \(p, se) ->- copyDWIMFix (paramName p) [] se []-- forM_ (zip red_x_params red_arrs) $ \(p, arr) ->- when (primType $ paramType p) $- copyDWIMFix arr [sExt64 local_tid] (Var $ paramName p) []-- sOp $ Imp.Barrier Imp.FenceLocal-- sComment "reduce the per-group results" $ do- groupReduce (sExt32 group_size) red_op_renamed red_arrs-- sComment "and back to memory with the final result" $- sWhen (local_tid .==. 0) $- forM_ (zip segred_pes $ lambdaParams red_op_renamed) $ \(pe, p) ->- copyDWIMFix- (patElemName pe)- (segment_gtids ++ vec_is)- (Var $ paramName p)- []
− src/Futhark/CodeGen/ImpGen/Kernels/SegScan.hs
@@ -1,68 +0,0 @@--- | Code generation for 'SegScan'. Dispatches to either a--- single-pass or two-pass implementation, depending on the nature of--- the scan and the chosen abckend.-module Futhark.CodeGen.ImpGen.Kernels.SegScan (compileSegScan) where--import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen hiding (compileProg)-import Futhark.CodeGen.ImpGen.Kernels.Base-import qualified Futhark.CodeGen.ImpGen.Kernels.SegScan.SinglePass as SinglePass-import qualified Futhark.CodeGen.ImpGen.Kernels.SegScan.TwoPass as TwoPass-import Futhark.IR.KernelsMem---- The single-pass scan does not support multiple operators, so jam--- them together here.-combineScans :: [SegBinOp KernelsMem] -> SegBinOp KernelsMem-combineScans ops =- SegBinOp- { segBinOpComm = mconcat (map segBinOpComm ops),- segBinOpLambda = lam',- segBinOpNeutral = concatMap segBinOpNeutral ops,- segBinOpShape = mempty -- Assumed- }- where- lams = map segBinOpLambda ops- xParams lam = take (length (lambdaReturnType lam)) (lambdaParams lam)- yParams lam = drop (length (lambdaReturnType lam)) (lambdaParams lam)- lam' =- Lambda- { lambdaParams = concatMap xParams lams ++ concatMap yParams lams,- lambdaReturnType = concatMap lambdaReturnType lams,- lambdaBody =- Body- ()- (mconcat (map (bodyStms . lambdaBody) lams))- (concatMap (bodyResult . lambdaBody) lams)- }--canBeSinglePass :: SegSpace -> [SegBinOp KernelsMem] -> Maybe (SegBinOp KernelsMem)-canBeSinglePass space ops- | [_] <- unSegSpace space,- all ok ops =- Just $ combineScans ops- | otherwise =- Nothing- where- ok op =- segBinOpShape op == mempty- && all primType (lambdaReturnType (segBinOpLambda op))---- | Compile 'SegScan' instance to host-level code with calls to--- various kernels.-compileSegScan ::- Pattern KernelsMem ->- SegLevel ->- SegSpace ->- [SegBinOp KernelsMem] ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegScan pat lvl space scans kbody = sWhen (0 .<. n) $ do- emit $ Imp.DebugPrint "\n# SegScan" Nothing- target <- hostTarget <$> askEnv- case target of- CUDA- | Just scan' <- canBeSinglePass space scans ->- SinglePass.compileSegScan pat lvl space scan' kbody- _ -> TwoPass.compileSegScan pat lvl space scans kbody- where- n = product $ map toInt64Exp $ segSpaceDims space
− src/Futhark/CodeGen/ImpGen/Kernels/SegScan/SinglePass.hs
@@ -1,489 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | Code generation for segmented and non-segmented scans. Uses a--- fast single-pass algorithm, but which only works on NVIDIA GPUs and--- with some constraints on the operator. We use this when we can.-module Futhark.CodeGen.ImpGen.Kernels.SegScan.SinglePass (compileSegScan) where--import Control.Monad.Except-import Data.List (zip4)-import Data.Maybe-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.Transform.Rename-import Futhark.Util (takeLast)-import Futhark.Util.IntegralExp (IntegralExp, divUp, quot)-import Prelude hiding (quot)--xParams, yParams :: SegBinOp KernelsMem -> [LParam KernelsMem]-xParams scan =- take (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))-yParams scan =- drop (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))--alignTo :: IntegralExp a => a -> a -> a-alignTo x a = (x `divUp` a) * a--createLocalArrays ::- Count GroupSize SubExp ->- SubExp ->- [PrimType] ->- InKernelGen (VName, [VName], [VName], VName, VName, [VName])-createLocalArrays (Count groupSize) m types = do- let groupSizeE = toInt64Exp groupSize- workSize = toInt64Exp m * groupSizeE- prefixArraysSize =- foldl (\acc tySize -> alignTo acc tySize + tySize * groupSizeE) 0 $- map primByteSize types- maxTransposedArraySize =- foldl1 sMax64 $ map (\ty -> workSize * primByteSize ty) types-- warpSize :: Num a => a- warpSize = 32- maxWarpExchangeSize =- foldl (\acc tySize -> alignTo acc tySize + tySize * fromInteger warpSize) 0 $- map primByteSize types- maxLookbackSize = maxWarpExchangeSize + warpSize- size = Imp.bytes $ maxLookbackSize `sMax64` prefixArraysSize `sMax64` maxTransposedArraySize-- varTE :: TV Int64 -> TPrimExp Int64 VName- varTE = le64 . tvVar-- byteOffsets <-- mapM (fmap varTE . dPrimV "byte_offsets") $- scanl (\off tySize -> alignTo off tySize + toInt64Exp groupSize * tySize) 0 $- map primByteSize types-- warpByteOffsets <-- mapM (fmap varTE . dPrimV "warp_byte_offset") $- scanl (\off tySize -> alignTo off tySize + warpSize * tySize) warpSize $- map primByteSize types-- sComment "Allocate reused shared memeory" $ return ()-- localMem <- sAlloc "local_mem" size (Space "local")- transposeArrayLength <- dPrimV "trans_arr_len" workSize-- sharedId <- sArrayInMem "shared_id" int32 (Shape [constant (1 :: Int32)]) localMem- sharedReadOffset <- sArrayInMem "shared_read_offset" int32 (Shape [constant (1 :: Int32)]) localMem-- transposedArrays <-- forM types $ \ty ->- sArrayInMem- "local_transpose_arr"- ty- (Shape [tvSize transposeArrayLength])- localMem-- prefixArrays <-- forM (zip byteOffsets types) $ \(off, ty) -> do- let off' = off `quot` primByteSize ty- sArray- "local_prefix_arr"- ty- (Shape [groupSize])- $ ArrayIn localMem $ IxFun.iotaOffset off' [pe64 groupSize]-- warpscan <- sArrayInMem "warpscan" int8 (Shape [constant (warpSize :: Int64)]) localMem- warpExchanges <-- forM (zip warpByteOffsets types) $ \(off, ty) -> do- let off' = off `quot` primByteSize ty- sArray- "warp_exchange"- ty- (Shape [constant (warpSize :: Int64)])- $ ArrayIn localMem $ IxFun.iotaOffset off' [warpSize]-- return (sharedId, transposedArrays, prefixArrays, sharedReadOffset, warpscan, warpExchanges)---- | Compile 'SegScan' instance to host-level code with calls to a--- single-pass kernel.-compileSegScan ::- Pattern KernelsMem ->- SegLevel ->- SegSpace ->- SegBinOp KernelsMem ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegScan pat lvl space scanOp kbody = do- let Pattern _ all_pes = pat- group_size = toInt64Exp <$> segGroupSize lvl- n = product $ map toInt64Exp $ segSpaceDims space- m :: Num a => a- m = 9- num_groups = Count (n `divUp` (unCount group_size * m))- num_threads = unCount num_groups * unCount group_size- (mapIdx, _) = head $ unSegSpace space- scanOpNe = segBinOpNeutral scanOp- tys = map (\(Prim pt) -> pt) $ lambdaReturnType $ segBinOpLambda scanOp- statusX, statusA, statusP :: Num a => a- statusX = 0- statusA = 1- statusP = 2- makeStatusUsed flag used = tvExp flag .|. (tvExp used .<<. 2)- unmakeStatusUsed :: TV Int8 -> TV Int8 -> TV Int8 -> InKernelGen ()- unmakeStatusUsed flagUsed flag used = do- used <-- tvExp flagUsed .>>. 2- flag <-- tvExp flagUsed .&. 3-- -- Allocate the shared memory for output component- numThreads <- dPrimV "numThreads" num_threads- numGroups <- dPrimV "numGroups" $ unCount num_groups-- globalId <- sStaticArray "id_counter" (Space "device") int32 $ Imp.ArrayZeros 1- statusFlags <- sAllocArray "status_flags" int8 (Shape [tvSize numGroups]) (Space "device")- (aggregateArrays, incprefixArrays) <-- fmap unzip $- forM tys $ \ty ->- (,) <$> sAllocArray "aggregates" ty (Shape [tvSize numGroups]) (Space "device")- <*> sAllocArray "incprefixes" ty (Shape [tvSize numGroups]) (Space "device")-- sReplicate statusFlags $ intConst Int8 statusX-- sKernelThread "segscan" num_groups group_size (segFlat space) $ do- constants <- kernelConstants <$> askEnv-- (sharedId, transposedArrays, prefixArrays, sharedReadOffset, warpscan, exchanges) <-- createLocalArrays (segGroupSize lvl) (intConst Int64 m) tys-- dynamicId <- dPrim "dynamic_id" int32- sWhen (kernelLocalThreadId constants .==. 0) $ do- (globalIdMem, _, globalIdOff) <- fullyIndexArray globalId [0]- sOp $- Imp.Atomic DefaultSpace $- Imp.AtomicAdd- Int32- (tvVar dynamicId)- globalIdMem- (Count $ unCount globalIdOff)- (untyped (1 :: Imp.TExp Int32))- copyDWIMFix sharedId [0] (tvSize dynamicId) []-- let localBarrier = Imp.Barrier Imp.FenceLocal- localFence = Imp.MemFence Imp.FenceLocal- globalFence = Imp.MemFence Imp.FenceGlobal-- sOp localBarrier- copyDWIMFix (tvVar dynamicId) [] (Var sharedId) [0]- sOp localBarrier-- blockOff <-- dPrimV "blockOff" $- sExt64 (tvExp dynamicId) * m * kernelGroupSize constants-- privateArrays <-- forM tys $ \ty ->- sAllocArray- "private"- ty- (Shape [intConst Int64 m])- (ScalarSpace [intConst Int64 m] ty)-- sComment "Load and map" $- sFor "i" m $ \i -> do- -- The map's input index- dPrimV_ mapIdx $- tvExp blockOff + sExt64 (kernelLocalThreadId constants)- + i * kernelGroupSize constants- -- Perform the map- let in_bounds =- compileStms mempty (kernelBodyStms kbody) $ do- let (all_scan_res, map_res) = splitAt (segBinOpResults [scanOp]) $ kernelBodyResult kbody-- -- Write map results to their global memory destinations- forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(dest, src) ->- copyDWIMFix (patElemName dest) [Imp.vi64 mapIdx] (kernelResultSubExp src) []-- -- Write to-scan results to private memory.- forM_ (zip privateArrays $ map kernelResultSubExp all_scan_res) $ \(dest, src) ->- copyDWIMFix dest [i] src []-- out_of_bounds =- forM_ (zip privateArrays scanOpNe) $ \(dest, ne) ->- copyDWIMFix dest [i] ne []-- sIf (Imp.vi64 mapIdx .<. n) in_bounds out_of_bounds-- sComment "Transpose scan inputs" $ do- forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do- sOp localBarrier- sFor "i" m $ \i -> do- sharedIdx <-- dPrimVE "sharedIdx" $- sExt64 (kernelLocalThreadId constants)- + i * kernelGroupSize constants- copyDWIMFix trans [sharedIdx] (Var priv) [i]- sOp localBarrier- sFor "i" m $ \i -> do- sharedIdx <- dPrimV "sharedIdx" $ kernelLocalThreadId constants * m + i- copyDWIMFix priv [sExt64 i] (Var trans) [sExt64 $ tvExp sharedIdx]- sOp localBarrier-- sComment "Per thread scan" $- -- We don't need to touch the first element, so only m-1- -- iterations here.- sFor "i" (m -1) $ \i -> do- let xs = map paramName $ xParams scanOp- ys = map paramName $ yParams scanOp-- forM_ (zip privateArrays $ zip3 xs ys tys) $ \(src, (x, y, ty)) -> do- dPrim_ x ty- dPrim_ y ty- copyDWIMFix x [] (Var src) [i]- copyDWIMFix y [] (Var src) [i + 1]-- compileStms mempty (bodyStms $ lambdaBody $ segBinOpLambda scanOp) $- forM_ (zip privateArrays $ bodyResult $ lambdaBody $ segBinOpLambda scanOp) $ \(dest, res) ->- copyDWIMFix dest [i + 1] res []-- sComment "Publish results in shared memory" $ do- forM_ (zip prefixArrays privateArrays) $ \(dest, src) ->- copyDWIMFix dest [sExt64 $ kernelLocalThreadId constants] (Var src) [m - 1]- sOp localBarrier-- scanOp' <- renameLambda $ segBinOpLambda scanOp-- accs <- mapM (dPrim "acc") tys- sComment "Scan results (with warp scan)" $ do- groupScan- Nothing -- TODO- (tvExp numThreads)- (kernelGroupSize constants)- scanOp'- prefixArrays-- sOp localBarrier-- let firstThread acc prefixes =- copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelGroupSize constants) - 1]- notFirstThread acc prefixes =- copyDWIMFix (tvVar acc) [] (Var prefixes) [sExt64 (kernelLocalThreadId constants) - 1]- sIf- (kernelLocalThreadId constants .==. 0)- (zipWithM_ firstThread accs prefixArrays)- (zipWithM_ notFirstThread accs prefixArrays)-- sOp localBarrier-- prefixes <- forM (zip scanOpNe tys) $ \(ne, ty) ->- dPrimV "prefix" $ TPrimExp $ toExp' ty ne- sComment "Perform lookback" $ do- sWhen (tvExp dynamicId .==. 0 .&&. kernelLocalThreadId constants .==. 0) $ do- everythingVolatile $- forM_ (zip incprefixArrays accs) $ \(incprefixArray, acc) ->- copyDWIMFix incprefixArray [tvExp dynamicId] (tvSize acc) []- sOp globalFence- everythingVolatile $- copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []- forM_ (zip scanOpNe accs) $ \(ne, acc) ->- copyDWIMFix (tvVar acc) [] ne []- -- end sWhen-- let warpSize = kernelWaveSize constants- sWhen (bNot (tvExp dynamicId .==. 0) .&&. kernelLocalThreadId constants .<. warpSize) $ do- sWhen (kernelLocalThreadId constants .==. 0) $ do- everythingVolatile $- forM_ (zip aggregateArrays accs) $ \(aggregateArray, acc) ->- copyDWIMFix aggregateArray [tvExp dynamicId] (tvSize acc) []- sOp globalFence- everythingVolatile $- copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusA) []- copyDWIMFix warpscan [0] (Var statusFlags) [tvExp dynamicId - 1]- -- sWhen- sOp localFence-- status <- dPrim "status" int8 :: InKernelGen (TV Int8)- copyDWIMFix (tvVar status) [] (Var warpscan) [0]-- sIf- (tvExp status .==. statusP)- ( sWhen (kernelLocalThreadId constants .==. 0) $- everythingVolatile $- forM_ (zip prefixes incprefixArrays) $ \(prefix, incprefixArray) ->- copyDWIMFix (tvVar prefix) [] (Var incprefixArray) [tvExp dynamicId - 1]- )- ( do- readOffset <-- dPrimV "readOffset" $- sExt32 $ tvExp dynamicId - sExt64 (kernelWaveSize constants)- let loopStop = warpSize * (-1)- sWhile (tvExp readOffset .>. loopStop) $ do- readI <- dPrimV "read_i" $ tvExp readOffset + kernelLocalThreadId constants- aggrs <- forM (zip scanOpNe tys) $ \(ne, ty) ->- dPrimV "aggr" $ TPrimExp $ toExp' ty ne- flag <- dPrimV "flag" statusX- used <- dPrimV "used" (0 :: Imp.TExp Int8)- everythingVolatile $- sWhen (tvExp readI .>=. 0) $ do- copyDWIMFix (tvVar flag) [] (Var statusFlags) [sExt64 $ tvExp readI]- sIf- (tvExp flag .==. statusP)- ( forM_ (zip incprefixArrays aggrs) $ \(incprefix, aggr) ->- copyDWIMFix (tvVar aggr) [] (Var incprefix) [sExt64 $ tvExp readI]- )- ( sWhen (tvExp flag .==. statusA) $ do- forM_ (zip aggrs aggregateArrays) $ \(aggr, aggregate) ->- copyDWIMFix (tvVar aggr) [] (Var aggregate) [sExt64 $ tvExp readI]- used <-- (1 :: Imp.TExp Int8)- )- -- end sIf- -- end sWhen- forM_ (zip exchanges aggrs) $ \(exchange, aggr) ->- copyDWIMFix exchange [sExt64 $ kernelLocalThreadId constants] (tvSize aggr) []- tmp <- dPrimV "tmp" $ makeStatusUsed flag used- copyDWIMFix warpscan [sExt64 $ kernelLocalThreadId constants] (tvSize tmp) []- sOp localFence-- (warpscanMem, warpscanSpace, warpscanOff) <-- fullyIndexArray warpscan [sExt64 warpSize - 1]- flag <-- TPrimExp (Imp.index warpscanMem warpscanOff int8 warpscanSpace Imp.Volatile)- sWhen (kernelLocalThreadId constants .==. 0) $ do- -- TODO: This is a single-threaded reduce- sIf- (bNot $ tvExp flag .==. statusP)- ( do- scanOp'' <- renameLambda scanOp'- let (agg1s, agg2s) = splitAt (length tys) $ map paramName $ lambdaParams scanOp''-- forM_ (zip3 agg1s scanOpNe tys) $ \(agg1, ne, ty) ->- dPrimV_ agg1 $ TPrimExp $ toExp' ty ne- zipWithM_ dPrim_ agg2s tys-- flag1 <- dPrimV "flag1" statusX- flag2 <- dPrim "flag2" int8- used1 <- dPrimV "used1" (0 :: Imp.TExp Int8)- used2 <- dPrim "used2" int8- sFor "i" warpSize $ \i -> do- copyDWIMFix (tvVar flag2) [] (Var warpscan) [sExt64 i]- unmakeStatusUsed flag2 flag2 used2- forM_ (zip agg2s exchanges) $ \(agg2, exchange) ->- copyDWIMFix agg2 [] (Var exchange) [sExt64 i]- sIf- (bNot $ tvExp flag2 .==. statusA)- ( do- flag1 <-- tvExp flag2- used1 <-- tvExp used2- forM_ (zip3 agg1s tys agg2s) $ \(agg1, ty, agg2) ->- agg1 <~~ toExp' ty (Var agg2)- )- ( do- used1 <-- tvExp used1 + tvExp used2- compileStms mempty (bodyStms $ lambdaBody scanOp'') $- forM_ (zip3 agg1s tys $ bodyResult $ lambdaBody scanOp'') $- \(agg1, ty, res) -> agg1 <~~ toExp' ty res- )- flag <-- tvExp flag1- used <-- tvExp used1- forM_ (zip3 aggrs tys agg1s) $ \(aggr, ty, agg1) ->- tvVar aggr <~~ toExp' ty (Var agg1)- )- -- else- ( forM_ (zip aggrs exchanges) $ \(aggr, exchange) ->- copyDWIMFix (tvVar aggr) [] (Var exchange) [sExt64 warpSize - 1]- )- -- end sIf- sIf- (tvExp flag .==. statusP)- (readOffset <-- loopStop)- (readOffset <-- tvExp readOffset - zExt32 (tvExp used))- copyDWIMFix sharedReadOffset [0] (tvSize readOffset) []- scanOp''' <- renameLambda scanOp'- let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scanOp'''- 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''') $- \(prefix, ty, res) -> prefix <-- TPrimExp (toExp' ty res)- -- end sWhen- sOp localFence- copyDWIMFix (tvVar readOffset) [] (Var sharedReadOffset) [0]- )- -- end sWhile- -- end sIf- sWhen (kernelLocalThreadId constants .==. 0) $ do- scanOp'''' <- renameLambda scanOp'- let xs = map paramName $ take (length tys) $ lambdaParams scanOp''''- ys = map paramName $ drop (length tys) $ lambdaParams scanOp''''- forM_ (zip xs prefixes) $ \(x, prefix) -> dPrimV_ x $ tvExp prefix- forM_ (zip ys accs) $ \(y, acc) -> dPrimV_ y $ tvExp acc- compileStms mempty (bodyStms $ lambdaBody scanOp'''') $- everythingVolatile $- forM_ (zip incprefixArrays $ bodyResult $ lambdaBody scanOp'''') $- \(incprefixArray, res) -> copyDWIMFix incprefixArray [tvExp dynamicId] res []- sOp globalFence- everythingVolatile $ copyDWIMFix statusFlags [tvExp dynamicId] (intConst Int8 statusP) []- forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->- copyDWIMFix exchange [0] (tvSize prefix) []- forM_ (zip3 accs tys scanOpNe) $ \(acc, ty, ne) ->- tvVar acc <~~ toExp' ty ne- -- end sWhen- -- end sWhen-- sWhen (bNot $ tvExp dynamicId .==. 0) $ do- sOp localBarrier- forM_ (zip exchanges prefixes) $ \(exchange, prefix) ->- copyDWIMFix (tvVar prefix) [] (Var exchange) [0]- sOp localBarrier- -- end sWhen- -- end sComment-- scanOp''''' <- renameLambda scanOp'- scanOp'''''' <- renameLambda scanOp'-- sComment "Distribute results" $ do- let (xs, ys) = splitAt (length tys) $ map paramName $ lambdaParams scanOp'''''- (xs', ys') = splitAt (length tys) $ map paramName $ lambdaParams scanOp''''''-- forM_ (zip4 (zip prefixes accs) (zip xs xs') (zip ys ys') tys) $- \((prefix, acc), (x, x'), (y, y'), ty) -> do- dPrim_ x ty- dPrim_ y ty- dPrimV_ x' $ tvExp prefix- dPrimV_ y' $ tvExp acc-- compileStms mempty (bodyStms $ lambdaBody scanOp'''''') $- forM_ (zip3 xs tys $ bodyResult $ lambdaBody scanOp'''''') $- \(x, ty, res) -> x <~~ toExp' ty res-- sFor "i" m $ \i -> do- forM_ (zip privateArrays ys) $ \(src, y) ->- copyDWIMFix y [] (Var src) [i]-- compileStms mempty (bodyStms $ lambdaBody scanOp''''') $- forM_ (zip privateArrays $ bodyResult $ lambdaBody scanOp''''') $- \(dest, res) ->- copyDWIMFix dest [i] res []-- sComment "Transpose scan output" $ do- forM_ (zip transposedArrays privateArrays) $ \(trans, priv) -> do- sOp localBarrier- sFor "i" m $ \i -> do- sharedIdx <-- dPrimV "sharedIdx" $- sExt64 (kernelLocalThreadId constants * m) + i- copyDWIMFix trans [tvExp sharedIdx] (Var priv) [i]- sOp localBarrier- sFor "i" m $ \i -> do- sharedIdx <-- dPrimV "sharedIdx" $- kernelLocalThreadId constants- + sExt32 (kernelGroupSize constants * i)- copyDWIMFix priv [i] (Var trans) [sExt64 $ tvExp sharedIdx]- sOp localBarrier-- sComment "Write block scan results to global memory" $- forM_ (zip (map patElemName all_pes) privateArrays) $ \(dest, src) ->- sFor "i" m $ \i -> do- dPrimV_ mapIdx $- tvExp blockOff + kernelGroupSize constants * i- + sExt64 (kernelLocalThreadId constants)- sWhen (Imp.vi64 mapIdx .<. n) $- copyDWIMFix dest [Imp.vi64 mapIdx] (Var src) [i]-- sComment "If this is the last block, reset the dynamicId" $- sWhen (tvExp dynamicId .==. unCount num_groups - 1) $- copyDWIMFix globalId [0] (constant (0 :: Int32)) []
− src/Futhark/CodeGen/ImpGen/Kernels/SegScan/TwoPass.hs
@@ -1,506 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | Code generation for segmented and non-segmented scans. Uses a--- fairly inefficient two-pass algorithm, but can handle anything.-module Futhark.CodeGen.ImpGen.Kernels.SegScan.TwoPass (compileSegScan) where--import Control.Monad.Except-import Control.Monad.State-import Data.List (delete, find, foldl', zip4)-import Data.Maybe-import qualified Futhark.CodeGen.ImpCode.Kernels as Imp-import Futhark.CodeGen.ImpGen-import Futhark.CodeGen.ImpGen.Kernels.Base-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.Transform.Rename-import Futhark.Util (takeLast)-import Futhark.Util.IntegralExp (divUp, quot, rem)-import Prelude hiding (quot, rem)---- Aggressively try to reuse memory for different SegBinOps, because--- we will run them sequentially after another.-makeLocalArrays ::- Count GroupSize SubExp ->- SubExp ->- [SegBinOp KernelsMem] ->- InKernelGen [[VName]]-makeLocalArrays (Count group_size) num_threads scans = do- (arrs, mems_and_sizes) <- runStateT (mapM onScan scans) mempty- let maxSize sizes = Imp.bytes $ foldl' sMax64 1 $ map Imp.unCount sizes- forM_ mems_and_sizes $ \(sizes, mem) ->- sAlloc_ mem (maxSize sizes) (Space "local")- return arrs- where- onScan (SegBinOp _ scan_op nes _) = do- let (scan_x_params, _scan_y_params) =- splitAt (length nes) $ lambdaParams scan_op- (arrs, used_mems) <- fmap unzip $- forM scan_x_params $ \p ->- case paramDec p of- MemArray pt shape _ (ArrayIn mem _) -> do- let shape' = Shape [num_threads] <> shape- arr <-- lift $- sArray "scan_arr" pt shape' $- ArrayIn mem $ IxFun.iota $ map pe64 $ shapeDims shape'- return (arr, [])- _ -> do- let pt = elemType $ paramType p- shape = Shape [group_size]- (sizes, mem') <- getMem pt shape- arr <- lift $ sArrayInMem "scan_arr" pt shape mem'- return (arr, [(sizes, mem')])- modify (<> concat used_mems)- return arrs-- getMem pt shape = do- let size = typeSize $ Array pt shape NoUniqueness- mems <- get- case (find ((size `elem`) . fst) mems, mems) of- (Just mem, _) -> do- modify $ delete mem- return mem- (Nothing, (size', mem) : mems') -> do- put mems'- return (size : size', mem)- (Nothing, []) -> do- mem <- lift $ sDeclareMem "scan_arr_mem" $ Space "local"- return ([size], mem)--type CrossesSegment = Maybe (Imp.TExp Int64 -> Imp.TExp Int64 -> Imp.TExp Bool)--localArrayIndex :: KernelConstants -> Type -> Imp.TExp Int64-localArrayIndex constants t =- if primType t- then sExt64 (kernelLocalThreadId constants)- else sExt64 (kernelGlobalThreadId constants)--barrierFor :: Lambda KernelsMem -> (Bool, Imp.Fence, InKernelGen ())-barrierFor scan_op = (array_scan, fence, sOp $ Imp.Barrier fence)- where- array_scan = not $ all primType $ lambdaReturnType scan_op- fence- | array_scan = Imp.FenceGlobal- | otherwise = Imp.FenceLocal--xParams, yParams :: SegBinOp KernelsMem -> [LParam KernelsMem]-xParams scan =- take (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))-yParams scan =- drop (length (segBinOpNeutral scan)) (lambdaParams (segBinOpLambda scan))--writeToScanValues ::- [VName] ->- ([PatElem KernelsMem], SegBinOp KernelsMem, [KernelResult]) ->- InKernelGen ()-writeToScanValues gtids (pes, scan, scan_res)- | shapeRank (segBinOpShape scan) > 0 =- forM_ (zip pes scan_res) $ \(pe, res) ->- copyDWIMFix- (patElemName pe)- (map Imp.vi64 gtids)- (kernelResultSubExp res)- []- | otherwise =- forM_ (zip (yParams scan) scan_res) $ \(p, res) ->- copyDWIMFix (paramName p) [] (kernelResultSubExp res) []--readToScanValues ::- [Imp.TExp Int64] ->- [PatElem KernelsMem] ->- SegBinOp KernelsMem ->- InKernelGen ()-readToScanValues is pes scan- | shapeRank (segBinOpShape scan) > 0 =- forM_ (zip (yParams scan) pes) $ \(p, pe) ->- copyDWIMFix (paramName p) [] (Var (patElemName pe)) is- | otherwise =- return ()--readCarries ::- Imp.TExp Int64 ->- [Imp.TExp Int64] ->- [Imp.TExp Int64] ->- [PatElem KernelsMem] ->- SegBinOp KernelsMem ->- InKernelGen ()-readCarries chunk_offset dims' vec_is pes scan- | shapeRank (segBinOpShape scan) > 0 = do- ltid <- kernelLocalThreadId . kernelConstants <$> askEnv- -- We may have to reload the carries from the output of the- -- previous chunk.- sIf- (chunk_offset .>. 0 .&&. ltid .==. 0)- ( do- let is = unflattenIndex dims' $ chunk_offset - 1- forM_ (zip (xParams scan) pes) $ \(p, pe) ->- copyDWIMFix (paramName p) [] (Var (patElemName pe)) (is ++ vec_is)- )- ( forM_ (zip (xParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->- copyDWIMFix (paramName p) [] ne []- )- | otherwise =- return ()---- | Produce partially scanned intervals; one per workgroup.-scanStage1 ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- SegSpace ->- [SegBinOp KernelsMem] ->- KernelBody KernelsMem ->- CallKernelGen (TV Int32, Imp.TExp Int64, CrossesSegment)-scanStage1 (Pattern _ 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'-- let (gtids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims- let num_elements = product dims'- elems_per_thread = num_elements `divUp` sExt64 (tvExp num_threads)- elems_per_group = unCount group_size' * elems_per_thread-- let crossesSegment =- case reverse dims' of- segment_size : _ : _ -> Just $ \from to ->- (to - from) .>. (to `rem` segment_size)- _ -> Nothing-- sKernelThread "scan_stage1" num_groups' group_size' (segFlat space) $ do- constants <- kernelConstants <$> askEnv- all_local_arrs <- makeLocalArrays group_size (tvSize num_threads) scans-- -- The variables from scan_op will be used for the carry and such- -- in the big chunking loop.- forM_ scans $ \scan -> do- dScope Nothing $ scopeOfLParams $ lambdaParams $ segBinOpLambda scan- forM_ (zip (xParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->- copyDWIMFix (paramName p) [] ne []-- sFor "j" elems_per_thread $ \j -> do- chunk_offset <-- dPrimV "chunk_offset" $- sExt64 (kernelGroupSize constants) * j- + sExt64 (kernelGroupId constants) * elems_per_group- flat_idx <-- dPrimV "flat_idx" $- tvExp chunk_offset + sExt64 (kernelLocalThreadId constants)- -- Construct segment indices.- zipWithM_ dPrimV_ gtids $ unflattenIndex dims' $ tvExp flat_idx-- let per_scan_pes = segBinOpChunks scans all_pes-- in_bounds =- foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'-- when_in_bounds = compileStms mempty (kernelBodyStms kbody) $ do- let (all_scan_res, map_res) =- splitAt (segBinOpResults scans) $ kernelBodyResult kbody- per_scan_res =- segBinOpChunks scans all_scan_res-- sComment "write to-scan values to parameters" $- mapM_ (writeToScanValues gtids) $- zip3 per_scan_pes scans per_scan_res-- sComment "write mapped values results to global memory" $- forM_ (zip (takeLast (length map_res) all_pes) map_res) $ \(pe, se) ->- copyDWIMFix- (patElemName pe)- (map Imp.vi64 gtids)- (kernelResultSubExp se)- []-- sComment "threads in bounds read input" $- sWhen in_bounds when_in_bounds-- forM_ (zip3 per_scan_pes scans all_local_arrs) $- \(pes, scan@(SegBinOp _ scan_op nes vec_shape), local_arrs) ->- sComment "do one intra-group scan operation" $ do- let rets = lambdaReturnType scan_op- scan_x_params = xParams scan- (array_scan, fence, barrier) = barrierFor scan_op-- when array_scan barrier-- sLoopNest vec_shape $ \vec_is -> do- sComment "maybe restore some to-scan values to parameters, or read neutral" $- sIf- in_bounds- ( do- readToScanValues (map Imp.vi64 gtids ++ vec_is) pes scan- readCarries (tvExp chunk_offset) dims' vec_is pes scan- )- ( forM_ (zip (yParams scan) (segBinOpNeutral scan)) $ \(p, ne) ->- copyDWIMFix (paramName p) [] ne []- )-- sComment "combine with carry and write to local memory" $- compileStms mempty (bodyStms $ lambdaBody scan_op) $- forM_ (zip3 rets local_arrs (bodyResult $ lambdaBody scan_op)) $- \(t, arr, se) ->- copyDWIMFix arr [localArrayIndex constants t] se []-- let crossesSegment' = do- f <- crossesSegment- Just $ \from to ->- let from' = sExt64 from + tvExp chunk_offset- to' = sExt64 to + tvExp chunk_offset- in f from' to'-- sOp $ Imp.ErrorSync fence-- -- We need to avoid parameter name clashes.- scan_op_renamed <- renameLambda scan_op- groupScan- crossesSegment'- (sExt64 $ tvExp num_threads)- (sExt64 $ kernelGroupSize constants)- scan_op_renamed- local_arrs-- sComment "threads in bounds write partial scan result" $- sWhen in_bounds $- forM_ (zip3 rets pes local_arrs) $ \(t, pe, arr) ->- copyDWIMFix- (patElemName pe)- (map Imp.vi64 gtids ++ vec_is)- (Var arr)- [localArrayIndex constants t]-- barrier-- let load_carry =- forM_ (zip local_arrs scan_x_params) $ \(arr, p) ->- copyDWIMFix- (paramName p)- []- (Var arr)- [ if primType $ paramType p- then sExt64 (kernelGroupSize constants) - 1- else- (sExt64 (kernelGroupId constants) + 1)- * sExt64 (kernelGroupSize constants) - 1- ]- load_neutral =- forM_ (zip nes scan_x_params) $ \(ne, p) ->- copyDWIMFix (paramName p) [] ne []-- sComment "first thread reads last element as carry-in for next iteration" $ do- crosses_segment <- dPrimVE "crosses_segment" $- case crossesSegment of- Nothing -> false- Just f ->- f- ( tvExp chunk_offset- + sExt64 (kernelGroupSize constants) -1- )- ( tvExp chunk_offset- + sExt64 (kernelGroupSize constants)- )- should_load_carry <-- dPrimVE "should_load_carry" $- kernelLocalThreadId constants .==. 0 .&&. bNot crosses_segment- sWhen should_load_carry load_carry- when array_scan barrier- sUnless should_load_carry load_neutral-- barrier-- return (num_threads, elems_per_group, crossesSegment)--scanStage2 ::- Pattern KernelsMem ->- TV Int32 ->- Imp.TExp Int64 ->- Count NumGroups SubExp ->- CrossesSegment ->- SegSpace ->- [SegBinOp KernelsMem] ->- CallKernelGen ()-scanStage2 (Pattern _ all_pes) stage1_num_threads elems_per_group num_groups crossesSegment space scans = do- let (gtids, dims) = unzip $ unSegSpace space- dims' = map toInt64Exp dims-- -- Our group size is the number of groups for the stage 1 kernel.- let group_size = Count $ unCount num_groups- group_size' = fmap toInt64Exp group_size-- let crossesSegment' = do- f <- crossesSegment- Just $ \from to ->- f- ((sExt64 from + 1) * elems_per_group - 1)- ((sExt64 to + 1) * elems_per_group - 1)-- sKernelThread "scan_stage2" 1 group_size' (segFlat space) $ do- constants <- kernelConstants <$> askEnv- per_scan_local_arrs <- makeLocalArrays group_size (tvSize stage1_num_threads) scans- let per_scan_rets = map (lambdaReturnType . segBinOpLambda) scans- per_scan_pes = segBinOpChunks scans all_pes-- flat_idx <-- dPrimV "flat_idx" $- (sExt64 (kernelLocalThreadId constants) + 1) * elems_per_group - 1- -- Construct segment indices.- zipWithM_ dPrimV_ gtids $ unflattenIndex dims' $ tvExp flat_idx-- forM_ (zip4 scans per_scan_local_arrs per_scan_rets per_scan_pes) $- \(SegBinOp _ scan_op nes vec_shape, local_arrs, rets, pes) ->- sLoopNest vec_shape $ \vec_is -> do- let glob_is = map Imp.vi64 gtids ++ vec_is-- in_bounds =- foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'-- when_in_bounds = forM_ (zip3 rets local_arrs pes) $ \(t, arr, pe) ->- copyDWIMFix- arr- [localArrayIndex constants t]- (Var $ patElemName pe)- glob_is-- when_out_of_bounds = forM_ (zip3 rets local_arrs nes) $ \(t, arr, ne) ->- copyDWIMFix arr [localArrayIndex constants t] ne []- (_, _, barrier) =- barrierFor scan_op-- sComment "threads in bound read carries; others get neutral element" $- sIf in_bounds when_in_bounds when_out_of_bounds-- barrier-- groupScan- crossesSegment'- (sExt64 $ tvExp stage1_num_threads)- (sExt64 $ kernelGroupSize constants)- scan_op- local_arrs-- sComment "threads in bounds write scanned carries" $- sWhen in_bounds $- forM_ (zip3 rets pes local_arrs) $ \(t, pe, arr) ->- copyDWIMFix- (patElemName pe)- glob_is- (Var arr)- [localArrayIndex constants t]--scanStage3 ::- Pattern KernelsMem ->- Count NumGroups SubExp ->- Count GroupSize SubExp ->- Imp.TExp Int64 ->- CrossesSegment ->- SegSpace ->- [SegBinOp KernelsMem] ->- CallKernelGen ()-scanStage3 (Pattern _ 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- dims' = map toInt64Exp dims- required_groups <-- dPrimVE "required_groups" $- sExt32 $ product dims' `divUp` sExt64 (unCount group_size')-- sKernelThread "scan_stage3" num_groups' group_size' (segFlat space) $- virtualiseGroups SegVirt required_groups $ \virt_group_id -> do- constants <- kernelConstants <$> askEnv-- -- Compute our logical index.- flat_idx <-- dPrimVE "flat_idx" $- sExt64 virt_group_id * sExt64 (unCount group_size')- + sExt64 (kernelLocalThreadId constants)- zipWithM_ dPrimV_ gtids $ unflattenIndex dims' flat_idx-- -- Figure out which group this element was originally in.- orig_group <- dPrimV "orig_group" $ flat_idx `quot` elems_per_group- -- Then the index of the carry-in of the preceding group.- carry_in_flat_idx <-- dPrimV "carry_in_flat_idx" $- tvExp orig_group * elems_per_group - 1- -- Figure out the logical index of the carry-in.- let carry_in_idx = unflattenIndex dims' $ tvExp carry_in_flat_idx-- -- Apply the carry if we are not in the scan results for the first- -- group, and are not the last element in such a group (because- -- then the carry was updated in stage 2), and we are not crossing- -- a segment boundary.- let in_bounds =- foldl1 (.&&.) $ zipWith (.<.) (map Imp.vi64 gtids) dims'- crosses_segment =- fromMaybe false $- crossesSegment- <*> pure (tvExp carry_in_flat_idx)- <*> pure flat_idx- is_a_carry = flat_idx .==. (tvExp orig_group + 1) * elems_per_group - 1- no_carry_in = tvExp orig_group .==. 0 .||. is_a_carry .||. crosses_segment-- let per_scan_pes = segBinOpChunks scans all_pes- sWhen in_bounds $- sUnless no_carry_in $- forM_ (zip per_scan_pes scans) $- \(pes, SegBinOp _ scan_op nes vec_shape) -> do- dScope Nothing $ scopeOfLParams $ lambdaParams scan_op- let (scan_x_params, scan_y_params) =- splitAt (length nes) $ lambdaParams scan_op-- sLoopNest vec_shape $ \vec_is -> do- forM_ (zip scan_x_params pes) $ \(p, pe) ->- copyDWIMFix- (paramName p)- []- (Var $ patElemName pe)- (carry_in_idx ++ vec_is)-- forM_ (zip scan_y_params pes) $ \(p, pe) ->- copyDWIMFix- (paramName p)- []- (Var $ patElemName pe)- (map Imp.vi64 gtids ++ vec_is)-- compileBody' scan_x_params $ lambdaBody scan_op-- forM_ (zip scan_x_params pes) $ \(p, pe) ->- copyDWIMFix- (patElemName pe)- (map Imp.vi64 gtids ++ vec_is)- (Var $ paramName p)- []---- | Compile 'SegScan' instance to host-level code with calls to--- various kernels.-compileSegScan ::- Pattern KernelsMem ->- SegLevel ->- SegSpace ->- [SegBinOp KernelsMem] ->- KernelBody KernelsMem ->- CallKernelGen ()-compileSegScan pat lvl space scans kbody = do- -- Since stage 2 involves a group size equal to the number of groups- -- used for stage 1, we have to cap this number to the maximum group- -- size.- stage1_max_num_groups <- dPrim "stage1_max_num_groups" int64- sOp $ Imp.GetSizeMax (tvVar stage1_max_num_groups) SizeGroup-- stage1_num_groups <-- fmap (Imp.Count . tvSize) $- dPrimV "stage1_num_groups" $- sMin64 (tvExp stage1_max_num_groups) $- toInt64Exp $ Imp.unCount $ segNumGroups lvl-- (stage1_num_threads, elems_per_group, crossesSegment) <-- scanStage1 pat stage1_num_groups (segGroupSize lvl) space scans kbody-- emit $ Imp.DebugPrint "elems_per_group" $ Just $ untyped elems_per_group-- scanStage2 pat stage1_num_threads elems_per_group stage1_num_groups crossesSegment space scans- scanStage3 pat (segNumGroups lvl) (segGroupSize lvl) elems_per_group crossesSegment space scans
− src/Futhark/CodeGen/ImpGen/Kernels/ToOpenCL.hs
@@ -1,888 +0,0 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}---- | This module defines a translation from imperative code with--- kernels to imperative code with OpenCL calls.-module Futhark.CodeGen.ImpGen.Kernels.ToOpenCL- ( kernelsToOpenCL,- kernelsToCUDA,- )-where--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 Futhark.CodeGen.Backends.GenericC as GC-import Futhark.CodeGen.Backends.SimpleRep-import Futhark.CodeGen.ImpCode.Kernels hiding (Program)-import qualified Futhark.CodeGen.ImpCode.Kernels as ImpKernels-import Futhark.CodeGen.ImpCode.OpenCL hiding (Program)-import qualified Futhark.CodeGen.ImpCode.OpenCL as ImpOpenCL-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 qualified Language.C.Quote.OpenCL as C-import qualified Language.C.Syntax as C--kernelsToCUDA, kernelsToOpenCL :: ImpKernels.Program -> ImpOpenCL.Program-kernelsToCUDA = translateKernels TargetCUDA-kernelsToOpenCL = translateKernels TargetOpenCL---- | Translate a kernels-program to an OpenCL-program.-translateKernels ::- KernelTarget ->- ImpKernels.Program ->- ImpOpenCL.Program-translateKernels target prog =- let ( prog',- ToOpenCL kernels device_funs used_types sizes failures- ) =- (`runState` initialOpenCL) . (`runReaderT` defFuns prog) $ do- let ImpKernels.Definitions- (ImpKernels.Constants ps consts)- (ImpKernels.Functions funs) = prog- consts' <- traverse (onHostOp target) consts- funs' <- forM funs $ \(fname, fun) ->- (fname,) <$> traverse (onHostOp target) fun-- return $- ImpOpenCL.Definitions- (ImpOpenCL.Constants ps consts')- (ImpOpenCL.Functions funs')-- (device_prototypes, device_defs) = unzip $ M.elems device_funs- kernels' = M.map fst kernels- 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- ]- in ImpOpenCL.Program- opencl_code- opencl_prelude- kernels'- (S.toList used_types)- (cleanSizes sizes)- failures- prog'- where- genPrelude TargetOpenCL = genOpenClPrelude- genPrelude TargetCUDA = const genCUDAPrelude---- | Due to simplifications after kernel extraction, some threshold--- parameters may contain KernelPaths that reference threshold--- parameters that no longer exist. We remove these here.-cleanSizes :: M.Map Name SizeClass -> M.Map Name SizeClass-cleanSizes m = M.map clean m- where- known = M.keys m- clean (SizeThreshold path def) =- SizeThreshold (filter ((`elem` known) . fst) path) def- clean s = s--pointerQuals :: Monad m => String -> m [C.TypeQual]-pointerQuals "global" = return [C.ctyquals|__global|]-pointerQuals "local" = return [C.ctyquals|__local|]-pointerQuals "private" = return [C.ctyquals|__private|]-pointerQuals "constant" = return [C.ctyquals|__constant|]-pointerQuals "write_only" = return [C.ctyquals|__write_only|]-pointerQuals "read_only" = return [C.ctyquals|__read_only|]-pointerQuals "kernel" = return [C.ctyquals|__kernel|]-pointerQuals s = error $ "'" ++ s ++ "' is not an OpenCL kernel address space."---- In-kernel name and per-workgroup size in bytes.-type LocalMemoryUse = (VName, Count Bytes Exp)--data KernelState = KernelState- { kernelLocalMemory :: [LocalMemoryUse],- kernelFailures :: [FailureMsg],- kernelNextSync :: Int,- -- | Has a potential failure occurred sine the last- -- ErrorSync?- kernelSyncPending :: Bool,- kernelHasBarriers :: Bool- }--newKernelState :: [FailureMsg] -> KernelState-newKernelState failures = KernelState mempty failures 0 False False--errorLabel :: KernelState -> String-errorLabel = ("error_" ++) . show . kernelNextSync--data ToOpenCL = ToOpenCL- { clKernels :: M.Map KernelName (KernelSafety, C.Func),- clDevFuns :: M.Map Name (C.Definition, C.Func),- clUsedTypes :: S.Set PrimType,- clSizes :: M.Map Name SizeClass,- clFailures :: [FailureMsg]- }--initialOpenCL :: ToOpenCL-initialOpenCL = ToOpenCL mempty mempty mempty mempty mempty--type AllFunctions = ImpKernels.Functions ImpKernels.HostOp--lookupFunction :: Name -> AllFunctions -> Maybe ImpKernels.Function-lookupFunction fname (ImpKernels.Functions fs) = lookup fname fs--type OnKernelM = ReaderT AllFunctions (State ToOpenCL)--addSize :: Name -> SizeClass -> OnKernelM ()-addSize key sclass =- modify $ \s -> s {clSizes = M.insert key sclass $ clSizes s}--onHostOp :: KernelTarget -> HostOp -> OnKernelM OpenCL-onHostOp target (CallKernel k) = onKernel target k-onHostOp _ (ImpKernels.GetSize v key size_class) = do- addSize key size_class- return $ ImpOpenCL.GetSize v key-onHostOp _ (ImpKernels.CmpSizeLe v key size_class x) = do- addSize key size_class- return $ ImpOpenCL.CmpSizeLe v key x-onHostOp _ (ImpKernels.GetSizeMax v size_class) =- return $ ImpOpenCL.GetSizeMax v size_class--genGPUCode ::- OpsMode ->- KernelCode ->- [FailureMsg] ->- GC.CompilerM KernelOp KernelState a ->- (a, GC.CompilerState KernelState)-genGPUCode mode body failures =- GC.runCompilerM- (inKernelOperations mode body)- blankNameSource- (newKernelState failures)---- Compilation of a device function that is not not invoked from the--- host, but is invoked by (perhaps multiple) kernels.-generateDeviceFun :: Name -> ImpKernels.Function -> OnKernelM ()-generateDeviceFun fname host_func = do- -- Functions are a priori always considered host-level, so we have- -- to convert them to device code. This is where most of our- -- limitations on device-side functions (no arrays, no parallelism)- -- comes from.- let device_func = fmap toDevice host_func- when (any memParam $ functionInput host_func) bad-- failures <- gets clFailures-- let params =- [ [C.cparam|__global int *global_failure|],- [C.cparam|__global typename int64_t *global_failure_args|]- ]- (func, cstate) =- genGPUCode FunMode (functionBody device_func) failures $- GC.compileFun mempty params (fname, device_func)- kstate = GC.compUserState cstate-- modify $ \s ->- s- { clUsedTypes = typesInCode (functionBody device_func) <> clUsedTypes s,- clDevFuns = M.insert fname func $ clDevFuns s,- clFailures = kernelFailures kstate- }-- -- Important to do this after the 'modify' call, so we propagate the- -- right clFailures.- void $ ensureDeviceFuns $ functionBody device_func- where- toDevice :: HostOp -> KernelOp- toDevice _ = bad-- memParam MemParam {} = True- memParam ScalarParam {} = False-- bad = compilerLimitationS "Cannot generate GPU functions that use arrays."---- Ensure that this device function is available, but don't regenerate--- it if it already exists.-ensureDeviceFun :: Name -> ImpKernels.Function -> OnKernelM ()-ensureDeviceFun fname host_func = do- exists <- gets $ M.member fname . clDevFuns- unless exists $ generateDeviceFun fname host_func--ensureDeviceFuns :: ImpKernels.KernelCode -> OnKernelM [Name]-ensureDeviceFuns code = do- let called = calledFuncs code- fmap catMaybes $- forM (S.toList called) $ \fname -> do- def <- asks $ lookupFunction fname- case def of- Just func -> do- ensureDeviceFun fname func- return $ Just fname- Nothing -> return Nothing--onKernel :: KernelTarget -> Kernel -> OnKernelM OpenCL-onKernel target kernel = do- called <- ensureDeviceFuns $ kernelBody kernel-- -- Crucial that this is done after 'ensureDeviceFuns', as the device- -- functions may themselves define failure points.- failures <- gets clFailures-- let (kernel_body, cstate) =- genGPUCode KernelMode (kernelBody kernel) failures $- GC.blockScope $ GC.compileCode $ kernelBody kernel- kstate = GC.compUserState cstate-- use_params = mapMaybe useAsParam $ kernelUses kernel-- (local_memory_args, local_memory_params, local_memory_init) =- unzip3 $- flip evalState (blankNameSource :: VNameSource) $- mapM (prepareLocalMemory target) $ kernelLocalMemory kstate-- -- CUDA has very strict restrictions on the number of blocks- -- permitted along the 'y' and 'z' dimensions of the grid- -- (1<<16). To work around this, we are going to dynamically- -- permute the block dimensions to move the largest one to the- -- 'x' dimension, which has a higher limit (1<<31). This means- -- we need to extend the kernel with extra parameters that- -- contain information about this permutation, but we only do- -- this for multidimensional kernels (at the time of this- -- writing, only transposes). The corresponding arguments are- -- added automatically in CCUDA.hs.- (perm_params, block_dim_init) =- case (target, num_groups) of- (TargetCUDA, [_, _, _]) ->- ( [ [C.cparam|const int block_dim0|],- [C.cparam|const int block_dim1|],- [C.cparam|const int block_dim2|]- ],- mempty- )- _ ->- ( mempty,- [ [C.citem|const int block_dim0 = 0;|],- [C.citem|const int block_dim1 = 1;|],- [C.citem|const int block_dim2 = 2;|]- ]- )-- (const_defs, const_undefs) = unzip $ mapMaybe constDef $ kernelUses kernel-- let (safety, error_init)- -- We conservatively assume that any called function can fail.- | not $ null called =- (SafetyFull, [])- | length (kernelFailures kstate) == length failures =- if kernelFailureTolerant kernel- then (SafetyNone, [])- else -- No possible failures in this kernel, so if we make- -- it past an initial check, then we are good to go.-- ( SafetyCheap,- [C.citems|if (*global_failure >= 0) { return; }|]- )- | otherwise =- if not (kernelHasBarriers kstate)- then- ( SafetyFull,- [C.citems|if (*global_failure >= 0) { return; }|]- )- else- ( SafetyFull,- [C.citems|- volatile __local bool local_failure;- if (failure_is_an_option) {- int failed = *global_failure >= 0;- if (failed) {- return;- }- }- // All threads write this value - it looks like CUDA has a compiler bug otherwise.- local_failure = false;- barrier(CLK_LOCAL_MEM_FENCE);- |]- )-- failure_params =- [ [C.cparam|__global int *global_failure|],- [C.cparam|int failure_is_an_option|],- [C.cparam|__global typename int64_t *global_failure_args|]- ]-- params =- perm_params- ++ take (numFailureParams safety) failure_params- ++ catMaybes local_memory_params- ++ use_params-- kernel_fun =- [C.cfun|__kernel void $id:name ($params:params) {- $items:const_defs- $items:block_dim_init- $items:local_memory_init- $items:error_init- $items:kernel_body-- $id:(errorLabel kstate): return;-- $items:const_undefs- }|]- modify $ \s ->- s- { clKernels = M.insert name (safety, kernel_fun) $ clKernels s,- clUsedTypes = typesInKernel kernel <> clUsedTypes s,- clFailures = kernelFailures kstate- }-- -- The argument corresponding to the global_failure parameters is- -- added automatically later.- let args =- catMaybes local_memory_args- ++ kernelArgs kernel-- return $ LaunchKernel safety name args num_groups group_size- where- name = kernelName kernel- num_groups = kernelNumGroups kernel- group_size = kernelGroupSize kernel-- prepareLocalMemory TargetOpenCL (mem, size) = do- mem_aligned <- newVName $ baseString mem ++ "_aligned"- 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;|]- )- 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];|]- )--useAsParam :: KernelUse -> Maybe C.Param-useAsParam (ScalarUse name bt) =- let ctp = case bt of- -- OpenCL does not permit bool as a kernel parameter type.- Bool -> [C.cty|unsigned char|]- Unit -> [C.cty|unsigned char|]- _ -> GC.primTypeToCType bt- in Just [C.cparam|$ty:ctp $id:name|]-useAsParam (MemoryUse name) =- Just [C.cparam|__global unsigned char *$id:name|]-useAsParam ConstUse {} =- Nothing---- Constants are #defined as macros. Since a constant name in one--- kernel might potentially (although unlikely) also be used for--- something else in another kernel, we #undef them after the kernel.-constDef :: KernelUse -> Maybe (C.BlockItem, C.BlockItem)-constDef (ConstUse v e) =- Just- ( [C.citem|$escstm:def|],- [C.citem|$escstm:undef|]- )- where- e' = compilePrimExp e- def = "#define " ++ pretty (C.toIdent v mempty) ++ " (" ++ prettyOneLine e' ++ ")"- undef = "#undef " ++ pretty (C.toIdent v mempty)-constDef _ = Nothing--openClCode :: [C.Func] -> String-openClCode kernels =- pretty [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 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. */-__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")--typedef char int8_t;-typedef short int16_t;-typedef int int32_t;-typedef long int64_t;--typedef uchar uint8_t;-typedef ushort uint16_t;-typedef uint uint32_t;-typedef ulong uint64_t;--// 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")-static inline void mem_fence_global() {- asm("membar.gl;");-}-$esc:("#else")-static inline void mem_fence_global() {- mem_fence(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);-}-$esc:("#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|]]- where- uses_float64 = FloatType Float64 `S.member` ts--genCUDAPrelude :: [C.Definition]-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")--typedef char int8_t;-typedef short int16_t;-typedef int int32_t;-typedef long long int64_t;-typedef unsigned char uint8_t;-typedef unsigned short uint16_t;-typedef unsigned int uint32_t;-typedef unsigned long long uint64_t;-typedef uint8_t uchar;-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")--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;- case 2: d = block_dim2; break;- }- switch (d) {- case 0: return blockIdx.x;- case 1: return blockIdx.y;- case 2: return blockIdx.z;- default: return 0;- }-}-$esc:("#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)-{- switch (d) {- case 0: d = block_dim0; break;- case 1: d = block_dim1; break;- case 2: d = block_dim2; break;- }- switch(d) {- case 0: return gridDim.x;- case 1: return gridDim.y;- case 2: return gridDim.z;- default: return 0;- }-}-$esc:("#define get_num_groups(d) get_num_groups_fn(block_dim0, block_dim1, block_dim2, d)")--static inline int get_local_id(int d)-{- switch (d) {- case 0: return threadIdx.x;- case 1: return threadIdx.y;- case 2: return threadIdx.z;- default: return 0;- }-}--static inline int get_local_size(int d)-{- switch (d) {- case 0: return blockDim.x;- case 1: return blockDim.y;- case 2: return blockDim.z;- default: return 0;- }-}--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)")--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)-{- __syncthreads();-}-static inline void mem_fence_local() {- __threadfence_block();-}-static inline void mem_fence_global() {- __threadfence();-}--$esc:("#define NAN (0.0/0.0)")-$esc:("#define INFINITY (1.0/0.0)")-extern volatile __shared__ char shared_mem[];-|]--compilePrimExp :: PrimExp KernelConst -> C.Exp-compilePrimExp e = runIdentity $ GC.compilePrimExp compileKernelConst e- where- compileKernelConst (SizeConst key) =- return [C.cexp|$id:(zEncodeString (pretty key))|]--kernelArgs :: Kernel -> [KernelArg]-kernelArgs = mapMaybe useToArg . kernelUses- where- useToArg (MemoryUse mem) = Just $ MemKArg mem- useToArg (ScalarUse v bt) = Just $ ValueKArg (LeafExp (ScalarVar v) bt) bt- useToArg ConstUse {} = Nothing--nextErrorLabel :: GC.CompilerM KernelOp KernelState String-nextErrorLabel =- errorLabel <$> GC.getUserState--incErrorLabel :: GC.CompilerM KernelOp KernelState ()-incErrorLabel =- GC.modifyUserState $ \s -> s {kernelNextSync = kernelNextSync s + 1}--pendingError :: Bool -> GC.CompilerM KernelOp KernelState ()-pendingError b =- GC.modifyUserState $ \s -> s {kernelSyncPending = b}--hasCommunication :: ImpKernels.KernelCode -> Bool-hasCommunication = any communicates- where- communicates ErrorSync {} = True- communicates Barrier {} = True- communicates _ = False---- Whether we are generating code for a kernel or a device function.--- This has minor effects, such as exactly how failures are--- propagated.-data OpsMode = KernelMode | FunMode deriving (Eq)--inKernelOperations ::- OpsMode ->- ImpKernels.KernelCode ->- GC.Operations KernelOp KernelState-inKernelOperations mode body =- GC.Operations- { GC.opsCompiler = kernelOps,- GC.opsMemoryType = kernelMemoryType,- GC.opsWriteScalar = kernelWriteScalar,- GC.opsReadScalar = kernelReadScalar,- GC.opsAllocate = cannotAllocate,- GC.opsDeallocate = cannotDeallocate,- GC.opsCopy = copyInKernel,- GC.opsStaticArray = noStaticArrays,- GC.opsFatMemory = False,- GC.opsError = errorInKernel,- GC.opsCall = callInKernel,- GC.opsCritical = mempty- }- where- has_communication = hasCommunication body-- fence FenceLocal = [C.cexp|CLK_LOCAL_MEM_FENCE|]- fence FenceGlobal = [C.cexp|CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE|]-- kernelOps :: GC.OpCompiler KernelOp KernelState- kernelOps (GetGroupId v i) =- GC.stm [C.cstm|$id:v = get_group_id($int:i);|]- kernelOps (GetLocalId v i) =- GC.stm [C.cstm|$id:v = get_local_id($int:i);|]- kernelOps (GetLocalSize v i) =- GC.stm [C.cstm|$id:v = get_local_size($int:i);|]- kernelOps (GetGlobalId v i) =- GC.stm [C.cstm|$id:v = get_global_id($int:i);|]- kernelOps (GetGlobalSize v i) =- GC.stm [C.cstm|$id:v = get_global_size($int:i);|]- kernelOps (GetLockstepWidth v) =- GC.stm [C.cstm|$id:v = LOCKSTEP_WIDTH;|]- kernelOps (Barrier f) = do- GC.stm [C.cstm|barrier($exp:(fence f));|]- GC.modifyUserState $ \s -> s {kernelHasBarriers = True}- kernelOps (MemFence FenceLocal) =- GC.stm [C.cstm|mem_fence_local();|]- kernelOps (MemFence FenceGlobal) =- GC.stm [C.cstm|mem_fence_global();|]- kernelOps (LocalAlloc name size) = do- 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';|]- kernelOps (ErrorSync f) = do- label <- nextErrorLabel- pending <- kernelSyncPending <$> GC.getUserState- when pending $ do- pendingError False- GC.stm [C.cstm|$id:label: barrier($exp:(fence f));|]- GC.stm [C.cstm|if (local_failure) { return; }|]- GC.stm [C.cstm|barrier(CLK_LOCAL_MEM_FENCE);|] -- intentional- GC.modifyUserState $ \s -> s {kernelHasBarriers = True}- incErrorLabel- kernelOps (Atomic space aop) = atomicOps space aop-- atomicCast s t = do- let volatile = [C.ctyquals|volatile|]- quals <- case s of- Space sid -> pointerQuals sid- _ -> pointerQuals "global"- return [C.cty|$tyquals:(volatile++quals) $ty:t|]-- atomicSpace (Space sid) = sid- atomicSpace _ = "global"-- doAtomic s t old arr ind val op ty = do- ind' <- GC.compileExp $ untyped $ unCount ind- val' <- GC.compileExp val- cast <- atomicCast s ty- GC.stm [C.cstm|$id:old = $id:op'(&(($ty:cast *)$id:arr)[$exp:ind'], ($ty:ty) $exp:val');|]- where- op' = op ++ "_" ++ pretty t ++ "_" ++ atomicSpace s-- doAtomicCmpXchg s t old arr ind cmp val ty = do- ind' <- GC.compileExp $ untyped $ unCount ind- cmp' <- GC.compileExp cmp- val' <- GC.compileExp val- cast <- atomicCast s ty- GC.stm [C.cstm|$id:old = $id:op(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:cmp', $exp:val');|]- where- op = "atomic_cmpxchg_" ++ pretty t ++ "_" ++ atomicSpace s- doAtomicXchg s t old arr ind val ty = do- cast <- atomicCast s ty- ind' <- GC.compileExp $ untyped $ unCount ind- val' <- GC.compileExp val- GC.stm [C.cstm|$id:old = $id:op(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:val');|]- where- op = "atomic_chg_" ++ pretty t ++ "_" ++ atomicSpace s- -- First the 64-bit operations.- atomicOps s (AtomicAdd Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_add" [C.cty|typename int64_t|]- atomicOps s (AtomicFAdd Float64 old arr ind val) =- doAtomic s Float64 old arr ind val "atomic_fadd" [C.cty|double|]- atomicOps s (AtomicSMax Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_smax" [C.cty|typename int64_t|]- atomicOps s (AtomicSMin Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_smin" [C.cty|typename int64_t|]- atomicOps s (AtomicUMax Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_umax" [C.cty|unsigned int64_t|]- atomicOps s (AtomicUMin Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_umin" [C.cty|unsigned int64_t|]- atomicOps s (AtomicAnd Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_and" [C.cty|typename int64_t|]- atomicOps s (AtomicOr Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_or" [C.cty|typename int64_t|]- atomicOps s (AtomicXor Int64 old arr ind val) =- doAtomic s Int64 old arr ind val "atomic_xor" [C.cty|typename int64_t|]- atomicOps s (AtomicCmpXchg (IntType Int64) old arr ind cmp val) =- doAtomicCmpXchg s (IntType Int64) old arr ind cmp val [C.cty|typename int64_t|]- atomicOps s (AtomicXchg (IntType Int64) old arr ind val) =- doAtomicXchg s (IntType Int64) old arr ind val [C.cty|typename int64_t|]- --- 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 (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) =- doAtomic s t old arr ind val "atomic_smin" [C.cty|int|]- atomicOps s (AtomicUMax t old arr ind val) =- doAtomic s t old arr ind val "atomic_umax" [C.cty|unsigned int|]- atomicOps s (AtomicUMin t old arr ind val) =- doAtomic s t old arr ind val "atomic_umin" [C.cty|unsigned int|]- atomicOps s (AtomicAnd t old arr ind val) =- doAtomic s t old arr ind val "atomic_and" [C.cty|int|]- atomicOps s (AtomicOr t old arr ind val) =- doAtomic s t old arr ind val "atomic_or" [C.cty|int|]- atomicOps s (AtomicXor t old arr ind val) =- doAtomic s t old arr ind val "atomic_xor" [C.cty|int|]- atomicOps s (AtomicCmpXchg t old arr ind cmp val) =- doAtomicCmpXchg s t old arr ind cmp val [C.cty|int|]- atomicOps s (AtomicXchg t old arr ind val) =- doAtomicXchg s t old arr ind val [C.cty|int|]-- cannotAllocate :: GC.Allocate KernelOp KernelState- cannotAllocate _ =- error "Cannot allocate memory in kernel"-- cannotDeallocate :: GC.Deallocate KernelOp KernelState- cannotDeallocate _ _ =- error "Cannot deallocate memory in kernel"-- copyInKernel :: GC.Copy KernelOp KernelState- copyInKernel _ _ _ _ _ _ _ =- error "Cannot bulk copy in kernel."-- noStaticArrays :: GC.StaticArray KernelOp KernelState- noStaticArrays _ _ _ _ =- error "Cannot create static array in kernel."-- kernelMemoryType space = do- quals <- pointerQuals space- return [C.cty|$tyquals:quals $ty:defaultMemBlockType|]-- kernelWriteScalar =- GC.writeScalarPointerWithQuals pointerQuals-- kernelReadScalar =- GC.readScalarPointerWithQuals pointerQuals-- whatNext = do- label <- nextErrorLabel- pendingError True- return $- if has_communication- then [C.citems|local_failure = true; goto $id:label;|]- else- if mode == FunMode- then [C.citems|return 1;|]- else [C.citems|return;|]-- callInKernel dests fname args- | isBuiltInFunction fname =- GC.opsCall GC.defaultOperations dests fname args- | otherwise = do- let out_args = [[C.cexp|&$id:d|] | d <- dests]- args' =- [C.cexp|global_failure|] :- [C.cexp|global_failure_args|] :- out_args ++ args-- what_next <- whatNext-- GC.item [C.citem|if ($id:(funName fname)($args:args') != 0) { $items:what_next; }|]-- errorInKernel msg@(ErrorMsg parts) backtrace = do- n <- length . kernelFailures <$> GC.getUserState- GC.modifyUserState $ \s ->- s {kernelFailures = kernelFailures s ++ [FailureMsg msg backtrace]}- let setArgs _ [] = return []- setArgs i (ErrorString {} : parts') = setArgs i parts'- setArgs i (ErrorInt32 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-- GC.stm- [C.cstm|{ if (atomic_cmpxchg_i32_global(global_failure, -1, $int:n) == -1)- { $stms:argstms; }- $items:what_next- }|]----- Checking requirements--typesInKernel :: Kernel -> S.Set PrimType-typesInKernel kernel = typesInCode $ kernelBody kernel--typesInCode :: ImpKernels.KernelCode -> S.Set PrimType-typesInCode Skip = mempty-typesInCode (c1 :>>: c2) = typesInCode c1 <> typesInCode c2-typesInCode (For _ e c) = typesInExp e <> typesInCode c-typesInCode (While (TPrimExp e) c) = typesInExp e <> typesInCode c-typesInCode DeclareMem {} = mempty-typesInCode (DeclareScalar _ _ t) = S.singleton t-typesInCode (DeclareArray _ _ t _) = S.singleton t-typesInCode (Allocate _ (Count (TPrimExp e)) _) = typesInExp e-typesInCode Free {} = mempty-typesInCode- ( Copy- _- (Count (TPrimExp e1))- _- _- (Count (TPrimExp e2))- _- (Count (TPrimExp e3))- ) =- typesInExp e1 <> typesInExp e2 <> typesInExp e3-typesInCode (Write _ (Count (TPrimExp e1)) t _ _ e2) =- typesInExp e1 <> S.singleton t <> typesInExp e2-typesInCode (SetScalar _ e) = typesInExp e-typesInCode SetMem {} = mempty-typesInCode (Call _ _ es) = mconcat $ map typesInArg es- where- typesInArg MemArg {} = mempty- typesInArg (ExpArg e) = typesInExp e-typesInCode (If (TPrimExp e) c1 c2) =- typesInExp e <> typesInCode c1 <> typesInCode c2-typesInCode (Assert e _ _) = typesInExp e-typesInCode (Comment _ c) = typesInCode c-typesInCode (DebugPrint _ v) = maybe mempty typesInExp v-typesInCode Op {} = mempty--typesInExp :: Exp -> S.Set PrimType-typesInExp (ValueExp v) = S.singleton $ primValueType v-typesInExp (BinOpExp _ e1 e2) = typesInExp e1 <> typesInExp e2-typesInExp (CmpOpExp _ e1 e2) = typesInExp e1 <> typesInExp e2-typesInExp (ConvOpExp op e) = S.fromList [from, to] <> typesInExp e- where- (from, to) = convOpType op-typesInExp (UnOpExp _ e) = typesInExp e-typesInExp (FunExp _ args t) = S.singleton t <> mconcat (map typesInExp args)-typesInExp (LeafExp (Index _ (Count (TPrimExp e)) t _ _) _) = S.singleton t <> typesInExp e-typesInExp (LeafExp ScalarVar {} _) = mempty
− src/Futhark/CodeGen/ImpGen/Kernels/Transpose.hs
@@ -1,386 +0,0 @@--- | Carefully optimised implementations of GPU transpositions.--- Written in ImpCode so we can compile it to both CUDA and OpenCL.-module Futhark.CodeGen.ImpGen.Kernels.Transpose- ( TransposeType (..),- TransposeArgs,- mapTransposeKernel,- )-where--import Futhark.CodeGen.ImpCode.Kernels-import Futhark.IR.Prop.Types-import Futhark.Util.IntegralExp (divUp, quot, rem)-import Prelude hiding (quot, rem)---- | Which form of transposition to generate code for.-data TransposeType- = TransposeNormal- | TransposeLowWidth- | TransposeLowHeight- | -- | For small arrays that do not- -- benefit from coalescing.- TransposeSmall- deriving (Eq, Ord, Show)---- | The types of the arguments accepted by a transposition function.-type TransposeArgs =- ( VName,- TExp Int32,- VName,- TExp Int32,- TExp Int32,- TExp Int32,- TExp Int32,- TExp Int32,- TExp Int32,- VName- )--elemsPerThread :: TExp Int32-elemsPerThread = 4--mapTranspose :: TExp Int32 -> TransposeArgs -> PrimType -> TransposeType -> KernelCode-mapTranspose block_dim args t kind =- case kind of- TransposeSmall ->- mconcat- [ get_ids,- dec our_array_offset $ vi32 get_global_id_0 `quot` (height * width) * (height * width),- dec x_index $ (vi32 get_global_id_0 `rem` (height * width)) `quot` height,- dec y_index $ vi32 get_global_id_0 `rem` height,- dec odata_offset $- (basic_odata_offset `quot` primByteSize t) + vi32 our_array_offset,- dec idata_offset $- (basic_idata_offset `quot` primByteSize t) + vi32 our_array_offset,- dec index_in $ vi32 y_index * width + vi32 x_index,- dec index_out $ vi32 x_index * height + vi32 y_index,- when- (vi32 get_global_id_0 .<. width * height * num_arrays)- ( Write odata (elements $ sExt64 $ vi32 odata_offset + vi32 index_out) t (Space "global") Nonvolatile $- index idata (elements $ sExt64 $ vi32 idata_offset + vi32 index_in) t (Space "global") Nonvolatile- )- ]- TransposeLowWidth ->- mkTranspose $- lowDimBody- (vi32 get_group_id_0 * block_dim + (vi32 get_local_id_0 `quot` muly))- ( vi32 get_group_id_1 * block_dim * muly + vi32 get_local_id_1- + (vi32 get_local_id_0 `rem` muly) * block_dim- )- ( vi32 get_group_id_1 * block_dim * muly + vi32 get_local_id_0- + (vi32 get_local_id_1 `rem` muly) * block_dim- )- (vi32 get_group_id_0 * block_dim + (vi32 get_local_id_1 `quot` muly))- TransposeLowHeight ->- mkTranspose $- lowDimBody- ( vi32 get_group_id_0 * block_dim * mulx + vi32 get_local_id_0- + (vi32 get_local_id_1 `rem` mulx) * block_dim- )- (vi32 get_group_id_1 * block_dim + (vi32 get_local_id_1 `quot` mulx))- (vi32 get_group_id_1 * block_dim + (vi32 get_local_id_0 `quot` mulx))- ( vi32 get_group_id_0 * block_dim * mulx + vi32 get_local_id_1- + (vi32 get_local_id_0 `rem` mulx) * block_dim- )- TransposeNormal ->- mkTranspose $- mconcat- [ dec x_index $ vi32 get_global_id_0,- dec y_index $ vi32 get_group_id_1 * tile_dim + vi32 get_local_id_1,- when (vi32 x_index .<. width) $- For j (untyped elemsPerThread) $- let i = vi32 j * (tile_dim `quot` elemsPerThread)- in mconcat- [ dec index_in $ (vi32 y_index + i) * width + vi32 x_index,- when (vi32 y_index + i .<. height) $- Write- block- ( elements $- sExt64 $- (vi32 get_local_id_1 + i) * (tile_dim + 1)- + vi32 get_local_id_0- )- t- (Space "local")- Nonvolatile- $ index- idata- (elements $ sExt64 $ vi32 idata_offset + vi32 index_in)- t- (Space "global")- Nonvolatile- ],- Op $ Barrier FenceLocal,- SetScalar x_index $ untyped $ vi32 get_group_id_1 * tile_dim + vi32 get_local_id_0,- SetScalar y_index $ untyped $ vi32 get_group_id_0 * tile_dim + vi32 get_local_id_1,- when (vi32 x_index .<. height) $- For j (untyped elemsPerThread) $- let i = vi32 j * (tile_dim `quot` elemsPerThread)- in mconcat- [ dec index_out $ (vi32 y_index + i) * height + vi32 x_index,- when (vi32 y_index + i .<. width) $- Write- odata- (elements $ sExt64 $ vi32 odata_offset + vi32 index_out)- t- (Space "global")- Nonvolatile- $ index- block- ( elements $- sExt64 $- vi32 get_local_id_0 * (tile_dim + 1) + vi32 get_local_id_1 + i- )- t- (Space "local")- Nonvolatile- ]- ]- where- dec v (TPrimExp e) =- DeclareScalar v Nonvolatile (primExpType e) <> SetScalar v e- tile_dim = 2 * block_dim-- when a b = If a b mempty-- ( odata,- basic_odata_offset,- idata,- basic_idata_offset,- width,- height,- mulx,- muly,- num_arrays,- block- ) = args-- -- Be extremely careful when editing this list to ensure that- -- the names match up. Also, be careful that the tags on- -- these names do not conflict with the tags of the- -- surrounding code. We accomplish the latter by using very- -- low tags (normal variables start at least in the low- -- hundreds).- [ our_array_offset,- x_index,- y_index,- odata_offset,- idata_offset,- index_in,- index_out,- get_global_id_0,- get_local_id_0,- get_local_id_1,- get_group_id_0,- get_group_id_1,- get_group_id_2,- j- ] =- zipWith (flip VName) [30 ..] $- map- nameFromString- [ "our_array_offset",- "x_index",- "y_index",- "odata_offset",- "idata_offset",- "index_in",- "index_out",- "get_global_id_0",- "get_local_id_0",- "get_local_id_1",- "get_group_id_0",- "get_group_id_1",- "get_group_id_2",- "j"- ]-- get_ids =- mconcat- [ DeclareScalar get_global_id_0 Nonvolatile int32,- Op $ GetGlobalId get_global_id_0 0,- DeclareScalar get_local_id_0 Nonvolatile int32,- Op $ GetLocalId get_local_id_0 0,- DeclareScalar get_local_id_1 Nonvolatile int32,- Op $ GetLocalId get_local_id_1 1,- DeclareScalar get_group_id_0 Nonvolatile int32,- Op $ GetGroupId get_group_id_0 0,- DeclareScalar get_group_id_1 Nonvolatile int32,- Op $ GetGroupId get_group_id_1 1,- DeclareScalar get_group_id_2 Nonvolatile int32,- Op $ GetGroupId get_group_id_2 2- ]-- mkTranspose body =- mconcat- [ get_ids,- dec our_array_offset $ vi32 get_group_id_2 * width * height,- dec odata_offset $- (basic_odata_offset `quot` primByteSize t) + vi32 our_array_offset,- dec idata_offset $- (basic_idata_offset `quot` primByteSize t) + vi32 our_array_offset,- body- ]-- lowDimBody x_in_index y_in_index x_out_index y_out_index =- mconcat- [ dec x_index x_in_index,- dec y_index y_in_index,- dec index_in $ vi32 y_index * width + vi32 x_index,- when (vi32 x_index .<. width .&&. vi32 y_index .<. height) $- Write- block- (elements $ sExt64 $ vi32 get_local_id_1 * (block_dim + 1) + vi32 get_local_id_0)- t- (Space "local")- Nonvolatile- $ index- idata- (elements $ sExt64 $ vi32 idata_offset + vi32 index_in)- t- (Space "global")- Nonvolatile,- Op $ Barrier FenceLocal,- SetScalar x_index $ untyped x_out_index,- SetScalar y_index $ untyped y_out_index,- dec index_out $ vi32 y_index * height + vi32 x_index,- when (vi32 x_index .<. height .&&. vi32 y_index .<. width) $- Write- odata- (elements $ sExt64 (vi32 odata_offset + vi32 index_out))- t- (Space "global")- Nonvolatile- $ index- block- (elements $ sExt64 $ vi32 get_local_id_0 * (block_dim + 1) + vi32 get_local_id_1)- t- (Space "local")- Nonvolatile- ]---- | Generate a transpose kernel. There is special support to handle--- input arrays with low width, low height, or both.------ Normally when transposing a @[2][n]@ array we would use a @FUT_BLOCK_DIM x--- FUT_BLOCK_DIM@ group to process a @[2][FUT_BLOCK_DIM]@ slice of the input--- array. This would mean that many of the threads in a group would be inactive.--- We try to remedy this by using a special kernel that will process a larger--- part of the input, by using more complex indexing. In our example, we could--- use all threads in a group if we are processing @(2/FUT_BLOCK_DIM)@ as large--- a slice of each rows per group. The variable @mulx@ contains this factor for--- the kernel to handle input arrays with low height.------ See issue #308 on GitHub for more details.------ These kernels are optimized to ensure all global reads and writes--- are coalesced, and to avoid bank conflicts in shared memory. Each--- thread group transposes a 2D tile of block_dim*2 by block_dim*2--- elements. The size of a thread group is block_dim/2 by--- block_dim*2, meaning that each thread will process 4 elements in a--- 2D tile. The shared memory array containing the 2D tile consists--- of block_dim*2 by block_dim*2+1 elements. Padding each row with--- an additional element prevents bank conflicts from occuring when--- the tile is accessed column-wise.-mapTransposeKernel ::- String ->- Integer ->- TransposeArgs ->- PrimType ->- TransposeType ->- Kernel-mapTransposeKernel desc block_dim_int args t kind =- Kernel- { kernelBody =- DeclareMem block (Space "local")- <> Op (LocalAlloc block block_size)- <> mapTranspose block_dim args t kind,- kernelUses = uses,- kernelNumGroups = map untyped num_groups,- kernelGroupSize = map untyped group_size,- kernelName = nameFromString name,- kernelFailureTolerant = True- }- where- pad2DBytes k = k * (k + 1) * primByteSize t- block_size =- bytes $- case kind of- TransposeSmall -> 1 :: TExp Int64- -- Not used, but AMD's OpenCL- -- does not like zero-size- -- local memory.- TransposeNormal -> fromInteger $ pad2DBytes $ 2 * block_dim_int- TransposeLowWidth -> fromInteger $ pad2DBytes block_dim_int- TransposeLowHeight -> fromInteger $ pad2DBytes block_dim_int- block_dim = fromInteger block_dim_int :: TExp Int32-- ( odata,- basic_odata_offset,- idata,- basic_idata_offset,- width,- height,- mulx,- muly,- num_arrays,- block- ) = args-- (num_groups, group_size) =- case kind of- TransposeSmall ->- ( [(num_arrays * width * height) `divUp` (block_dim * block_dim)],- [block_dim * block_dim]- )- TransposeLowWidth ->- lowDimKernelAndGroupSize block_dim num_arrays width $ height `divUp` muly- TransposeLowHeight ->- lowDimKernelAndGroupSize block_dim num_arrays (width `divUp` mulx) height- TransposeNormal ->- let actual_dim = block_dim * 2- in ( [ width `divUp` actual_dim,- height `divUp` actual_dim,- num_arrays- ],- [actual_dim, actual_dim `quot` elemsPerThread, 1]- )-- uses =- map- (`ScalarUse` int32)- ( namesToList $- mconcat $- map- freeIn- [ basic_odata_offset,- basic_idata_offset,- num_arrays,- width,- height,- mulx,- muly- ]- )- ++ map MemoryUse [odata, idata]-- name =- case kind of- TransposeSmall -> desc ++ "_small"- TransposeLowHeight -> desc ++ "_low_height"- TransposeLowWidth -> desc ++ "_low_width"- TransposeNormal -> desc--lowDimKernelAndGroupSize ::- TExp Int32 ->- TExp Int32 ->- TExp Int32 ->- TExp Int32 ->- ([TExp Int32], [TExp Int32])-lowDimKernelAndGroupSize block_dim num_arrays x_elems y_elems =- ( [ x_elems `divUp` block_dim,- y_elems `divUp` block_dim,- num_arrays- ],- [block_dim, block_dim, 1]- )
src/Futhark/CodeGen/ImpGen/Multicore/Base.hs view
@@ -23,7 +23,6 @@ import Control.Monad import Data.Bifunctor-import Data.List (elemIndex, find) import qualified Data.Map as M import Data.Maybe import qualified Futhark.CodeGen.ImpCode.Multicore as Imp@@ -31,7 +30,6 @@ import Futhark.Error import Futhark.IR.MCMem import Futhark.Transform.Rename-import Futhark.Util (maybeNth) import Prelude hiding (quot, rem) -- | Is there an atomic t'BinOp' corresponding to this t'BinOp'?@@ -70,7 +68,7 @@ toParam name (Prim pt) = return [Imp.ScalarParam name pt] toParam name (Mem space) = return [Imp.MemParam name space] toParam name Array {} = pure <$> arrParam name-toParam name Acc {} = error $ "toParam Acc: " ++ pretty name+toParam _name Acc {} = pure [] -- FIXME? Are we sure this works? getSpace :: SegOp () MCMem -> SegSpace getSpace (SegHist _ space _ _ _) = space@@ -156,10 +154,10 @@ isLoadBalanced (Imp.Op (Imp.ParLoop _ _ _ code _ _ _)) = isLoadBalanced code isLoadBalanced _ = True -segBinOpComm' :: [SegBinOp lore] -> Commutativity+segBinOpComm' :: [SegBinOp rep] -> Commutativity segBinOpComm' = mconcat . map segBinOpComm -decideScheduling' :: SegOp () lore -> Imp.Code -> Imp.Scheduling+decideScheduling' :: SegOp () rep -> Imp.Code -> Imp.Scheduling decideScheduling' SegHist {} _ = Imp.Static decideScheduling' SegScan {} _ = Imp.Static decideScheduling' (SegRed _ _ reds _ _) code =@@ -244,25 +242,25 @@ -- | A function for generating code for an atomic update. Assumes -- that the bucket is in-bounds.-type DoAtomicUpdate lore r =+type DoAtomicUpdate rep r = [VName] -> [Imp.TExp Int64] -> MulticoreGen () -- | The mechanism that will be used for performing the atomic update. -- Approximates how efficient it will be. Ordered from most to least -- efficient.-data AtomicUpdate lore r- = AtomicPrim (DoAtomicUpdate lore r)+data AtomicUpdate rep r+ = AtomicPrim (DoAtomicUpdate rep r) | -- | Can be done by efficient swaps.- AtomicCAS (DoAtomicUpdate lore r)+ AtomicCAS (DoAtomicUpdate rep r) | -- | Requires explicit locking.- AtomicLocking (Locking -> DoAtomicUpdate lore r)+ AtomicLocking (Locking -> DoAtomicUpdate rep r) atomicUpdateLocking :: AtomicBinOp -> Lambda MCMem -> AtomicUpdate MCMem () atomicUpdateLocking atomicBinOp lam- | Just ops_and_ts <- splitOp lam,+ | Just ops_and_ts <- lamIsBinOp lam, all (\(_, t, _, _) -> supportedPrims $ primBitSize t) ops_and_ts = primOrCas ops_and_ts $ \arrs bucket -> -- If the operator is a vectorised binary operator on 32-bit values,@@ -408,24 +406,6 @@ (sExt32 <$> bucket_offset) (tvVar run_loop) (toBits (Imp.var x t))---- | Horizontally fission a lambda that models a binary operator.-splitOp :: ASTLore lore => Lambda lore -> Maybe [(BinOp, PrimType, VName, VName)]-splitOp 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) $- stmsToList $ bodyStms $ lambdaBody lam- i <- Var res `elemIndex` bodyResult (lambdaBody lam)- xp <- maybeNth i $ lambdaParams lam- yp <- maybeNth (n + i) $ lambdaParams lam- guard $ paramName xp == x- guard $ paramName yp == y- Prim t <- Just $ patElemType pe- return (op, t, paramName xp, paramName yp)- splitStm _ = Nothing -- TODO for supporting 8 and 16 bits (and 128) -- we need a functions for converting to and from bits
src/Futhark/CodeGen/ImpGen/Multicore/SegHist.hs view
@@ -30,7 +30,7 @@ -- | Split some list into chunks equal to the number of values -- returned by each 'SegBinOp'-segHistOpChunks :: [HistOp lore] -> [a] -> [[a]]+segHistOpChunks :: [HistOp rep] -> [a] -> [[a]] segHistOpChunks = chunks . map (length . histNeutral) nonsegmentedHist ::
src/Futhark/CodeGen/ImpGen/OpenCL.hs view
@@ -7,11 +7,11 @@ import Data.Bifunctor (second) import qualified Futhark.CodeGen.ImpCode.OpenCL as OpenCL-import Futhark.CodeGen.ImpGen.Kernels-import Futhark.CodeGen.ImpGen.Kernels.ToOpenCL-import Futhark.IR.KernelsMem+import Futhark.CodeGen.ImpGen.GPU+import Futhark.CodeGen.ImpGen.GPU.ToOpenCL+import Futhark.IR.GPUMem import Futhark.MonadFreshNames -- | Compile the program to ImpCode with OpenCL kernels.-compileProg :: MonadFreshNames m => Prog KernelsMem -> m (Warnings, OpenCL.Program)+compileProg :: MonadFreshNames m => Prog GPUMem -> m (Warnings, OpenCL.Program) compileProg prog = second kernelsToOpenCL <$> compileProgOpenCL prog
src/Futhark/CodeGen/SetDefaultSpace.hs view
@@ -38,10 +38,10 @@ param setExtValueSpace :: Space -> ExternalValue -> ExternalValue-setExtValueSpace space (OpaqueValue desc vs) =- OpaqueValue desc $ map (setValueSpace space) vs-setExtValueSpace space (TransparentValue v) =- TransparentValue $ setValueSpace space v+setExtValueSpace space (OpaqueValue u desc vs) =+ OpaqueValue u desc $ map (setValueSpace space) vs+setExtValueSpace space (TransparentValue u v) =+ TransparentValue u $ setValueSpace space v setValueSpace :: Space -> ValueDesc -> ValueDesc setValueSpace space (ArrayValue mem _ bt ept shape) =
src/Futhark/Compiler.hs view
@@ -70,8 +70,8 @@ -- 'Pipeline', and finish up with the given 'Action'. runCompilerOnProgram :: FutharkConfig ->- Pipeline I.SOACS lore ->- Action lore ->+ Pipeline I.SOACS rep ->+ Action rep -> FilePath -> IO () runCompilerOnProgram config pipeline action file = do@@ -95,9 +95,9 @@ -- 'Pipeline', and return it. runPipelineOnProgram :: FutharkConfig ->- Pipeline I.SOACS tolore ->+ Pipeline I.SOACS torep -> FilePath ->- FutharkM (Prog tolore)+ FutharkM (Prog torep) runPipelineOnProgram config pipeline file = do when (pipelineVerbose pipeline_config) $ logMsg ("Reading and type-checking source program" :: String)
src/Futhark/Compiler/CLI.hs view
@@ -32,13 +32,13 @@ -- | The longer action description. String -> -- | The pipeline to use.- Pipeline SOACS lore ->+ Pipeline SOACS rep -> -- | The action to take on the result of the pipeline. ( FutharkConfig -> cfg -> CompilerMode -> FilePath ->- Prog lore ->+ Prog rep -> FutharkM () ) -> -- | Program name
src/Futhark/Construct.hs view
@@ -28,8 +28,8 @@ -- A monad that implements 'MonadBinder' 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'Lore' type family, which--- indicates which lore it works with. Inside a 'MonadBinder' we can+-- 'MonadBinder' also implements the t'REp' type family, which+-- indicates which rep it works with. Inside a 'MonadBinder' we can -- use 'collectStms' to gather up the 'Stms' added with 'addStm' in -- some nested computation. --@@ -119,7 +119,7 @@ letSubExp :: MonadBinder m => String ->- Exp (Lore m) ->+ Exp (Rep m) -> m SubExp letSubExp _ (BasicOp (SubExp se)) = return se letSubExp desc e = Var <$> letExp desc e@@ -127,7 +127,7 @@ letExp :: MonadBinder m => String ->- Exp (Lore m) ->+ Exp (Rep m) -> m VName letExp _ (BasicOp (SubExp (Var v))) = return v@@ -144,7 +144,7 @@ String -> VName -> Slice SubExp ->- Exp (Lore m) ->+ Exp (Rep m) -> m VName letInPlace desc src slice e = do tmp <- letSubExp (desc ++ "_tmp") e@@ -153,14 +153,14 @@ letSubExps :: MonadBinder m => String ->- [Exp (Lore m)] ->+ [Exp (Rep m)] -> m [SubExp] letSubExps desc = mapM $ letSubExp desc letTupExp :: (MonadBinder m) => String ->- Exp (Lore m) ->+ Exp (Rep m) -> m [VName] letTupExp _ (BasicOp (SubExp (Var v))) = return [v]@@ -173,7 +173,7 @@ letTupExp' :: (MonadBinder m) => String ->- Exp (Lore m) ->+ Exp (Rep m) -> m [SubExp] letTupExp' _ (BasicOp (SubExp se)) = return [se] letTupExp' name ses = map Var <$> letTupExp name ses@@ -181,25 +181,25 @@ eSubExp :: MonadBinder m => SubExp ->- m (Exp (Lore m))+ m (Exp (Rep m)) eSubExp = pure . BasicOp . SubExp eIf ::- (MonadBinder m, BranchType (Lore m) ~ ExtType) =>- m (Exp (Lore m)) ->- m (Body (Lore m)) ->- m (Body (Lore m)) ->- m (Exp (Lore m))+ (MonadBinder m, BranchType (Rep m) ~ ExtType) =>+ m (Exp (Rep m)) ->+ m (Body (Rep m)) ->+ m (Body (Rep m)) ->+ m (Exp (Rep m)) eIf ce te fe = eIf' ce te fe IfNormal -- | As 'eIf', but an 'IfSort' can be given. eIf' ::- (MonadBinder m, BranchType (Lore m) ~ ExtType) =>- m (Exp (Lore m)) ->- m (Body (Lore m)) ->- m (Body (Lore m)) ->+ (MonadBinder m, BranchType (Rep m) ~ ExtType) =>+ m (Exp (Rep m)) ->+ m (Body (Rep m)) ->+ m (Body (Rep m)) -> IfSort ->- m (Exp (Lore m))+ m (Exp (Rep m)) eIf' ce te fe if_sort = do ce' <- letSubExp "cond" =<< ce te' <- insertStmsM te@@ -222,7 +222,7 @@ -- The type of a body. Watch out: this only works for the degenerate -- case where the body does not already return its context.-bodyExtType :: (HasScope lore m, Monad m) => Body lore -> m [ExtType]+bodyExtType :: (HasScope rep m, Monad m) => Body rep -> m [ExtType] bodyExtType (Body _ stms res) = existentialiseExtTypes (M.keys stmsscope) . staticShapes <$> extendedScope (traverse subExpType res) stmsscope@@ -232,9 +232,9 @@ eBinOp :: MonadBinder m => BinOp ->- m (Exp (Lore m)) ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eBinOp op x y = do x' <- letSubExp "x" =<< x y' <- letSubExp "y" =<< y@@ -243,9 +243,9 @@ eCmpOp :: MonadBinder m => CmpOp ->- m (Exp (Lore m)) ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eCmpOp op x y = do x' <- letSubExp "x" =<< x y' <- letSubExp "y" =<< y@@ -254,16 +254,16 @@ eConvOp :: MonadBinder m => ConvOp ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eConvOp op x = do x' <- letSubExp "x" =<< x return $ BasicOp $ ConvOp op x' eSignum :: MonadBinder m =>- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eSignum em = do e <- em e' <- letSubExp "signum_arg" e@@ -276,14 +276,14 @@ eCopy :: MonadBinder m =>- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eCopy e = BasicOp . Copy <$> (letExp "copy_arg" =<< e) eBody :: (MonadBinder m) =>- [m (Exp (Lore m))] ->- m (Body (Lore m))+ [m (Exp (Rep m))] ->+ m (Body (Rep m)) eBody es = buildBody_ $ do es' <- sequence es xs <- mapM (letTupExp "x") es'@@ -291,8 +291,8 @@ eLambda :: MonadBinder m =>- Lambda (Lore m) ->- [m (Exp (Lore m))] ->+ Lambda (Rep m) ->+ [m (Exp (Rep m))] -> m [SubExp] eLambda lam args = do zipWithM_ bindParam (lambdaParams lam) args@@ -303,9 +303,9 @@ eRoundToMultipleOf :: MonadBinder m => IntType ->- m (Exp (Lore m)) ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eRoundToMultipleOf t x d = ePlus x (eMod (eMinus d (eMod x d)) d) where@@ -318,9 +318,9 @@ MonadBinder m => Int -> VName ->- m (Exp (Lore m)) ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) ->+ m (Exp (Rep m)) eSliceArray d arr i n = do arr_t <- lookupType arr let skips = map (slice (constant (0 :: Int64))) $ take d $ arrayDims arr_t@@ -334,8 +334,8 @@ eOutOfBounds :: MonadBinder m => VName ->- [m (Exp (Lore m))] ->- m (Exp (Lore m))+ [m (Exp (Rep m))] ->+ m (Exp (Rep m)) eOutOfBounds arr is = do arr_t <- lookupType arr let ws = arrayDims arr_t@@ -354,11 +354,11 @@ -- | Write to an index of the array, if within bounds. Otherwise, -- nothing. Produces the updated array. eWriteArray ::- (MonadBinder m, BranchType (Lore m) ~ ExtType) =>+ (MonadBinder m, BranchType (Rep m) ~ ExtType) => VName ->- [m (Exp (Lore m))] ->- m (Exp (Lore m)) ->- m (Exp (Lore m))+ [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@@ -381,7 +381,7 @@ ifCommon [arr_t] -- | Construct an unspecified value of the given type.-eBlank :: MonadBinder m => Type -> m (Exp (Lore m))+eBlank :: MonadBinder 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"@@ -419,14 +419,14 @@ BinOp -> SubExp -> [SubExp] ->- m (Exp (Lore m))+ m (Exp (Rep m)) foldBinOp _ ne [] = return $ BasicOp $ SubExp ne foldBinOp bop ne (e : es) = eBinOp bop (pure $ BasicOp $ SubExp e) (foldBinOp bop ne es) -- | True if all operands are true.-eAll :: MonadBinder m => [SubExp] -> m (Exp (Lore m))+eAll :: MonadBinder m => [SubExp] -> m (Exp (Rep m)) eAll [] = pure $ BasicOp $ SubExp $ constant True eAll (x : xs) = foldBinOp LogAnd x xs @@ -435,25 +435,25 @@ -- result types are the same. (This assumption should be fixed at -- some point.) binOpLambda ::- (MonadBinder m, Bindable (Lore m)) =>+ (MonadBinder m, Bindable (Rep m)) => BinOp -> PrimType ->- m (Lambda (Lore m))+ m (Lambda (Rep m)) binOpLambda bop t = binLambda (BinOp bop) t t -- | As 'binOpLambda', but for t'CmpOp's. cmpOpLambda ::- (MonadBinder m, Bindable (Lore m)) =>+ (MonadBinder m, Bindable (Rep m)) => CmpOp ->- m (Lambda (Lore m))+ m (Lambda (Rep m)) cmpOpLambda cop = binLambda (CmpOp cop) (cmpOpType cop) Bool binLambda ::- (MonadBinder m, Bindable (Lore m)) =>+ (MonadBinder m, Bindable (Rep m)) => (SubExp -> SubExp -> BasicOp) -> PrimType -> PrimType ->- m (Lambda (Lore m))+ m (Lambda (Rep m)) binLambda bop arg_t ret_t = do x <- newVName "x" y <- newVName "y"@@ -473,9 +473,9 @@ -- | Easily construct a 'Lambda' within a 'MonadBinder'. mkLambda :: MonadBinder m =>- [LParam (Lore m)] ->+ [LParam (Rep m)] -> m Result ->- m (Lambda (Lore m))+ m (Lambda (Rep m)) mkLambda params m = do (body, ret) <- buildBody . localScope (scopeOfLParams params) $ do res <- m@@ -521,7 +521,7 @@ ifCommon ts = IfDec (staticShapes ts) IfNormal -- | Conveniently construct a body that contains no bindings.-resultBody :: Bindable lore => [SubExp] -> Body lore+resultBody :: Bindable rep => [SubExp] -> Body rep resultBody = mkBody mempty -- | Conveniently construct a body that contains no bindings - but@@ -529,15 +529,15 @@ resultBodyM :: MonadBinder m => [SubExp] ->- m (Body (Lore m))+ m (Body (Rep m)) resultBodyM = mkBodyM mempty -- | Evaluate the action, producing a body, then wrap it in all the -- bindings it created using 'addStm'. insertStmsM :: (MonadBinder m) =>- m (Body (Lore m)) ->- m (Body (Lore m))+ m (Body (Rep m)) ->+ m (Body (Rep m)) insertStmsM m = do (Body _ bnds res, otherbnds) <- collectStms m mkBodyM (otherbnds <> bnds) res@@ -548,7 +548,7 @@ buildBody :: MonadBinder m => m (Result, a) ->- m (Body (Lore m), a)+ m (Body (Rep m), a) buildBody m = do ((res, v), stms) <- collectStms m body <- mkBodyM stms res@@ -558,16 +558,16 @@ buildBody_ :: MonadBinder m => m Result ->- m (Body (Lore m))+ m (Body (Rep m)) buildBody_ m = fst <$> buildBody ((,()) <$> m) -- | Change that result where evaluation of the body would stop. Also -- change type annotations at branches. mapResult ::- Bindable lore =>- (Result -> Body lore) ->- Body lore ->- Body lore+ Bindable rep =>+ (Result -> Body rep) ->+ Body rep ->+ Body rep mapResult f (Body _ bnds res) = let Body _ bnds2 newres = f res in mkBody (bnds <> bnds2) newres@@ -625,15 +625,15 @@ -- | Can be used as the definition of 'mkLetNames' for a 'Bindable' -- instance for simple representations. simpleMkLetNames ::- ( ExpDec lore ~ (),- LetDec lore ~ Type,+ ( ExpDec rep ~ (),+ LetDec rep ~ Type, MonadFreshNames m,- TypedOp (Op lore),- HasScope lore m+ TypedOp (Op rep),+ HasScope rep m ) => [VName] ->- Exp lore ->- m (Stm lore)+ Exp rep ->+ m (Stm rep) simpleMkLetNames names e = do et <- expExtType e (ts, shapes) <- instantiateShapes' et@@ -644,7 +644,7 @@ -- | Instances of this class can be converted to Futhark expressions -- within a 'MonadBinder'. class ToExp a where- toExp :: MonadBinder m => a -> m (Exp (Lore m))+ toExp :: MonadBinder m => a -> m (Exp (Rep m)) instance ToExp SubExp where toExp = return . BasicOp . SubExp
src/Futhark/IR.hs view
@@ -1,7 +1,4 @@--- | A convenient re-export of basic AST modules. Note that--- "Futhark.IR.Lore" is not exported, as this would--- cause name clashes. You are advised to use a qualified import of--- the lore module, if you need it.+-- | A convenient re-export of basic AST modules. module Futhark.IR ( module Futhark.IR.Prop, module Futhark.IR.Traversals,
src/Futhark/IR/Aliases.hs view
@@ -8,7 +8,7 @@ -- | A representation where all bindings are annotated with aliasing -- information. module Futhark.IR.Aliases- ( -- * The Lore definition+ ( -- * The representation definition Aliases, AliasDec (..), VarAliases,@@ -60,8 +60,8 @@ import Futhark.Transform.Substitute import qualified Futhark.Util.Pretty as PP --- | The lore for the basic representation.-data Aliases lore+-- | The rep for the basic representation.+data Aliases rep -- | A wrapper around 'AliasDec' to get around the fact that we need an -- 'Ord' instance, which 'AliasDec does not have.@@ -102,18 +102,15 @@ -- consumed inside of it. type BodyAliasing = ([VarAliases], ConsumedInExp) -instance- (Decorations lore, CanBeAliased (Op lore)) =>- Decorations (Aliases lore)- where- type LetDec (Aliases lore) = (VarAliases, LetDec lore)- type ExpDec (Aliases lore) = (ConsumedInExp, ExpDec lore)- type BodyDec (Aliases lore) = (BodyAliasing, BodyDec lore)- type FParamInfo (Aliases lore) = FParamInfo lore- type LParamInfo (Aliases lore) = LParamInfo lore- type RetType (Aliases lore) = RetType lore- type BranchType (Aliases lore) = BranchType lore- type Op (Aliases lore) = OpWithAliases (Op lore)+instance (RepTypes rep, CanBeAliased (Op rep)) => RepTypes (Aliases rep) where+ type LetDec (Aliases rep) = (VarAliases, LetDec rep)+ type ExpDec (Aliases rep) = (ConsumedInExp, ExpDec rep)+ type BodyDec (Aliases rep) = (BodyAliasing, BodyDec rep)+ type FParamInfo (Aliases rep) = FParamInfo rep+ type LParamInfo (Aliases rep) = LParamInfo rep+ type RetType (Aliases rep) = RetType rep+ type BranchType (Aliases rep) = BranchType rep+ type Op (Aliases rep) = OpWithAliases (Op rep) instance AliasesOf (VarAliases, dec) where aliasesOf = unAliases . fst@@ -121,28 +118,28 @@ instance FreeDec AliasDec withoutAliases ::- (HasScope (Aliases lore) m, Monad m) =>- ReaderT (Scope lore) m a ->+ (HasScope (Aliases rep) m, Monad m) =>+ ReaderT (Scope rep) m a -> m a withoutAliases m = do scope <- asksScope removeScopeAliases runReaderT m scope -instance (ASTLore lore, CanBeAliased (Op lore)) => ASTLore (Aliases lore) where+instance (ASTRep rep, CanBeAliased (Op rep)) => ASTRep (Aliases rep) where expTypesFromPattern = withoutAliases . expTypesFromPattern . removePatternAliases -instance (ASTLore lore, CanBeAliased (Op lore)) => Aliased (Aliases lore) where+instance (ASTRep rep, CanBeAliased (Op rep)) => Aliased (Aliases rep) where bodyAliases = map unAliases . fst . fst . bodyDec consumedInBody = unAliases . snd . fst . bodyDec -instance (ASTLore lore, CanBeAliased (Op lore)) => PrettyLore (Aliases lore) where- ppExpLore (consumed, inner) e =+instance (ASTRep rep, CanBeAliased (Op rep)) => PrettyRep (Aliases rep) where+ ppExpDec (consumed, inner) e = maybeComment $ catMaybes [ exp_dec, merge_dec,- ppExpLore inner $ removeExpAliases e+ ppExpDec inner $ removeExpAliases e ] where merge_dec =@@ -180,20 +177,20 @@ PP.text "-- Result of " <> PP.ppr name <> PP.text " aliases " <> PP.commasep (map PP.ppr als') -removeAliases :: CanBeAliased (Op lore) => Rephraser Identity (Aliases lore) lore+removeAliases :: CanBeAliased (Op rep) => Rephraser Identity (Aliases rep) rep removeAliases = Rephraser- { rephraseExpLore = return . snd,- rephraseLetBoundLore = return . snd,- rephraseBodyLore = return . snd,- rephraseFParamLore = return,- rephraseLParamLore = return,+ { rephraseExpDec = return . snd,+ rephraseLetBoundDec = return . snd,+ rephraseBodyDec = return . snd,+ rephraseFParamDec = return,+ rephraseLParamDec = return, rephraseRetType = return, rephraseBranchType = return, rephraseOp = return . removeOpAliases } -removeScopeAliases :: Scope (Aliases lore) -> Scope lore+removeScopeAliases :: Scope (Aliases rep) -> Scope rep removeScopeAliases = M.map unAlias where unAlias (LetName (_, dec)) = LetName dec@@ -202,33 +199,33 @@ unAlias (IndexName it) = IndexName it removeProgAliases ::- CanBeAliased (Op lore) =>- Prog (Aliases lore) ->- Prog lore+ CanBeAliased (Op rep) =>+ Prog (Aliases rep) ->+ Prog rep removeProgAliases = runIdentity . rephraseProg removeAliases removeFunDefAliases ::- CanBeAliased (Op lore) =>- FunDef (Aliases lore) ->- FunDef lore+ CanBeAliased (Op rep) =>+ FunDef (Aliases rep) ->+ FunDef rep removeFunDefAliases = runIdentity . rephraseFunDef removeAliases removeExpAliases ::- CanBeAliased (Op lore) =>- Exp (Aliases lore) ->- Exp lore+ CanBeAliased (Op rep) =>+ Exp (Aliases rep) ->+ Exp rep removeExpAliases = runIdentity . rephraseExp removeAliases removeStmAliases ::- CanBeAliased (Op lore) =>- Stm (Aliases lore) ->- Stm lore+ CanBeAliased (Op rep) =>+ Stm (Aliases rep) ->+ Stm rep removeStmAliases = runIdentity . rephraseStm removeAliases removeLambdaAliases ::- CanBeAliased (Op lore) =>- Lambda (Aliases lore) ->- Lambda lore+ CanBeAliased (Op rep) =>+ Lambda (Aliases rep) ->+ Lambda rep removeLambdaAliases = runIdentity . rephraseLambda removeAliases removePatternAliases ::@@ -237,26 +234,26 @@ removePatternAliases = runIdentity . rephrasePattern (return . snd) addAliasesToPattern ::- (ASTLore lore, CanBeAliased (Op lore), Typed dec) =>+ (ASTRep rep, CanBeAliased (Op rep), Typed dec) => PatternT dec ->- Exp (Aliases lore) ->+ Exp (Aliases rep) -> PatternT (VarAliases, dec) addAliasesToPattern pat e = uncurry Pattern $ mkPatternAliases pat e mkAliasedBody ::- (ASTLore lore, CanBeAliased (Op lore)) =>- BodyDec lore ->- Stms (Aliases lore) ->+ (ASTRep rep, CanBeAliased (Op rep)) =>+ BodyDec rep ->+ Stms (Aliases rep) -> Result ->- Body (Aliases lore)-mkAliasedBody innerlore bnds res =- Body (mkBodyAliases bnds res, innerlore) bnds res+ Body (Aliases rep)+mkAliasedBody dec bnds res =+ Body (mkBodyAliases bnds res, dec) bnds res mkPatternAliases ::- (Aliased lore, Typed dec) =>+ (Aliased rep, Typed dec) => PatternT dec ->- Exp lore ->+ Exp rep -> ( [PatElemT (VarAliases, dec)], [PatElemT (VarAliases, dec)] )@@ -273,7 +270,7 @@ ) where annotateBindee bindee names =- bindee `setPatElemLore` (AliasDec names', patElemDec bindee)+ bindee `setPatElemDec` (AliasDec names', patElemDec bindee) where names' = case patElemType bindee of@@ -282,9 +279,9 @@ _ -> mempty mkContextAliases ::- Aliased lore =>+ Aliased rep => PatternT dec ->- Exp lore ->+ Exp rep -> [Names] mkContextAliases pat (DoLoop ctxmerge valmerge _ body) = let ctx = map fst ctxmerge@@ -307,8 +304,8 @@ replicate (length $ patternContextElements pat) mempty mkBodyAliases ::- Aliased lore =>- Stms lore ->+ Aliased rep =>+ Stms rep -> Result -> BodyAliasing mkBodyAliases bnds res =@@ -326,8 +323,8 @@ -- | The aliases of the result and everything consumed in the given -- statements. mkStmsAliases ::- Aliased lore =>- Stms lore ->+ Aliased rep =>+ Stms rep -> [SubExp] -> ([Names], Names) mkStmsAliases bnds res = delve mempty $ stmsToList bnds@@ -349,9 +346,9 @@ ) trackAliases ::- Aliased lore =>+ Aliased rep => AliasesAndConsumed ->- Stm lore ->+ Stm rep -> AliasesAndConsumed trackAliases (aliasmap, consumed) stm = let pat = stmPattern stm@@ -371,18 +368,18 @@ look k = M.findWithDefault mempty k aliasmap mkAliasedLetStm ::- (ASTLore lore, CanBeAliased (Op lore)) =>- Pattern lore ->- StmAux (ExpDec lore) ->- Exp (Aliases lore) ->- Stm (Aliases lore)+ (ASTRep rep, CanBeAliased (Op rep)) =>+ Pattern rep ->+ StmAux (ExpDec rep) ->+ Exp (Aliases rep) ->+ Stm (Aliases rep) mkAliasedLetStm pat (StmAux cs attrs dec) e = Let (addAliasesToPattern pat e) (StmAux cs attrs (AliasDec $ consumedInExp e, dec)) e -instance (Bindable lore, CanBeAliased (Op lore)) => Bindable (Aliases lore) where+instance (Bindable rep, CanBeAliased (Op rep)) => Bindable (Aliases rep) where mkExpDec pat e = let dec = mkExpDec (removePatternAliases pat) $ removeExpAliases e in (AliasDec $ consumedInExp e, dec)@@ -397,7 +394,7 @@ return $ mkAliasedLetStm pat dec e mkBody bnds res =- let Body bodylore _ _ = mkBody (fmap removeStmAliases bnds) res- in mkAliasedBody bodylore bnds res+ let Body bodyrep _ _ = mkBody (fmap removeStmAliases bnds) res+ in mkAliasedBody bodyrep bnds res -instance (ASTLore (Aliases lore), Bindable (Aliases lore)) => BinderOps (Aliases lore)+instance (ASTRep (Aliases rep), Bindable (Aliases rep)) => BinderOps (Aliases rep)
− src/Futhark/IR/Decorations.hs
@@ -1,92 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}---- | The core Futhark AST is parameterised by a @lore@ type parameter,--- which is then used to invoke the type families defined here.-module Futhark.IR.Decorations- ( Decorations (..),- module Futhark.IR.RetType,- )-where--import qualified Data.Kind-import Futhark.IR.Prop.Types-import Futhark.IR.RetType-import Futhark.IR.Syntax.Core---- | A collection of type families, along with constraints specifying--- that the types they map to should satisfy some minimal--- requirements.-class- ( Show (LetDec l),- Show (ExpDec l),- Show (BodyDec l),- Show (FParamInfo l),- Show (LParamInfo l),- Show (RetType l),- Show (BranchType l),- Show (Op l),- Eq (LetDec l),- Eq (ExpDec l),- Eq (BodyDec l),- Eq (FParamInfo l),- Eq (LParamInfo l),- Eq (RetType l),- Eq (BranchType l),- Eq (Op l),- Ord (LetDec l),- Ord (ExpDec l),- Ord (BodyDec l),- Ord (FParamInfo l),- Ord (LParamInfo l),- Ord (RetType l),- Ord (BranchType l),- Ord (Op l),- IsRetType (RetType l),- IsBodyType (BranchType l),- Typed (FParamInfo l),- Typed (LParamInfo l),- Typed (LetDec l),- DeclTyped (FParamInfo l)- ) =>- Decorations l- where- -- | Decoration for every let-pattern element.- type LetDec l :: Data.Kind.Type-- type LetDec l = Type-- -- | Decoration for every expression.- type ExpDec l :: Data.Kind.Type-- type ExpDec l = ()-- -- | Decoration for every body.- type BodyDec l :: Data.Kind.Type-- type BodyDec l = ()-- -- | Decoration for every (non-lambda) function parameter.- type FParamInfo l :: Data.Kind.Type-- type FParamInfo l = DeclType-- -- | Decoration for every lambda function parameter.- type LParamInfo l :: Data.Kind.Type-- type LParamInfo l = Type-- -- | The return type decoration of function calls.- type RetType l :: Data.Kind.Type-- type RetType l = DeclExtType-- -- | The return type decoration of branches.- type BranchType l :: Data.Kind.Type-- type BranchType l = ExtType-- -- | Extensible operation.- type Op l :: Data.Kind.Type-- type Op l = ()
+ src/Futhark/IR/GPU.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}++-- | A representation with flat parallelism via GPU-oriented kernels.+module Futhark.IR.GPU+ ( GPU,++ -- * Module re-exports+ module Futhark.IR.Prop,+ module Futhark.IR.Traversals,+ module Futhark.IR.Pretty,+ module Futhark.IR.Syntax,+ module Futhark.IR.GPU.Kernel,+ module Futhark.IR.GPU.Sizes,+ module Futhark.IR.SOACS.SOAC,+ )+where++import Futhark.Binder+import Futhark.Construct+import Futhark.IR.GPU.Kernel+import Futhark.IR.GPU.Sizes+import Futhark.IR.Pretty+import Futhark.IR.Prop+import Futhark.IR.SOACS.SOAC hiding (HistOp (..))+import Futhark.IR.Syntax+import Futhark.IR.Traversals+import qualified Futhark.TypeCheck as TypeCheck++-- | The phantom data type for the kernels representation.+data GPU++instance RepTypes GPU where+ type Op GPU = HostOp GPU (SOAC GPU)++instance ASTRep GPU where+ expTypesFromPattern = return . expExtTypesFromPattern++instance TypeCheck.CheckableOp GPU where+ checkOp = typeCheckGPUOp Nothing+ where+ typeCheckGPUOp lvl =+ typeCheckHostOp (typeCheckGPUOp . Just) lvl typeCheckSOAC++instance TypeCheck.Checkable GPU++instance Bindable GPU where+ mkBody = Body ()+ mkExpPat ctx val _ = basicPattern ctx val+ mkExpDec _ _ = ()+ mkLetNames = simpleMkLetNames++instance BinderOps GPU++instance PrettyRep GPU++instance HasSegOp GPU where+ type SegOpLevel GPU = SegLevel+ asSegOp (SegOp op) = Just op+ asSegOp _ = Nothing+ segOp = SegOp
+ src/Futhark/IR/GPU/Kernel.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.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/Simplify.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Futhark.IR.GPU.Simplify+ ( simplifyGPU,+ simplifyLambda,+ GPU,++ -- * Building blocks+ simplifyKernelOp,+ )+where++import qualified Futhark.Analysis.SymbolTable as ST+import Futhark.IR.GPU+import qualified Futhark.IR.SOACS.Simplify as SOAC+import Futhark.MonadFreshNames+import qualified Futhark.Optimise.Simplify as Simplify+import qualified Futhark.Optimise.Simplify.Engine as Engine+import Futhark.Optimise.Simplify.Rep+import Futhark.Optimise.Simplify.Rule+import Futhark.Optimise.Simplify.Rules+import Futhark.Pass+import Futhark.Tools+import qualified Futhark.Transform.FirstOrderTransform as FOT++simpleGPU :: Simplify.SimpleOps GPU+simpleGPU = Simplify.bindableSimpleOps $ simplifyKernelOp SOAC.simplifySOAC++simplifyGPU :: Prog GPU -> PassM (Prog GPU)+simplifyGPU =+ Simplify.simplifyProg simpleGPU kernelRules Simplify.noExtraHoistBlockers++simplifyLambda ::+ (HasScope GPU m, MonadFreshNames m) =>+ Lambda GPU ->+ m (Lambda GPU)+simplifyLambda =+ Simplify.simplifyLambda simpleGPU kernelRules Engine.noExtraHoistBlockers++simplifyKernelOp ::+ ( Engine.SimplifiableRep rep,+ BodyDec rep ~ ()+ ) =>+ Simplify.SimplifyOp rep op ->+ HostOp rep op ->+ Engine.SimpleM rep (HostOp (Wise rep) (OpWithWisdom op), Stms (Wise rep))+simplifyKernelOp f (OtherOp op) = do+ (op', stms) <- f op+ return (OtherOp op', stms)+simplifyKernelOp _ (SegOp op) = do+ (op', hoisted) <- simplifySegOp op+ return (SegOp op', hoisted)+simplifyKernelOp _ (SizeOp (SplitSpace o w i elems_per_thread)) =+ (,)+ <$> ( SizeOp+ <$> ( SplitSpace <$> Engine.simplify o <*> Engine.simplify w+ <*> Engine.simplify i+ <*> Engine.simplify elems_per_thread+ )+ )+ <*> pure mempty+simplifyKernelOp _ (SizeOp (GetSize key size_class)) =+ return (SizeOp $ GetSize key size_class, mempty)+simplifyKernelOp _ (SizeOp (GetSizeMax size_class)) =+ return (SizeOp $ GetSizeMax size_class, mempty)+simplifyKernelOp _ (SizeOp (CmpSizeLe key size_class x)) = do+ x' <- Engine.simplify x+ return (SizeOp $ CmpSizeLe key size_class x', mempty)+simplifyKernelOp _ (SizeOp (CalcNumGroups w max_num_groups group_size)) = do+ w' <- Engine.simplify w+ return (SizeOp $ CalcNumGroups w' max_num_groups group_size, mempty)++instance BinderOps (Wise GPU)++instance HasSegOp (Wise GPU) where+ type SegOpLevel (Wise GPU) = SegLevel+ asSegOp (SegOp op) = Just op+ asSegOp _ = Nothing+ segOp = SegOp++instance SOAC.HasSOAC (Wise GPU) where+ asSOAC (OtherOp soac) = Just soac+ asSOAC _ = Nothing+ soacOp = OtherOp++kernelRules :: RuleBook (Wise GPU)+kernelRules =+ standardRules <> segOpRules+ <> ruleBook+ [ RuleOp redomapIotaToLoop,+ RuleOp SOAC.simplifyKnownIterationSOAC,+ RuleOp SOAC.removeReplicateMapping,+ RuleOp SOAC.liftIdentityMapping+ ]+ [ RuleBasicOp removeUnnecessaryCopy+ ]++-- We turn reductions over (solely) iotas into do-loops, because there+-- is no useful structure here anyway. This is mostly a hack to work+-- around the fact that loop tiling would otherwise pointlessly tile+-- them.+redomapIotaToLoop :: TopDownRuleOp (Wise GPU)+redomapIotaToLoop vtable pat aux (OtherOp soac@(Screma _ [arr] form))+ | Just _ <- isRedomapSOAC form,+ Just (Iota {}, _) <- ST.lookupBasicOp arr vtable =+ Simplify $ certifying (stmAuxCerts aux) $ FOT.transformSOAC pat soac+redomapIotaToLoop _ _ _ _ =+ Skip
+ src/Futhark/IR/GPU/Sizes.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Trustworthy #-}++-- | In the context of this module, a "size" is any kind of tunable+-- (run-time) constant.+module Futhark.IR.GPU.Sizes+ ( SizeClass (..),+ sizeDefault,+ KernelPath,+ Count (..),+ NumGroups,+ GroupSize,+ NumThreads,+ )+where++import Data.Int (Int64)+import Data.Traversable+import Futhark.IR.Prop.Names (FreeIn)+import Futhark.Transform.Substitute+import Futhark.Util.IntegralExp (IntegralExp)+import Futhark.Util.Pretty+import Language.Futhark.Core (Name)+import Prelude hiding (id, (.))++-- | An indication of which comparisons have been performed to get to+-- this point, as well as the result of each comparison.+type KernelPath = [(Name, Bool)]++-- | The class of some kind of configurable size. Each class may+-- impose constraints on the valid values.+data SizeClass+ = -- | A threshold with an optional default.+ SizeThreshold KernelPath (Maybe Int64)+ | SizeGroup+ | SizeNumGroups+ | SizeTile+ | SizeRegTile+ | -- | Likely not useful on its own, but querying the+ -- maximum can be handy.+ SizeLocalMemory+ | -- | A bespoke size with a default.+ SizeBespoke Name Int64+ deriving (Eq, Ord, Show)++instance Pretty SizeClass where+ ppr (SizeThreshold path def) =+ "threshold" <> parens (def' <> comma <+> spread (map pStep path))+ where+ pStep (v, True) = ppr v+ pStep (v, False) = "!" <> ppr v+ def' = maybe "def" ppr def+ ppr SizeGroup = text "group_size"+ ppr SizeNumGroups = text "num_groups"+ ppr SizeTile = text "tile_size"+ ppr SizeRegTile = text "reg_tile_size"+ ppr SizeLocalMemory = text "local_memory"+ ppr (SizeBespoke k def) =+ text "bespoke" <> parens (ppr k <> comma <+> ppr def)++-- | The default value for the size. If 'Nothing', that means the backend gets to decide.+sizeDefault :: SizeClass -> Maybe Int64+sizeDefault (SizeThreshold _ x) = x+sizeDefault (SizeBespoke _ x) = Just x+sizeDefault _ = Nothing++-- | A wrapper supporting a phantom type for indicating what we are counting.+newtype Count u e = Count {unCount :: e}+ deriving (Eq, Ord, Show, Num, IntegralExp, FreeIn, Pretty, Substitute)++instance Functor (Count u) where+ fmap = fmapDefault++instance Foldable (Count u) where+ foldMap = foldMapDefault++instance Traversable (Count u) where+ traverse f (Count x) = Count <$> f x++-- | Phantom type for the number of groups of some kernel.+data NumGroups++-- | Phantom type for the group size of some kernel.+data GroupSize++-- | Phantom type for number of threads.+data NumThreads
+ src/Futhark/IR/GPUMem.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}++module Futhark.IR.GPUMem+ ( GPUMem,++ -- * Simplification+ simplifyProg,+ simplifyStms,+ simpleGPUMem,++ -- * Module re-exports+ module Futhark.IR.Mem,+ module Futhark.IR.GPU.Kernel,+ )+where++import Futhark.Analysis.PrimExp.Convert+import qualified Futhark.Analysis.UsageTable as UT+import Futhark.IR.GPU.Kernel+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 qualified Futhark.TypeCheck as TC++data GPUMem++instance RepTypes GPUMem where+ type LetDec GPUMem = LetDecMem+ type FParamInfo GPUMem = FParamMem+ type LParamInfo GPUMem = LParamMem+ type RetType GPUMem = RetTypeMem+ type BranchType GPUMem = BranchTypeMem+ type Op GPUMem = MemOp (HostOp GPUMem ())++instance ASTRep GPUMem where+ expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern++instance OpReturns GPUMem where+ opReturns (Alloc _ space) =+ return [MemMem space]+ opReturns (Inner (SegOp op)) = segOpReturns op+ opReturns k = extReturns <$> opType k++instance PrettyRep GPUMem++instance TC.CheckableOp GPUMem where+ checkOp = typeCheckMemoryOp Nothing+ where+ typeCheckMemoryOp _ (Alloc size _) =+ TC.require [Prim int64] size+ typeCheckMemoryOp lvl (Inner op) =+ typeCheckHostOp (typeCheckMemoryOp . Just) lvl (const $ return ()) op++instance TC.Checkable GPUMem where+ checkFParamDec = checkMemInfo+ checkLParamDec = checkMemInfo+ checkLetBoundDec = checkMemInfo+ checkRetType = mapM_ $ TC.checkExtType . declExtTypeOf+ primFParam name t = return $ Param name (MemPrim t)+ matchPattern = matchPatternToExp+ matchReturnType = matchFunctionReturnType+ matchBranchType = matchBranchReturnType+ matchLoopResult = matchLoopResultMem++instance BinderOps GPUMem where+ mkExpDecB _ _ = return ()+ mkBodyB stms res = return $ Body () stms res+ mkLetNamesB = mkLetNamesB' ()++instance BinderOps (Engine.Wise GPUMem) where+ mkExpDecB pat e = return $ Engine.mkWiseExpDec pat () e+ mkBodyB stms res = return $ Engine.mkWiseBody () stms res+ mkLetNamesB = mkLetNamesB''++simplifyProg :: Prog GPUMem -> PassM (Prog GPUMem)+simplifyProg = simplifyProgGeneric simpleGPUMem++simplifyStms ::+ (HasScope GPUMem m, MonadFreshNames m) =>+ Stms GPUMem ->+ m+ ( Engine.SymbolTable (Engine.Wise GPUMem),+ Stms GPUMem+ )+simplifyStms = simplifyStmsGeneric simpleGPUMem++simpleGPUMem :: Engine.SimpleOps GPUMem+simpleGPUMem =+ simpleGeneric usage $ simplifyKernelOp $ const $ return ((), mempty)+ where+ -- Slightly hackily, we look at the inside of SegGroup operations+ -- to figure out the sizes of local memory allocations, and add+ -- usages for those sizes. This is necessary so the simplifier+ -- will hoist those sizes out as far as possible (most+ -- importantly, past the versioning If).+ usage (SegOp (SegMap SegGroup {} _ _ kbody)) = localAllocs kbody+ usage _ = mempty+ localAllocs = foldMap stmLocalAlloc . kernelBodyStms+ stmLocalAlloc = expLocalAlloc . stmExp+ expLocalAlloc (Op (Alloc (Var v) (Space "local"))) =+ UT.sizeUsage v+ expLocalAlloc _ =+ mempty
− src/Futhark/IR/Kernels.hs
@@ -1,62 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}---- | A representation with flat parallelism via GPU-oriented kernels.-module Futhark.IR.Kernels- ( -- * The Lore definition- Kernels,-- -- * Module re-exports- module Futhark.IR.Prop,- module Futhark.IR.Traversals,- module Futhark.IR.Pretty,- module Futhark.IR.Syntax,- module Futhark.IR.Kernels.Kernel,- module Futhark.IR.Kernels.Sizes,- module Futhark.IR.SOACS.SOAC,- )-where--import Futhark.Binder-import Futhark.Construct-import Futhark.IR.Kernels.Kernel-import Futhark.IR.Kernels.Sizes-import Futhark.IR.Pretty-import Futhark.IR.Prop-import Futhark.IR.SOACS.SOAC hiding (HistOp (..))-import Futhark.IR.Syntax-import Futhark.IR.Traversals-import qualified Futhark.TypeCheck as TypeCheck---- | The phantom data type for the kernels representation.-data Kernels--instance Decorations Kernels where- type Op Kernels = HostOp Kernels (SOAC Kernels)--instance ASTLore Kernels where- expTypesFromPattern = return . expExtTypesFromPattern--instance TypeCheck.CheckableOp Kernels where- checkOp = typeCheckKernelsOp Nothing- where- typeCheckKernelsOp lvl =- typeCheckHostOp (typeCheckKernelsOp . Just) lvl typeCheckSOAC--instance TypeCheck.Checkable Kernels--instance Bindable Kernels where- mkBody = Body ()- mkExpPat ctx val _ = basicPattern ctx val- mkExpDec _ _ = ()- mkLetNames = simpleMkLetNames--instance BinderOps Kernels--instance PrettyLore Kernels--instance HasSegOp Kernels where- type SegOpLevel Kernels = SegLevel- asSegOp (SegOp op) = Just op- asSegOp _ = Nothing- segOp = SegOp
− src/Futhark/IR/Kernels/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.Kernels.Kernel- ( -- * Size operations- SizeOp (..),-- -- * Host operations- HostOp (..),- typeCheckHostOp,-- -- * SegOp refinements- SegLevel (..),-- -- * Reexports- module Futhark.IR.Kernels.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.Kernels.Sizes-import Futhark.IR.Prop.Aliases-import Futhark.IR.SegOp-import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore-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 lore => SizeOp -> TC.TypeM lore ()-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 lore op- = -- | A segmented operation.- SegOp (SegOp SegLevel lore)- | SizeOp SizeOp- | OtherOp op- deriving (Eq, Ord, Show)--instance (ASTLore lore, Substitute op) => Substitute (HostOp lore 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 (ASTLore lore, Rename op) => Rename (HostOp lore op) where- rename (SegOp op) = SegOp <$> rename op- rename (OtherOp op) = OtherOp <$> rename op- rename (SizeOp op) = SizeOp <$> rename op--instance (ASTLore lore, IsOp op) => IsOp (HostOp lore 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 lore op) where- opType (SegOp op) = opType op- opType (OtherOp op) = opType op- opType (SizeOp op) = opType op--instance (Aliased lore, AliasedOp op, ASTLore lore) => AliasedOp (HostOp lore 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 (ASTLore lore, FreeIn op) => FreeIn (HostOp lore op) where- freeIn' (SegOp op) = freeIn' op- freeIn' (OtherOp op) = freeIn' op- freeIn' (SizeOp op) = freeIn' op--instance (CanBeAliased (Op lore), CanBeAliased op, ASTLore lore) => CanBeAliased (HostOp lore op) where- type OpWithAliases (HostOp lore op) = HostOp (Aliases lore) (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 lore), CanBeWise op, ASTLore lore) => CanBeWise (HostOp lore op) where- type OpWithWisdom (HostOp lore op) = HostOp (Wise lore) (OpWithWisdom op)-- removeOpWisdom (SegOp op) = SegOp $ removeOpWisdom op- removeOpWisdom (OtherOp op) = OtherOp $ removeOpWisdom op- removeOpWisdom (SizeOp op) = SizeOp op--instance (ASTLore lore, ST.IndexOp op) => ST.IndexOp (HostOp lore 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 (PrettyLore lore, PP.Pretty op) => PP.Pretty (HostOp lore op) where- ppr (SegOp op) = ppr op- ppr (OtherOp op) = ppr op- ppr (SizeOp op) = ppr op--instance (OpMetrics (Op lore), OpMetrics op) => OpMetrics (HostOp lore op) where- opMetrics (SegOp op) = opMetrics op- opMetrics (OtherOp op) = opMetrics op- opMetrics (SizeOp op) = opMetrics op--checkSegLevel ::- TC.Checkable lore =>- Maybe SegLevel ->- SegLevel ->- TC.TypeM lore ()-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 lore =>- (SegLevel -> OpWithAliases (Op lore) -> TC.TypeM lore ()) ->- Maybe SegLevel ->- (op -> TC.TypeM lore ()) ->- HostOp (Aliases lore) op ->- TC.TypeM lore ()-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/Kernels/Simplify.hs
@@ -1,113 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Futhark.IR.Kernels.Simplify- ( simplifyKernels,- simplifyLambda,- Kernels,-- -- * Building blocks- simplifyKernelOp,- )-where--import qualified Futhark.Analysis.SymbolTable as ST-import Futhark.IR.Kernels-import qualified Futhark.IR.SOACS.Simplify as SOAC-import Futhark.MonadFreshNames-import qualified Futhark.Optimise.Simplify as Simplify-import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore-import Futhark.Optimise.Simplify.Rule-import Futhark.Optimise.Simplify.Rules-import Futhark.Pass-import Futhark.Tools-import qualified Futhark.Transform.FirstOrderTransform as FOT--simpleKernels :: Simplify.SimpleOps Kernels-simpleKernels = Simplify.bindableSimpleOps $ simplifyKernelOp SOAC.simplifySOAC--simplifyKernels :: Prog Kernels -> PassM (Prog Kernels)-simplifyKernels =- Simplify.simplifyProg simpleKernels kernelRules Simplify.noExtraHoistBlockers--simplifyLambda ::- (HasScope Kernels m, MonadFreshNames m) =>- Lambda Kernels ->- m (Lambda Kernels)-simplifyLambda =- Simplify.simplifyLambda simpleKernels kernelRules Engine.noExtraHoistBlockers--simplifyKernelOp ::- ( Engine.SimplifiableLore lore,- BodyDec lore ~ ()- ) =>- Simplify.SimplifyOp lore op ->- HostOp lore op ->- Engine.SimpleM lore (HostOp (Wise lore) (OpWithWisdom op), Stms (Wise lore))-simplifyKernelOp f (OtherOp op) = do- (op', stms) <- f op- return (OtherOp op', stms)-simplifyKernelOp _ (SegOp op) = do- (op', hoisted) <- simplifySegOp op- return (SegOp op', hoisted)-simplifyKernelOp _ (SizeOp (SplitSpace o w i elems_per_thread)) =- (,)- <$> ( SizeOp- <$> ( SplitSpace <$> Engine.simplify o <*> Engine.simplify w- <*> Engine.simplify i- <*> Engine.simplify elems_per_thread- )- )- <*> pure mempty-simplifyKernelOp _ (SizeOp (GetSize key size_class)) =- return (SizeOp $ GetSize key size_class, mempty)-simplifyKernelOp _ (SizeOp (GetSizeMax size_class)) =- return (SizeOp $ GetSizeMax size_class, mempty)-simplifyKernelOp _ (SizeOp (CmpSizeLe key size_class x)) = do- x' <- Engine.simplify x- return (SizeOp $ CmpSizeLe key size_class x', mempty)-simplifyKernelOp _ (SizeOp (CalcNumGroups w max_num_groups group_size)) = do- w' <- Engine.simplify w- return (SizeOp $ CalcNumGroups w' max_num_groups group_size, mempty)--instance BinderOps (Wise Kernels)--instance HasSegOp (Wise Kernels) where- type SegOpLevel (Wise Kernels) = SegLevel- asSegOp (SegOp op) = Just op- asSegOp _ = Nothing- segOp = SegOp--instance SOAC.HasSOAC (Wise Kernels) where- asSOAC (OtherOp soac) = Just soac- asSOAC _ = Nothing- soacOp = OtherOp--kernelRules :: RuleBook (Wise Kernels)-kernelRules =- standardRules <> segOpRules- <> ruleBook- [ RuleOp redomapIotaToLoop,- RuleOp SOAC.simplifyKnownIterationSOAC,- RuleOp SOAC.removeReplicateMapping,- RuleOp SOAC.liftIdentityMapping- ]- [ RuleBasicOp removeUnnecessaryCopy- ]---- We turn reductions over (solely) iotas into do-loops, because there--- is no useful structure here anyway. This is mostly a hack to work--- around the fact that loop tiling would otherwise pointlessly tile--- them.-redomapIotaToLoop :: TopDownRuleOp (Wise Kernels)-redomapIotaToLoop vtable pat aux (OtherOp soac@(Screma _ [arr] form))- | Just _ <- isRedomapSOAC form,- Just (Iota {}, _) <- ST.lookupBasicOp arr vtable =- Simplify $ certifying (stmAuxCerts aux) $ FOT.transformSOAC pat soac-redomapIotaToLoop _ _ _ _ =- Skip
− src/Futhark/IR/Kernels/Sizes.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Trustworthy #-}---- | In the context of this module, a "size" is any kind of tunable--- (run-time) constant.-module Futhark.IR.Kernels.Sizes- ( SizeClass (..),- sizeDefault,- KernelPath,- Count (..),- NumGroups,- GroupSize,- NumThreads,- )-where--import Data.Int (Int64)-import Data.Traversable-import Futhark.IR.Prop.Names (FreeIn)-import Futhark.Transform.Substitute-import Futhark.Util.IntegralExp (IntegralExp)-import Futhark.Util.Pretty-import Language.Futhark.Core (Name)-import Prelude hiding (id, (.))---- | An indication of which comparisons have been performed to get to--- this point, as well as the result of each comparison.-type KernelPath = [(Name, Bool)]---- | The class of some kind of configurable size. Each class may--- impose constraints on the valid values.-data SizeClass- = -- | A threshold with an optional default.- SizeThreshold KernelPath (Maybe Int64)- | SizeGroup- | SizeNumGroups- | SizeTile- | SizeRegTile- | -- | Likely not useful on its own, but querying the- -- maximum can be handy.- SizeLocalMemory- | -- | A bespoke size with a default.- SizeBespoke Name Int64- deriving (Eq, Ord, Show)--instance Pretty SizeClass where- ppr (SizeThreshold path def) =- "threshold" <> parens (def' <> comma <+> spread (map pStep path))- where- pStep (v, True) = ppr v- pStep (v, False) = "!" <> ppr v- def' = maybe "def" ppr def- ppr SizeGroup = text "group_size"- ppr SizeNumGroups = text "num_groups"- ppr SizeTile = text "tile_size"- ppr SizeRegTile = text "reg_tile_size"- ppr SizeLocalMemory = text "local_memory"- ppr (SizeBespoke k def) =- text "bespoke" <> parens (ppr k <> comma <+> ppr def)---- | The default value for the size. If 'Nothing', that means the backend gets to decide.-sizeDefault :: SizeClass -> Maybe Int64-sizeDefault (SizeThreshold _ x) = x-sizeDefault (SizeBespoke _ x) = Just x-sizeDefault _ = Nothing---- | A wrapper supporting a phantom type for indicating what we are counting.-newtype Count u e = Count {unCount :: e}- deriving (Eq, Ord, Show, Num, IntegralExp, FreeIn, Pretty, Substitute)--instance Functor (Count u) where- fmap = fmapDefault--instance Foldable (Count u) where- foldMap = foldMapDefault--instance Traversable (Count u) where- traverse f (Count x) = Count <$> f x---- | Phantom type for the number of groups of some kernel.-data NumGroups---- | Phantom type for the group size of some kernel.-data GroupSize---- | Phantom type for number of threads.-data NumThreads
− src/Futhark/IR/KernelsMem.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}--module Futhark.IR.KernelsMem- ( KernelsMem,-- -- * Simplification- simplifyProg,- simplifyStms,- simpleKernelsMem,-- -- * Module re-exports- module Futhark.IR.Mem,- module Futhark.IR.Kernels.Kernel,- )-where--import Futhark.Analysis.PrimExp.Convert-import qualified Futhark.Analysis.UsageTable as UT-import Futhark.IR.Kernels.Kernel-import Futhark.IR.Kernels.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 qualified Futhark.TypeCheck as TC--data KernelsMem--instance Decorations KernelsMem where- type LetDec KernelsMem = LetDecMem- type FParamInfo KernelsMem = FParamMem- type LParamInfo KernelsMem = LParamMem- type RetType KernelsMem = RetTypeMem- type BranchType KernelsMem = BranchTypeMem- type Op KernelsMem = MemOp (HostOp KernelsMem ())--instance ASTLore KernelsMem where- expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern--instance OpReturns KernelsMem where- opReturns (Alloc _ space) =- return [MemMem space]- opReturns (Inner (SegOp op)) = segOpReturns op- opReturns k = extReturns <$> opType k--instance PrettyLore KernelsMem--instance TC.CheckableOp KernelsMem where- checkOp = typeCheckMemoryOp Nothing- where- typeCheckMemoryOp _ (Alloc size _) =- TC.require [Prim int64] size- typeCheckMemoryOp lvl (Inner op) =- typeCheckHostOp (typeCheckMemoryOp . Just) lvl (const $ return ()) op--instance TC.Checkable KernelsMem where- checkFParamLore = checkMemInfo- checkLParamLore = checkMemInfo- checkLetBoundLore = checkMemInfo- checkRetType = mapM_ $ TC.checkExtType . declExtTypeOf- primFParam name t = return $ Param name (MemPrim t)- matchPattern = matchPatternToExp- matchReturnType = matchFunctionReturnType- matchBranchType = matchBranchReturnType- matchLoopResult = matchLoopResultMem--instance BinderOps KernelsMem where- mkExpDecB _ _ = return ()- mkBodyB stms res = return $ Body () stms res- mkLetNamesB = mkLetNamesB' ()--instance BinderOps (Engine.Wise KernelsMem) where- mkExpDecB pat e = return $ Engine.mkWiseExpDec pat () e- mkBodyB stms res = return $ Engine.mkWiseBody () stms res- mkLetNamesB = mkLetNamesB''--simplifyProg :: Prog KernelsMem -> PassM (Prog KernelsMem)-simplifyProg = simplifyProgGeneric simpleKernelsMem--simplifyStms ::- (HasScope KernelsMem m, MonadFreshNames m) =>- Stms KernelsMem ->- m- ( Engine.SymbolTable (Engine.Wise KernelsMem),- Stms KernelsMem- )-simplifyStms = simplifyStmsGeneric simpleKernelsMem--simpleKernelsMem :: Engine.SimpleOps KernelsMem-simpleKernelsMem =- simpleGeneric usage $ simplifyKernelOp $ const $ return ((), mempty)- where- -- Slightly hackily, we look at the inside of SegGroup operations- -- to figure out the sizes of local memory allocations, and add- -- usages for those sizes. This is necessary so the simplifier- -- will hoist those sizes out as far as possible (most- -- importantly, past the versioning If).- usage (SegOp (SegMap SegGroup {} _ _ kbody)) = localAllocs kbody- usage _ = mempty- localAllocs = foldMap stmLocalAlloc . kernelBodyStms- stmLocalAlloc = expLocalAlloc . stmExp- expLocalAlloc (Op (Alloc (Var v) (Space "local"))) =- UT.sizeUsage v- expLocalAlloc _ =- mempty
src/Futhark/IR/MC.hs view
@@ -4,8 +4,7 @@ -- | A representation for multicore CPU parallelism. module Futhark.IR.MC- ( -- * The Lore definition- MC,+ ( MC, -- * Simplification simplifyProg,@@ -39,10 +38,10 @@ data MC -instance Decorations MC where+instance RepTypes MC where type Op MC = MCOp MC (SOAC MC) -instance ASTLore MC where+instance ASTRep MC where expTypesFromPattern = return . expExtTypesFromPattern instance TypeCheck.CheckableOp MC where@@ -60,7 +59,7 @@ instance BinderOps (Engine.Wise MC) -instance PrettyLore MC+instance PrettyRep MC simpleMC :: Simplify.SimpleOps MC simpleMC = Simplify.bindableSimpleOps $ simplifyMCOp SOAC.simplifySOAC
src/Futhark/IR/MC/Op.hs view
@@ -24,7 +24,7 @@ import Futhark.IR.SegOp import qualified Futhark.Optimise.Simplify as Simplify import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Transform.Rename import Futhark.Transform.Substitute import qualified Futhark.TypeCheck as TC@@ -40,45 +40,45 @@ -- | An operation for the multicore representation. Feel free to -- extend this on an ad hoc basis as needed. Parameterised with some -- other operation.-data MCOp lore op+data MCOp rep op = -- | The first 'SegOp' (if it exists) contains nested parallelism, -- while the second one has a fully sequential body. They are -- semantically fully equivalent. ParOp- (Maybe (SegOp () lore))- (SegOp () lore)+ (Maybe (SegOp () rep))+ (SegOp () rep) | -- | Something else (in practice often a SOAC). OtherOp op deriving (Eq, Ord, Show) -instance (ASTLore lore, Substitute op) => Substitute (MCOp lore op) where+instance (ASTRep rep, Substitute op) => Substitute (MCOp rep op) where substituteNames substs (ParOp par_op op) = ParOp (substituteNames substs <$> par_op) (substituteNames substs op) substituteNames substs (OtherOp op) = OtherOp $ substituteNames substs op -instance (ASTLore lore, Rename op) => Rename (MCOp lore op) where+instance (ASTRep rep, Rename op) => Rename (MCOp rep op) where rename (ParOp par_op op) = ParOp <$> rename par_op <*> rename op rename (OtherOp op) = OtherOp <$> rename op -instance (ASTLore lore, FreeIn op) => FreeIn (MCOp lore op) where+instance (ASTRep rep, FreeIn op) => FreeIn (MCOp rep op) where freeIn' (ParOp par_op op) = freeIn' par_op <> freeIn' op freeIn' (OtherOp op) = freeIn' op -instance (ASTLore lore, IsOp op) => IsOp (MCOp lore op) where+instance (ASTRep rep, IsOp op) => IsOp (MCOp rep op) where safeOp (ParOp _ op) = safeOp op safeOp (OtherOp op) = safeOp op cheapOp (ParOp _ op) = cheapOp op cheapOp (OtherOp op) = cheapOp op -instance TypedOp op => TypedOp (MCOp lore op) where+instance TypedOp op => TypedOp (MCOp rep op) where opType (ParOp _ op) = opType op opType (OtherOp op) = opType op instance- (Aliased lore, AliasedOp op, ASTLore lore) =>- AliasedOp (MCOp lore op)+ (Aliased rep, AliasedOp op, ASTRep rep) =>+ AliasedOp (MCOp rep op) where opAliases (ParOp _ op) = opAliases op opAliases (OtherOp op) = opAliases op@@ -87,10 +87,10 @@ consumedInOp (OtherOp op) = consumedInOp op instance- (CanBeAliased (Op lore), CanBeAliased op, ASTLore lore) =>- CanBeAliased (MCOp lore op)+ (CanBeAliased (Op rep), CanBeAliased op, ASTRep rep) =>+ CanBeAliased (MCOp rep op) where- type OpWithAliases (MCOp lore op) = MCOp (Aliases lore) (OpWithAliases op)+ type OpWithAliases (MCOp rep op) = MCOp (Aliases rep) (OpWithAliases op) addOpAliases aliases (ParOp par_op op) = ParOp (addOpAliases aliases <$> par_op) (addOpAliases aliases op)@@ -103,36 +103,36 @@ OtherOp $ removeOpAliases op instance- (CanBeWise (Op lore), CanBeWise op, ASTLore lore) =>- CanBeWise (MCOp lore op)+ (CanBeWise (Op rep), CanBeWise op, ASTRep rep) =>+ CanBeWise (MCOp rep op) where- type OpWithWisdom (MCOp lore op) = MCOp (Wise lore) (OpWithWisdom op)+ type OpWithWisdom (MCOp rep op) = MCOp (Wise rep) (OpWithWisdom op) removeOpWisdom (ParOp par_op op) = ParOp (removeOpWisdom <$> par_op) (removeOpWisdom op) removeOpWisdom (OtherOp op) = OtherOp $ removeOpWisdom op -instance (ASTLore lore, ST.IndexOp op) => ST.IndexOp (MCOp lore op) where+instance (ASTRep rep, ST.IndexOp op) => ST.IndexOp (MCOp rep op) where indexOp vtable k (ParOp _ op) is = ST.indexOp vtable k op is indexOp vtable k (OtherOp op) is = ST.indexOp vtable k op is -instance (PrettyLore lore, Pretty op) => Pretty (MCOp lore op) where+instance (PrettyRep rep, Pretty op) => Pretty (MCOp rep op) where ppr (ParOp Nothing op) = ppr op ppr (ParOp (Just par_op) op) = "par" <+> nestedBlock "{" "}" (ppr par_op) </> "seq" <+> nestedBlock "{" "}" (ppr op) ppr (OtherOp op) = ppr op -instance (OpMetrics (Op lore), OpMetrics op) => OpMetrics (MCOp lore op) where+instance (OpMetrics (Op rep), OpMetrics op) => OpMetrics (MCOp rep op) where opMetrics (ParOp par_op op) = opMetrics par_op >> opMetrics op opMetrics (OtherOp op) = opMetrics op typeCheckMCOp ::- TC.Checkable lore =>- (op -> TC.TypeM lore ()) ->- MCOp (Aliases lore) op ->- TC.TypeM lore ()+ TC.Checkable rep =>+ (op -> TC.TypeM rep ()) ->+ MCOp (Aliases rep) op ->+ TC.TypeM rep () typeCheckMCOp _ (ParOp (Just par_op) op) = do -- It is valid for the same array to be consumed in both par_op and op. _ <- typeCheckSegOp return par_op `TC.alternative` typeCheckSegOp return op@@ -142,12 +142,12 @@ typeCheckMCOp f (OtherOp op) = f op simplifyMCOp ::- ( Engine.SimplifiableLore lore,- BodyDec lore ~ ()+ ( Engine.SimplifiableRep rep,+ BodyDec rep ~ () ) =>- Simplify.SimplifyOp lore op ->- MCOp lore op ->- Engine.SimpleM lore (MCOp (Wise lore) (OpWithWisdom op), Stms (Wise lore))+ Simplify.SimplifyOp rep op ->+ MCOp rep op ->+ Engine.SimpleM rep (MCOp (Wise rep) (OpWithWisdom op), Stms (Wise rep)) simplifyMCOp f (OtherOp op) = do (op', stms) <- f op return (OtherOp op', stms)
src/Futhark/IR/MCMem.hs view
@@ -29,7 +29,7 @@ data MCMem -instance Decorations MCMem where+instance RepTypes MCMem where type LetDec MCMem = LetDecMem type FParamInfo MCMem = FParamMem type LParamInfo MCMem = LParamMem@@ -37,7 +37,7 @@ type BranchType MCMem = BranchTypeMem type Op MCMem = MemOp (MCOp MCMem ()) -instance ASTLore MCMem where+instance ASTRep MCMem where expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern instance OpReturns MCMem where@@ -45,7 +45,7 @@ opReturns (Inner (ParOp _ op)) = segOpReturns op opReturns (Inner (OtherOp ())) = pure [] -instance PrettyLore MCMem+instance PrettyRep MCMem instance TC.CheckableOp MCMem where checkOp = typeCheckMemoryOp@@ -56,9 +56,9 @@ typeCheckMCOp pure op instance TC.Checkable MCMem where- checkFParamLore = checkMemInfo- checkLParamLore = checkMemInfo- checkLetBoundLore = checkMemInfo+ checkFParamDec = checkMemInfo+ checkLParamDec = checkMemInfo+ checkLetBoundDec = checkMemInfo checkRetType = mapM_ (TC.checkExtType . declExtTypeOf) primFParam name t = return $ Param name (MemPrim t) matchPattern = matchPatternToExp
src/Futhark/IR/Mem.hs view
@@ -128,7 +128,7 @@ import Futhark.IR.Syntax import Futhark.IR.Traversals import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Transform.Rename import Futhark.Transform.Substitute import qualified Futhark.TypeCheck as TC@@ -151,16 +151,15 @@ class AllocOp op where allocOp :: SubExp -> Space -> op -type Mem lore =- ( AllocOp (Op lore),- FParamInfo lore ~ FParamMem,- LParamInfo lore ~ LParamMem,- LetDec lore ~ LetDecMem,- RetType lore ~ RetTypeMem,- BranchType lore ~ BranchTypeMem,- ASTLore lore,- Decorations lore,- OpReturns lore+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 ) instance IsRetType FunReturns where@@ -324,15 +323,15 @@ rename = substituteRename simplifyIxFun ::- Engine.SimplifiableLore lore =>+ Engine.SimplifiableRep rep => IxFun ->- Engine.SimpleM lore IxFun+ Engine.SimpleM rep IxFun simplifyIxFun = traverse $ fmap isInt64 . simplifyPrimExp . untyped simplifyExtIxFun ::- Engine.SimplifiableLore lore =>+ Engine.SimplifiableRep rep => ExtIxFun ->- Engine.SimpleM lore ExtIxFun+ Engine.SimpleM rep ExtIxFun simplifyExtIxFun = traverse $ fmap isInt64 . simplifyExtPrimExp . untyped isStaticIxFun :: ExtIxFun -> Maybe IxFun@@ -533,20 +532,20 @@ bodyReturnsToExpReturns = noUniquenessReturns . maybeReturns matchRetTypeToResult ::- (Mem lore, TC.Checkable lore) =>+ (Mem rep, TC.Checkable rep) => [FunReturns] -> Result ->- TC.TypeM lore ()+ TC.TypeM rep () matchRetTypeToResult rettype result = do scope <- askScope result_ts <- runReaderT (mapM subExpMemInfo result) $ removeScopeAliases scope matchReturnType rettype result result_ts matchFunctionReturnType ::- (Mem lore, TC.Checkable lore) =>+ (Mem rep, TC.Checkable rep) => [FunReturns] -> Result ->- TC.TypeM lore ()+ TC.TypeM rep () matchFunctionReturnType rettype result = do matchRetTypeToResult rettype result mapM_ checkResultSubExp result@@ -570,11 +569,11 @@ ++ pretty ixfun matchLoopResultMem ::- (Mem lore, TC.Checkable lore) =>- [FParam (Aliases lore)] ->- [FParam (Aliases lore)] ->+ (Mem rep, TC.Checkable rep) =>+ [FParam (Aliases rep)] ->+ [FParam (Aliases rep)] -> [SubExp] ->- TC.TypeM lore ()+ TC.TypeM rep () matchLoopResultMem ctx val = matchRetTypeToResult rettype where ctx_names = map paramName ctx@@ -607,10 +606,10 @@ ixfun' = existentialiseIxFun ctx_names ixfun matchBranchReturnType ::- (Mem lore, TC.Checkable lore) =>+ (Mem rep, TC.Checkable rep) => [BodyReturns] ->- Body (Aliases lore) ->- TC.TypeM lore ()+ Body (Aliases rep) ->+ TC.TypeM rep () matchBranchReturnType rettype (Body _ stms res) = do scope <- askScope ts <- runReaderT (mapM subExpMemInfo res) $ removeScopeAliases (scope <> scopeOf stms)@@ -649,7 +648,7 @@ [MemInfo ExtSize u MemReturn] -> [SubExp] -> [MemInfo SubExp NoUniqueness MemBind] ->- TC.TypeM lore ()+ 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@@ -769,7 +768,7 @@ pretty y ] - bad :: String -> TC.TypeM lore a+ bad :: String -> TC.TypeM rep a bad s = TC.bad $ TC.TypeError $@@ -792,10 +791,10 @@ either bad return =<< runExceptT (zipWithM_ checkReturn rettype val_ts) matchPatternToExp ::- (Mem lore, TC.Checkable lore) =>- Pattern (Aliases lore) ->- Exp (Aliases lore) ->- TC.TypeM lore ()+ (Mem rep, TC.Checkable rep) =>+ Pattern (Aliases rep) ->+ Exp (Aliases rep) ->+ TC.TypeM rep () matchPatternToExp pat e = do scope <- asksScope removeScopeAliases rt <- runReaderT (expReturns $ removeExpAliases e) scope@@ -866,9 +865,9 @@ extInIxFn ixfun = S.fromList $ concatMap (mapMaybe isExt . toList) ixfun varMemInfo ::- Mem lore =>+ Mem rep => VName ->- TC.TypeM lore (MemInfo SubExp NoUniqueness MemBind)+ TC.TypeM rep (MemInfo SubExp NoUniqueness MemBind) varMemInfo name = do dec <- TC.lookupVar name @@ -878,7 +877,7 @@ LParamName summary -> return summary IndexName it -> return $ MemPrim $ IntType it -nameInfoToMemInfo :: Mem lore => NameInfo lore -> MemBound NoUniqueness+nameInfoToMemInfo :: Mem rep => NameInfo rep -> MemBound NoUniqueness nameInfoToMemInfo info = case info of FParamName summary -> noUniquenessReturns summary@@ -887,20 +886,20 @@ IndexName it -> MemPrim $ IntType it lookupMemInfo ::- (HasScope lore m, Mem lore) =>+ (HasScope rep m, Mem rep) => VName -> m (MemInfo SubExp NoUniqueness MemBind) lookupMemInfo = fmap nameInfoToMemInfo . lookupInfo subExpMemInfo ::- (HasScope lore m, Monad m, Mem lore) =>+ (HasScope rep m, Monad m, Mem rep) => SubExp -> m (MemInfo SubExp NoUniqueness MemBind) subExpMemInfo (Var v) = lookupMemInfo v subExpMemInfo (Constant v) = return $ MemPrim $ primValueType v lookupArraySummary ::- (Mem lore, HasScope lore m, Monad m) =>+ (Mem rep, HasScope rep m, Monad m) => VName -> m (VName, IxFun.IxFun (TPrimExp Int64 VName)) lookupArraySummary name = do@@ -912,10 +911,10 @@ error $ "Variable " ++ pretty name ++ " does not look like an array." checkMemInfo ::- TC.Checkable lore =>+ TC.Checkable rep => VName -> MemInfo SubExp u MemBind ->- TC.TypeM lore ()+ TC.TypeM rep () checkMemInfo _ (MemPrim _) = return () checkMemInfo _ (MemMem (ScalarSpace d _)) = mapM_ (TC.require [Prim int64]) d checkMemInfo _ (MemMem _) = return ()@@ -1002,7 +1001,7 @@ convert (Free v) = Free <$> pe64 v arrayVarReturns ::- (HasScope lore m, Monad m, Mem lore) =>+ (HasScope rep m, Monad m, Mem rep) => VName -> m (PrimType, Shape, VName, IxFun) arrayVarReturns v = do@@ -1014,7 +1013,7 @@ error $ "arrayVarReturns: " ++ pretty v ++ " is not an array." varReturns ::- (HasScope lore m, Monad m, Mem lore) =>+ (HasScope rep m, Monad m, Mem rep) => VName -> m ExpReturns varReturns v = do@@ -1031,7 +1030,7 @@ MemAcc acc ispace ts u -> return $ MemAcc acc ispace ts u -subExpReturns :: (HasScope lore m, Monad m, Mem lore) => SubExp -> m ExpReturns+subExpReturns :: (HasScope rep m, Monad m, Mem rep) => SubExp -> m ExpReturns subExpReturns (Var v) = varReturns v subExpReturns (Constant v) =@@ -1041,10 +1040,10 @@ -- "return type with memory annotations" of the expression. expReturns :: ( Monad m,- LocalScope lore m,- Mem lore+ LocalScope rep m,+ Mem rep ) =>- Exp lore ->+ Exp rep -> m [ExpReturns] expReturns (BasicOp (SubExp se)) = pure <$> subExpReturns se@@ -1137,7 +1136,7 @@ num_accs = length inputs sliceInfo ::- (Monad m, HasScope lore m, Mem lore) =>+ (Monad m, HasScope rep m, Mem rep) => VName -> Slice SubExp -> m (MemInfo SubExp NoUniqueness MemBind)@@ -1153,10 +1152,10 @@ ixfun (map (fmap (isInt64 . primExpFromSubExp int64)) slice) -class TypedOp (Op lore) => OpReturns lore where+class TypedOp (Op rep) => OpReturns rep where opReturns ::- (Monad m, HasScope lore m) =>- Op lore ->+ (Monad m, HasScope rep m) =>+ Op rep -> m [ExpReturns] opReturns op = extReturns <$> opType op
src/Futhark/IR/Mem/Simplify.hs view
@@ -22,7 +22,7 @@ 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.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule import Futhark.Optimise.Simplify.Rules import Futhark.Pass@@ -30,17 +30,17 @@ import Futhark.Util simpleGeneric ::- (SimplifyMemory lore, Op lore ~ MemOp inner) =>+ (SimplifyMemory rep, Op rep ~ MemOp inner) => (OpWithWisdom inner -> UT.UsageTable) ->- Simplify.SimplifyOp lore inner ->- Simplify.SimpleOps lore+ Simplify.SimplifyOp rep inner ->+ Simplify.SimpleOps rep simpleGeneric = simplifiable simplifyProgGeneric ::- (SimplifyMemory lore, Op lore ~ MemOp inner) =>- Simplify.SimpleOps lore ->- Prog lore ->- PassM (Prog lore)+ (SimplifyMemory rep, Op rep ~ MemOp inner) =>+ Simplify.SimpleOps rep ->+ Prog rep ->+ PassM (Prog rep) simplifyProgGeneric ops = Simplify.simplifyProg ops@@ -59,14 +59,14 @@ not $ all primType $ patternTypes pat simplifyStmsGeneric ::- ( HasScope lore m,+ ( HasScope rep m, MonadFreshNames m,- SimplifyMemory lore,- Op lore ~ MemOp inner+ SimplifyMemory rep,+ Op rep ~ MemOp inner ) =>- Simplify.SimpleOps lore ->- Stms lore ->- m (ST.SymbolTable (Wise lore), Stms lore)+ Simplify.SimpleOps rep ->+ Stms rep ->+ m (ST.SymbolTable (Wise rep), Stms rep) simplifyStmsGeneric ops stms = do scope <- askScope Simplify.simplifyStms@@ -76,18 +76,18 @@ scope stms -isResultAlloc :: Op lore ~ MemOp op => Engine.BlockPred lore+isResultAlloc :: Op rep ~ MemOp op => Engine.BlockPred rep isResultAlloc _ usage (Let (AST.Pattern [] [bindee]) _ (Op Alloc {})) = UT.isInResult (patElemName bindee) usage isResultAlloc _ _ _ = False -isAlloc :: Op lore ~ MemOp op => Engine.BlockPred lore+isAlloc :: Op rep ~ MemOp op => Engine.BlockPred rep isAlloc _ _ (Let _ _ (Op Alloc {})) = True isAlloc _ _ _ = False blockers ::- (Op lore ~ MemOp inner) =>- Simplify.HoistBlockers lore+ (Op rep ~ MemOp inner) =>+ Simplify.HoistBlockers rep blockers = Engine.noExtraHoistBlockers { Engine.blockHoistPar = isAlloc,@@ -96,17 +96,17 @@ } -- | Some constraints that must hold for the simplification rules to work.-type SimplifyMemory lore =- ( Simplify.SimplifiableLore lore,- ExpDec lore ~ (),- BodyDec lore ~ (),- AllocOp (Op (Wise lore)),- CanBeWise (Op lore),- BinderOps (Wise lore),- Mem lore+type SimplifyMemory rep =+ ( Simplify.SimplifiableRep rep,+ ExpDec rep ~ (),+ BodyDec rep ~ (),+ AllocOp (Op (Wise rep)),+ CanBeWise (Op rep),+ BinderOps (Wise rep),+ Mem rep ) -callKernelRules :: SimplifyMemory lore => RuleBook (Wise lore)+callKernelRules :: SimplifyMemory rep => RuleBook (Wise rep) callKernelRules = standardRules <> ruleBook@@ -121,7 +121,7 @@ -- 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 lore => TopDownRuleIf (Wise lore)+unExistentialiseMemory :: SimplifyMemory rep => TopDownRuleIf (Wise rep) unExistentialiseMemory vtable pat _ (cond, tbranch, fbranch, ifdec) | ST.simplifyMemory vtable, fixable <- foldl hasConcretisableMemory mempty $ patternElements pat,@@ -192,10 +192,10 @@ -- | If we are copying something that is itself a copy, just copy the -- original one instead. copyCopyToCopy ::- ( BinderOps lore,- LetDec lore ~ (VarWisdom, MemBound u)+ ( BinderOps rep,+ LetDec rep ~ (VarWisdom, MemBound u) ) =>- TopDownRuleBasicOp lore+ TopDownRuleBasicOp rep copyCopyToCopy vtable pat@(Pattern [] [pat_elem]) _ (Copy v1) | Just (BasicOp (Copy v2), v1_cs) <- ST.lookupExp v1 vtable, Just (_, MemArray _ _ _ (ArrayIn srcmem src_ixfun)) <-@@ -218,10 +218,10 @@ -- | If the destination of a copy is the same as the source, just -- remove it. removeIdentityCopy ::- ( BinderOps lore,- LetDec lore ~ (VarWisdom, MemBound u)+ ( BinderOps rep,+ LetDec rep ~ (VarWisdom, MemBound u) ) =>- TopDownRuleBasicOp lore+ TopDownRuleBasicOp rep removeIdentityCopy vtable pat@(Pattern [] [pe]) _ (Copy v) | (_, MemArray _ _ _ (ArrayIn dest_mem dest_ixfun)) <- patElemDec pe, Just (_, MemArray _ _ _ (ArrayIn src_mem src_ixfun)) <-@@ -234,7 +234,7 @@ -- 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 lore => TopDownRuleOp (Wise lore)+decertifySafeAlloc :: SimplifyMemory rep => TopDownRuleOp (Wise rep) decertifySafeAlloc _ pat (StmAux cs attrs _) op | cs /= mempty, [Mem _] <- patternTypes pat,
src/Futhark/IR/Parse.hs view
@@ -5,8 +5,8 @@ -- | Parser for the Futhark core language. module Futhark.IR.Parse ( parseSOACS,- parseKernels,- parseKernelsMem,+ parseGPU,+ parseGPUMem, parseMC, parseMCMem, parseSeq,@@ -23,9 +23,9 @@ import Data.Void import Futhark.Analysis.PrimExp.Parse import Futhark.IR-import Futhark.IR.Kernels (Kernels)-import qualified Futhark.IR.Kernels.Kernel as Kernel-import Futhark.IR.KernelsMem (KernelsMem)+import Futhark.IR.GPU (GPU)+import qualified Futhark.IR.GPU.Kernel as Kernel+import Futhark.IR.GPUMem (GPUMem) import Futhark.IR.MC (MC) import qualified Futhark.IR.MC.Op as MC import Futhark.IR.MCMem (MCMem)@@ -335,46 +335,46 @@ -- bits. Essentially a manually passed-around type class dictionary, -- because ambiguities make it impossible to write this with actual -- type classes.-data PR lore = PR- { pRetType :: Parser (RetType lore),- pBranchType :: Parser (BranchType lore),- pFParamInfo :: Parser (FParamInfo lore),- pLParamInfo :: Parser (LParamInfo lore),- pLetDec :: Parser (LetDec lore),- pOp :: Parser (Op lore),- pBodyDec :: BodyDec lore,- pExpDec :: ExpDec lore+data PR rep = PR+ { pRetType :: Parser (RetType rep),+ pBranchType :: Parser (BranchType rep),+ pFParamInfo :: Parser (FParamInfo rep),+ pLParamInfo :: Parser (LParamInfo rep),+ pLetDec :: Parser (LetDec rep),+ pOp :: Parser (Op rep),+ pBodyDec :: BodyDec rep,+ pExpDec :: ExpDec rep } -pRetTypes :: PR lore -> Parser [RetType lore]+pRetTypes :: PR rep -> Parser [RetType rep] pRetTypes pr = braces $ pRetType pr `sepBy` pComma -pBranchTypes :: PR lore -> Parser [BranchType lore]+pBranchTypes :: PR rep -> Parser [BranchType rep] pBranchTypes pr = braces $ pBranchType pr `sepBy` pComma pParam :: Parser t -> Parser (Param t) pParam p = Param <$> pVName <*> (pColon *> p) -pFParam :: PR lore -> Parser (FParam lore)+pFParam :: PR rep -> Parser (FParam rep) pFParam = pParam . pFParamInfo -pFParams :: PR lore -> Parser [FParam lore]+pFParams :: PR rep -> Parser [FParam rep] pFParams pr = parens $ pFParam pr `sepBy` pComma -pLParam :: PR lore -> Parser (LParam lore)+pLParam :: PR rep -> Parser (LParam rep) pLParam = pParam . pLParamInfo -pLParams :: PR lore -> Parser [LParam lore]+pLParams :: PR rep -> Parser [LParam rep] pLParams pr = braces $ pLParam pr `sepBy` pComma -pPatElem :: PR lore -> Parser (PatElem lore)+pPatElem :: PR rep -> Parser (PatElem rep) pPatElem pr = (PatElem <$> pVName <*> (pColon *> pLetDec pr)) <?> "pattern element" -pPattern :: PR lore -> Parser (Pattern lore)+pPattern :: PR rep -> Parser (Pattern rep) pPattern pr = uncurry Pattern <$> pPatternLike (pPatElem pr) -pIf :: PR lore -> Parser (Exp lore)+pIf :: PR rep -> Parser (Exp rep) pIf pr = keyword "if" $> f <*> pSort <*> pSubExp <*> (keyword "then" *> pBranchBody)@@ -395,22 +395,24 @@ braces (pBody pr) ] -pApply :: PR lore -> Parser (Exp lore)+pApply :: PR rep -> Parser (Exp rep) pApply pr =- keyword "apply"- $> Apply- <*> pName- <*> parens (pArg `sepBy` pComma) <* pColon- <*> pRetTypes pr- <*> pure (Safe, mempty, mempty)+ keyword "apply" *> (p =<< choice [lexeme "<unsafe>" $> Unsafe, pure Safe]) where+ p safety =+ Apply+ <$> pName+ <*> parens (pArg `sepBy` pComma) <* pColon+ <*> pRetTypes pr+ <*> pure (safety, mempty, mempty)+ pArg = choice [ lexeme "*" $> (,Consume) <*> pSubExp, (,Observe) <$> pSubExp ] -pLoop :: PR lore -> Parser (Exp lore)+pLoop :: PR rep -> Parser (Exp rep) pLoop pr = keyword "loop" $> uncurry DoLoop <*> pLoopParams@@ -434,7 +436,7 @@ keyword "while" $> WhileLoop <*> pVName ] -pLambda :: PR lore -> Parser (Lambda lore)+pLambda :: PR rep -> Parser (Lambda rep) pLambda pr = choice [ lexeme "\\"@@ -447,20 +449,20 @@ where lam params ret body = Lambda params body ret -pReduce :: PR lore -> Parser (SOAC.Reduce lore)+pReduce :: PR rep -> Parser (SOAC.Reduce rep) pReduce pr = SOAC.Reduce <$> pComm <*> pLambda pr <* pComma <*> braces (pSubExp `sepBy` pComma) -pScan :: PR lore -> Parser (SOAC.Scan lore)+pScan :: PR rep -> Parser (SOAC.Scan rep) pScan pr = SOAC.Scan <$> pLambda pr <* pComma <*> braces (pSubExp `sepBy` pComma) -pWithAcc :: PR lore -> Parser (Exp lore)+pWithAcc :: PR rep -> Parser (Exp rep) pWithAcc pr = keyword "with_acc" *> parens (WithAcc <$> braces (pInput `sepBy` pComma) <* pComma <*> pLambda pr)@@ -474,7 +476,7 @@ ) pCombFun = parens ((,) <$> pLambda pr <* pComma <*> pSubExps) -pExp :: PR lore -> Parser (Exp lore)+pExp :: PR rep -> Parser (Exp rep) pExp pr = choice [ pIf pr,@@ -485,7 +487,7 @@ BasicOp <$> pBasicOp ] -pStm :: PR lore -> Parser (Stm lore)+pStm :: PR rep -> Parser (Stm rep) pStm pr = keyword "let" $> Let <*> pPattern pr <* pEqual <*> pStmAux <*> pExp pr where@@ -497,10 +499,10 @@ pure mempty ] -pStms :: PR lore -> Parser (Stms lore)+pStms :: PR rep -> Parser (Stms rep) pStms pr = stmsFromList <$> many (pStm pr) -pBody :: PR lore -> Parser (Body lore)+pBody :: PR rep -> Parser (Body rep) pBody pr = choice [ Body (pBodyDec pr) <$> pStms pr <* keyword "in" <*> pResult,@@ -517,14 +519,15 @@ <* pComma <*> pEntryPointTypes where pEntryPointTypes = braces (pEntryPointType `sepBy` pComma)- pEntryPointType =+ pEntryPointType = do+ u <- pUniqueness choice- [ "direct" $> TypeDirect,- "unsigned" $> TypeUnsigned,- "opaque" *> parens (TypeOpaque <$> pStringLiteral <* pComma <*> pInt)+ [ "direct" $> TypeDirect u,+ "unsigned" $> TypeUnsigned u,+ "opaque" *> parens (TypeOpaque u <$> pStringLiteral <* pComma <*> pInt) ] -pFunDef :: PR lore -> Parser (FunDef lore)+pFunDef :: PR rep -> Parser (FunDef rep) pFunDef pr = do attrs <- pAttrs entry <-@@ -538,10 +541,10 @@ FunDef entry attrs fname ret fparams <$> (pEqual *> braces (pBody pr)) -pProg :: PR lore -> Parser (Prog lore)+pProg :: PR rep -> Parser (Prog rep) pProg pr = Prog <$> pStms pr <*> many (pFunDef pr) -pSOAC :: PR lore -> Parser (SOAC.SOAC lore)+pSOAC :: PR rep -> Parser (SOAC.SOAC rep) pSOAC pr = choice [ keyword "map" *> pScrema pMapForm,@@ -742,13 +745,13 @@ pure (dim, blk_tile, reg_tile) pWrite = (,) <$> pSlice <* pEqual <*> pSubExp -pKernelBody :: PR lore -> Parser (SegOp.KernelBody lore)+pKernelBody :: PR rep -> Parser (SegOp.KernelBody rep) pKernelBody pr = SegOp.KernelBody (pBodyDec pr) <$> pStms pr <* keyword "return" <*> braces (pKernelResult `sepBy` pComma) -pSegOp :: PR lore -> Parser lvl -> Parser (SegOp.SegOp lvl lore)+pSegOp :: PR rep -> Parser lvl -> Parser (SegOp.SegOp lvl rep) pSegOp pr pLvl = choice [ keyword "segmap" *> pSegMap,@@ -805,7 +808,7 @@ pure SegOp.SegNoVirt ] -pHostOp :: PR lore -> Parser op -> Parser (Kernel.HostOp lore op)+pHostOp :: PR rep -> Parser op -> Parser (Kernel.HostOp rep op) pHostOp pr pOther = choice [ Kernel.SegOp <$> pSegOp pr pSegLevel,@@ -813,7 +816,7 @@ Kernel.OtherOp <$> pOther ] -pMCOp :: PR lore -> Parser op -> Parser (MC.MCOp lore op)+pMCOp :: PR rep -> Parser op -> Parser (MC.MCOp rep op) pMCOp pr pOther = choice [ MC.ParOp . Just@@ -944,17 +947,17 @@ where op = pMemOp empty -prKernels :: PR Kernels-prKernels =+prGPU :: PR GPU+prGPU = PR pDeclExtType pExtType pDeclType pType pType op () () where- op = pHostOp prKernels (pSOAC prKernels)+ op = pHostOp prGPU (pSOAC prGPU) -prKernelsMem :: PR KernelsMem-prKernelsMem =+prGPUMem :: PR GPUMem+prGPUMem = PR pRetTypeMem pBranchTypeMem pFParamMem pLParamMem pLetDecMem op () () where- op = pMemOp $ pHostOp prKernelsMem empty+ op = pMemOp $ pHostOp prGPUMem empty prMC :: PR MC prMC =@@ -968,28 +971,28 @@ where op = pMemOp $ pMCOp prMCMem empty -parseLore :: PR lore -> FilePath -> T.Text -> Either T.Text (Prog lore)-parseLore pr fname s =+parseRep :: PR rep -> FilePath -> T.Text -> Either T.Text (Prog rep)+parseRep pr fname s = either (Left . T.pack . errorBundlePretty) Right $ parse (whitespace *> pProg pr <* eof) fname s parseSOACS :: FilePath -> T.Text -> Either T.Text (Prog SOACS)-parseSOACS = parseLore prSOACS+parseSOACS = parseRep prSOACS parseSeq :: FilePath -> T.Text -> Either T.Text (Prog Seq)-parseSeq = parseLore prSeq+parseSeq = parseRep prSeq parseSeqMem :: FilePath -> T.Text -> Either T.Text (Prog SeqMem)-parseSeqMem = parseLore prSeqMem+parseSeqMem = parseRep prSeqMem -parseKernels :: FilePath -> T.Text -> Either T.Text (Prog Kernels)-parseKernels = parseLore prKernels+parseGPU :: FilePath -> T.Text -> Either T.Text (Prog GPU)+parseGPU = parseRep prGPU -parseKernelsMem :: FilePath -> T.Text -> Either T.Text (Prog KernelsMem)-parseKernelsMem = parseLore prKernelsMem+parseGPUMem :: FilePath -> T.Text -> Either T.Text (Prog GPUMem)+parseGPUMem = parseRep prGPUMem parseMC :: FilePath -> T.Text -> Either T.Text (Prog MC)-parseMC = parseLore prMC+parseMC = parseRep prMC parseMCMem :: FilePath -> T.Text -> Either T.Text (Prog MCMem)-parseMCMem = parseLore prMCMem+parseMCMem = parseRep prMCMem
src/Futhark/IR/Pretty.hs view
@@ -11,7 +11,7 @@ module Futhark.IR.Pretty ( prettyTuple, pretty,- PrettyLore (..),+ PrettyRep (..), ppTuple', ) where@@ -21,31 +21,31 @@ import Futhark.IR.Syntax import Futhark.Util.Pretty --- | The class of lores whose annotations can be prettyprinted.+-- | The class of representations whose annotations can be prettyprinted. class- ( Decorations lore,- Pretty (RetType lore),- Pretty (BranchType lore),- Pretty (FParamInfo lore),- Pretty (LParamInfo lore),- Pretty (LetDec lore),- Pretty (Op lore)+ ( RepTypes rep,+ Pretty (RetType rep),+ Pretty (BranchType rep),+ Pretty (FParamInfo rep),+ Pretty (LParamInfo rep),+ Pretty (LetDec rep),+ Pretty (Op rep) ) =>- PrettyLore lore+ PrettyRep rep where- ppExpLore :: ExpDec lore -> Exp lore -> Maybe Doc- ppExpLore _ _ = Nothing+ ppExpDec :: ExpDec rep -> Exp rep -> Maybe Doc+ ppExpDec _ _ = Nothing instance Pretty VName where ppr (VName vn i) = ppr vn <> text "_" <> text (show i) -instance Pretty NoUniqueness where- ppr _ = mempty- instance Pretty Commutativity where ppr Commutative = text "commutative" ppr Noncommutative = text "noncommutative" +instance Pretty NoUniqueness where+ ppr _ = mempty+ instance Pretty Shape where ppr = mconcat . map (brackets . ppr) . shapeDims @@ -96,10 +96,10 @@ ppr (Certificates []) = empty ppr (Certificates cs) = text "#" <> braces (commasep (map ppr cs)) -instance PrettyLore lore => Pretty (Stms lore) where+instance PrettyRep rep => Pretty (Stms rep) where ppr = stack . map ppr . stmsToList -instance PrettyLore lore => Pretty (Body lore) where+instance PrettyRep rep => Pretty (Body rep) where ppr (Body _ stms res) | null stms = braces (commasep $ map ppr res) | otherwise =@@ -115,7 +115,7 @@ where f v = text "#[" <> ppr v <> text "]" -stmAttrAnnots :: Stm lore -> [Doc]+stmAttrAnnots :: Stm rep -> [Doc] stmAttrAnnots = attrAnnots . stmAuxAttrs . stmAux certAnnots :: Certificates -> [Doc]@@ -123,7 +123,7 @@ | cs == mempty = [] | otherwise = [ppr cs] -stmCertAnnots :: Stm lore -> [Doc]+stmCertAnnots :: Stm rep -> [Doc] stmCertAnnots = certAnnots . stmAuxCerts . stmAux instance Pretty (PatElemT dec) => Pretty (PatternT dec) where@@ -135,7 +135,7 @@ instance Pretty t => Pretty (Param t) where ppr (Param name t) = ppr name <+> colon <+> align (ppr t) -instance PrettyLore lore => Pretty (Stm lore) where+instance PrettyRep rep => Pretty (Stm rep) where ppr bnd@(Let pat aux e) = align . hang 2 $ text "let" <+> align (ppr pat)@@ -154,7 +154,7 @@ stmannot = concat- [ maybeToList (ppExpLore (stmAuxDec aux) e),+ [ maybeToList (ppExpDec (stmAuxDec aux) e), stmAttrAnnots bnd, stmCertAnnots bnd ]@@ -210,7 +210,7 @@ p (ErrorInt32 x) = ppr x <+> colon <+> text "i32" p (ErrorInt64 x) = ppr x <+> colon <+> text "i64" -instance PrettyLore lore => Pretty (Exp lore) where+instance PrettyRep rep => Pretty (Exp rep) where ppr (If c t f (IfDec ret ifsort)) = text "if" <+> info' <+> ppr c </> text "then"@@ -229,18 +229,17 @@ | otherwise = nestedBlock "{" "}" $ ppr b ppr (BasicOp op) = ppr op ppr (Apply fname args ret (safety, _, _)) =- text "apply"+ applykw <+> text (nameToString fname)- <> safety' <> apply (map (align . pprArg) args) </> colon <+> braces (commasep $ map ppr ret) where pprArg (arg, Consume) = text "*" <> ppr arg pprArg (arg, _) = ppr arg- safety' = case safety of- Unsafe -> text "<unsafe>"- Safe -> mempty+ applykw = case safety of+ Unsafe -> text "apply <unsafe>"+ Safe -> text "apply" ppr (Op op) = ppr op ppr (DoLoop ctx val form loopbody) = text "loop" <+> ppPattern ctxparams valparams@@ -273,7 +272,7 @@ pprLoopVar (p, a) = ppr p <+> text "in" <+> ppr a ppr (WithAcc inputs lam) = text "with_acc"- <> parens (braces (commasep $ map ppInput inputs) <> comma </> ppr lam)+ <> parens (braces (commastack $ map ppInput inputs) <> comma </> ppr lam) where ppInput (shape, arrs, op) = parens@@ -284,7 +283,7 @@ comma </> parens (ppr op' <> comma </> ppTuple' (map ppr nes)) ) -instance PrettyLore lore => Pretty (Lambda lore) where+instance PrettyRep rep => Pretty (Lambda rep) where ppr (Lambda [] (Body _ stms []) []) | stms == mempty = text "nilFn" ppr (Lambda params body rettype) = text "\\" <+> ppTuple' params@@ -292,14 +291,15 @@ </> indent 2 (ppr body) instance Pretty EntryPointType where- ppr TypeDirect = "direct"- ppr TypeUnsigned = "unsigned"- ppr (TypeOpaque desc n) = "opaque" <> apply [ppr (show desc), ppr n]+ ppr (TypeDirect u) = ppr u <> "direct"+ ppr (TypeUnsigned u) = ppr u <> "unsigned"+ ppr (TypeOpaque u desc n) = ppr u <> "opaque" <> apply [ppr (show desc), ppr n] -instance PrettyLore lore => Pretty (FunDef lore) where+instance PrettyRep rep => Pretty (FunDef rep) where ppr (FunDef entry attrs name rettype fparams body) = annot (attrAnnots attrs) $- fun <+> text (nameToString name)+ fun+ </> indent 2 (text (nameToString name)) <+> apply (map ppr fparams) </> indent 2 (colon <+> align (ppTuple' rettype)) <+> equals@@ -315,7 +315,7 @@ </> ppTuple' ret_entry ) -instance PrettyLore lore => Pretty (Prog lore) where+instance PrettyRep rep => Pretty (Prog rep) where ppr (Prog consts funs) = stack $ punctuate line $ ppr consts : map ppr funs
src/Futhark/IR/Prop.hs view
@@ -35,13 +35,15 @@ certify, expExtTypesFromPattern, attrsForAssert,+ lamIsBinOp, ASTConstraints, IsOp (..),- ASTLore (..),+ ASTRep (..), ) where -import Data.List (find)+import Control.Monad+import Data.List (elemIndex, find) import qualified Data.Map.Strict as M import Data.Maybe (isJust, mapMaybe) import qualified Data.Set as S@@ -57,6 +59,7 @@ import Futhark.IR.Syntax import Futhark.Transform.Rename (Rename, Renameable) import Futhark.Transform.Substitute (Substitutable, Substitute)+import Futhark.Util (maybeNth) import Futhark.Util.Pretty -- | @isBuiltInFunction k@ is 'True' if @k@ is an element of 'builtInFunctions'.@@ -70,7 +73,7 @@ namify (k, (paramts, ret, _)) = (nameFromString k, (ret, paramts)) -- | If the expression is a t'BasicOp', return it, otherwise 'Nothing'.-asBasicOp :: Exp lore -> Maybe BasicOp+asBasicOp :: Exp rep -> Maybe BasicOp asBasicOp (BasicOp op) = Just op asBasicOp _ = Nothing @@ -78,7 +81,7 @@ -- any required certificates have been checked) in any context. For -- example, array indexing is not safe, as the index may be out of -- bounds. On the other hand, adding two numbers cannot fail.-safeExp :: IsOp (Op lore) => Exp lore -> Bool+safeExp :: IsOp (Op rep) => Exp rep -> Bool safeExp (BasicOp op) = safeBasicOp op where safeBasicOp (BinOp (SDiv _ Safe) _ _) = True@@ -131,7 +134,7 @@ safeExp WithAcc {} = True -- Although unlikely to matter. safeExp (Op op) = safeOp op -safeBody :: IsOp (Op lore) => Body lore -> Bool+safeBody :: IsOp (Op rep) => Body rep -> Bool safeBody = all (safeExp . stmExp) . bodyStms -- | Return the variable names used in 'Var' subexpressions. May contain@@ -148,7 +151,7 @@ -- Based on pattern matching and checking whether the lambda -- represents a known arithmetic operator; don't expect anything -- clever here.-commutativeLambda :: Lambda lore -> Bool+commutativeLambda :: Lambda rep -> Bool commutativeLambda lam = let body = lambdaBody lam n2 = length (lambdaParams lam) `div` 2@@ -171,20 +174,20 @@ -- the parameters of the original function (they must all come at the -- end). entryPointSize :: EntryPointType -> Int-entryPointSize (TypeOpaque _ x) = x-entryPointSize TypeUnsigned = 1-entryPointSize TypeDirect = 1+entryPointSize (TypeOpaque _ _ x) = x+entryPointSize (TypeUnsigned _) = 1+entryPointSize (TypeDirect _) = 1 -- | A 'StmAux' with empty 'Certificates'. defAux :: dec -> StmAux dec defAux = StmAux mempty mempty -- | The certificates associated with a statement.-stmCerts :: Stm lore -> Certificates+stmCerts :: Stm rep -> Certificates stmCerts = stmAuxCerts . stmAux -- | Add certificates to a statement.-certify :: Certificates -> Stm lore -> Stm lore+certify :: Certificates -> Stm rep -> Stm rep certify cs1 (Let pat (StmAux cs2 attrs dec) e) = Let pat (StmAux (cs2 <> cs1) attrs dec) e @@ -205,31 +208,31 @@ safeOp () = True cheapOp () = True --- | Lore-specific attributes; also means the lore supports some basic--- facilities.+-- | Representation-specific attributes; also means the rep supports+-- some basic facilities. class- ( Decorations lore,- PrettyLore lore,- Renameable lore,- Substitutable lore,- FreeDec (ExpDec lore),- FreeIn (LetDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- IsOp (Op lore)+ ( RepTypes rep,+ PrettyRep rep,+ Renameable rep,+ Substitutable rep,+ FreeDec (ExpDec rep),+ FreeIn (LetDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ IsOp (Op rep) ) =>- ASTLore lore+ ASTRep rep where -- | Given a pattern, construct the type of a body that would match- -- it. An implementation for many lores would be+ -- it. An implementation for many representations would be -- 'expExtTypesFromPattern'. expTypesFromPattern ::- (HasScope lore m, Monad m) =>- Pattern lore ->- m [BranchType lore]+ (HasScope rep m, Monad m) =>+ Pattern rep ->+ m [BranchType rep] -- | Construct the type of an expression that would match the pattern. expExtTypesFromPattern :: Typed dec => PatternT dec -> [ExtType]@@ -244,3 +247,21 @@ Attrs $ S.filter attrForAssert attrs where attrForAssert = (== AttrComp "warn" ["safety_checks"])++-- | Horizontally fission a lambda that models a binary operator.+lamIsBinOp :: ASTRep rep => Lambda rep -> Maybe [(BinOp, PrimType, VName, VName)]+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) $+ stmsToList $ bodyStms $ lambdaBody lam+ i <- Var res `elemIndex` bodyResult (lambdaBody lam)+ xp <- maybeNth i $ lambdaParams lam+ yp <- maybeNth (n + i) $ lambdaParams lam+ guard $ paramName xp == x+ guard $ paramName yp == y+ Prim t <- Just $ patElemType pe+ return (op, t, paramName xp, paramName yp)+ splitStm _ = Nothing
src/Futhark/IR/Prop/Aliases.hs view
@@ -40,19 +40,13 @@ import Futhark.IR.Prop.Types import Futhark.IR.Syntax --- | The class of lores that contain aliasing information.-class- ( Decorations lore,- AliasedOp (Op lore),- AliasesOf (LetDec lore)- ) =>- Aliased lore- where+-- | The class of representations that contain aliasing information.+class (RepTypes rep, AliasedOp (Op rep), AliasesOf (LetDec rep)) => Aliased rep where -- | The aliases of the body results.- bodyAliases :: Body lore -> [Names]+ bodyAliases :: Body rep -> [Names] -- | The variables consumed in the body.- consumedInBody :: Body lore -> Names+ consumedInBody :: Body rep -> Names vnameAliases :: VName -> Names vnameAliases = oneName@@ -95,7 +89,7 @@ returnAliases t [(subExpAliases se, d) | (se, d) <- args] -- | The aliases of an expression, one per non-context value returned.-expAliases :: (Aliased lore) => Exp lore -> [Names]+expAliases :: (Aliased rep) => Exp rep -> [Names] expAliases (If _ tb fb dec) = drop (length all_aliases - length ts) all_aliases where@@ -140,11 +134,11 @@ maskAliases als Observe = als -- | The variables consumed in this statement.-consumedInStm :: Aliased lore => Stm lore -> Names+consumedInStm :: Aliased rep => Stm rep -> Names consumedInStm = consumedInExp . stmExp -- | The variables consumed in this expression.-consumedInExp :: (Aliased lore) => Exp lore -> Names+consumedInExp :: (Aliased rep) => Exp rep -> Names consumedInExp (Apply _ args _ _) = mconcat (map (consumeArg . first subExpAliases) args) where@@ -178,7 +172,7 @@ consumedInExp (Op op) = consumedInOp op -- | The variables consumed by this lambda.-consumedByLambda :: Aliased lore => Lambda lore -> Names+consumedByLambda :: Aliased rep => Lambda rep -> Names consumedByLambda = consumedInBody . lambdaBody -- | The aliases of each pattern element (including the context).@@ -197,7 +191,7 @@ aliasesOf = aliasesOf . patElemDec -- | Also includes the name itself.-lookupAliases :: AliasesOf (LetDec lore) => VName -> Scope lore -> Names+lookupAliases :: AliasesOf (LetDec rep) => VName -> Scope rep -> Names lookupAliases v scope = case M.lookup v scope of Just (LetName dec) ->@@ -220,7 +214,7 @@ -- | The class of operations that can be given aliasing information. -- This is a somewhat subtle concept that is only used in the--- simplifier and when using "lore adapters".+-- simplifier and when using "rep adapters". class AliasedOp (OpWithAliases op) => CanBeAliased op where -- | The op that results when we add aliases to this op. type OpWithAliases op :: Data.Kind.Type
src/Futhark/IR/Prop/Names.hs view
@@ -132,16 +132,16 @@ fvNames = FV freeWalker ::- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- Walker lore (State FV)+ Walker rep (State FV) freeWalker = Walker { walkOnSubExp = modify . (<>) . freeIn',@@ -160,16 +160,16 @@ -- statements and result. Filters away the names that are bound by -- the statements. freeInStmsAndRes ::- ( FreeIn (Op lore),- FreeIn (LetDec lore),- FreeIn (LParamInfo lore),- FreeIn (FParamInfo lore),- FreeDec (BodyDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeDec (ExpDec lore)+ ( FreeIn (Op rep),+ FreeIn (LetDec rep),+ FreeIn (LParamInfo rep),+ FreeIn (FParamInfo rep),+ FreeDec (BodyDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeDec (ExpDec rep) ) =>- Stms lore ->+ Stms rep -> Result -> FV freeInStmsAndRes stms res =@@ -207,63 +207,63 @@ freeIn' = foldMap freeIn' instance- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- FreeIn (FunDef lore)+ FreeIn (FunDef rep) where freeIn' (FunDef _ _ _ rettype params body) = fvBind (namesFromList $ map paramName params) $ freeIn' rettype <> freeIn' params <> freeIn' body instance- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- FreeIn (Lambda lore)+ FreeIn (Lambda rep) where freeIn' (Lambda params body rettype) = fvBind (namesFromList $ map paramName params) $ freeIn' rettype <> freeIn' params <> freeIn' body instance- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- FreeIn (Body lore)+ FreeIn (Body rep) where freeIn' (Body dec stms res) = precomputed dec $ freeIn' dec <> freeInStmsAndRes stms res instance- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- FreeIn (Exp lore)+ FreeIn (Exp rep) where freeIn' (DoLoop ctxmerge valmerge form loopbody) = let (ctxparams, ctxinits) = unzip ctxmerge@@ -282,22 +282,22 @@ freeIn' e = execState (walkExpM freeWalker e) mempty instance- ( FreeDec (ExpDec lore),- FreeDec (BodyDec lore),- FreeIn (FParamInfo lore),- FreeIn (LParamInfo lore),- FreeIn (LetDec lore),- FreeIn (RetType lore),- FreeIn (BranchType lore),- FreeIn (Op lore)+ ( FreeDec (ExpDec rep),+ FreeDec (BodyDec rep),+ FreeIn (FParamInfo rep),+ FreeIn (LParamInfo rep),+ FreeIn (LetDec rep),+ FreeIn (RetType rep),+ FreeIn (BranchType rep),+ FreeIn (Op rep) ) =>- FreeIn (Stm lore)+ FreeIn (Stm rep) where freeIn' (Let pat (StmAux cs attrs dec) e) = freeIn' cs <> freeIn' attrs <> precomputed dec (freeIn' dec <> freeIn' e <> freeIn' pat) -instance FreeIn (Stm lore) => FreeIn (Stms lore) where+instance FreeIn (Stm rep) => FreeIn (Stms rep) where freeIn' = foldMap freeIn' instance FreeIn Names where@@ -346,7 +346,7 @@ instance FreeIn dec => FreeIn (PatElemT dec) where freeIn' (PatElem _ dec) = freeIn' dec -instance FreeIn (LParamInfo lore) => FreeIn (LoopForm lore) where+instance FreeIn (LParamInfo rep) => FreeIn (LoopForm rep) where freeIn' (ForLoop _ _ bound loop_vars) = freeIn' bound <> freeIn' loop_vars freeIn' (WhileLoop cond) = freeIn' cond @@ -398,17 +398,17 @@ precomputed _ fv = fv -- | The names bound by the bindings immediately in a t'Body'.-boundInBody :: Body lore -> Names+boundInBody :: Body rep -> Names boundInBody = boundByStms . bodyStms -- | The names bound by a binding.-boundByStm :: Stm lore -> Names+boundByStm :: Stm rep -> Names boundByStm = namesFromList . patternNames . stmPattern -- | The names bound by the bindings.-boundByStms :: Stms lore -> Names+boundByStms :: Stms rep -> Names boundByStms = foldMap boundByStm -- | The names of the lambda parameters plus the index parameter.-boundByLambda :: Lambda lore -> [VName]+boundByLambda :: Lambda rep -> [VName] boundByLambda lam = map paramName (lambdaParams lam)
src/Futhark/IR/Prop/Patterns.hs view
@@ -12,7 +12,7 @@ -- * Pattern elements patElemIdent, patElemType,- setPatElemLore,+ setPatElemDec, patternElements, patternIdents, patternContextIdents,@@ -52,9 +52,9 @@ patElemType :: Typed dec => PatElemT dec -> Type patElemType = typeOf --- | Set the lore of a t'PatElem'.-setPatElemLore :: PatElemT oldattr -> newattr -> PatElemT newattr-setPatElemLore pe x = fmap (const x) pe+-- | Set the rep of a t'PatElem'.+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]
src/Futhark/IR/Prop/Reshape.hs view
@@ -48,7 +48,7 @@ -- | Construct a 'Reshape' where all dimension changes are -- 'DimCoercion's.-shapeCoerce :: [SubExp] -> VName -> Exp lore+shapeCoerce :: [SubExp] -> VName -> Exp rep shapeCoerce newdims arr = BasicOp $ Reshape (map DimCoercion newdims) arr
src/Futhark/IR/Prop/Scope.hs view
@@ -41,22 +41,22 @@ import qualified Control.Monad.RWS.Strict import Control.Monad.Reader import qualified Data.Map.Strict as M-import Futhark.IR.Decorations import Futhark.IR.Pretty () import Futhark.IR.Prop.Patterns import Futhark.IR.Prop.Types+import Futhark.IR.Rep import Futhark.IR.Syntax -- | How some name in scope was bound.-data NameInfo lore- = LetName (LetDec lore)- | FParamName (FParamInfo lore)- | LParamName (LParamInfo lore)+data NameInfo rep+ = LetName (LetDec rep)+ | FParamName (FParamInfo rep)+ | LParamName (LParamInfo rep) | IndexName IntType -deriving instance Decorations lore => Show (NameInfo lore)+deriving instance RepTypes rep => Show (NameInfo rep) -instance Decorations lore => Typed (NameInfo lore) where+instance RepTypes rep => Typed (NameInfo rep) where typeOf (LetName dec) = typeOf dec typeOf (FParamName dec) = typeOf dec typeOf (LParamName dec) = typeOf dec@@ -64,14 +64,14 @@ -- | A scope is a mapping from variable names to information about -- that name.-type Scope lore = M.Map VName (NameInfo lore)+type Scope rep = M.Map VName (NameInfo rep) -- | The class of applicative functors (or more common in practice: -- monads) that permit the lookup of variable types. A default method -- for 'lookupType' exists, which is sufficient (if not always -- maximally efficient, and using 'error' to fail) when 'askScope' -- is defined.-class (Applicative m, Decorations lore) => HasScope lore m | m -> lore where+class (Applicative m, RepTypes rep) => HasScope rep m | m -> rep where -- | Return the type of the given variable, or fail if it is not in -- the type environment. lookupType :: VName -> m Type@@ -79,7 +79,7 @@ -- | Return the info of the given variable, or fail if it is not in -- the type environment.- lookupInfo :: VName -> m (NameInfo lore)+ lookupInfo :: VName -> m (NameInfo rep) lookupInfo name = asksScope (M.findWithDefault notFound name) where@@ -90,144 +90,144 @@ -- | Return the type environment contained in the applicative -- functor.- askScope :: m (Scope lore)+ askScope :: m (Scope rep) -- | Return the result of applying some function to the type -- environment.- asksScope :: (Scope lore -> a) -> m a+ asksScope :: (Scope rep -> a) -> m a asksScope f = f <$> askScope instance- (Applicative m, Monad m, Decorations lore) =>- HasScope lore (ReaderT (Scope lore) m)+ (Applicative m, Monad m, RepTypes rep) =>+ HasScope rep (ReaderT (Scope rep) m) where askScope = ask -instance (Monad m, HasScope lore m) => HasScope lore (ExceptT e m) where+instance (Monad m, HasScope rep m) => HasScope rep (ExceptT e m) where askScope = lift askScope instance- (Applicative m, Monad m, Monoid w, Decorations lore) =>- HasScope lore (Control.Monad.RWS.Strict.RWST (Scope lore) w s m)+ (Applicative m, Monad m, Monoid w, RepTypes rep) =>+ HasScope rep (Control.Monad.RWS.Strict.RWST (Scope rep) w s m) where askScope = ask instance- (Applicative m, Monad m, Monoid w, Decorations lore) =>- HasScope lore (Control.Monad.RWS.Lazy.RWST (Scope lore) w s m)+ (Applicative m, Monad m, Monoid w, RepTypes rep) =>+ HasScope rep (Control.Monad.RWS.Lazy.RWST (Scope rep) w s m) where askScope = ask -- | The class of monads that not only provide a 'Scope', but also -- the ability to locally extend it. A 'Reader' containing a -- 'Scope' is the prototypical example of such a monad.-class (HasScope lore m, Monad m) => LocalScope lore m where+class (HasScope rep m, Monad m) => LocalScope rep m where -- | Run a computation with an extended type environment. Note that -- this is intended to *add* to the current type environment, it -- does not replace it.- localScope :: Scope lore -> m a -> m a+ localScope :: Scope rep -> m a -> m a -instance (Monad m, LocalScope lore m) => LocalScope lore (ExceptT e m) where+instance (Monad m, LocalScope rep m) => LocalScope rep (ExceptT e m) where localScope = mapExceptT . localScope instance- (Applicative m, Monad m, Decorations lore) =>- LocalScope lore (ReaderT (Scope lore) m)+ (Applicative m, Monad m, RepTypes rep) =>+ LocalScope rep (ReaderT (Scope rep) m) where localScope = local . M.union instance- (Applicative m, Monad m, Monoid w, Decorations lore) =>- LocalScope lore (Control.Monad.RWS.Strict.RWST (Scope lore) w s m)+ (Applicative m, Monad m, Monoid w, RepTypes rep) =>+ LocalScope rep (Control.Monad.RWS.Strict.RWST (Scope rep) w s m) where localScope = local . M.union instance- (Applicative m, Monad m, Monoid w, Decorations lore) =>- LocalScope lore (Control.Monad.RWS.Lazy.RWST (Scope lore) w s m)+ (Applicative m, Monad m, Monoid w, RepTypes rep) =>+ LocalScope rep (Control.Monad.RWS.Lazy.RWST (Scope rep) w s m) where localScope = local . M.union -- | The class of things that can provide a scope. There is no -- overarching rule for what this means. For a 'Stm', it is the -- corresponding pattern. For a t'Lambda', is is the parameters.-class Scoped lore a | a -> lore where- scopeOf :: a -> Scope lore+class Scoped rep a | a -> rep where+ scopeOf :: a -> Scope rep -- | Extend the monadic scope with the 'scopeOf' the given value.-inScopeOf :: (Scoped lore a, LocalScope lore m) => a -> m b -> m b+inScopeOf :: (Scoped rep a, LocalScope rep m) => a -> m b -> m b inScopeOf = localScope . scopeOf -instance Scoped lore a => Scoped lore [a] where+instance Scoped rep a => Scoped rep [a] where scopeOf = mconcat . map scopeOf -instance Scoped lore (Stms lore) where+instance Scoped rep (Stms rep) where scopeOf = foldMap scopeOf -instance Scoped lore (Stm lore) where+instance Scoped rep (Stm rep) where scopeOf = scopeOfPattern . stmPattern -instance Scoped lore (FunDef lore) where+instance Scoped rep (FunDef rep) where scopeOf = scopeOfFParams . funDefParams -instance Scoped lore (VName, NameInfo lore) where+instance Scoped rep (VName, NameInfo rep) where scopeOf = uncurry M.singleton -instance Scoped lore (LoopForm lore) where+instance Scoped rep (LoopForm rep) where scopeOf (WhileLoop _) = mempty scopeOf (ForLoop i it _ xs) = M.insert i (IndexName it) $ scopeOfLParams (map fst xs) -- | The scope of a pattern.-scopeOfPattern :: LetDec lore ~ dec => PatternT dec -> Scope lore+scopeOfPattern :: LetDec rep ~ dec => PatternT dec -> Scope rep scopeOfPattern = mconcat . map scopeOfPatElem . patternElements -- | The scope of a pattern element.-scopeOfPatElem :: LetDec lore ~ dec => PatElemT dec -> Scope lore+scopeOfPatElem :: LetDec rep ~ dec => PatElemT dec -> Scope rep scopeOfPatElem (PatElem name dec) = M.singleton name $ LetName dec -- | The scope of some lambda parameters. scopeOfLParams ::- LParamInfo lore ~ dec =>+ LParamInfo rep ~ dec => [Param dec] ->- Scope lore+ Scope rep scopeOfLParams = M.fromList . map f where f param = (paramName param, LParamName $ paramDec param) -- | The scope of some function or loop parameters. scopeOfFParams ::- FParamInfo lore ~ dec =>+ FParamInfo rep ~ dec => [Param dec] ->- Scope lore+ Scope rep scopeOfFParams = M.fromList . map f where f param = (paramName param, FParamName $ paramDec param) -instance Scoped lore (Lambda lore) where+instance Scoped rep (Lambda rep) where scopeOf lam = scopeOfLParams $ lambdaParams lam --- | A constraint that indicates two lores have the same 'NameInfo'+-- | A constraint that indicates two representations have the same 'NameInfo' -- representation.-type SameScope lore1 lore2 =- ( LetDec lore1 ~ LetDec lore2,- FParamInfo lore1 ~ FParamInfo lore2,- LParamInfo lore1 ~ LParamInfo lore2+type SameScope rep1 rep2 =+ ( LetDec rep1 ~ LetDec rep2,+ FParamInfo rep1 ~ FParamInfo rep2,+ LParamInfo rep1 ~ LParamInfo rep2 ) -- | If two scopes are really the same, then you can convert one to -- the other. castScope ::- SameScope fromlore tolore =>- Scope fromlore ->- Scope tolore+ SameScope fromrep torep =>+ Scope fromrep ->+ Scope torep castScope = M.map castNameInfo castNameInfo ::- SameScope fromlore tolore =>- NameInfo fromlore ->- NameInfo tolore+ SameScope fromrep torep =>+ NameInfo fromrep ->+ NameInfo torep castNameInfo (LetName dec) = LetName dec castNameInfo (FParamName dec) = FParamName dec castNameInfo (LParamName dec) = LParamName dec@@ -236,17 +236,17 @@ -- | A monad transformer that carries around an extended 'Scope'. -- Its 'lookupType' method will first look in the extended 'Scope', -- and then use the 'lookupType' method of the underlying monad.-newtype ExtendedScope lore m a = ExtendedScope (ReaderT (Scope lore) m a)+newtype ExtendedScope rep m a = ExtendedScope (ReaderT (Scope rep) m a) deriving ( Functor, Applicative, Monad,- MonadReader (Scope lore)+ MonadReader (Scope rep) ) instance- (HasScope lore m, Monad m) =>- HasScope lore (ExtendedScope lore m)+ (HasScope rep m, Monad m) =>+ HasScope rep (ExtendedScope rep m) where lookupType name = do res <- asks $ fmap typeOf . M.lookup name@@ -255,7 +255,7 @@ -- | Run a computation in the extended type environment. extendedScope ::- ExtendedScope lore m a ->- Scope lore ->+ ExtendedScope rep m a ->+ Scope rep -> m a extendedScope (ExtendedScope m) = runReaderT m
src/Futhark/IR/Prop/TypeOf.hs view
@@ -51,14 +51,14 @@ -- | @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@.-mapType :: SubExp -> Lambda lore -> [Type]+mapType :: SubExp -> Lambda rep -> [Type] mapType outersize f = [ arrayOf t (Shape [outersize]) NoUniqueness | t <- lambdaReturnType f ] -- | The type of a primitive operation.-primOpType :: HasScope lore m => BasicOp -> m [Type]+primOpType :: HasScope rep m => BasicOp -> m [Type] primOpType (SubExp se) = pure <$> subExpType se primOpType (Opaque se) =@@ -121,8 +121,8 @@ -- | The type of an expression. expExtType ::- (HasScope lore m, TypedOp (Op lore)) =>- Exp lore ->+ (HasScope rep m, TypedOp (Op rep)) =>+ Exp rep -> m [ExtType] expExtType (Apply _ _ rt _) = pure $ map (fromDecl . declExtTypeOf) rt expExtType (If _ _ _ rt) = pure $ map extTypeOf $ ifReturns rt@@ -141,22 +141,22 @@ -- | The number of values returned by an expression. expExtTypeSize ::- (Decorations lore, TypedOp (Op lore)) =>- Exp lore ->+ (RepTypes rep, TypedOp (Op rep)) =>+ Exp rep -> Int expExtTypeSize = length . feelBad . expExtType -- FIXME, this is a horrible quick hack.-newtype FeelBad lore a = FeelBad {feelBad :: a}+newtype FeelBad rep a = FeelBad {feelBad :: a} -instance Functor (FeelBad lore) where+instance Functor (FeelBad rep) where fmap f = FeelBad . f . feelBad -instance Applicative (FeelBad lore) where+instance Applicative (FeelBad rep) where pure = FeelBad f <*> x = FeelBad $ feelBad f $ feelBad x -instance Decorations lore => HasScope lore (FeelBad lore) where+instance RepTypes rep => HasScope rep (FeelBad rep) where lookupType = const $ pure $ Prim $ IntType Int64 askScope = pure mempty
+ src/Futhark/IR/Rep.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | The core Futhark AST is parameterised by a @rep@ type parameter,+-- which is then used to invoke the type families defined here.+module Futhark.IR.Rep+ ( RepTypes (..),+ module Futhark.IR.RetType,+ )+where++import qualified Data.Kind+import Futhark.IR.Prop.Types+import Futhark.IR.RetType+import Futhark.IR.Syntax.Core++-- | A collection of type families giving various common types for a+-- representation, along with constraints specifying that the types+-- they map to should satisfy some minimal requirements.+class+ ( Show (LetDec l),+ Show (ExpDec l),+ Show (BodyDec l),+ Show (FParamInfo l),+ Show (LParamInfo l),+ Show (RetType l),+ Show (BranchType l),+ Show (Op l),+ Eq (LetDec l),+ Eq (ExpDec l),+ Eq (BodyDec l),+ Eq (FParamInfo l),+ Eq (LParamInfo l),+ Eq (RetType l),+ Eq (BranchType l),+ Eq (Op l),+ Ord (LetDec l),+ Ord (ExpDec l),+ Ord (BodyDec l),+ Ord (FParamInfo l),+ Ord (LParamInfo l),+ Ord (RetType l),+ Ord (BranchType l),+ Ord (Op l),+ IsRetType (RetType l),+ IsBodyType (BranchType l),+ Typed (FParamInfo l),+ Typed (LParamInfo l),+ Typed (LetDec l),+ DeclTyped (FParamInfo l)+ ) =>+ RepTypes l+ where+ -- | Decoration for every let-pattern element.+ type LetDec l :: Data.Kind.Type++ type LetDec l = Type++ -- | Decoration for every expression.+ type ExpDec l :: Data.Kind.Type++ type ExpDec l = ()++ -- | Decoration for every body.+ type BodyDec l :: Data.Kind.Type++ type BodyDec l = ()++ -- | Decoration for every (non-lambda) function parameter.+ type FParamInfo l :: Data.Kind.Type++ type FParamInfo l = DeclType++ -- | Decoration for every lambda function parameter.+ type LParamInfo l :: Data.Kind.Type++ type LParamInfo l = Type++ -- | The return type decoration of function calls.+ type RetType l :: Data.Kind.Type++ type RetType l = DeclExtType++ -- | The return type decoration of branches.+ type BranchType l :: Data.Kind.Type++ type BranchType l = ExtType++ -- | Extensible operation.+ type Op l :: Data.Kind.Type++ type Op l = ()
src/Futhark/IR/SOACS.hs view
@@ -3,8 +3,7 @@ -- | A simple representation with SOACs and nested parallelism. module Futhark.IR.SOACS- ( -- * The Lore definition- SOACS,+ ( SOACS, -- * Syntax types Body,@@ -54,13 +53,13 @@ -- like Standard ML. Instead, we have to abuse the namespace/module -- system. --- | The lore for the basic representation.+-- | The rep for the basic representation. data SOACS -instance Decorations SOACS where+instance RepTypes SOACS where type Op SOACS = SOAC SOACS -instance ASTLore SOACS where+instance ASTRep SOACS where expTypesFromPattern = return . expExtTypesFromPattern type Exp = AST.Exp SOACS@@ -94,4 +93,4 @@ instance BinderOps SOACS -instance PrettyLore SOACS+instance PrettyRep SOACS
src/Futhark/IR/SOACS/SOAC.hs view
@@ -66,7 +66,7 @@ import Futhark.IR import Futhark.IR.Aliases (Aliases, removeLambdaAliases) import Futhark.IR.Prop.Aliases-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Transform.Rename import Futhark.Transform.Substitute import qualified Futhark.TypeCheck as TC@@ -76,8 +76,8 @@ import Prelude hiding (id, (.)) -- | A second-order array combinator (SOAC).-data SOAC lore- = Stream SubExp [VName] (StreamForm lore) [SubExp] (Lambda lore)+data SOAC rep+ = Stream SubExp [VName] (StreamForm rep) [SubExp] (Lambda rep) | -- | @Scatter <length> <lambda> <inputs> <outputs>@ -- -- Scatter maps values from a set of input arrays to indices and values of a@@ -115,27 +115,27 @@ -- will correspond to the first two output values, and so on. For this -- example, <lambda> should return a total of 11 values, 8 index values and -- 3 output values.- Scatter SubExp (Lambda lore) [VName] [(Shape, Int, VName)]+ Scatter SubExp (Lambda rep) [VName] [(Shape, Int, VName)] | -- | @Hist <length> <dest-arrays-and-ops> <bucket fun> <input arrays>@ -- -- The first SubExp is the length of the input arrays. The first -- list describes the operations to perform. The t'Lambda' is the -- bucket function. Finally comes the input images.- Hist SubExp [HistOp lore] (Lambda lore) [VName]+ Hist SubExp [HistOp rep] (Lambda rep) [VName] | -- | A combination of scan, reduction, and map. The first -- t'SubExp' is the size of the input arrays.- Screma SubExp [VName] (ScremaForm lore)+ Screma SubExp [VName] (ScremaForm rep) deriving (Eq, Ord, Show) -- | Information about computing a single histogram.-data HistOp lore = HistOp+data HistOp rep = HistOp { histWidth :: SubExp, -- | Race factor @RF@ means that only @1/RF@ -- bins are used. histRaceFactor :: SubExp, histDest :: [VName], histNeutral :: [SubExp],- histOp :: Lambda lore+ histOp :: Lambda rep } deriving (Eq, Ord, Show) @@ -147,21 +147,21 @@ deriving (Eq, Ord, Show) -- | What kind of stream is this?-data StreamForm lore- = Parallel StreamOrd Commutativity (Lambda lore)+data StreamForm rep+ = Parallel StreamOrd Commutativity (Lambda rep) | Sequential deriving (Eq, Ord, Show) -- | The essential parts of a 'Screma' factored out (everything -- except the input arrays).-data ScremaForm lore+data ScremaForm rep = ScremaForm- [Scan lore]- [Reduce lore]- (Lambda lore)+ [Scan rep]+ [Reduce rep]+ (Lambda rep) deriving (Eq, Ord, Show) -singleBinOp :: Bindable lore => [Lambda lore] -> Lambda lore+singleBinOp :: Bindable rep => [Lambda rep] -> Lambda rep singleBinOp lams = Lambda { lambdaParams = concatMap xParams lams ++ concatMap yParams lams,@@ -176,37 +176,37 @@ yParams lam = drop (length (lambdaReturnType lam)) (lambdaParams lam) -- | How to compute a single scan result.-data Scan lore = Scan- { scanLambda :: Lambda lore,+data Scan rep = Scan+ { scanLambda :: Lambda rep, scanNeutral :: [SubExp] } deriving (Eq, Ord, Show) -- | How many reduction results are produced by these 'Scan's?-scanResults :: [Scan lore] -> Int+scanResults :: [Scan rep] -> Int scanResults = sum . map (length . scanNeutral) -- | Combine multiple scan operators to a single operator.-singleScan :: Bindable lore => [Scan lore] -> Scan lore+singleScan :: Bindable rep => [Scan rep] -> Scan rep singleScan scans = let scan_nes = concatMap scanNeutral scans scan_lam = singleBinOp $ map scanLambda scans in Scan scan_lam scan_nes -- | How to compute a single reduction result.-data Reduce lore = Reduce+data Reduce rep = Reduce { redComm :: Commutativity,- redLambda :: Lambda lore,+ redLambda :: Lambda rep, redNeutral :: [SubExp] } deriving (Eq, Ord, Show) -- | How many reduction results are produced by these 'Reduce's?-redResults :: [Reduce lore] -> Int+redResults :: [Reduce rep] -> Int redResults = sum . map (length . redNeutral) -- | Combine multiple reduction operators to a single operator.-singleReduce :: Bindable lore => [Reduce lore] -> Reduce lore+singleReduce :: Bindable rep => [Reduce rep] -> Reduce rep singleReduce reds = let red_nes = concatMap redNeutral reds red_lam = singleBinOp $ map redLambda reds@@ -214,7 +214,7 @@ -- | The types produced by a single 'Screma', given the size of the -- input array.-scremaType :: SubExp -> ScremaForm lore -> [Type]+scremaType :: SubExp -> ScremaForm rep -> [Type] scremaType w (ScremaForm scans reds map_lam) = scan_tps ++ red_tps ++ map (`arrayOfRow` w) map_tps where@@ -227,9 +227,9 @@ -- | Construct a lambda that takes parameters of the given types and -- simply returns them unchanged. mkIdentityLambda ::- (Bindable lore, MonadFreshNames m) =>+ (Bindable rep, MonadFreshNames m) => [Type] ->- m (Lambda lore)+ m (Lambda rep) mkIdentityLambda ts = do params <- mapM (newParam "x") ts return@@ -240,31 +240,31 @@ } -- | Is the given lambda an identity lambda?-isIdentityLambda :: Lambda lore -> Bool+isIdentityLambda :: Lambda rep -> Bool isIdentityLambda lam = bodyResult (lambdaBody lam) == map (Var . paramName) (lambdaParams lam) -- | A lambda with no parameters that returns no values.-nilFn :: Bindable lore => Lambda lore+nilFn :: Bindable rep => Lambda rep nilFn = Lambda mempty (mkBody mempty mempty) mempty -- | Construct a Screma with possibly multiple scans, and -- the given map function.-scanomapSOAC :: [Scan lore] -> Lambda lore -> ScremaForm lore+scanomapSOAC :: [Scan rep] -> Lambda rep -> ScremaForm rep scanomapSOAC scans = ScremaForm scans [] -- | Construct a Screma with possibly multiple reductions, and -- the given map function.-redomapSOAC :: [Reduce lore] -> Lambda lore -> ScremaForm lore+redomapSOAC :: [Reduce rep] -> Lambda rep -> ScremaForm rep redomapSOAC = ScremaForm [] -- | Construct a Screma with possibly multiple scans, and identity map -- function. scanSOAC ::- (Bindable lore, MonadFreshNames m) =>- [Scan lore] ->- m (ScremaForm lore)+ (Bindable rep, MonadFreshNames m) =>+ [Scan rep] ->+ m (ScremaForm rep) scanSOAC scans = scanomapSOAC scans <$> mkIdentityLambda ts where ts = concatMap (lambdaReturnType . scanLambda) scans@@ -272,40 +272,40 @@ -- | Construct a Screma with possibly multiple reductions, and -- identity map function. reduceSOAC ::- (Bindable lore, MonadFreshNames m) =>- [Reduce lore] ->- m (ScremaForm lore)+ (Bindable rep, MonadFreshNames m) =>+ [Reduce rep] ->+ m (ScremaForm rep) reduceSOAC reds = redomapSOAC reds <$> mkIdentityLambda ts where ts = concatMap (lambdaReturnType . redLambda) reds -- | Construct a Screma corresponding to a map.-mapSOAC :: Lambda lore -> ScremaForm lore+mapSOAC :: Lambda rep -> ScremaForm rep mapSOAC = ScremaForm [] [] -- | Does this Screma correspond to a scan-map composition?-isScanomapSOAC :: ScremaForm lore -> Maybe ([Scan lore], Lambda lore)+isScanomapSOAC :: ScremaForm rep -> Maybe ([Scan rep], Lambda rep) isScanomapSOAC (ScremaForm scans reds map_lam) = do guard $ null reds guard $ not $ null scans return (scans, map_lam) -- | Does this Screma correspond to pure scan?-isScanSOAC :: ScremaForm lore -> Maybe [Scan lore]+isScanSOAC :: ScremaForm rep -> Maybe [Scan rep] isScanSOAC form = do (scans, map_lam) <- isScanomapSOAC form guard $ isIdentityLambda map_lam return scans -- | Does this Screma correspond to a reduce-map composition?-isRedomapSOAC :: ScremaForm lore -> Maybe ([Reduce lore], Lambda lore)+isRedomapSOAC :: ScremaForm rep -> Maybe ([Reduce rep], Lambda rep) isRedomapSOAC (ScremaForm scans reds map_lam) = do guard $ null scans guard $ not $ null reds return (reds, map_lam) -- | Does this Screma correspond to a pure reduce?-isReduceSOAC :: ScremaForm lore -> Maybe [Reduce lore]+isReduceSOAC :: ScremaForm rep -> Maybe [Reduce rep] isReduceSOAC form = do (reds, map_lam) <- isRedomapSOAC form guard $ isIdentityLambda map_lam@@ -313,7 +313,7 @@ -- | Does this Screma correspond to a simple map, without any -- reduction or scan results?-isMapSOAC :: ScremaForm lore -> Maybe (Lambda lore)+isMapSOAC :: ScremaForm rep -> Maybe (Lambda rep) isMapSOAC (ScremaForm scans reds map_lam) = do guard $ null scans guard $ null reds@@ -369,14 +369,14 @@ in splitAt num_indices results -- | Like 'Mapper', but just for 'SOAC's.-data SOACMapper flore tlore m = SOACMapper+data SOACMapper frep trep m = SOACMapper { mapOnSOACSubExp :: SubExp -> m SubExp,- mapOnSOACLambda :: Lambda flore -> m (Lambda tlore),+ mapOnSOACLambda :: Lambda frep -> m (Lambda trep), mapOnSOACVName :: VName -> m VName } -- | A mapper that simply returns the SOAC verbatim.-identitySOACMapper :: Monad m => SOACMapper lore lore m+identitySOACMapper :: Monad m => SOACMapper rep rep m identitySOACMapper = SOACMapper { mapOnSOACSubExp = return,@@ -389,9 +389,9 @@ -- and is done left-to-right. mapSOACM :: (Applicative m, Monad m) =>- SOACMapper flore tlore m ->- SOAC flore ->- m (SOAC tlore)+ SOACMapper frep trep m ->+ SOAC frep ->+ m (SOAC trep) mapSOACM tv (Stream size arrs form accs lam) = Stream <$> mapOnSOACSubExp tv size <*> mapM (mapOnSOACVName tv) arrs@@ -448,7 +448,7 @@ <*> mapOnSOACLambda tv map_lam ) -instance ASTLore lore => FreeIn (SOAC lore) where+instance ASTRep rep => FreeIn (SOAC rep) where freeIn' = flip execState mempty . mapSOACM free where walk f x = modify (<> f x) >> return x@@ -459,7 +459,7 @@ mapOnSOACVName = walk freeIn' } -instance ASTLore lore => Substitute (SOAC lore) where+instance ASTRep rep => Substitute (SOAC rep) where substituteNames subst = runIdentity . mapSOACM substitute where@@ -470,13 +470,13 @@ mapOnSOACVName = return . substituteNames subst } -instance ASTLore lore => Rename (SOAC lore) where+instance ASTRep rep => Rename (SOAC rep) where rename = mapSOACM renamer where renamer = SOACMapper rename rename rename -- | The type of a SOAC.-soacType :: SOAC lore -> [Type]+soacType :: SOAC rep -> [Type] soacType (Stream outersize _ _ accs lam) = map (substNamesInType substs) rtp where@@ -495,10 +495,10 @@ soacType (Screma w _arrs form) = scremaType w form -instance TypedOp (SOAC lore) where+instance TypedOp (SOAC rep) where opType = pure . staticShapes . soacType -instance (ASTLore lore, Aliased lore) => AliasedOp (SOAC lore) where+instance (ASTRep rep, Aliased rep) => AliasedOp (SOAC rep) where opAliases = map (const mempty) . soacType -- Only map functions can consume anything. The operands to scan@@ -527,20 +527,20 @@ namesFromList $ concatMap histDest ops mapHistOp ::- (Lambda flore -> Lambda tlore) ->- HistOp flore ->- HistOp tlore+ (Lambda frep -> Lambda trep) ->+ HistOp frep ->+ HistOp trep mapHistOp f (HistOp w rf dests nes lam) = HistOp w rf dests nes $ f lam instance- ( ASTLore lore,- ASTLore (Aliases lore),- CanBeAliased (Op lore)+ ( ASTRep rep,+ ASTRep (Aliases rep),+ CanBeAliased (Op rep) ) =>- CanBeAliased (SOAC lore)+ CanBeAliased (SOAC rep) where- type OpWithAliases (SOAC lore) = SOAC (Aliases lore)+ type OpWithAliases (SOAC rep) = SOAC (Aliases rep) addOpAliases aliases (Stream size arr form accs lam) = Stream size arr (analyseStreamForm form) accs $@@ -571,7 +571,7 @@ where remove = SOACMapper return (return . removeLambdaAliases) return -instance ASTLore lore => IsOp (SOAC lore) where+instance ASTRep rep => IsOp (SOAC rep) where safeOp _ = False cheapOp _ = True @@ -588,14 +588,14 @@ substNamesInSubExp subs (Var idd) = M.findWithDefault (Var idd) idd subs -instance (ASTLore lore, CanBeWise (Op lore)) => CanBeWise (SOAC lore) where- type OpWithWisdom (SOAC lore) = SOAC (Wise lore)+instance (ASTRep rep, CanBeWise (Op rep)) => CanBeWise (SOAC rep) where+ type OpWithWisdom (SOAC rep) = SOAC (Wise rep) removeOpWisdom = runIdentity . mapSOACM remove where remove = SOACMapper return (return . removeLambdaWisdom) return -instance Decorations lore => ST.IndexOp (SOAC lore) where+instance RepTypes rep => ST.IndexOp (SOAC rep) where indexOp vtable k soac [i] = do (lam, se, arr_params, arrs) <- lambdaAndSubExp soac let arr_indexes = M.fromList $ catMaybes $ zipWith arrIndex arr_params arrs@@ -634,7 +634,7 @@ indexOp _ _ _ _ = Nothing -- | Type-check a SOAC.-typeCheckSOAC :: TC.Checkable lore => SOAC (Aliases lore) -> TC.TypeM lore ()+typeCheckSOAC :: TC.Checkable rep => SOAC (Aliases rep) -> TC.TypeM rep () typeCheckSOAC (Stream size arrexps form accexps lam) = do TC.require [Prim int64] size accargs <- mapM TC.checkArg accexps@@ -804,7 +804,7 @@ "Map function return type " ++ prettyTuple map_lam_ts ++ " wrong for given scan and reduction functions." -instance OpMetrics (Op lore) => OpMetrics (SOAC lore) where+instance OpMetrics (Op rep) => OpMetrics (SOAC rep) where opMetrics (Stream _ _ _ _ lam) = inside "Stream" $ lambdaMetrics lam opMetrics (Scatter _len lam _ivs _as) =@@ -817,7 +817,7 @@ mapM_ (lambdaMetrics . redLambda) reds lambdaMetrics map_lam -instance PrettyLore lore => PP.Pretty (SOAC lore) where+instance PrettyRep rep => PP.Pretty (SOAC rep) where ppr (Stream size arrs form acc lam) = case form of Parallel o comm lam0 ->@@ -879,7 +879,7 @@ -- | Prettyprint the given Screma. ppScrema ::- (PrettyLore lore, Pretty inp) => SubExp -> [inp] -> ScremaForm lore -> Doc+ (PrettyRep rep, Pretty inp) => SubExp -> [inp] -> ScremaForm rep -> Doc ppScrema w arrs (ScremaForm scans reds map_lam) = text "screma" <> parens@@ -890,7 +890,7 @@ </> ppr map_lam ) -instance PrettyLore lore => Pretty (Scan lore) where+instance PrettyRep rep => Pretty (Scan rep) where ppr (Scan scan_lam scan_nes) = ppr scan_lam <> comma </> PP.braces (commasep $ map ppr scan_nes) @@ -898,17 +898,17 @@ ppComm Noncommutative = mempty ppComm Commutative = text "commutative " -instance PrettyLore lore => Pretty (Reduce lore) where+instance PrettyRep rep => Pretty (Reduce rep) where ppr (Reduce comm red_lam red_nes) = ppComm comm <> ppr red_lam <> comma </> PP.braces (commasep $ map ppr red_nes) -- | Prettyprint the given histogram operation. ppHist ::- (PrettyLore lore, Pretty inp) =>+ (PrettyRep rep, Pretty inp) => SubExp ->- [HistOp lore] ->- Lambda lore ->+ [HistOp rep] ->+ Lambda rep -> [inp] -> Doc ppHist len ops bucket_fun imgs =
src/Futhark/IR/SOACS/Simplify.hs view
@@ -41,7 +41,7 @@ import Futhark.MonadFreshNames import qualified Futhark.Optimise.Simplify as Simplify import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule import Futhark.Optimise.Simplify.Rules import Futhark.Optimise.Simplify.Rules.ClosedForm@@ -93,8 +93,8 @@ Simplify.simplifyStms simpleSOACS soacRules Engine.noExtraHoistBlockers mempty simplifySOAC ::- Simplify.SimplifiableLore lore =>- Simplify.SimplifyOp lore (SOAC lore)+ Simplify.SimplifiableRep rep =>+ Simplify.SimplifyOp rep (SOAC rep) simplifySOAC (Stream outerdim arr form nes lam) = do outerdim' <- Engine.simplify outerdim (form', form_hoisted) <- simplifyStreamForm form@@ -155,10 +155,10 @@ instance BinderOps (Wise SOACS) fixLambdaParams ::- (MonadBinder m, Bindable (Lore m), BinderOps (Lore m)) =>- AST.Lambda (Lore m) ->+ (MonadBinder m, Bindable (Rep m), BinderOps (Rep m)) =>+ AST.Lambda (Rep m) -> [Maybe SubExp] ->- m (AST.Lambda (Lore m))+ m (AST.Lambda (Rep m)) fixLambdaParams lam fixes = do body <- runBodyBinder $ localScope (scopeOfLParams $ lambdaParams lam) $ do@@ -177,7 +177,7 @@ maybeFix p (Just x) = letBindNames [paramName p] $ BasicOp $ SubExp x maybeFix _ Nothing = return () -removeLambdaResults :: [Bool] -> AST.Lambda lore -> AST.Lambda lore+removeLambdaResults :: [Bool] -> AST.Lambda rep -> AST.Lambda rep removeLambdaResults keep lam = lam { lambdaBody = lam_body',@@ -193,11 +193,11 @@ soacRules :: RuleBook (Wise SOACS) soacRules = standardRules <> ruleBook topDownRules bottomUpRules --- | Does this lore contain 'SOAC's in its t'Op's? A lore must be an+-- | Does this rep contain 'SOAC's in its t'Op's? A rep must be an -- instance of this class for the simplification rules to work.-class HasSOAC lore where- asSOAC :: Op lore -> Maybe (SOAC lore)- soacOp :: SOAC lore -> Op lore+class HasSOAC rep where+ asSOAC :: Op rep -> Maybe (SOAC rep)+ soacOp :: SOAC rep -> Op rep instance HasSOAC (Wise SOACS) where asSOAC = Just@@ -256,11 +256,11 @@ Skip liftIdentityMapping ::- forall lore.- (Bindable lore, Simplify.SimplifiableLore lore, HasSOAC (Wise lore)) =>- TopDownRuleOp (Wise lore)+ forall rep.+ (Bindable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) =>+ TopDownRuleOp (Wise rep) liftIdentityMapping _ pat aux op- | Just (Screma w arrs form :: SOAC (Wise lore)) <- asSOAC op,+ | Just (Screma w arrs form :: SOAC (Wise rep)) <- asSOAC op, Just fun <- isMapSOAC form = do let inputMap = M.fromList $ zip (map paramName $ lambdaParams fun) arrs free = freeIn $ lambdaBody fun@@ -339,8 +339,8 @@ -- | Remove all arguments to the map that are simply replicates. -- These can be turned into free variables instead. removeReplicateMapping ::- (Bindable lore, Simplify.SimplifiableLore lore, HasSOAC (Wise lore)) =>- TopDownRuleOp (Wise lore)+ (Bindable rep, Simplify.SimplifiableRep rep, HasSOAC (Wise rep)) =>+ TopDownRuleOp (Wise rep) removeReplicateMapping vtable pat aux op | Just (Screma w arrs form) <- asSOAC op, Just fun <- isMapSOAC form,@@ -358,13 +358,13 @@ removeReplicateWrite _ _ _ _ = Skip removeReplicateInput ::- Aliased lore =>- ST.SymbolTable lore ->- AST.Lambda lore ->+ Aliased rep =>+ ST.SymbolTable rep ->+ AST.Lambda rep -> [VName] -> Maybe- ( [([VName], Certificates, AST.Exp lore)],- AST.Lambda lore,+ ( [([VName], Certificates, AST.Exp rep)],+ AST.Lambda rep, [VName] ) removeReplicateInput vtable fun arrs@@ -659,8 +659,8 @@ -- For now we just remove singleton SOACs. simplifyKnownIterationSOAC ::- (Bindable lore, Simplify.SimplifiableLore lore, HasSOAC (Wise lore)) =>- TopDownRuleOp (Wise lore)+ (Bindable 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, oneIsh k = Simplify $ do
src/Futhark/IR/SegOp.hs view
@@ -14,6 +14,7 @@ ( SegOp (..), SegVirt (..), segLevel,+ segBody, segSpace, typeCheckSegOp, SegSpace (..),@@ -79,7 +80,7 @@ import Futhark.IR.Mem import Futhark.IR.Prop.Aliases import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule import Futhark.Tools import Futhark.Transform.Rename@@ -121,7 +122,7 @@ SplitStrided <$> rename stride -- | An operator for 'SegHist'.-data HistOp lore = HistOp+data HistOp rep = HistOp { histWidth :: SubExp, histRaceFactor :: SubExp, histDest :: [VName],@@ -132,14 +133,14 @@ -- "dimensions". This is used to generate more efficient -- code. histShape :: Shape,- histOp :: Lambda lore+ histOp :: Lambda rep } deriving (Eq, Ord, Show) -- | The type of a histogram produced by a 'HistOp'. This can be -- different from the type of the 'histDest's in case we are -- dealing with a segmented histogram.-histType :: HistOp lore -> [Type]+histType :: HistOp rep -> [Type] histType op = map ( (`arrayOfRow` histWidth op)@@ -148,9 +149,9 @@ $ lambdaReturnType $ histOp op -- | An operator for 'SegScan' and 'SegRed'.-data SegBinOp lore = SegBinOp+data SegBinOp rep = SegBinOp { segBinOpComm :: Commutativity,- segBinOpLambda :: Lambda lore,+ segBinOpLambda :: Lambda rep, segBinOpNeutral :: [SubExp], -- | In case this operator is semantically a vectorised -- operator (corresponding to a perfect map nest in the@@ -162,26 +163,26 @@ deriving (Eq, Ord, Show) -- | How many reduction results are produced by these 'SegBinOp's?-segBinOpResults :: [SegBinOp lore] -> Int+segBinOpResults :: [SegBinOp rep] -> Int segBinOpResults = sum . map (length . segBinOpNeutral) -- | Split some list into chunks equal to the number of values -- returned by each 'SegBinOp'-segBinOpChunks :: [SegBinOp lore] -> [a] -> [[a]]+segBinOpChunks :: [SegBinOp rep] -> [a] -> [[a]] segBinOpChunks = chunks . map (length . segBinOpNeutral) -- | The body of a 'SegOp'.-data KernelBody lore = KernelBody- { kernelBodyLore :: BodyDec lore,- kernelBodyStms :: Stms lore,+data KernelBody rep = KernelBody+ { kernelBodyDec :: BodyDec rep,+ kernelBodyStms :: Stms rep, kernelBodyResult :: [KernelResult] } -deriving instance Decorations lore => Ord (KernelBody lore)+deriving instance RepTypes rep => Ord (KernelBody rep) -deriving instance Decorations lore => Show (KernelBody lore)+deriving instance RepTypes rep => Show (KernelBody rep) -deriving instance Decorations lore => Eq (KernelBody lore)+deriving instance RepTypes rep => Eq (KernelBody rep) -- | Metadata about whether there is a subtle point to this -- 'KernelResult'. This is used to protect things like tiling, which@@ -249,13 +250,13 @@ freeIn' (RegTileReturns dims_n_tiles v) = freeIn' dims_n_tiles <> freeIn' v -instance ASTLore lore => FreeIn (KernelBody lore) where+instance ASTRep rep => FreeIn (KernelBody rep) where freeIn' (KernelBody dec stms res) = fvBind bound_in_stms $ freeIn' dec <> freeIn' stms <> freeIn' res where bound_in_stms = foldMap boundByStm stms -instance ASTLore lore => Substitute (KernelBody lore) where+instance ASTRep rep => Substitute (KernelBody rep) where substituteNames subst (KernelBody dec stms res) = KernelBody (substituteNames subst dec)@@ -283,7 +284,7 @@ (substituteNames subst dims_n_tiles) (substituteNames subst v) -instance ASTLore lore => Rename (KernelBody lore) where+instance ASTRep rep => Rename (KernelBody rep) where rename (KernelBody dec stms res) = do dec' <- rename dec renamingStms stms $ \stms' ->@@ -294,35 +295,35 @@ -- | Perform alias analysis on a 'KernelBody'. aliasAnalyseKernelBody ::- ( ASTLore lore,- CanBeAliased (Op lore)+ ( ASTRep rep,+ CanBeAliased (Op rep) ) => AliasTable ->- KernelBody lore ->- KernelBody (Aliases lore)+ KernelBody rep ->+ KernelBody (Aliases rep) aliasAnalyseKernelBody aliases (KernelBody dec stms res) = let Body dec' stms' _ = Alias.analyseBody aliases $ Body dec stms [] in KernelBody dec' stms' res removeKernelBodyAliases ::- CanBeAliased (Op lore) =>- KernelBody (Aliases lore) ->- KernelBody lore+ CanBeAliased (Op rep) =>+ KernelBody (Aliases rep) ->+ KernelBody rep removeKernelBodyAliases (KernelBody (_, dec) stms res) = KernelBody dec (fmap removeStmAliases stms) res removeKernelBodyWisdom ::- CanBeWise (Op lore) =>- KernelBody (Wise lore) ->- KernelBody lore+ CanBeWise (Op rep) =>+ KernelBody (Wise rep) ->+ KernelBody rep removeKernelBodyWisdom (KernelBody dec stms res) = let Body dec' stms' _ = removeBodyWisdom $ Body dec stms [] in KernelBody dec' stms' res -- | The variables consumed in the kernel body. consumedInKernelBody ::- Aliased lore =>- KernelBody lore ->+ Aliased rep =>+ KernelBody rep -> Names consumedInKernelBody (KernelBody dec stms res) = consumedInBody (Body dec stms []) <> mconcat (map consumedByReturn res)@@ -331,12 +332,12 @@ consumedByReturn _ = mempty checkKernelBody ::- TC.Checkable lore =>+ TC.Checkable rep => [Type] ->- KernelBody (Aliases lore) ->- TC.TypeM lore ()+ KernelBody (Aliases rep) ->+ TC.TypeM rep () checkKernelBody ts (KernelBody (_, dec) stms kres) = do- TC.checkBodyLore dec+ TC.checkBodyDec dec -- We consume the kernel results (when applicable) before -- type-checking the stms, so we will get an error if a statement -- uses an array that is written to in a result.@@ -408,10 +409,10 @@ (dims, blk_tiles, reg_tiles) = unzip3 dims_n_tiles expected = t `arrayOfShape` Shape (blk_tiles ++ reg_tiles) -kernelBodyMetrics :: OpMetrics (Op lore) => KernelBody lore -> MetricsM ()+kernelBodyMetrics :: OpMetrics (Op rep) => KernelBody rep -> MetricsM () kernelBodyMetrics = mapM_ stmMetrics . kernelBodyStms -instance PrettyLore lore => Pretty (KernelBody lore) where+instance PrettyRep rep => Pretty (KernelBody rep) where ppr (KernelBody _ stms res) = PP.stack (map ppr (stmsToList stms)) </> text "return" <+> PP.braces (PP.commasep $ map ppr res)@@ -477,11 +478,11 @@ -- | A 'Scope' containing all the identifiers brought into scope by -- this 'SegSpace'.-scopeOfSegSpace :: SegSpace -> Scope lore+scopeOfSegSpace :: SegSpace -> Scope rep scopeOfSegSpace (SegSpace phys space) = M.fromList $ zip (phys : map fst space) $ repeat $ IndexName Int64 -checkSegSpace :: TC.Checkable lore => SegSpace -> TC.TypeM lore ()+checkSegSpace :: TC.Checkable rep => SegSpace -> TC.TypeM rep () checkSegSpace (SegSpace _ dims) = mapM_ (TC.require [Prim int64] . snd) dims @@ -495,29 +496,38 @@ -- of information. For example, in GPU backends, it is used to -- indicate whether the 'SegOp' is expected to run at the thread-level -- or the group-level.-data SegOp lvl lore- = SegMap lvl SegSpace [Type] (KernelBody lore)+data SegOp lvl rep+ = SegMap lvl SegSpace [Type] (KernelBody rep) | -- | The KernelSpace must always have at least two dimensions, -- implying that the result of a SegRed is always an array.- SegRed lvl SegSpace [SegBinOp lore] [Type] (KernelBody lore)- | SegScan lvl SegSpace [SegBinOp lore] [Type] (KernelBody lore)- | SegHist lvl SegSpace [HistOp lore] [Type] (KernelBody lore)+ SegRed lvl SegSpace [SegBinOp rep] [Type] (KernelBody rep)+ | SegScan lvl SegSpace [SegBinOp rep] [Type] (KernelBody rep)+ | SegHist lvl SegSpace [HistOp rep] [Type] (KernelBody rep) deriving (Eq, Ord, Show) -- | The level of a 'SegOp'.-segLevel :: SegOp lvl lore -> lvl+segLevel :: SegOp lvl rep -> lvl segLevel (SegMap lvl _ _ _) = lvl segLevel (SegRed lvl _ _ _ _) = lvl segLevel (SegScan lvl _ _ _ _) = lvl segLevel (SegHist lvl _ _ _ _) = lvl -- | The space of a 'SegOp'.-segSpace :: SegOp lvl lore -> SegSpace+segSpace :: SegOp lvl rep -> SegSpace segSpace (SegMap _ lvl _ _) = lvl segSpace (SegRed _ lvl _ _ _) = lvl segSpace (SegScan _ lvl _ _ _) = lvl segSpace (SegHist _ lvl _ _ _) = lvl +-- | The body of a 'SegOp'.+segBody :: SegOp lvl rep -> KernelBody rep+segBody segop =+ case segop of+ SegMap _ _ _ body -> body+ SegRed _ _ _ _ body -> body+ SegScan _ _ _ _ body -> body+ SegHist _ _ _ _ body -> body+ segResultShape :: SegSpace -> Type -> KernelResult -> Type segResultShape _ t (WriteReturns shape _ _) = t `arrayOfShape` shape@@ -531,7 +541,7 @@ t `arrayOfShape` Shape (map (\(dim, _, _) -> dim) dims_n_tiles) -- | The return type of a 'SegOp'.-segOpType :: SegOp lvl lore -> [Type]+segOpType :: SegOp lvl rep -> [Type] segOpType (SegMap _ space ts kbody) = zipWith (segResultShape space) ts $ kernelBodyResult kbody segOpType (SegRed _ space reds ts kbody) =@@ -567,12 +577,12 @@ dims = segSpaceDims space segment_dims = init dims -instance TypedOp (SegOp lvl lore) where+instance TypedOp (SegOp lvl rep) where opType = pure . staticShapes . segOpType instance- (ASTLore lore, Aliased lore, ASTConstraints lvl) =>- AliasedOp (SegOp lvl lore)+ (ASTRep rep, Aliased rep, ASTConstraints lvl) =>+ AliasedOp (SegOp lvl rep) where opAliases = map (const mempty) . segOpType @@ -587,10 +597,10 @@ -- | Type check a 'SegOp', given a checker for its level. typeCheckSegOp ::- TC.Checkable lore =>- (lvl -> TC.TypeM lore ()) ->- SegOp lvl (Aliases lore) ->- TC.TypeM lore ()+ TC.Checkable rep =>+ (lvl -> TC.TypeM rep ()) ->+ SegOp lvl (Aliases rep) ->+ TC.TypeM rep () typeCheckSegOp checkLvl (SegMap lvl space ts kbody) = do checkLvl lvl checkScanRed space [] ts kbody@@ -660,12 +670,12 @@ segment_dims = init $ segSpaceDims space checkScanRed ::- TC.Checkable lore =>+ TC.Checkable rep => SegSpace ->- [(Lambda (Aliases lore), [SubExp], Shape)] ->+ [(Lambda (Aliases rep), [SubExp], Shape)] -> [Type] ->- KernelBody (Aliases lore) ->- TC.TypeM lore ()+ KernelBody (Aliases rep) ->+ TC.TypeM rep () checkScanRed space ops ts kbody = do checkSegSpace space mapM_ TC.checkType ts@@ -698,16 +708,16 @@ checkKernelBody ts kbody -- | Like 'Mapper', but just for 'SegOp's.-data SegOpMapper lvl flore tlore m = SegOpMapper+data SegOpMapper lvl frep trep m = SegOpMapper { mapOnSegOpSubExp :: SubExp -> m SubExp,- mapOnSegOpLambda :: Lambda flore -> m (Lambda tlore),- mapOnSegOpBody :: KernelBody flore -> m (KernelBody tlore),+ mapOnSegOpLambda :: Lambda frep -> m (Lambda trep),+ mapOnSegOpBody :: KernelBody frep -> m (KernelBody trep), mapOnSegOpVName :: VName -> m VName, mapOnSegOpLevel :: lvl -> m lvl } -- | A mapper that simply returns the 'SegOp' verbatim.-identitySegOpMapper :: Monad m => SegOpMapper lvl lore lore m+identitySegOpMapper :: Monad m => SegOpMapper lvl rep rep m identitySegOpMapper = SegOpMapper { mapOnSegOpSubExp = return,@@ -719,7 +729,7 @@ mapOnSegSpace :: Monad f =>- SegOpMapper lvl flore tlore f ->+ SegOpMapper lvl frep trep f -> SegSpace -> f SegSpace mapOnSegSpace tv (SegSpace phys dims) =@@ -727,9 +737,9 @@ mapSegBinOp :: Monad m =>- SegOpMapper lvl flore tlore m ->- SegBinOp flore ->- m (SegBinOp tlore)+ SegOpMapper lvl frep trep m ->+ SegBinOp frep ->+ m (SegBinOp trep) mapSegBinOp tv (SegBinOp comm red_op nes shape) = SegBinOp comm <$> mapOnSegOpLambda tv red_op@@ -739,9 +749,9 @@ -- | Apply a 'SegOpMapper' to the given 'SegOp'. mapSegOpM :: (Applicative m, Monad m) =>- SegOpMapper lvl flore tlore m ->- SegOp lvl flore ->- m (SegOp lvl tlore)+ SegOpMapper lvl frep trep m ->+ SegOp lvl frep ->+ m (SegOp lvl trep) mapSegOpM tv (SegMap lvl space ts body) = SegMap <$> mapOnSegOpLevel tv lvl@@ -780,7 +790,7 @@ mapOnSegOpType :: Monad m =>- SegOpMapper lvl flore tlore m ->+ SegOpMapper lvl frep trep m -> Type -> m Type mapOnSegOpType _tv t@Prim {} = pure t@@ -795,8 +805,8 @@ mapOnSegOpType _tv (Mem s) = pure $ Mem s instance- (ASTLore lore, Substitute lvl) =>- Substitute (SegOp lvl lore)+ (ASTRep rep, Substitute lvl) =>+ Substitute (SegOp lvl rep) where substituteNames subst = runIdentity . mapSegOpM substitute where@@ -810,16 +820,16 @@ } instance- (ASTLore lore, ASTConstraints lvl) =>- Rename (SegOp lvl lore)+ (ASTRep rep, ASTConstraints lvl) =>+ Rename (SegOp lvl rep) where rename = mapSegOpM renamer where renamer = SegOpMapper rename rename rename rename rename instance- (ASTLore lore, FreeIn (LParamInfo lore), FreeIn lvl) =>- FreeIn (SegOp lvl lore)+ (ASTRep rep, FreeIn (LParamInfo rep), FreeIn lvl) =>+ FreeIn (SegOp lvl rep) where freeIn' e = flip execState mempty $ mapSegOpM free e where@@ -833,7 +843,7 @@ mapOnSegOpLevel = walk freeIn' } -instance OpMetrics (Op lore) => OpMetrics (SegOp lvl lore) where+instance OpMetrics (Op rep) => OpMetrics (SegOp lvl rep) where opMetrics (SegMap _ _ _ body) = inside "SegMap" $ kernelBodyMetrics body opMetrics (SegRed _ _ reds _ body) =@@ -858,7 +868,7 @@ ) <+> parens (text "~" <> ppr phys) -instance PrettyLore lore => Pretty (SegBinOp lore) where+instance PrettyRep rep => Pretty (SegBinOp rep) where ppr (SegBinOp comm lam nes shape) = PP.braces (PP.commasep $ map ppr nes) <> PP.comma </> ppr shape <> PP.comma@@ -868,7 +878,7 @@ Commutative -> text "commutative " Noncommutative -> mempty -instance (PrettyLore lore, PP.Pretty lvl) => PP.Pretty (SegOp lvl lore) where+instance (PrettyRep rep, PP.Pretty lvl) => PP.Pretty (SegOp lvl rep) where ppr (SegMap lvl space ts body) = text "segmap" <> ppr lvl </> PP.align (ppr space)@@ -905,14 +915,14 @@ </> ppr op instance- ( ASTLore lore,- ASTLore (Aliases lore),- CanBeAliased (Op lore),+ ( ASTRep rep,+ ASTRep (Aliases rep),+ CanBeAliased (Op rep), ASTConstraints lvl ) =>- CanBeAliased (SegOp lvl lore)+ CanBeAliased (SegOp lvl rep) where- type OpWithAliases (SegOp lvl lore) = SegOp lvl (Aliases lore)+ type OpWithAliases (SegOp lvl rep) = SegOp lvl (Aliases rep) addOpAliases aliases = runIdentity . mapSegOpM alias where@@ -935,10 +945,10 @@ return instance- (CanBeWise (Op lore), ASTLore lore, ASTConstraints lvl) =>- CanBeWise (SegOp lvl lore)+ (CanBeWise (Op rep), ASTRep rep, ASTConstraints lvl) =>+ CanBeWise (SegOp lvl rep) where- type OpWithWisdom (SegOp lvl lore) = SegOp lvl (Wise lore)+ type OpWithWisdom (SegOp lvl rep) = SegOp lvl (Wise rep) removeOpWisdom = runIdentity . mapSegOpM remove where@@ -950,7 +960,7 @@ return return -instance ASTLore lore => ST.IndexOp (SegOp lvl lore) where+instance ASTRep rep => ST.IndexOp (SegOp lvl rep) where indexOp vtable k (SegMap _ space _ kbody) is = do Returns ResultMaySimplify se <- maybeNth k $ kernelBodyResult kbody guard $ length gtids <= length is@@ -995,8 +1005,8 @@ indexOp _ _ _ _ = Nothing instance- (ASTLore lore, ASTConstraints lvl) =>- IsOp (SegOp lvl lore)+ (ASTRep rep, ASTConstraints lvl) =>+ IsOp (SegOp lvl rep) where cheapOp _ = False safeOp _ = True@@ -1032,11 +1042,11 @@ <*> Engine.simplify what mkWiseKernelBody ::- (ASTLore lore, CanBeWise (Op lore)) =>- BodyDec lore ->- Stms (Wise lore) ->+ (ASTRep rep, CanBeWise (Op rep)) =>+ BodyDec rep ->+ Stms (Wise rep) -> [KernelResult] ->- KernelBody (Wise lore)+ KernelBody (Wise rep) mkWiseKernelBody dec bnds res = let Body dec' _ _ = mkWiseBody dec bnds res_vs in KernelBody dec' bnds res@@ -1045,9 +1055,9 @@ mkKernelBodyM :: MonadBinder m =>- Stms (Lore m) ->+ Stms (Rep m) -> [KernelResult] ->- m (KernelBody (Lore m))+ m (KernelBody (Rep m)) mkKernelBodyM stms kres = do Body dec' _ _ <- mkBodyM stms res_ses return $ KernelBody dec' stms kres@@ -1055,10 +1065,10 @@ res_ses = map kernelResultSubExp kres simplifyKernelBody ::- (Engine.SimplifiableLore lore, BodyDec lore ~ ()) =>+ (Engine.SimplifiableRep rep, BodyDec rep ~ ()) => SegSpace ->- KernelBody lore ->- Engine.SimpleM lore (KernelBody (Wise lore), Stms (Wise lore))+ KernelBody rep ->+ Engine.SimpleM rep (KernelBody (Wise rep), Stms (Wise rep)) simplifyKernelBody space (KernelBody _ stms res) = do par_blocker <- Engine.asksEngineEnv $ Engine.blockHoistPar . Engine.envHoistBlockers @@ -1090,16 +1100,16 @@ consumedInResult _ = [] -segSpaceSymbolTable :: ASTLore lore => SegSpace -> ST.SymbolTable lore+segSpaceSymbolTable :: ASTRep rep => SegSpace -> ST.SymbolTable rep segSpaceSymbolTable (SegSpace flat gtids_and_dims) = foldl' f (ST.fromScope $ M.singleton flat $ IndexName Int64) gtids_and_dims where f vtable (gtid, dim) = ST.insertLoopVar gtid Int64 dim vtable simplifySegBinOp ::- Engine.SimplifiableLore lore =>- SegBinOp lore ->- Engine.SimpleM lore (SegBinOp (Wise lore), Stms (Wise lore))+ Engine.SimplifiableRep rep =>+ SegBinOp rep ->+ Engine.SimpleM rep (SegBinOp (Wise rep), Stms (Wise rep)) simplifySegBinOp (SegBinOp comm lam nes shape) = do (lam', hoisted) <- Engine.localVtable (\vtable -> vtable {ST.simplifyMemory = True}) $@@ -1110,12 +1120,12 @@ -- | Simplify the given 'SegOp'. simplifySegOp ::- ( Engine.SimplifiableLore lore,- BodyDec lore ~ (),+ ( Engine.SimplifiableRep rep,+ BodyDec rep ~ (), Engine.Simplifiable lvl ) =>- SegOp lvl lore ->- Engine.SimpleM lore (SegOp lvl (Wise lore), Stms (Wise lore))+ SegOp lvl rep ->+ Engine.SimpleM rep (SegOp lvl (Wise rep), Stms (Wise rep)) simplifySegOp (SegMap lvl space ts kbody) = do (lvl', space', ts') <- Engine.simplify (lvl, space, ts) (kbody', body_hoisted) <- simplifyKernelBody space kbody@@ -1181,23 +1191,23 @@ scope = scopeOfSegSpace space scope_vtable = ST.fromScope scope --- | Does this lore contain 'SegOp's in its t'Op's? A lore must be an+-- | Does this rep contain 'SegOp's in its t'Op's? A rep must be an -- instance of this class for the simplification rules to work.-class HasSegOp lore where- type SegOpLevel lore- asSegOp :: Op lore -> Maybe (SegOp (SegOpLevel lore) lore)- segOp :: SegOp (SegOpLevel lore) lore -> Op lore+class HasSegOp rep where+ type SegOpLevel rep+ asSegOp :: Op rep -> Maybe (SegOp (SegOpLevel rep) rep)+ segOp :: SegOp (SegOpLevel rep) rep -> Op rep -- | Simplification rules for simplifying 'SegOp's. segOpRules ::- (HasSegOp lore, BinderOps lore, Bindable lore) =>- RuleBook lore+ (HasSegOp rep, BinderOps rep, Bindable rep) =>+ RuleBook rep segOpRules = ruleBook [RuleOp segOpRuleTopDown] [RuleOp segOpRuleBottomUp] segOpRuleTopDown ::- (HasSegOp lore, BinderOps lore, Bindable lore) =>- TopDownRuleOp lore+ (HasSegOp rep, BinderOps rep, Bindable rep) =>+ TopDownRuleOp rep segOpRuleTopDown vtable pat dec op | Just op' <- asSegOp op = topDownSegOp vtable pat dec op'@@ -1205,8 +1215,8 @@ Skip segOpRuleBottomUp ::- (HasSegOp lore, BinderOps lore) =>- BottomUpRuleOp lore+ (HasSegOp rep, BinderOps rep) =>+ BottomUpRuleOp rep segOpRuleBottomUp vtable pat dec op | Just op' <- asSegOp op = bottomUpSegOp vtable pat dec op'@@ -1214,12 +1224,12 @@ Skip topDownSegOp ::- (HasSegOp lore, BinderOps lore, Bindable lore) =>- ST.SymbolTable lore ->- Pattern lore ->- StmAux (ExpDec lore) ->- SegOp (SegOpLevel lore) lore ->- Rule lore+ (HasSegOp rep, BinderOps rep, Bindable rep) =>+ ST.SymbolTable rep ->+ Pattern 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@@ -1308,11 +1318,11 @@ -- A convenient way of operating on the type and body of a SegOp, -- without worrying about exactly what kind it is. segOpGuts ::- SegOp (SegOpLevel lore) lore ->+ SegOp (SegOpLevel rep) rep -> ( [Type],- KernelBody lore,+ KernelBody rep, Int,- [Type] -> KernelBody lore -> SegOp (SegOpLevel lore) lore+ [Type] -> KernelBody rep -> SegOp (SegOpLevel rep) rep ) segOpGuts (SegMap lvl space kts body) = (kts, body, 0, SegMap lvl space)@@ -1324,12 +1334,12 @@ (kts, body, sum $ map (length . histDest) ops, SegHist lvl space ops) bottomUpSegOp ::- (HasSegOp lore, BinderOps lore) =>- (ST.SymbolTable lore, UT.UsageTable) ->- Pattern lore ->- StmAux (ExpDec lore) ->- SegOp (SegOpLevel lore) lore ->- Rule lore+ (HasSegOp rep, BinderOps rep) =>+ (ST.SymbolTable rep, UT.UsageTable) ->+ Pattern 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@@ -1419,8 +1429,8 @@ --- Memory kernelBodyReturns ::- (Mem lore, HasScope lore m, Monad m) =>- KernelBody lore ->+ (Mem rep, HasScope rep m, Monad m) =>+ KernelBody rep -> [ExpReturns] -> m [ExpReturns] kernelBodyReturns = zipWithM correct . kernelBodyResult@@ -1430,8 +1440,8 @@ -- | Like 'segOpType', but for memory representations. segOpReturns ::- (Mem lore, Monad m, HasScope lore m) =>- SegOp lvl lore ->+ (Mem rep, Monad m, HasScope rep m) =>+ SegOp lvl rep -> m [ExpReturns] segOpReturns k@(SegMap _ _ _ kbody) = kernelBodyReturns kbody . extReturns =<< opType k
src/Futhark/IR/Seq.hs view
@@ -3,8 +3,7 @@ -- | A sequential representation. module Futhark.IR.Seq- ( -- * The Lore definition- Seq,+ ( Seq, -- * Simplification simplifyProg,@@ -32,10 +31,10 @@ -- | The phantom type for the Seq representation. data Seq -instance Decorations Seq where+instance RepTypes Seq where type Op Seq = () -instance ASTLore Seq where+instance ASTRep Seq where expTypesFromPattern = return . expExtTypesFromPattern instance TypeCheck.CheckableOp Seq where@@ -51,7 +50,7 @@ instance BinderOps Seq -instance PrettyLore Seq+instance PrettyRep Seq instance BinderOps (Engine.Wise Seq)
src/Futhark/IR/SeqMem.hs view
@@ -13,12 +13,10 @@ -- * Module re-exports module Futhark.IR.Mem,- module Futhark.IR.Kernels.Kernel, ) where import Futhark.Analysis.PrimExp.Convert-import Futhark.IR.Kernels.Kernel import Futhark.IR.Mem import Futhark.IR.Mem.Simplify import qualified Futhark.Optimise.Simplify.Engine as Engine@@ -28,7 +26,7 @@ data SeqMem -instance Decorations SeqMem where+instance RepTypes SeqMem where type LetDec SeqMem = LetDecMem type FParamInfo SeqMem = FParamMem type LParamInfo SeqMem = LParamMem@@ -36,14 +34,14 @@ type BranchType SeqMem = BranchTypeMem type Op SeqMem = MemOp () -instance ASTLore SeqMem where+instance ASTRep SeqMem where expTypesFromPattern = return . map snd . snd . bodyReturnsFromPattern instance OpReturns SeqMem where opReturns (Alloc _ space) = return [MemMem space] opReturns (Inner ()) = pure [] -instance PrettyLore SeqMem+instance PrettyRep SeqMem instance TC.CheckableOp SeqMem where checkOp (Alloc size _) =@@ -52,9 +50,9 @@ pure () instance TC.Checkable SeqMem where- checkFParamLore = checkMemInfo- checkLParamLore = checkMemInfo- checkLetBoundLore = checkMemInfo+ checkFParamDec = checkMemInfo+ checkLParamDec = checkMemInfo+ checkLetBoundDec = checkMemInfo checkRetType = mapM_ (TC.checkExtType . declExtTypeOf) primFParam name t = return $ Param name (MemPrim t) matchPattern = matchPatternToExp
src/Futhark/IR/Syntax.hs view
@@ -71,37 +71,37 @@ -- in {b_13} -- @ ----- == Lores+-- == Representations -- -- Most AST types ('Stm', 'ExpT', t'Prog', etc) are parameterised by a--- type parameter with the somewhat silly name @lore@. The lore--- specifies how to fill out various polymorphic parts of the AST.--- For example, 'ExpT' has a constructor v'Op' whose payload depends--- on @lore@, via the use of a type family called t'Op' (a kind of--- type-level function) which is applied to the @lore@. The SOACS--- representation ("Futhark.IR.SOACS") thus uses a lore--- called @SOACS@, and defines that @Op SOACS@ is a SOAC, while the--- Kernels representation ("Futhark.IR.Kernels") defines--- @Op Kernels@ as some kind of kernel construct. Similarly, various--- other decorations (e.g. what information we store in a t'PatElemT')--- are also type families.+-- type parameter @rep@. The representation specifies how to fill out+-- various polymorphic parts of the AST. For example, 'ExpT' has a+-- constructor v'Op' whose payload depends on @rep@, via the use of a+-- type family called t'Op' (a kind of type-level function) which is+-- applied to the @rep@. The SOACS representation+-- ("Futhark.IR.SOACS") thus uses a rep called @SOACS@, and defines+-- that @Op SOACS@ is a SOAC, while the Kernels representation+-- ("Futhark.IR.Kernels") defines @Op Kernels@ as some kind of kernel+-- construct. Similarly, various other decorations (e.g. what+-- information we store in a t'PatElemT') are also type families. -- -- The full list of possible decorations is defined as part of the--- type class 'Decorations' (although other type families are also+-- type class 'RepTypes' (although other type families are also -- used elsewhere in the compiler on an ad hoc basis). ----- Essentially, the @lore@ type parameter functions as a kind of+-- Essentially, the @rep@ type parameter functions as a kind of -- proxy, saving us from having to parameterise the AST type with all -- the different forms of decorations that we desire (it would easily -- become a type with a dozen type parameters). ----- Defining a new representation (or /lore/) thus requires you to+-- Defining a new representation (or /rep/) thus requires you to -- define an empty datatype and implement a handful of type class -- instances for it. See the source of "Futhark.IR.Seq" -- for what is likely the simplest example. module Futhark.IR.Syntax ( module Language.Futhark.Core,- module Futhark.IR.Decorations,+ pretty,+ module Futhark.IR.Rep, module Futhark.IR.Syntax.Core, -- * Types@@ -172,8 +172,9 @@ import qualified Data.Set as S import Data.String import Data.Traversable (fmapDefault, foldMapDefault)-import Futhark.IR.Decorations+import Futhark.IR.Rep import Futhark.IR.Syntax.Core+import Futhark.Util.Pretty (pretty) import Language.Futhark.Core import Prelude hiding (id, (.)) @@ -204,7 +205,7 @@ withoutAttrs (Attrs x) (Attrs y) = Attrs $ x `S.difference` y -- | A type alias for namespace control.-type PatElem lore = PatElemT (LetDec lore)+type PatElem rep = PatElemT (LetDec rep) -- | A pattern is conceptually just a list of names and their types. data PatternT dec = Pattern@@ -232,7 +233,7 @@ Pattern <$> traverse (traverse f) ctx <*> traverse (traverse f) vals -- | A type alias for namespace control.-type Pattern lore = PatternT (LetDec lore)+type Pattern rep = PatternT (LetDec rep) -- | Auxilliary Information associated with a statement. data StmAux dec = StmAux@@ -247,38 +248,38 @@ StmAux (cs1 <> cs2) (attrs1 <> attrs2) (dec1 <> dec2) -- | A local variable binding.-data Stm lore = Let+data Stm rep = Let { -- | Pattern.- stmPattern :: Pattern lore,+ stmPattern :: Pattern rep, -- | Auxiliary information statement.- stmAux :: StmAux (ExpDec lore),+ stmAux :: StmAux (ExpDec rep), -- | Expression.- stmExp :: Exp lore+ stmExp :: Exp rep } -deriving instance Decorations lore => Ord (Stm lore)+deriving instance RepTypes rep => Ord (Stm rep) -deriving instance Decorations lore => Show (Stm lore)+deriving instance RepTypes rep => Show (Stm rep) -deriving instance Decorations lore => Eq (Stm lore)+deriving instance RepTypes rep => Eq (Stm rep) -- | A sequence of statements.-type Stms lore = Seq.Seq (Stm lore)+type Stms rep = Seq.Seq (Stm rep) -- | A single statement.-oneStm :: Stm lore -> Stms lore+oneStm :: Stm rep -> Stms rep oneStm = Seq.singleton -- | Convert a statement list to a statement sequence.-stmsFromList :: [Stm lore] -> Stms lore+stmsFromList :: [Stm rep] -> Stms rep stmsFromList = Seq.fromList -- | Convert a statement sequence to a statement list.-stmsToList :: Stms lore -> [Stm lore]+stmsToList :: Stms rep -> [Stm rep] stmsToList = toList -- | The first statement in the sequence, if any.-stmsHead :: Stms lore -> Maybe (Stm lore, Stms lore)+stmsHead :: Stms rep -> Maybe (Stm rep, Stms rep) stmsHead stms = case Seq.viewl stms of stm Seq.:< stms' -> Just (stm, stms') Seq.EmptyL -> Nothing@@ -288,17 +289,17 @@ -- | A body consists of a number of bindings, terminating in a result -- (essentially a tuple literal).-data BodyT lore = Body- { bodyDec :: BodyDec lore,- bodyStms :: Stms lore,+data BodyT rep = Body+ { bodyDec :: BodyDec rep,+ bodyStms :: Stms rep, bodyResult :: Result } -deriving instance Decorations lore => Ord (BodyT lore)+deriving instance RepTypes rep => Ord (BodyT rep) -deriving instance Decorations lore => Show (BodyT lore)+deriving instance RepTypes rep => Show (BodyT rep) -deriving instance Decorations lore => Eq (BodyT lore)+deriving instance RepTypes rep => Eq (BodyT rep) -- | Type alias for namespace reasons. type Body = BodyT@@ -405,42 +406,42 @@ deriving (Eq, Ord, Show) -- | The root Futhark expression type. The v'Op' constructor contains--- a lore-specific operation. Do-loops, branches and function calls+-- a rep-specific operation. Do-loops, branches and function calls -- are special. Everything else is a simple t'BasicOp'.-data ExpT lore+data ExpT rep = -- | A simple (non-recursive) operation. BasicOp BasicOp- | Apply Name [(SubExp, Diet)] [RetType lore] (Safety, SrcLoc, [SrcLoc])- | If SubExp (BodyT lore) (BodyT lore) (IfDec (BranchType lore))+ | 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 lore, SubExp)] [(FParam lore, SubExp)] (LoopForm lore) (BodyT lore)+ DoLoop [(FParam rep, SubExp)] [(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 -- write index space. The corresponding arrays must all have this -- shape outermost. This construct is not part of 'BasicOp'- -- because we need the @lore@ parameter.- WithAcc [(Shape, [VName], Maybe (Lambda lore, [SubExp]))] (Lambda lore)- | Op (Op lore)+ -- because we need the @rep@ parameter.+ WithAcc [(Shape, [VName], Maybe (Lambda rep, [SubExp]))] (Lambda rep)+ | Op (Op rep) -deriving instance Decorations lore => Eq (ExpT lore)+deriving instance RepTypes rep => Eq (ExpT rep) -deriving instance Decorations lore => Show (ExpT lore)+deriving instance RepTypes rep => Show (ExpT rep) -deriving instance Decorations lore => Ord (ExpT lore)+deriving instance RepTypes rep => Ord (ExpT rep) -- | For-loop or while-loop?-data LoopForm lore- = ForLoop VName IntType SubExp [(LParam lore, VName)]+data LoopForm rep+ = ForLoop VName IntType SubExp [(LParam rep, VName)] | WhileLoop VName -deriving instance Decorations lore => Eq (LoopForm lore)+deriving instance RepTypes rep => Eq (LoopForm rep) -deriving instance Decorations lore => Show (LoopForm lore)+deriving instance RepTypes rep => Show (LoopForm rep) -deriving instance Decorations lore => Ord (LoopForm lore)+deriving instance RepTypes rep => Ord (LoopForm rep) -- | Data associated with a branch. data IfDec rt = IfDec@@ -472,44 +473,44 @@ type Exp = ExpT -- | Anonymous function for use in a SOAC.-data LambdaT lore = Lambda- { lambdaParams :: [LParam lore],- lambdaBody :: BodyT lore,+data LambdaT rep = Lambda+ { lambdaParams :: [LParam rep],+ lambdaBody :: BodyT rep, lambdaReturnType :: [Type] } -deriving instance Decorations lore => Eq (LambdaT lore)+deriving instance RepTypes rep => Eq (LambdaT rep) -deriving instance Decorations lore => Show (LambdaT lore)+deriving instance RepTypes rep => Show (LambdaT rep) -deriving instance Decorations lore => Ord (LambdaT lore)+deriving instance RepTypes rep => Ord (LambdaT rep) -- | Type alias for namespacing reasons. type Lambda = LambdaT -- | A function and loop parameter.-type FParam lore = Param (FParamInfo lore)+type FParam rep = Param (FParamInfo rep) -- | A lambda parameter.-type LParam lore = Param (LParamInfo lore)+type LParam rep = Param (LParamInfo rep) -- | Function Declarations-data FunDef lore = FunDef+data FunDef rep = FunDef { -- | Contains a value if this function is -- an entry point. funDefEntryPoint :: Maybe EntryPoint, funDefAttrs :: Attrs, funDefName :: Name,- funDefRetType :: [RetType lore],- funDefParams :: [FParam lore],- funDefBody :: BodyT lore+ funDefRetType :: [RetType rep],+ funDefParams :: [FParam rep],+ funDefBody :: BodyT rep } -deriving instance Decorations lore => Eq (FunDef lore)+deriving instance RepTypes rep => Eq (FunDef rep) -deriving instance Decorations lore => Show (FunDef lore)+deriving instance RepTypes rep => Show (FunDef rep) -deriving instance Decorations lore => Ord (FunDef lore)+deriving instance RepTypes rep => Ord (FunDef rep) -- | Information about the parameters and return value of an entry -- point. The first element is for parameters, the second for return@@ -521,24 +522,24 @@ data EntryPointType = -- | Is an unsigned integer or array of unsigned -- integers.- TypeUnsigned+ TypeUnsigned Uniqueness | -- | A black box type comprising this many core -- values. The string is a human-readable -- description with no other semantics.- TypeOpaque String Int+ TypeOpaque Uniqueness String Int | -- | Maps directly.- TypeDirect+ TypeDirect Uniqueness deriving (Eq, Show, Ord) -- | An entire Futhark program.-data Prog lore = Prog+data Prog rep = Prog { -- | Top-level constants that are computed at program startup, and -- which are in scope inside all functions.- progConsts :: Stms lore,+ progConsts :: Stms rep, -- | The functions comprising the program. All funtions are also -- available in scope in the definitions of the constants, so be -- careful not to introduce circular dependencies (not currently -- checked).- progFuns :: [FunDef lore]+ progFuns :: [FunDef rep] } deriving (Eq, Ord, Show)
src/Futhark/IR/Syntax/Core.hs view
@@ -5,7 +5,7 @@ -- | The most primitive ("core") aspects of the AST. Split out of -- "Futhark.IR.Syntax" in order for--- "Futhark.IR.Decorations" to use these definitions. This+-- "Futhark.IR.Rep" to use these definitions. This -- module is re-exported from "Futhark.IR.Syntax" and -- there should be no reason to include it explicitly. module Futhark.IR.Syntax.Core@@ -13,6 +13,7 @@ module Futhark.IR.Primitive, -- * Types+ Commutativity (..), Uniqueness (..), NoUniqueness (..), ShapeBase (..),@@ -66,6 +67,19 @@ import Futhark.IR.Primitive import Language.Futhark.Core import Prelude hiding (id, (.))++-- | Whether some operator is commutative or not. The 'Monoid'+-- instance returns the least commutative of its arguments.+data Commutativity+ = Noncommutative+ | Commutative+ deriving (Eq, Ord, Show)++instance Semigroup Commutativity where+ (<>) = min++instance Monoid Commutativity where+ mempty = Commutative -- | The size of an array type as a list of its dimension sizes, with -- the type of sizes being parametric.
src/Futhark/IR/Traversals.hs view
@@ -46,21 +46,21 @@ -- | Express a monad mapping operation on a syntax node. Each element -- of this structure expresses the operation to be performed on a -- given child.-data Mapper flore tlore m = Mapper+data Mapper frep trep m = Mapper { mapOnSubExp :: SubExp -> m SubExp, -- | Most bodies are enclosed in a scope, which is passed along -- for convenience.- mapOnBody :: Scope tlore -> Body flore -> m (Body tlore),+ mapOnBody :: Scope trep -> Body frep -> m (Body trep), mapOnVName :: VName -> m VName,- mapOnRetType :: RetType flore -> m (RetType tlore),- mapOnBranchType :: BranchType flore -> m (BranchType tlore),- mapOnFParam :: FParam flore -> m (FParam tlore),- mapOnLParam :: LParam flore -> m (LParam tlore),- mapOnOp :: Op flore -> m (Op tlore)+ mapOnRetType :: RetType frep -> m (RetType trep),+ mapOnBranchType :: BranchType frep -> m (BranchType trep),+ mapOnFParam :: FParam frep -> m (FParam trep),+ mapOnLParam :: LParam frep -> m (LParam trep),+ mapOnOp :: Op frep -> m (Op trep) } -- | A mapper that simply returns the tree verbatim.-identityMapper :: Monad m => Mapper lore lore m+identityMapper :: Monad m => Mapper rep rep m identityMapper = Mapper { mapOnSubExp = return,@@ -78,9 +78,9 @@ -- into subexpressions. The mapping is done left-to-right. mapExpM :: (Applicative m, Monad m) =>- Mapper flore tlore m ->- Exp flore ->- m (Exp tlore)+ Mapper frep trep m ->+ Exp frep ->+ m (Exp trep) mapExpM tv (BasicOp (SubExp se)) = BasicOp <$> (SubExp <$> mapOnSubExp tv se) mapExpM tv (BasicOp (ArrayLit els rowt)) =@@ -174,14 +174,14 @@ mapExpM tv (Op op) = Op <$> mapOnOp tv op -mapOnShape :: Monad m => Mapper flore tlore m -> Shape -> m Shape+mapOnShape :: Monad m => Mapper frep trep m -> Shape -> m Shape mapOnShape tv (Shape ds) = Shape <$> mapM (mapOnSubExp tv) ds mapOnLoopForm :: Monad m =>- Mapper flore tlore m ->- LoopForm flore ->- m (LoopForm tlore)+ Mapper frep trep m ->+ LoopForm frep ->+ m (LoopForm trep) mapOnLoopForm tv (ForLoop i it bound loop_vars) = ForLoop <$> mapOnVName tv i <*> pure it <*> mapOnSubExp tv bound <*> (zip <$> mapM (mapOnLParam tv) loop_lparams <*> mapM (mapOnVName tv) loop_arrs)@@ -192,9 +192,9 @@ mapOnLambda :: Monad m =>- Mapper flore tlore m ->- Lambda flore ->- m (Lambda tlore)+ Mapper frep trep m ->+ Lambda frep ->+ m (Lambda trep) mapOnLambda tv (Lambda params body ret) = do params' <- mapM (mapOnLParam tv) params Lambda params'@@ -202,25 +202,25 @@ <*> mapM (mapOnType (mapOnSubExp tv)) ret -- | Like 'mapExpM', but in the 'Identity' monad.-mapExp :: Mapper flore tlore Identity -> Exp flore -> Exp tlore+mapExp :: Mapper frep trep Identity -> Exp frep -> Exp trep mapExp m = runIdentity . mapExpM m -- | Express a monad expression on a syntax node. Each element of -- this structure expresses the action to be performed on a given -- child.-data Walker lore m = Walker+data Walker rep m = Walker { walkOnSubExp :: SubExp -> m (),- walkOnBody :: Scope lore -> Body lore -> m (),+ walkOnBody :: Scope rep -> Body rep -> m (), walkOnVName :: VName -> m (),- walkOnRetType :: RetType lore -> m (),- walkOnBranchType :: BranchType lore -> m (),- walkOnFParam :: FParam lore -> m (),- walkOnLParam :: LParam lore -> m (),- walkOnOp :: Op lore -> m ()+ walkOnRetType :: RetType rep -> m (),+ walkOnBranchType :: BranchType rep -> m (),+ walkOnFParam :: FParam rep -> m (),+ walkOnLParam :: LParam rep -> m (),+ walkOnOp :: Op rep -> m () } -- | A no-op traversal.-identityWalker :: Monad m => Walker lore m+identityWalker :: Monad m => Walker rep m identityWalker = Walker { walkOnSubExp = const $ return (),@@ -233,10 +233,10 @@ walkOnOp = const $ return () } -walkOnShape :: Monad m => Walker lore m -> Shape -> m ()+walkOnShape :: Monad m => Walker rep m -> Shape -> m () walkOnShape tv (Shape ds) = mapM_ (walkOnSubExp tv) ds -walkOnType :: Monad m => Walker lore m -> Type -> m ()+walkOnType :: Monad m => Walker rep m -> Type -> m () walkOnType _ Prim {} = return () walkOnType tv (Acc acc ispace ts _) = do walkOnVName tv acc@@ -245,7 +245,7 @@ walkOnType _ Mem {} = return () walkOnType tv (Array _ shape _) = walkOnShape tv shape -walkOnLoopForm :: Monad m => Walker lore m -> LoopForm lore -> m ()+walkOnLoopForm :: Monad m => Walker rep m -> LoopForm rep -> m () walkOnLoopForm tv (ForLoop i _ bound loop_vars) = walkOnVName tv i >> walkOnSubExp tv bound >> mapM_ (walkOnLParam tv) loop_lparams@@ -255,14 +255,14 @@ walkOnLoopForm tv (WhileLoop cond) = walkOnVName tv cond -walkOnLambda :: Monad m => Walker lore m -> Lambda lore -> m ()+walkOnLambda :: Monad m => Walker rep m -> Lambda rep -> m () walkOnLambda tv (Lambda params body ret) = do mapM_ (walkOnLParam tv) params walkOnBody tv (scopeOfLParams params) body mapM_ (walkOnType tv) ret -- | As 'mapExpM', but do not construct a result AST.-walkExpM :: Monad m => Walker lore m -> Exp lore -> m ()+walkExpM :: Monad m => Walker rep m -> Exp rep -> m () walkExpM tv (BasicOp (SubExp se)) = walkOnSubExp tv se walkExpM tv (BasicOp (ArrayLit els rowt)) =
src/Futhark/Internalise/Defunctionalise.hs view
@@ -1091,11 +1091,9 @@ typeFromSV (Dynamic tp) = tp typeFromSV (LambdaSV _ _ _ env) =- Scalar $- Record $- M.fromList $- map (bimap (nameFromString . pretty) (typeFromSV . bindingSV)) $- M.toList env+ Scalar . Record . M.fromList $+ map (bimap (nameFromString . pretty) (typeFromSV . bindingSV)) $+ M.toList env typeFromSV (RecordSV ls) = let ts = map (fmap typeFromSV) ls in Scalar $ Record $ M.fromList ts@@ -1174,13 +1172,7 @@ | ps' <- sortOn fst ps, svs' <- sortOn fst svs = RecordPattern- ( zipWith- ( \(n, p) (_, sv) ->- (n, updatePattern p sv)- )- ps'- svs'- )+ (zipWith (\(n, p) (_, sv) -> (n, updatePattern p sv)) ps' svs') loc updatePattern (PatternParens pat loc) sv = PatternParens (updatePattern pat sv) loc@@ -1251,9 +1243,14 @@ ++ "but the defunctionaliser expects a monomorphic input program." (tparams', params', body', sv) <- defuncLet (map typeParamName tparams) params body rettype- let rettype' = combineTypeShapes rettype $ anySizes $ toStruct $ typeOf body' globals <- asks fst- let bound_sizes = S.fromList tparams' <> globals+ let bound_sizes = foldMap patternNames 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+ -- applications of lifted functions, we don't properly update+ -- the types in the return type annotation.+ combineTypeShapes rettype $ first (anyDimIfNotBound bound_sizes) $ toStruct $ typeOf body' (missing_dims, params'') <- sizesForAll bound_sizes params' return ( valbind@@ -1272,18 +1269,17 @@ }, M.singleton name $ Binding- ( Just- ( first- (map typeParamName)- (valBindTypeScheme valbind)- )- )+ (Just (first (map typeParamName) (valBindTypeScheme valbind))) sv, case sv of DynamicFun {} -> True Dynamic {} -> True _ -> False )+ where+ anyDimIfNotBound bound_sizes (NamedDim v)+ | qualLeaf v `S.notMember` bound_sizes = AnyDim $ Just $ qualLeaf v+ anyDimIfNotBound _ d = d -- | Defunctionalize a list of top-level declarations. defuncVals :: [ValBind] -> DefM ()
src/Futhark/Internalise/Exps.hs view
@@ -152,16 +152,17 @@ entryPointType (t, ts) | E.Scalar (E.Prim E.Unsigned {}) <- E.entryType t =- [I.TypeUnsigned]+ [I.TypeUnsigned u] | E.Array _ _ (E.Prim E.Unsigned {}) _ <- E.entryType t =- [I.TypeUnsigned]+ [I.TypeUnsigned u] | E.Scalar E.Prim {} <- E.entryType t =- [I.TypeDirect]+ [I.TypeDirect u] | E.Array _ _ E.Prim {} _ <- E.entryType t =- [I.TypeDirect]+ [I.TypeDirect u] | otherwise =- [I.TypeOpaque desc $ length ts]+ [I.TypeOpaque u desc $ length ts] where+ u = foldl max Nonunique $ map I.uniqueness ts desc = maybe (prettyOneLine t') typeExpOpaqueName $ E.entryAscribed t t' = noSizes (E.entryType t) `E.setUniqueness` Nonunique typeExpOpaqueName (TEApply te TypeArgExpDim {} _) =
src/Futhark/Internalise/Monad.hs view
@@ -84,7 +84,7 @@ putNameSource src = modify $ \s -> s {stateNameSource = src} instance MonadBinder InternaliseM where- type Lore InternaliseM = SOACS+ type Rep InternaliseM = SOACS mkExpDecM pat e = InternaliseM $ mkExpDecM pat e mkBodyM bnds res = InternaliseM $ mkBodyM bnds res mkLetNamesM pat e = InternaliseM $ mkLetNamesM pat e
src/Futhark/Optimise/BlkRegTiling.hs view
@@ -24,13 +24,13 @@ import qualified Data.Map.Strict as M import Data.Maybe import qualified Data.Sequence as Seq-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.MonadFreshNames import Futhark.Optimise.TileLoops.Shared import Futhark.Tools import Futhark.Transform.Rename -mmBlkRegTiling :: Stm Kernels -> TileM (Maybe (Stms Kernels, Stm Kernels))+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, -- check kernel has one result of primitive type@@ -416,7 +416,7 @@ return $ Just (host_stms, new_kernel) mmBlkRegTiling _ = return Nothing -ceilDiv :: MonadBinder m => SubExp -> SubExp -> m (Exp (Lore m))+ceilDiv :: MonadBinder 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@@ -446,9 +446,9 @@ [VName] -> -- loop inits ( VName -> [VName] -> -- (loop var -> loop inits -> loop body)- Binder Kernels (Body Kernels)+ Binder GPU (Body GPU) ) ->- Binder Kernels [VName]+ Binder 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 []@@ -466,8 +466,8 @@ forLoop :: SubExp -> [VName] ->- (VName -> [VName] -> Binder Kernels (Body Kernels)) ->- Binder Kernels VName+ (VName -> [VName] -> Binder GPU (Body GPU)) ->+ Binder GPU VName forLoop i_bound merge body = do res_list <- forLoop' i_bound merge body return $ head res_list@@ -479,10 +479,10 @@ -- creates Stms corresponding to binding of new_params, -- lambda body, and binding of lambda result to res_name. rebindLambda ::- Lambda Kernels ->+ Lambda GPU -> [VName] -> [VName] ->- Stms Kernels+ Stms GPU rebindLambda lam new_params res_names = stmsFromList ( zipWith@@ -513,8 +513,8 @@ -- | Tries to identify the following pattern: -- code followed by some Screma followed by more code. matchCodeStreamCode ::- Stms Kernels ->- (Stms Kernels, Maybe (Stm Kernels), Stms Kernels)+ Stms GPU ->+ (Stms GPU, Maybe (Stm GPU), Stms GPU) matchCodeStreamCode kstms = let (code1, screma, code2) = foldl@@ -568,9 +568,9 @@ processIndirections :: Names -> -- input arrays to redomap Names -> -- variables on which the result of redomap depends on.- Maybe (Stms Kernels, M.Map VName (Stm Kernels)) ->- Stm Kernels ->- Maybe (Stms Kernels, M.Map VName (Stm Kernels))+ Maybe (Stms GPU, M.Map VName (Stm GPU)) ->+ Stm GPU ->+ Maybe (Stms GPU, M.Map VName (Stm GPU)) processIndirections arrs _ acc stm@(Let patt _ (BasicOp (Index _ _))) | Just (ss, tab) <- acc, [p] <- patternValueElements patt,@@ -599,7 +599,7 @@ se8 :: SubExp se8 = intConst Int64 8 -getParTiles :: (String, String) -> (Name, Name) -> SubExp -> Binder Kernels (SubExp, SubExp)+getParTiles :: (String, String) -> (Name, Name) -> SubExp -> Binder GPU (SubExp, SubExp) getParTiles (t_str, r_str) (t_name, r_name) len_dim = case len_dim of Constant (IntValue (Int64Value 8)) ->@@ -613,7 +613,7 @@ r <- letSubExp r_str $ Op $ SizeOp $ GetSize r_name SizeRegTile return (t, r) -getSeqTile :: String -> Name -> SubExp -> SubExp -> SubExp -> Binder Kernels SubExp+getSeqTile :: String -> Name -> SubExp -> SubExp -> SubExp -> Binder 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))) ->@@ -695,9 +695,9 @@ -- a) each of the statements is a slice that produces one of the -- streamed arrays ----- mmBlkRegTiling :: Stm Kernels -> TileM (Maybe (Stms Kernels, Stm Kernels))+-- mmBlkRegTiling :: Stm GPU -> TileM (Maybe (Stms GPU, Stm GPU)) -- mmBlkRegTiling (Let pat aux (Op (SegOp (SegMap SegThread{} seg_space ts old_kbody))))-doRegTiling3D :: Stm Kernels -> TileM (Maybe (Stms Kernels, Stm Kernels))+doRegTiling3D :: Stm GPU -> TileM (Maybe (Stms GPU, Stm GPU)) doRegTiling3D (Let pat aux (Op (SegOp old_kernel))) | SegMap SegThread {} space kertp (KernelBody () kstms kres) <- old_kernel, -- build the variance table, that records, for@@ -992,14 +992,14 @@ getResNm (Returns ResultMaySimplify (Var res_nm)) = Just res_nm getResNm _ = Nothing - limitTile :: String -> SubExp -> SubExp -> Binder Kernels SubExp+ limitTile :: String -> SubExp -> SubExp -> Binder 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 Kernels), M.Map VName (PrimType, Stm Kernels)) ->- (VName, Stm Kernels) ->- Binder Kernels (M.Map VName (Stm Kernels), M.Map VName (PrimType, Stm Kernels))+ (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)) insertTranspose variance (gidz, _) (tab_inn, tab_out) (p_nm, stm@(Let patt yy (BasicOp (Index arr_nm slc)))) | [p] <- patternValueElements patt, ptp <- elemType $ patElemType p,
src/Futhark/Optimise/CSE.hs view
@@ -46,7 +46,7 @@ removeProgAliases, removeStmAliases, )-import qualified Futhark.IR.Kernels.Kernel as Kernel+import qualified Futhark.IR.GPU.Kernel as Kernel import qualified Futhark.IR.MC as MC import qualified Futhark.IR.Mem as Memory import Futhark.IR.Prop.Aliases@@ -54,22 +54,22 @@ import Futhark.Pass import Futhark.Transform.Substitute -consumedInStms :: Aliased lore => Stms lore -> Names+consumedInStms :: Aliased rep => Stms rep -> Names consumedInStms = snd . flip mkStmsAliases [] -- | Perform CSE on every function in a program. -- -- If the boolean argument is false, the pass will not perform CSE on--- expressions producing arrays. This should be disabled when the lore has+-- expressions producing arrays. This should be disabled when the rep has -- memory information, since at that point arrays have identity beyond their -- value. performCSE ::- ( ASTLore lore,- CanBeAliased (Op lore),- CSEInOp (OpWithAliases (Op lore))+ ( ASTRep rep,+ CanBeAliased (Op rep),+ CSEInOp (OpWithAliases (Op rep)) ) => Bool ->- Pass lore lore+ Pass rep rep performCSE cse_arrays = Pass "CSE" "Combine common subexpressions." $ fmap removeProgAliases@@ -87,34 +87,34 @@ -- | Perform CSE on a single function. -- -- If the boolean argument is false, the pass will not perform CSE on--- expressions producing arrays. This should be disabled when the lore has+-- expressions producing arrays. This should be disabled when the rep has -- memory information, since at that point arrays have identity beyond their -- value. performCSEOnFunDef ::- ( ASTLore lore,- CanBeAliased (Op lore),- CSEInOp (OpWithAliases (Op lore))+ ( ASTRep rep,+ CanBeAliased (Op rep),+ CSEInOp (OpWithAliases (Op rep)) ) => Bool ->- FunDef lore ->- FunDef lore+ FunDef rep ->+ FunDef rep performCSEOnFunDef cse_arrays = removeFunDefAliases . cseInFunDef cse_arrays . analyseFun -- | Perform CSE on some statements. -- -- If the boolean argument is false, the pass will not perform CSE on--- expressions producing arrays. This should be disabled when the lore has+-- expressions producing arrays. This should be disabled when the rep has -- memory information, since at that point arrays have identity beyond their -- value. performCSEOnStms ::- ( ASTLore lore,- CanBeAliased (Op lore),- CSEInOp (OpWithAliases (Op lore))+ ( ASTRep rep,+ CanBeAliased (Op rep),+ CSEInOp (OpWithAliases (Op rep)) ) => Bool ->- Stms lore ->- Stms lore+ Stms rep ->+ Stms rep performCSEOnStms cse_arrays = fmap removeStmAliases . f . fst . analyseStms mempty where@@ -129,10 +129,10 @@ (newCSEState cse_arrays) cseInFunDef ::- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) => Bool ->- FunDef lore ->- FunDef lore+ FunDef rep ->+ FunDef rep cseInFunDef cse_arrays fundec = fundec { funDefBody =@@ -150,13 +150,13 @@ | primType $ declExtTypeOf t = Observe | otherwise = Consume -type CSEM lore = Reader (CSEState lore)+type CSEM rep = Reader (CSEState rep) cseInBody ::- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) => [Diet] ->- Body lore ->- CSEM lore (Body lore)+ Body rep ->+ CSEM rep (Body rep) cseInBody ds (Body bodydec stms res) = do (stms', res') <- cseInStms (res_cons <> stms_cons) (stmsToList stms) $ do@@ -170,19 +170,19 @@ consumeResult _ _ = mempty cseInLambda ::- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>- Lambda lore ->- CSEM lore (Lambda lore)+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) =>+ Lambda rep ->+ CSEM rep (Lambda rep) cseInLambda lam = do body' <- cseInBody (map (const Observe) $ lambdaReturnType lam) $ lambdaBody lam return lam {lambdaBody = body'} cseInStms ::- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) => Names ->- [Stm lore] ->- CSEM lore a ->- CSEM lore (Stms lore, a)+ [Stm rep] ->+ CSEM rep a ->+ CSEM rep (Stms rep, a) cseInStms _ [] m = do a <- m return (mempty, a)@@ -208,11 +208,11 @@ | otherwise = Observe cseInStm ::- ASTLore lore =>+ ASTRep rep => Names ->- Stm lore ->- ([Stm lore] -> CSEM lore a) ->- CSEM lore a+ Stm rep ->+ ([Stm rep] -> CSEM rep a) ->+ CSEM rep a cseInStm consumed (Let pat (StmAux cs attrs edec) e) m = do CSEState (esubsts, nsubsts) cse_arrays <- ask let e' = substituteNames nsubsts e@@ -239,70 +239,70 @@ | patElemName pe `nameIn` consumed = True | otherwise = False -type ExpressionSubstitutions lore =+type ExpressionSubstitutions rep = M.Map- (ExpDec lore, Exp lore)- (Pattern lore)+ (ExpDec rep, Exp rep)+ (Pattern rep) type NameSubstitutions = M.Map VName VName -data CSEState lore = CSEState- { _cseSubstitutions :: (ExpressionSubstitutions lore, NameSubstitutions),+data CSEState rep = CSEState+ { _cseSubstitutions :: (ExpressionSubstitutions rep, NameSubstitutions), _cseArrays :: Bool } -newCSEState :: Bool -> CSEState lore+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) -addNameSubst :: PatternT dec -> PatternT dec -> CSEState lore -> CSEState lore+addNameSubst :: PatternT dec -> PatternT dec -> CSEState rep -> CSEState rep addNameSubst pat subpat (CSEState (esubsts, nsubsts) cse_arrays) = CSEState (esubsts, mkSubsts pat subpat `M.union` nsubsts) cse_arrays addExpSubst ::- ASTLore lore =>- Pattern lore ->- ExpDec lore ->- Exp lore ->- CSEState lore ->- CSEState lore+ ASTRep rep =>+ Pattern rep ->+ ExpDec rep ->+ Exp rep ->+ CSEState rep ->+ CSEState rep addExpSubst pat edec e (CSEState (esubsts, nsubsts) cse_arrays) = CSEState (M.insert (edec, e) pat esubsts, nsubsts) cse_arrays -- | The operations that permit CSE. class CSEInOp op where -- | Perform CSE within any nested expressions.- cseInOp :: op -> CSEM lore op+ cseInOp :: op -> CSEM rep op instance CSEInOp () where cseInOp () = return () -subCSE :: CSEM lore r -> CSEM otherlore r+subCSE :: CSEM rep r -> CSEM otherrep r subCSE m = do CSEState _ cse_arrays <- ask return $ runReader m $ newCSEState cse_arrays instance- ( ASTLore lore,- Aliased lore,- CSEInOp (Op lore),+ ( ASTRep rep,+ Aliased rep,+ CSEInOp (Op rep), CSEInOp op ) =>- CSEInOp (Kernel.HostOp lore op)+ CSEInOp (Kernel.HostOp rep op) where cseInOp (Kernel.SegOp op) = Kernel.SegOp <$> cseInOp op cseInOp (Kernel.OtherOp op) = Kernel.OtherOp <$> cseInOp op cseInOp x = return x instance- ( ASTLore lore,- Aliased lore,- CSEInOp (Op lore),+ ( ASTRep rep,+ Aliased rep,+ CSEInOp (Op rep), CSEInOp op ) =>- CSEInOp (MC.MCOp lore op)+ CSEInOp (MC.MCOp rep op) where cseInOp (MC.ParOp par_op op) = MC.ParOp <$> traverse cseInOp par_op <*> cseInOp op@@ -310,8 +310,8 @@ MC.OtherOp <$> cseInOp op instance- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>- CSEInOp (Kernel.SegOp lvl lore)+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) =>+ CSEInOp (Kernel.SegOp lvl rep) where cseInOp = subCSE@@ -319,9 +319,9 @@ (Kernel.SegOpMapper return cseInLambda cseInKernelBody return return) cseInKernelBody ::- (ASTLore lore, Aliased lore, CSEInOp (Op lore)) =>- Kernel.KernelBody lore ->- CSEM lore (Kernel.KernelBody lore)+ (ASTRep rep, Aliased rep, CSEInOp (Op rep)) =>+ Kernel.KernelBody rep ->+ CSEM rep (Kernel.KernelBody rep) cseInKernelBody (Kernel.KernelBody bodydec bnds res) = do Body _ bnds' _ <- cseInBody (map (const Observe) res) $ Body bodydec bnds [] return $ Kernel.KernelBody bodydec bnds' res@@ -331,10 +331,10 @@ cseInOp (Memory.Inner k) = Memory.Inner <$> subCSE (cseInOp k) instance- ( ASTLore lore,- CanBeAliased (Op lore),- CSEInOp (OpWithAliases (Op lore))+ ( ASTRep rep,+ CanBeAliased (Op rep),+ CSEInOp (OpWithAliases (Op rep)) ) =>- CSEInOp (SOAC.SOAC (Aliases lore))+ CSEInOp (SOAC.SOAC (Aliases rep)) where cseInOp = subCSE . SOAC.mapSOACM (SOAC.SOACMapper return cseInLambda return)
src/Futhark/Optimise/DoubleBuffer.hs view
@@ -22,7 +22,7 @@ -- 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.-module Futhark.Optimise.DoubleBuffer (doubleBufferKernels, doubleBufferMC) where+module Futhark.Optimise.DoubleBuffer (doubleBufferGPU, doubleBufferMC) where import Control.Monad.Reader import Control.Monad.State@@ -31,24 +31,24 @@ import qualified Data.Map.Strict as M import Data.Maybe import Futhark.Construct-import Futhark.IR.KernelsMem as Kernels+import Futhark.IR.GPUMem as GPU import Futhark.IR.MCMem as MC import qualified Futhark.IR.Mem.IxFun as IxFun import Futhark.Pass import Futhark.Pass.ExplicitAllocations (arraySizeInBytesExp)-import Futhark.Pass.ExplicitAllocations.Kernels ()+import Futhark.Pass.ExplicitAllocations.GPU () import Futhark.Util (maybeHead) -- | The pass for GPU kernels.-doubleBufferKernels :: Pass KernelsMem KernelsMem-doubleBufferKernels = doubleBuffer optimiseKernelsOp+doubleBufferGPU :: Pass GPUMem GPUMem+doubleBufferGPU = doubleBuffer optimiseGPUOp -- | The pass for multicore doubleBufferMC :: Pass MCMem MCMem doubleBufferMC = doubleBuffer optimiseMCOp -- | The double buffering pass definition.-doubleBuffer :: Mem lore => OptimiseOp lore -> Pass lore lore+doubleBuffer :: Mem rep => OptimiseOp rep -> Pass rep rep doubleBuffer onOp = Pass { passName = "Double buffer",@@ -66,51 +66,51 @@ env = Env mempty doNotTouchLoop onOp doNotTouchLoop ctx val body = return (mempty, ctx, val, body) -type OptimiseLoop lore =- [(FParam lore, SubExp)] ->- [(FParam lore, SubExp)] ->- Body lore ->+type OptimiseLoop rep =+ [(FParam rep, SubExp)] ->+ [(FParam rep, SubExp)] ->+ Body rep -> DoubleBufferM- lore- ( [Stm lore],- [(FParam lore, SubExp)],- [(FParam lore, SubExp)],- Body lore+ rep+ ( [Stm rep],+ [(FParam rep, SubExp)],+ [(FParam rep, SubExp)],+ Body rep ) -type OptimiseOp lore =- Op lore -> DoubleBufferM lore (Op lore)+type OptimiseOp rep =+ Op rep -> DoubleBufferM rep (Op rep) -data Env lore = Env- { envScope :: Scope lore,- envOptimiseLoop :: OptimiseLoop lore,- envOptimiseOp :: OptimiseOp lore+data Env rep = Env+ { envScope :: Scope rep,+ envOptimiseLoop :: OptimiseLoop rep,+ envOptimiseOp :: OptimiseOp rep } -newtype DoubleBufferM lore a = DoubleBufferM- { runDoubleBufferM :: ReaderT (Env lore) (State VNameSource) a+newtype DoubleBufferM rep a = DoubleBufferM+ { runDoubleBufferM :: ReaderT (Env rep) (State VNameSource) a }- deriving (Functor, Applicative, Monad, MonadReader (Env lore), MonadFreshNames)+ deriving (Functor, Applicative, Monad, MonadReader (Env rep), MonadFreshNames) -instance ASTLore lore => HasScope lore (DoubleBufferM lore) where+instance ASTRep rep => HasScope rep (DoubleBufferM rep) where askScope = asks envScope -instance ASTLore lore => LocalScope lore (DoubleBufferM lore) where+instance ASTRep rep => LocalScope rep (DoubleBufferM rep) where localScope scope = local $ \env -> env {envScope = envScope env <> scope} -optimiseBody :: ASTLore lore => Body lore -> DoubleBufferM lore (Body lore)+optimiseBody :: ASTRep rep => Body rep -> DoubleBufferM rep (Body rep) optimiseBody body = do bnds' <- optimiseStms $ stmsToList $ bodyStms body return $ body {bodyStms = stmsFromList bnds'} -optimiseStms :: ASTLore lore => [Stm lore] -> DoubleBufferM lore [Stm lore]+optimiseStms :: ASTRep rep => [Stm rep] -> DoubleBufferM rep [Stm rep] optimiseStms [] = return [] optimiseStms (e : es) = do e_es <- optimiseStm e es' <- localScope (castScope $ scopeOf e_es) $ optimiseStms es return $ e_es ++ es' -optimiseStm :: forall lore. ASTLore lore => Stm lore -> DoubleBufferM lore [Stm lore]+optimiseStm :: forall rep. ASTRep rep => Stm rep -> DoubleBufferM rep [Stm rep] optimiseStm (Let pat aux (DoLoop ctx val form body)) = do body' <- localScope (scopeOf form <> scopeOfFParams (map fst $ ctx ++ val)) $@@ -125,12 +125,12 @@ optimise onOp = identityMapper { mapOnBody = \_ x ->- optimiseBody x :: DoubleBufferM lore (Body lore),+ optimiseBody x :: DoubleBufferM rep (Body rep), mapOnOp = onOp } -optimiseKernelsOp :: OptimiseOp KernelsMem-optimiseKernelsOp (Inner (SegOp op)) =+optimiseGPUOp :: OptimiseOp GPUMem+optimiseGPUOp (Inner (SegOp op)) = local inSegOp $ Inner . SegOp <$> mapSegOpM mapper op where mapper =@@ -139,7 +139,7 @@ mapOnSegOpBody = optimiseKernelBody } inSegOp env = env {envOptimiseLoop = optimiseLoop}-optimiseKernelsOp op = return op+optimiseGPUOp op = return op optimiseMCOp :: OptimiseOp MCMem optimiseMCOp (Inner (ParOp par_op op)) =@@ -156,34 +156,34 @@ optimiseMCOp op = return op optimiseKernelBody ::- ASTLore lore =>- KernelBody lore ->- DoubleBufferM lore (KernelBody lore)+ ASTRep rep =>+ KernelBody rep ->+ DoubleBufferM rep (KernelBody rep) optimiseKernelBody kbody = do stms' <- optimiseStms $ stmsToList $ kernelBodyStms kbody return $ kbody {kernelBodyStms = stmsFromList stms'} optimiseLambda ::- ASTLore lore =>- Lambda lore ->- DoubleBufferM lore (Lambda lore)+ ASTRep rep =>+ Lambda rep ->+ DoubleBufferM rep (Lambda rep) optimiseLambda lam = do body <- localScope (castScope $ scopeOf lam) $ optimiseBody $ lambdaBody lam return lam {lambdaBody = body} -type Constraints lore =- ( ASTLore lore,- FParamInfo lore ~ FParamMem,- LParamInfo lore ~ LParamMem,- RetType lore ~ RetTypeMem,- LetDec lore ~ LetDecMem,- BranchType lore ~ BranchTypeMem,- ExpDec lore ~ (),- BodyDec lore ~ (),- OpReturns lore+type Constraints rep =+ ( ASTRep rep,+ FParamInfo rep ~ FParamMem,+ LParamInfo rep ~ LParamMem,+ RetType rep ~ RetTypeMem,+ LetDec rep ~ LetDecMem,+ BranchType rep ~ BranchTypeMem,+ ExpDec rep ~ (),+ BodyDec rep ~ (),+ OpReturns rep ) -optimiseLoop :: (Constraints lore, Op lore ~ MemOp inner, BinderOps lore) => OptimiseLoop lore+optimiseLoop :: (Constraints rep, Op rep ~ MemOp inner, BinderOps rep) => OptimiseLoop rep optimiseLoop ctx val body = do -- We start out by figuring out which of the merge variables should -- be double-buffered.@@ -273,10 +273,10 @@ _ -> return NoBuffer allocStms ::- (Constraints lore, Op lore ~ MemOp inner, BinderOps lore) =>- [(FParam lore, SubExp)] ->+ (Constraints rep, Op rep ~ MemOp inner, BinderOps rep) =>+ [(FParam rep, SubExp)] -> [DoubleBuffer] ->- DoubleBufferM lore ([(FParam lore, SubExp)], [Stm lore])+ DoubleBufferM rep ([(FParam rep, SubExp)], [Stm rep]) allocStms merge = runWriterT . zipWithM allocation merge where allocation m@(Param pname _, _) (BufferAlloc name size space b) = do@@ -310,11 +310,11 @@ return (f, se) doubleBufferResult ::- (Constraints lore) =>- [FParam lore] ->+ (Constraints rep) =>+ [FParam rep] -> [DoubleBuffer] ->- Body lore ->- Body lore+ Body rep ->+ Body rep doubleBufferResult valparams buffered (Body _ bnds res) = let (ctx_res, val_res) = splitAt (length res - length valparams) res (copybnds, val_res') =
src/Futhark/Optimise/Fusion/Composing.hs view
@@ -44,11 +44,11 @@ -- The result is the fused function, and a list of the array inputs -- expected by the SOAC containing the fused function. fuseMaps ::- Bindable lore =>+ Bindable rep => -- | The producer var names that still need to be returned Names -> -- | Function of SOAC to be fused.- Lambda lore ->+ Lambda rep -> -- | Input of SOAC to be fused. [SOAC.Input] -> -- | Output of SOAC to be fused. The@@ -58,12 +58,12 @@ -- bind a single element of that output. [(VName, Ident)] -> -- | Function to be fused with.- Lambda lore ->+ Lambda rep -> -- | Input of SOAC to be fused with. [SOAC.Input] -> -- | The fused lambda and the inputs of -- the resulting SOAC.- (Lambda lore, [SOAC.Input])+ (Lambda rep, [SOAC.Input]) fuseMaps unfus_nms lam1 inp1 out1 lam2 inp2 = (lam2', M.elems inputmap) where lam2' =@@ -96,19 +96,19 @@ --(unfus_accpat, unfus_arrpat) = splitAt (length unfus_accs) unfus_pat fuseInputs ::- Bindable lore =>+ Bindable rep => Names ->- Lambda lore ->+ Lambda rep -> [SOAC.Input] -> [(VName, Ident)] ->- Lambda lore ->+ Lambda rep -> [SOAC.Input] -> ( [Ident], [Ident], [Ident], M.Map Ident SOAC.Input,- Body lore -> Body lore,- Body lore -> Body lore+ Body rep -> Body rep,+ Body rep -> Body rep ) fuseInputs unfus_nms lam1 inp1 out1 lam2 inp2 = (lam2redparams, unfus_vars, outbnds, inputmap, makeCopies, makeCopiesInner)@@ -172,9 +172,9 @@ _ -> (m, ra) removeDuplicateInputs ::- Bindable lore =>+ Bindable rep => M.Map Ident SOAC.Input ->- (M.Map Ident SOAC.Input, Body lore -> Body lore)+ (M.Map Ident SOAC.Input, Body rep -> Body rep) removeDuplicateInputs = fst . M.foldlWithKey' comb ((M.empty, id), M.empty) where comb ((parmap, inner), arrmap) par arr =@@ -192,19 +192,19 @@ `insertStm` b fuseRedomap ::- Bindable lore =>+ Bindable rep => Names -> [VName] ->- Lambda lore ->+ Lambda rep -> [SubExp] -> [SubExp] -> [SOAC.Input] -> [(VName, Ident)] ->- Lambda lore ->+ Lambda rep -> [SubExp] -> [SubExp] -> [SOAC.Input] ->- (Lambda lore, [SOAC.Input])+ (Lambda rep, [SOAC.Input]) fuseRedomap unfus_nms outVars@@ -282,7 +282,7 @@ } in (res_lam', new_inp) -mergeReduceOps :: Lambda lore -> Lambda lore -> Lambda lore+mergeReduceOps :: Lambda rep -> Lambda rep -> Lambda rep mergeReduceOps (Lambda par1 bdy1 rtp1) (Lambda par2 bdy2 rtp2) = let body' = Body
src/Futhark/Optimise/Fusion/LoopKernel.hs view
@@ -429,7 +429,7 @@ (body_p, body_c) = (lambdaBody lam_p, lambdaBody lam_c) body' = Body- { bodyDec = bodyDec body_p, -- body_p and body_c have the same lores+ { bodyDec = bodyDec body_p, -- body_p and body_c have the same decorations bodyStms = bodyStms body_p <> bodyStms body_c, bodyResult = take c_num_buckets (bodyResult body_c)@@ -461,7 +461,7 @@ let (body_p, body_c) = (lambdaBody lam_p, lambdaBody lam_c) let body' = Body- { bodyDec = bodyDec body_p, -- body_p and body_c have the same lores+ { bodyDec = bodyDec body_p, -- body_p and body_c have the same decorations bodyStms = bodyStms body_p <> bodyStms body_c, bodyResult = zipW as_c (bodyResult body_c) as_p (bodyResult body_p) }@@ -547,7 +547,7 @@ --------------------------------- _ -> fail "Cannot fuse" -getStreamOrder :: StreamForm lore -> StreamOrd+getStreamOrder :: StreamForm rep -> StreamOrd getStreamOrder (Parallel o _ _) = o getStreamOrder Sequential = InOrder
src/Futhark/Optimise/InPlaceLowering.hs view
@@ -62,7 +62,7 @@ -- FIXME: the implementation is not finished yet. Specifically, not -- all of the above conditions are checked. module Futhark.Optimise.InPlaceLowering- ( inPlaceLoweringKernels,+ ( inPlaceLoweringGPU, inPlaceLoweringSeq, inPlaceLoweringMC, )@@ -73,15 +73,15 @@ import Futhark.Analysis.Alias import Futhark.Binder import Futhark.IR.Aliases-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.IR.MC import Futhark.IR.Seq (Seq) import Futhark.Optimise.InPlaceLowering.LowerIntoStm import Futhark.Pass -- | Apply the in-place lowering optimisation to the given program.-inPlaceLoweringKernels :: Pass Kernels Kernels-inPlaceLoweringKernels = inPlaceLowering onKernelOp lowerUpdateKernels+inPlaceLoweringGPU :: Pass GPU GPU+inPlaceLoweringGPU = inPlaceLowering onKernelOp lowerUpdateGPU -- | Apply the in-place lowering optimisation to the given program. inPlaceLoweringSeq :: Pass Seq Seq@@ -93,10 +93,10 @@ -- | Apply the in-place lowering optimisation to the given program. inPlaceLowering ::- Constraints lore =>- OnOp lore ->- LowerUpdate lore (ForwardingM lore) ->- Pass lore lore+ Constraints rep =>+ OnOp rep ->+ LowerUpdate rep (ForwardingM rep) ->+ Pass rep rep inPlaceLowering onOp lower = Pass "In-place lowering" "Lower in-place updates into loops" $ fmap removeProgAliases@@ -119,12 +119,12 @@ descend [] m = m descend (stm : stms) m = bindingStm stm $ descend stms m -type Constraints lore = (Bindable lore, CanBeAliased (Op lore))+type Constraints rep = (Bindable rep, CanBeAliased (Op rep)) optimiseBody ::- Constraints lore =>- Body (Aliases lore) ->- ForwardingM lore (Body (Aliases lore))+ Constraints rep =>+ Body (Aliases rep) ->+ ForwardingM rep (Body (Aliases rep)) optimiseBody (Body als bnds res) = do bnds' <- deepen $@@ -136,10 +136,10 @@ seen (Var v) = seenVar v optimiseStms ::- Constraints lore =>- [Stm (Aliases lore)] ->- ForwardingM lore () ->- ForwardingM lore [Stm (Aliases lore)]+ Constraints rep =>+ [Stm (Aliases rep)] ->+ ForwardingM rep () ->+ ForwardingM rep [Stm (Aliases rep)] optimiseStms [] m = m >> return [] optimiseStms (bnd : bnds) m = do (bnds', bup) <- tapBottomUp $ bindingStm bnd $ optimiseStms bnds m@@ -179,11 +179,11 @@ maybeForward ve v dec cs src slice checkIfForwardableUpdate _ = return () -optimiseInStm :: Constraints lore => Stm (Aliases lore) -> ForwardingM lore (Stm (Aliases lore))+optimiseInStm :: Constraints rep => Stm (Aliases rep) -> ForwardingM rep (Stm (Aliases rep)) optimiseInStm (Let pat dec e) = Let pat dec <$> optimiseExp e -optimiseExp :: Constraints lore => Exp (Aliases lore) -> ForwardingM lore (Exp (Aliases lore))+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) $@@ -199,9 +199,9 @@ } onSegOp ::- (Bindable lore, CanBeAliased (Op lore)) =>- SegOp lvl (Aliases lore) ->- ForwardingM lore (SegOp lvl (Aliases lore))+ (Bindable rep, CanBeAliased (Op rep)) =>+ SegOp lvl (Aliases rep) ->+ ForwardingM rep (SegOp lvl (Aliases rep)) onSegOp op = bindingScope (scopeOfSegSpace (segSpace op)) $ do let mapper = identitySegOpMapper {mapOnSegOpBody = onKernelBody}@@ -217,63 +217,63 @@ onMCOp (ParOp par_op op) = ParOp <$> traverse onSegOp par_op <*> onSegOp op onMCOp op = return op -onKernelOp :: OnOp Kernels+onKernelOp :: OnOp GPU onKernelOp (SegOp op) = SegOp <$> onSegOp op onKernelOp op = return op -data Entry lore = Entry+data Entry rep = Entry { entryNumber :: Int, entryAliases :: Names, entryDepth :: Int, entryOptimisable :: Bool,- entryType :: NameInfo (Aliases lore)+ entryType :: NameInfo (Aliases rep) } -type VTable lore = M.Map VName (Entry lore)+type VTable rep = M.Map VName (Entry rep) -type OnOp lore = Op (Aliases lore) -> ForwardingM lore (Op (Aliases lore))+type OnOp rep = Op (Aliases rep) -> ForwardingM rep (Op (Aliases rep)) -data TopDown lore = TopDown+data TopDown rep = TopDown { topDownCounter :: Int,- topDownTable :: VTable lore,+ topDownTable :: VTable rep, topDownDepth :: Int,- topLowerUpdate :: LowerUpdate lore (ForwardingM lore),- topOnOp :: OnOp lore+ topLowerUpdate :: LowerUpdate rep (ForwardingM rep),+ topOnOp :: OnOp rep } -data BottomUp lore = BottomUp+data BottomUp rep = BottomUp { bottomUpSeen :: Names,- forwardThese :: [DesiredUpdate (LetDec (Aliases lore))]+ forwardThese :: [DesiredUpdate (LetDec (Aliases rep))] } -instance Semigroup (BottomUp lore) where+instance Semigroup (BottomUp rep) where BottomUp seen1 forward1 <> BottomUp seen2 forward2 = BottomUp (seen1 <> seen2) (forward1 <> forward2) -instance Monoid (BottomUp lore) where+instance Monoid (BottomUp rep) where mempty = BottomUp mempty mempty -newtype ForwardingM lore a = ForwardingM (RWS (TopDown lore) (BottomUp lore) VNameSource a)+newtype ForwardingM rep a = ForwardingM (RWS (TopDown rep) (BottomUp rep) VNameSource a) deriving ( Monad, Applicative, Functor,- MonadReader (TopDown lore),- MonadWriter (BottomUp lore),+ MonadReader (TopDown rep),+ MonadWriter (BottomUp rep), MonadState VNameSource ) -instance MonadFreshNames (ForwardingM lore) where+instance MonadFreshNames (ForwardingM rep) where getNameSource = get putNameSource = put -instance Constraints lore => HasScope (Aliases lore) (ForwardingM lore) where+instance Constraints rep => HasScope (Aliases rep) (ForwardingM rep) where askScope = M.map entryType <$> asks topDownTable runForwardingM ::- LowerUpdate lore (ForwardingM lore) ->- OnOp lore ->- ForwardingM lore a ->+ LowerUpdate rep (ForwardingM rep) ->+ OnOp rep ->+ ForwardingM rep a -> VNameSource -> (a, VNameSource) runForwardingM f g (ForwardingM m) src =@@ -290,10 +290,10 @@ } bindingParams ::- (dec -> NameInfo (Aliases lore)) ->+ (dec -> NameInfo (Aliases rep)) -> [Param dec] ->- ForwardingM lore a ->- ForwardingM lore a+ ForwardingM rep a ->+ ForwardingM rep a bindingParams f params = local $ \(TopDown n vtable d x y) -> let entry fparam = ( paramName fparam,@@ -303,15 +303,15 @@ in TopDown (n + 1) (M.union entries vtable) d x y bindingFParams ::- [FParam (Aliases lore)] ->- ForwardingM lore a ->- ForwardingM lore a+ [FParam (Aliases rep)] ->+ ForwardingM rep a ->+ ForwardingM rep a bindingFParams = bindingParams FParamName bindingScope ::- Scope (Aliases lore) ->- ForwardingM lore a ->- ForwardingM lore a+ Scope (Aliases rep) ->+ ForwardingM rep a ->+ ForwardingM rep a bindingScope scope = local $ \(TopDown n vtable d x y) -> let entries = M.map entry scope infoAliases (LetName (aliases, _)) = unAliases aliases@@ -320,9 +320,9 @@ in TopDown (n + 1) (entries <> vtable) d x y bindingStm ::- Stm (Aliases lore) ->- ForwardingM lore a ->- ForwardingM lore a+ Stm (Aliases rep) ->+ ForwardingM rep a ->+ ForwardingM rep a bindingStm (Let pat _ _) = local $ \(TopDown n vtable d x y) -> let entries = M.fromList $ map entry $ patternElements pat entry patElem =@@ -332,7 +332,7 @@ ) in TopDown (n + 1) (M.union entries vtable) d x y -bindingNumber :: VName -> ForwardingM lore Int+bindingNumber :: VName -> ForwardingM rep Int bindingNumber name = do res <- asks $ fmap entryNumber . M.lookup name . topDownTable case res of@@ -343,16 +343,16 @@ ++ pretty name ++ " not found." -deepen :: ForwardingM lore a -> ForwardingM lore a+deepen :: ForwardingM rep a -> ForwardingM rep a deepen = local $ \env -> env {topDownDepth = topDownDepth env + 1} -areAvailableBefore :: Names -> VName -> ForwardingM lore Bool+areAvailableBefore :: Names -> VName -> ForwardingM rep Bool areAvailableBefore names point = do pointN <- bindingNumber point nameNs <- mapM bindingNumber $ namesToList names return $ all (< pointN) nameNs -isInCurrentBody :: VName -> ForwardingM lore Bool+isInCurrentBody :: VName -> ForwardingM rep Bool isInCurrentBody name = do current <- asks topDownDepth res <- asks $ fmap entryDepth . M.lookup name . topDownTable@@ -364,7 +364,7 @@ ++ pretty name ++ " not found." -isOptimisable :: VName -> ForwardingM lore Bool+isOptimisable :: VName -> ForwardingM rep Bool isOptimisable name = do res <- asks $ fmap entryOptimisable . M.lookup name . topDownTable case res of@@ -375,7 +375,7 @@ ++ pretty name ++ " not found." -seenVar :: VName -> ForwardingM lore ()+seenVar :: VName -> ForwardingM rep () seenVar name = do aliases <- asks $@@ -384,20 +384,20 @@ . topDownTable tell $ mempty {bottomUpSeen = oneName name <> aliases} -tapBottomUp :: ForwardingM lore a -> ForwardingM lore (a, BottomUp lore)+tapBottomUp :: ForwardingM rep a -> ForwardingM rep (a, BottomUp rep) tapBottomUp m = do (x, bup) <- listen m return (x, bup) maybeForward ::- Constraints lore =>+ Constraints rep => VName -> VName ->- LetDec (Aliases lore) ->+ LetDec (Aliases rep) -> Certificates -> VName -> Slice SubExp ->- ForwardingM lore ()+ ForwardingM rep () maybeForward v dest_nm dest_dec cs src slice = do -- Checks condition (2) available <-
src/Futhark/Optimise/InPlaceLowering/LowerIntoStm.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE TypeFamilies #-} module Futhark.Optimise.InPlaceLowering.LowerIntoStm- ( lowerUpdateKernels,+ ( lowerUpdateGPU, lowerUpdate, LowerUpdate, DesiredUpdate (..),@@ -17,7 +17,7 @@ import Futhark.Analysis.PrimExp.Convert import Futhark.Construct import Futhark.IR.Aliases-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.Optimise.InPlaceLowering.SubstituteIndices data DesiredUpdate dec = DesiredUpdate@@ -38,19 +38,19 @@ updateHasValue :: VName -> DesiredUpdate dec -> Bool updateHasValue name = (name ==) . updateValue -type LowerUpdate lore m =- Scope (Aliases lore) ->- Stm (Aliases lore) ->- [DesiredUpdate (LetDec (Aliases lore))] ->- Maybe (m [Stm (Aliases lore)])+type LowerUpdate rep m =+ Scope (Aliases rep) ->+ Stm (Aliases rep) ->+ [DesiredUpdate (LetDec (Aliases rep))] ->+ Maybe (m [Stm (Aliases rep)]) lowerUpdate :: ( MonadFreshNames m,- Bindable lore,- LetDec lore ~ Type,- CanBeAliased (Op lore)+ Bindable rep,+ LetDec rep ~ Type,+ CanBeAliased (Op rep) ) =>- LowerUpdate lore m+ LowerUpdate rep m lowerUpdate scope (Let pat aux (DoLoop ctx val form body)) updates = do canDo <- lowerUpdateIntoLoop scope updates pat ctx val form body Just $ do@@ -76,8 +76,8 @@ lowerUpdate _ _ _ = Nothing -lowerUpdateKernels :: MonadFreshNames m => LowerUpdate Kernels m-lowerUpdateKernels+lowerUpdateGPU :: MonadFreshNames m => LowerUpdate GPU m+lowerUpdateGPU scope (Let pat aux (Op (SegOp (SegMap lvl space ts kbody)))) updates@@ -99,20 +99,20 @@ source_used_in_kbody = mconcat (map (`lookupAliases` scope) (namesToList (freeIn kbody))) `namesIntersect` mconcat (map ((`lookupAliases` scope) . updateSource) updates)-lowerUpdateKernels scope stm updates = lowerUpdate scope stm updates+lowerUpdateGPU scope stm updates = lowerUpdate scope stm updates lowerUpdatesIntoSegMap :: MonadFreshNames m =>- Scope (Aliases Kernels) ->- Pattern (Aliases Kernels) ->- [DesiredUpdate (LetDec (Aliases Kernels))] ->+ Scope (Aliases GPU) ->+ Pattern (Aliases GPU) ->+ [DesiredUpdate (LetDec (Aliases GPU))] -> SegSpace ->- KernelBody (Aliases Kernels) ->+ KernelBody (Aliases GPU) -> Maybe ( m- ( Pattern (Aliases Kernels),- KernelBody (Aliases Kernels),- Stms (Aliases Kernels)+ ( Pattern (Aliases GPU),+ KernelBody (Aliases GPU),+ Stms (Aliases GPU) ) ) lowerUpdatesIntoSegMap scope pat updates kspace kbody = do@@ -167,28 +167,28 @@ Just $ return (pe, mempty, ret, mempty) lowerUpdateIntoLoop ::- ( Bindable lore,- BinderOps lore,- Aliased lore,- LetDec lore ~ (als, Type),+ ( Bindable rep,+ BinderOps rep,+ Aliased rep,+ LetDec rep ~ (als, Type), MonadFreshNames m ) =>- Scope lore ->- [DesiredUpdate (LetDec lore)] ->- Pattern lore ->- [(FParam lore, SubExp)] ->- [(FParam lore, SubExp)] ->- LoopForm lore ->- Body lore ->+ Scope rep ->+ [DesiredUpdate (LetDec rep)] ->+ Pattern rep ->+ [(FParam rep, SubExp)] ->+ [(FParam rep, SubExp)] ->+ LoopForm rep ->+ Body rep -> Maybe ( m- ( [Stm lore],- [Stm lore],+ ( [Stm rep],+ [Stm rep], [Ident], [Ident],- [(FParam lore, SubExp)],- [(FParam lore, SubExp)],- Body lore+ [(FParam rep, SubExp)],+ [(FParam rep, SubExp)],+ Body rep ) ) lowerUpdateIntoLoop scope updates pat ctx val form body = do@@ -239,9 +239,9 @@ resmap = zip (bodyResult body) $ patternValueIdents pat mkMerges ::- (MonadFreshNames m, Bindable lore) =>+ (MonadFreshNames m, Bindable rep) => [LoopResultSummary (als, Type)] ->- m ([(Param DeclType, SubExp)], [Stm lore], [Stm lore])+ m ([(Param DeclType, SubExp)], [Stm rep], [Stm rep]) mkMerges summaries = do ((origmerge, extramerge), (prebnds, postbnds)) <- runWriterT $ partitionEithers <$> mapM mkMerge summaries@@ -292,10 +292,10 @@ Left (inPatternAs summary) summariseLoop ::- ( Aliased lore,+ ( Aliased rep, MonadFreshNames m ) =>- Scope lore ->+ Scope rep -> [DesiredUpdate (als, Type)] -> Names -> [(SubExp, Ident)] ->@@ -354,10 +354,10 @@ return (name, (cs, nm, dec, is)) manipulateResult ::- (Bindable lore, MonadFreshNames m) =>- [LoopResultSummary (LetDec lore)] ->- IndexSubstitutions (LetDec lore) ->- m (Result, Stms lore)+ (Bindable 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
src/Futhark/Optimise/InPlaceLowering/SubstituteIndices.hs view
@@ -25,9 +25,9 @@ type IndexSubstitutions dec = [(VName, IndexSubstitution dec)] typeEnvFromSubstitutions ::- LetDec lore ~ dec =>+ LetDec rep ~ dec => IndexSubstitutions dec ->- Scope lore+ Scope rep typeEnvFromSubstitutions = M.fromList . map (fromSubstitution . snd) where fromSubstitution (_, name, t, _) =@@ -36,42 +36,42 @@ -- | Perform the substitution. substituteIndices :: ( MonadFreshNames m,- BinderOps lore,- Bindable lore,- Aliased lore,- LetDec lore ~ dec+ BinderOps rep,+ Bindable rep,+ Aliased rep,+ LetDec rep ~ dec ) => IndexSubstitutions dec ->- Stms lore ->- m (IndexSubstitutions dec, Stms lore)+ Stms rep ->+ m (IndexSubstitutions dec, Stms rep) substituteIndices substs bnds = runBinderT (substituteIndicesInStms substs bnds) types where types = typeEnvFromSubstitutions substs substituteIndicesInStms ::- (MonadBinder m, Bindable (Lore m), Aliased (Lore m)) =>- IndexSubstitutions (LetDec (Lore m)) ->- Stms (Lore m) ->- m (IndexSubstitutions (LetDec (Lore m)))+ (MonadBinder m, Bindable (Rep m), Aliased (Rep m)) =>+ IndexSubstitutions (LetDec (Rep m)) ->+ Stms (Rep m) ->+ m (IndexSubstitutions (LetDec (Rep m))) substituteIndicesInStms = foldM substituteIndicesInStm substituteIndicesInStm ::- (MonadBinder m, Bindable (Lore m), Aliased (Lore m)) =>- IndexSubstitutions (LetDec (Lore m)) ->- Stm (Lore m) ->- m (IndexSubstitutions (LetDec (Lore m)))-substituteIndicesInStm substs (Let pat lore e) = do+ (MonadBinder m, Bindable (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- addStm $ Let pat' lore e'+ addStm $ Let pat' rep e' return substs' substituteIndicesInPattern ::- (MonadBinder m, LetDec (Lore m) ~ dec) =>- IndexSubstitutions (LetDec (Lore m)) ->+ (MonadBinder m, LetDec (Rep m) ~ dec) =>+ IndexSubstitutions (LetDec (Rep m)) -> PatternT dec ->- m (IndexSubstitutions (LetDec (Lore 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@@ -81,13 +81,13 @@ substituteIndicesInExp :: ( MonadBinder m,- Bindable (Lore m),- Aliased (Lore m),- LetDec (Lore m) ~ dec+ Bindable (Rep m),+ Aliased (Rep m),+ LetDec (Rep m) ~ dec ) =>- IndexSubstitutions (LetDec (Lore m)) ->- Exp (Lore m) ->- m (Exp (Lore m))+ IndexSubstitutions (LetDec (Rep m)) ->+ Exp (Rep m) ->+ m (Exp (Rep m)) substituteIndicesInExp substs (Op op) = do let used_in_op = filter ((`nameIn` freeIn op) . fst) substs var_substs <- fmap mconcat $@@ -137,7 +137,7 @@ substituteIndicesInSubExp :: MonadBinder m =>- IndexSubstitutions (LetDec (Lore m)) ->+ IndexSubstitutions (LetDec (Rep m)) -> SubExp -> m SubExp substituteIndicesInSubExp substs (Var v) =@@ -147,7 +147,7 @@ substituteIndicesInVar :: MonadBinder m =>- IndexSubstitutions (LetDec (Lore m)) ->+ IndexSubstitutions (LetDec (Rep m)) -> VName -> m VName substituteIndicesInVar substs v@@ -161,10 +161,10 @@ return v substituteIndicesInBody ::- (MonadBinder m, Bindable (Lore m), Aliased (Lore m)) =>- IndexSubstitutions (LetDec (Lore m)) ->- Body (Lore m) ->- m (Body (Lore m))+ (MonadBinder m, Bindable (Rep m), Aliased (Rep m)) =>+ IndexSubstitutions (LetDec (Rep m)) ->+ Body (Rep m) ->+ m (Body (Rep m)) substituteIndicesInBody substs (Body _ stms res) = do (substs', stms') <- inScopeOf stms $
src/Futhark/Optimise/InliningDeadFun.hs view
@@ -26,7 +26,7 @@ simplifyFun, ) import Futhark.Optimise.CSE-import Futhark.Optimise.Simplify.Lore (addScopeWisdom)+import Futhark.Optimise.Simplify.Rep (addScopeWisdom) import Futhark.Pass import Futhark.Transform.CopyPropagate ( copyPropagateInFun,
+ src/Futhark/Optimise/ReuseAllocations.hs view
@@ -0,0 +1,255 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE TypeFamilies #-}++-- | This module implements an optimization that tries to statically reuse+-- kernel-level allocations. The goal is to lower the static memory usage, which+-- might allow more programs to run using intra-group parallelism.+module Futhark.Optimise.ReuseAllocations (optimise) where++import Control.Exception+import Control.Monad.Reader+import Control.Monad.State.Strict+import Data.Function ((&))+import Data.Map (Map, (!))+import qualified Data.Map as M+import Data.Set (Set)+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.Construct+import Futhark.IR.GPUMem+import qualified Futhark.Optimise.ReuseAllocations.GreedyColoring as GreedyColoring+import Futhark.Pass (Pass (..), PassM)+import qualified Futhark.Pass as Pass+import Futhark.Util (invertMap)++-- | A mapping from allocation names to their size and space.+type Allocs = Map VName (SubExp, Space)++getAllocsStm :: Stm GPUMem -> Allocs+getAllocsStm (Let (Pattern [] [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)) =+ foldMap getAllocsStm (bodyStms body)+getAllocsStm _ = mempty++getAllocsSegOp :: SegOp lvl GPUMem -> Allocs+getAllocsSegOp (SegMap _ _ _ body) =+ foldMap getAllocsStm (kernelBodyStms body)+getAllocsSegOp (SegRed _ _ _ _ body) =+ foldMap getAllocsStm (kernelBodyStms body)+getAllocsSegOp (SegScan _ _ _ _ body) =+ foldMap getAllocsStm (kernelBodyStms body)+getAllocsSegOp (SegHist _ _ _ _ body) =+ foldMap getAllocsStm (kernelBodyStms body)++setAllocsStm :: Map VName SubExp -> Stm GPUMem -> Stm GPUMem+setAllocsStm m stm@(Let (Pattern [] [PatElem name _]) _ (Op (Alloc _ _)))+ | Just s <- M.lookup name m =+ stm {stmExp = BasicOp $ SubExp s}+setAllocsStm _ stm@(Let _ _ (Op (Alloc _ _))) = stm+setAllocsStm m stm@(Let _ _ (Op (Inner (SegOp segop)))) =+ stm {stmExp = Op $ Inner $ SegOp $ setAllocsSegOp m segop}+setAllocsStm m stm@(Let _ _ (If cse then_body else_body dec)) =+ stm+ { stmExp =+ If+ cse+ (then_body {bodyStms = setAllocsStm m <$> bodyStms then_body})+ (else_body {bodyStms = setAllocsStm m <$> bodyStms else_body})+ dec+ }+setAllocsStm m stm@(Let _ _ (DoLoop ctx vals form body)) =+ stm+ { stmExp =+ DoLoop+ ctx+ vals+ form+ (body {bodyStms = setAllocsStm m <$> bodyStms body})+ }+setAllocsStm _ stm = stm++setAllocsSegOp ::+ Map VName SubExp ->+ SegOp lvl GPUMem ->+ SegOp lvl GPUMem+setAllocsSegOp m (SegMap lvl sp tps body) =+ SegMap lvl sp tps $+ body {kernelBodyStms = setAllocsStm m <$> kernelBodyStms body}+setAllocsSegOp m (SegRed lvl sp segbinops tps body) =+ SegRed lvl sp segbinops tps $+ body {kernelBodyStms = setAllocsStm m <$> kernelBodyStms body}+setAllocsSegOp m (SegScan lvl sp segbinops tps body) =+ SegScan lvl sp segbinops tps $+ body {kernelBodyStms = setAllocsStm m <$> kernelBodyStms body}+setAllocsSegOp m (SegHist lvl sp segbinops tps body) =+ SegHist lvl sp segbinops tps $+ body {kernelBodyStms = setAllocsStm m <$> kernelBodyStms body}++maxSubExp :: MonadBinder m => Set SubExp -> m SubExp+maxSubExp = helper . S.toList+ where+ helper (s1 : s2 : sexps) = do+ z <- letSubExp "maxSubHelper" $ BasicOp $ BinOp (UMax Int64) s1 s2+ helper (z : sexps)+ helper [s] =+ return s+ helper [] = error "impossible"++definedInExp :: Exp GPUMem -> Set VName+definedInExp (Op (Inner (SegOp segop))) =+ definedInSegOp segop+definedInExp (If _ then_body else_body _) =+ foldMap definedInStm (bodyStms then_body)+ <> foldMap definedInStm (bodyStms else_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+ in definedInExp stmExp <> definedInside++definedInSegOp :: SegOp lvl GPUMem -> Set VName+definedInSegOp (SegMap _ _ _ body) =+ foldMap definedInStm $ kernelBodyStms body+definedInSegOp (SegRed _ _ _ _ body) =+ foldMap definedInStm $ kernelBodyStms body+definedInSegOp (SegScan _ _ _ _ body) =+ foldMap definedInStm $ kernelBodyStms body+definedInSegOp (SegHist _ _ _ _ body) =+ foldMap definedInStm $ kernelBodyStms body++isKernelInvariant :: SegOp lvl GPUMem -> (SubExp, space) -> Bool+isKernelInvariant segop (Var vname, _) =+ not $ vname `S.member` definedInSegOp segop+isKernelInvariant _ _ = True++onKernelBodyStms ::+ MonadBinder m =>+ SegOp lvl GPUMem ->+ (Stms GPUMem -> m (Stms GPUMem)) ->+ m (SegOp lvl GPUMem)+onKernelBodyStms (SegMap lvl space ts body) f = do+ stms <- f $ kernelBodyStms body+ return $ SegMap lvl space ts $ body {kernelBodyStms = stms}+onKernelBodyStms (SegRed lvl space binops ts body) f = do+ stms <- f $ kernelBodyStms body+ return $ SegRed lvl space binops ts $ body {kernelBodyStms = stms}+onKernelBodyStms (SegScan lvl space binops ts body) f = do+ stms <- f $ kernelBodyStms body+ return $ SegScan lvl space binops ts $ body {kernelBodyStms = stms}+onKernelBodyStms (SegHist lvl space binops ts body) f = do+ 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`,+-- replace allocations and references to memory blocks inside with a (hopefully)+-- reduced number of allocations.+optimiseKernel ::+ (MonadBinder m, Rep m ~ GPUMem) =>+ Interference.Graph VName ->+ SegOp lvl GPUMem ->+ m (SegOp lvl GPUMem)+optimiseKernel graph segop0 = do+ segop <- onKernelBodyStms segop0 $ onKernels $ optimiseKernel graph+ let allocs = M.filter (isKernelInvariant segop) $ getAllocsSegOp segop+ (colorspaces, coloring) =+ GreedyColoring.colorGraph+ (fmap snd allocs)+ graph+ (maxes, maxstms) <-+ invertMap coloring+ & M.elems+ & mapM (maxSubExp . S.map (fst . (allocs !)))+ & collectStms+ (colors, stms) <-+ assert (length maxes == M.size colorspaces) maxes+ & zip [0 ..]+ & mapM (\(i, x) -> letSubExp "color" $ Op $ Alloc x $ colorspaces ! i)+ & collectStms+ let segop' = setAllocsSegOp (fmap (colors !!) coloring) segop+ return $ case segop' of+ SegMap lvl sp tps body ->+ SegMap lvl sp tps $+ body {kernelBodyStms = maxstms <> stms <> kernelBodyStms body}+ SegRed lvl sp binops tps body ->+ SegRed lvl sp binops tps $+ body {kernelBodyStms = maxstms <> stms <> kernelBodyStms body}+ SegScan lvl sp binops tps body ->+ SegScan lvl sp binops tps $+ body {kernelBodyStms = maxstms <> stms <> kernelBodyStms body}+ SegHist lvl sp binops tps body ->+ SegHist lvl sp binops tps $+ body {kernelBodyStms = maxstms <> stms <> kernelBodyStms body}++-- | Helper function that modifies kernels found inside some statements.+onKernels ::+ LocalScope GPUMem m =>+ (SegOp SegLevel GPUMem -> m (SegOp SegLevel GPUMem)) ->+ Stms GPUMem ->+ m (Stms GPUMem)+onKernels f =+ mapM helper+ where+ helper stm@Let {stmExp = Op (Inner (SegOp segop))} =+ inScopeOf stm $ do+ exp' <- f segop+ return $ stm {stmExp = Op $ Inner $ SegOp exp'}+ helper stm@Let {stmExp = If c then_body else_body dec} =+ inScopeOf stm $ do+ then_body_stms <- f `onKernels` bodyStms then_body+ else_body_stms <- f `onKernels` bodyStms else_body+ return $+ stm+ { stmExp =+ If+ c+ (then_body {bodyStms = then_body_stms})+ (else_body {bodyStms = else_body_stms})+ dec+ }+ helper stm@Let {stmExp = DoLoop ctx vals form body} =+ inScopeOf stm $ do+ stms <- f `onKernels` bodyStms body+ return $ stm {stmExp = DoLoop ctx vals form (body {bodyStms = stms})}+ helper stm =+ inScopeOf stm $ return stm++-- | Perform the reuse-allocations optimization.+optimise :: Pass GPUMem GPUMem+optimise =+ Pass "reuse allocations" "reuse allocations" $ \prog ->+ let (lumap, _) = LastUse.analyseProg prog+ graph =+ foldMap+ ( \f ->+ runReader+ ( Interference.analyseGPU lumap $+ bodyStms $ funDefBody f+ )+ $ scopeOf f+ )+ $ progFuns prog+ in Pass.intraproceduralTransformation (onStms graph) prog+ where+ onStms ::+ Interference.Graph VName ->+ Scope GPUMem ->+ Stms GPUMem ->+ PassM (Stms GPUMem)+ onStms graph scope stms = do+ let m = localScope scope $ optimiseKernel graph `onKernels` stms+ fmap fst $ modifyNameSource $ runState (runBinderT m mempty)
+ src/Futhark/Optimise/ReuseAllocations/GreedyColoring.hs view
@@ -0,0 +1,61 @@+-- | Provides a greedy graph-coloring algorithm.+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++-- | A map of values to the set "neighbors" in the graph+type Neighbors a = Map a (Set a)++-- | Computes the neighbor map of a graph.+neighbors :: Ord a => Interference.Graph a -> Neighbors a+neighbors =+ S.foldr+ ( \(x, y) acc ->+ acc+ & M.insertWith S.union x (S.singleton y)+ & M.insertWith S.union y (S.singleton x)+ )+ M.empty++firstAvailable :: Eq space => Map Int space -> Set Int -> Int -> space -> (Map Int space, Int)+firstAvailable spaces xs i sp =+ case (i `S.member` xs, spaces !? i) of+ (False, Just sp') | sp' == sp -> (spaces, i)+ (False, Nothing) -> (M.insert i sp spaces, i)+ _ -> firstAvailable spaces xs (i + 1) sp++colorNode ::+ (Ord a, Eq space) =>+ Neighbors a ->+ (a, space) ->+ (Map Int space, Coloring a) ->+ (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)+ (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+-- 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 ->+ Interference.Graph a ->+ (Map Int space, Coloring a)+colorGraph spaces graph =+ let nodes = S.fromList $ M.toList spaces+ nbs = neighbors graph+ in S.foldr (colorNode nbs) mempty nodes
src/Futhark/Optimise/Simplify.hs view
@@ -15,7 +15,7 @@ Engine.bindableSimpleOps, Engine.noExtraHoistBlockers, Engine.neverHoist,- Engine.SimplifiableLore,+ Engine.SimplifiableRep, Engine.HoistBlockers, RuleBook, )@@ -27,7 +27,7 @@ import Futhark.IR import Futhark.MonadFreshNames import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule import Futhark.Pass @@ -35,12 +35,12 @@ -- output, meaningful simplification may not have taken place - the -- order of bindings may simply have been rearranged. simplifyProg ::- Engine.SimplifiableLore lore =>- Engine.SimpleOps lore ->- RuleBook (Engine.Wise lore) ->- Engine.HoistBlockers lore ->- Prog lore ->- PassM (Prog lore)+ Engine.SimplifiableRep rep =>+ Engine.SimpleOps rep ->+ RuleBook (Engine.Wise rep) ->+ Engine.HoistBlockers rep ->+ Prog rep ->+ PassM (Prog rep) simplifyProg simpl rules blockers (Prog consts funs) = do (consts_vtable, consts') <- simplifyConsts@@ -84,13 +84,13 @@ -- | Run a simplification operation to convergence. simplifySomething ::- (MonadFreshNames m, Engine.SimplifiableLore lore) =>- (a -> Engine.SimpleM lore b) ->+ (MonadFreshNames m, Engine.SimplifiableRep rep) =>+ (a -> Engine.SimpleM rep b) -> (b -> a) ->- Engine.SimpleOps lore ->- RuleBook (Wise lore) ->- Engine.HoistBlockers lore ->- ST.SymbolTable (Wise lore) ->+ Engine.SimpleOps rep ->+ RuleBook (Wise rep) ->+ Engine.HoistBlockers rep ->+ ST.SymbolTable (Wise rep) -> a -> m a simplifySomething f g simpl rules blockers vtable x = do@@ -104,26 +104,26 @@ -- order of bindings may simply have been rearranged. Runs in a loop -- until convergence. simplifyFun ::- (MonadFreshNames m, Engine.SimplifiableLore lore) =>- Engine.SimpleOps lore ->- RuleBook (Engine.Wise lore) ->- Engine.HoistBlockers lore ->- ST.SymbolTable (Wise lore) ->- FunDef lore ->- m (FunDef lore)+ (MonadFreshNames m, Engine.SimplifiableRep rep) =>+ Engine.SimpleOps rep ->+ RuleBook (Engine.Wise rep) ->+ Engine.HoistBlockers rep ->+ ST.SymbolTable (Wise rep) ->+ FunDef rep ->+ m (FunDef rep) simplifyFun = simplifySomething Engine.simplifyFun removeFunDefWisdom -- | Simplify just a single t'Lambda'. simplifyLambda :: ( MonadFreshNames m,- HasScope lore m,- Engine.SimplifiableLore lore+ HasScope rep m,+ Engine.SimplifiableRep rep ) =>- Engine.SimpleOps lore ->- RuleBook (Engine.Wise lore) ->- Engine.HoistBlockers lore ->- Lambda lore ->- m (Lambda lore)+ Engine.SimpleOps rep ->+ RuleBook (Engine.Wise rep) ->+ Engine.HoistBlockers rep ->+ Lambda rep ->+ m (Lambda rep) simplifyLambda simpl rules blockers orig_lam = do vtable <- ST.fromScope . addScopeWisdom <$> askScope simplifySomething@@ -137,13 +137,13 @@ -- | Simplify a sequence of 'Stm's. simplifyStms ::- (MonadFreshNames m, Engine.SimplifiableLore lore) =>- Engine.SimpleOps lore ->- RuleBook (Engine.Wise lore) ->- Engine.HoistBlockers lore ->- Scope lore ->- Stms lore ->- m (ST.SymbolTable (Wise lore), Stms lore)+ (MonadFreshNames m, Engine.SimplifiableRep rep) =>+ Engine.SimpleOps rep ->+ RuleBook (Engine.Wise rep) ->+ Engine.HoistBlockers rep ->+ Scope rep ->+ Stms rep ->+ m (ST.SymbolTable (Wise rep), Stms rep) simplifyStms simpl rules blockers scope = simplifySomething f g simpl rules blockers vtable . (mempty,) where@@ -153,10 +153,10 @@ g = second $ fmap removeStmWisdom loopUntilConvergence ::- (MonadFreshNames m, Engine.SimplifiableLore lore) =>- Engine.Env lore ->- Engine.SimpleOps lore ->- (a -> Engine.SimpleM lore b) ->+ (MonadFreshNames m, Engine.SimplifiableRep rep) =>+ Engine.Env rep ->+ Engine.SimpleOps rep ->+ (a -> Engine.SimpleM rep b) -> (b -> a) -> a -> m a
src/Futhark/Optimise/Simplify/Engine.hs view
@@ -48,7 +48,7 @@ localVtable, -- * Building blocks- SimplifiableLore,+ SimplifiableRep, Simplifiable (..), simplifyStms, simplifyFun,@@ -61,7 +61,7 @@ hoistStms, blockIf, enterLoop,- module Futhark.Optimise.Simplify.Lore,+ module Futhark.Optimise.Simplify.Rep, ) where @@ -75,35 +75,35 @@ import Futhark.Construct import Futhark.IR import Futhark.IR.Prop.Aliases-import Futhark.Optimise.Simplify.Lore+import Futhark.Optimise.Simplify.Rep import Futhark.Optimise.Simplify.Rule import Futhark.Util (nubOrd, splitFromEnd) -data HoistBlockers lore = HoistBlockers+data HoistBlockers rep = HoistBlockers { -- | Blocker for hoisting out of parallel loops.- blockHoistPar :: BlockPred (Wise lore),+ blockHoistPar :: BlockPred (Wise rep), -- | Blocker for hoisting out of sequential loops.- blockHoistSeq :: BlockPred (Wise lore),+ blockHoistSeq :: BlockPred (Wise rep), -- | Blocker for hoisting out of branches.- blockHoistBranch :: BlockPred (Wise lore),- isAllocation :: Stm (Wise lore) -> Bool+ blockHoistBranch :: BlockPred (Wise rep),+ isAllocation :: Stm (Wise rep) -> Bool } -noExtraHoistBlockers :: HoistBlockers lore+noExtraHoistBlockers :: HoistBlockers rep noExtraHoistBlockers = HoistBlockers neverBlocks neverBlocks neverBlocks (const False) -neverHoist :: HoistBlockers lore+neverHoist :: HoistBlockers rep neverHoist = HoistBlockers alwaysBlocks alwaysBlocks alwaysBlocks (const False) -data Env lore = Env- { envRules :: RuleBook (Wise lore),- envHoistBlockers :: HoistBlockers lore,- envVtable :: ST.SymbolTable (Wise lore)+data Env rep = Env+ { envRules :: RuleBook (Wise rep),+ envHoistBlockers :: HoistBlockers rep,+ envVtable :: ST.SymbolTable (Wise rep) } -emptyEnv :: RuleBook (Wise lore) -> HoistBlockers lore -> Env lore+emptyEnv :: RuleBook (Wise rep) -> HoistBlockers rep -> Env rep emptyEnv rules blockers = Env { envRules = rules,@@ -111,33 +111,33 @@ envVtable = mempty } -type Protect m = SubExp -> Pattern (Lore m) -> Op (Lore m) -> Maybe (m ())+type Protect m = SubExp -> Pattern (Rep m) -> Op (Rep m) -> Maybe (m ()) -data SimpleOps lore = SimpleOps+data SimpleOps rep = SimpleOps { mkExpDecS ::- ST.SymbolTable (Wise lore) ->- Pattern (Wise lore) ->- Exp (Wise lore) ->- SimpleM lore (ExpDec (Wise lore)),+ ST.SymbolTable (Wise rep) ->+ Pattern (Wise rep) ->+ Exp (Wise rep) ->+ SimpleM rep (ExpDec (Wise rep)), mkBodyS ::- ST.SymbolTable (Wise lore) ->- Stms (Wise lore) ->+ ST.SymbolTable (Wise rep) ->+ Stms (Wise rep) -> Result ->- SimpleM lore (Body (Wise lore)),+ SimpleM rep (Body (Wise rep)), -- | 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 lore)),- opUsageS :: Op (Wise lore) -> UT.UsageTable,- simplifyOpS :: SimplifyOp lore (Op lore)+ protectHoistedOpS :: Protect (Binder (Wise rep)),+ opUsageS :: Op (Wise rep) -> UT.UsageTable,+ simplifyOpS :: SimplifyOp rep (Op rep) } -type SimplifyOp lore op = op -> SimpleM lore (OpWithWisdom op, Stms (Wise lore))+type SimplifyOp rep op = op -> SimpleM rep (OpWithWisdom op, Stms (Wise rep)) bindableSimpleOps ::- (SimplifiableLore lore, Bindable lore) =>- SimplifyOp lore (Op lore) ->- SimpleOps lore+ (SimplifiableRep rep, Bindable rep) =>+ SimplifyOp rep (Op rep) ->+ SimpleOps rep bindableSimpleOps = SimpleOps mkExpDecS' mkBodyS' protectHoistedOpS' (const mempty) where@@ -145,10 +145,10 @@ mkBodyS' _ bnds res = return $ mkBody bnds res protectHoistedOpS' _ _ _ = Nothing -newtype SimpleM lore a+newtype SimpleM rep a = SimpleM ( ReaderT- (SimpleOps lore, Env lore)+ (SimpleOps rep, Env rep) (State (VNameSource, Bool, Certificates)) a )@@ -156,15 +156,15 @@ ( Applicative, Functor, Monad,- MonadReader (SimpleOps lore, Env lore),+ MonadReader (SimpleOps rep, Env rep), MonadState (VNameSource, Bool, Certificates) ) -instance MonadFreshNames (SimpleM lore) where+instance MonadFreshNames (SimpleM rep) where putNameSource src = modify $ \(_, b, c) -> (src, b, c) getNameSource = gets $ \(a, _, _) -> a -instance SimplifiableLore lore => HasScope (Wise lore) (SimpleM lore) where+instance SimplifiableRep rep => HasScope (Wise rep) (SimpleM rep) where askScope = ST.toScope <$> askVtable lookupType name = do vtable <- askVtable@@ -177,37 +177,37 @@ ++ " in symbol table." instance- SimplifiableLore lore =>- LocalScope (Wise lore) (SimpleM lore)+ SimplifiableRep rep =>+ LocalScope (Wise rep) (SimpleM rep) where localScope types = localVtable (<> ST.fromScope types) runSimpleM ::- SimpleM lore a ->- SimpleOps lore ->- Env lore ->+ SimpleM rep a ->+ SimpleOps rep ->+ Env rep -> VNameSource -> ((a, Bool), VNameSource) runSimpleM (SimpleM m) simpl env src = let (x, (src', b, _)) = runState (runReaderT m (simpl, env)) (src, False, mempty) in ((x, b), src') -askEngineEnv :: SimpleM lore (Env lore)+askEngineEnv :: SimpleM rep (Env rep) askEngineEnv = asks snd -asksEngineEnv :: (Env lore -> a) -> SimpleM lore a+asksEngineEnv :: (Env rep -> a) -> SimpleM rep a asksEngineEnv f = f <$> askEngineEnv -askVtable :: SimpleM lore (ST.SymbolTable (Wise lore))+askVtable :: SimpleM rep (ST.SymbolTable (Wise rep)) askVtable = asksEngineEnv envVtable localVtable ::- (ST.SymbolTable (Wise lore) -> ST.SymbolTable (Wise lore)) ->- SimpleM lore a ->- SimpleM lore a+ (ST.SymbolTable (Wise rep) -> ST.SymbolTable (Wise rep)) ->+ SimpleM rep a ->+ SimpleM rep a localVtable f = local $ \(ops, env) -> (ops, env {envVtable = f $ envVtable env}) -collectCerts :: SimpleM lore a -> SimpleM lore (a, Certificates)+collectCerts :: SimpleM rep a -> SimpleM rep (a, Certificates) collectCerts m = do x <- m (a, b, cs) <- get@@ -216,40 +216,40 @@ -- | Mark that we have changed something and it would be a good idea -- to re-run the simplifier.-changed :: SimpleM lore ()+changed :: SimpleM rep () changed = modify $ \(src, _, cs) -> (src, True, cs) -usedCerts :: Certificates -> SimpleM lore ()+usedCerts :: Certificates -> SimpleM rep () usedCerts cs = modify $ \(a, b, c) -> (a, b, cs <> c) -- | Indicate in the symbol table that we have descended into a loop.-enterLoop :: SimpleM lore a -> SimpleM lore a+enterLoop :: SimpleM rep a -> SimpleM rep a enterLoop = localVtable ST.deepen -bindFParams :: SimplifiableLore lore => [FParam (Wise lore)] -> SimpleM lore a -> SimpleM lore a+bindFParams :: SimplifiableRep rep => [FParam (Wise rep)] -> SimpleM rep a -> SimpleM rep a bindFParams params = localVtable $ ST.insertFParams params -bindLParams :: SimplifiableLore lore => [LParam (Wise lore)] -> SimpleM lore a -> SimpleM lore a+bindLParams :: SimplifiableRep rep => [LParam (Wise rep)] -> SimpleM rep a -> SimpleM rep a bindLParams params = localVtable $ \vtable -> foldr ST.insertLParam vtable params bindArrayLParams ::- SimplifiableLore lore =>- [LParam (Wise lore)] ->- SimpleM lore a ->- SimpleM lore a+ SimplifiableRep rep =>+ [LParam (Wise rep)] ->+ SimpleM rep a ->+ SimpleM rep a bindArrayLParams params = localVtable $ \vtable -> foldl' (flip ST.insertLParam) vtable params bindMerge ::- SimplifiableLore lore =>- [(FParam (Wise lore), SubExp, SubExp)] ->- SimpleM lore a ->- SimpleM lore a+ SimplifiableRep rep =>+ [(FParam (Wise rep), SubExp, SubExp)] ->+ SimpleM rep a ->+ SimpleM rep a bindMerge = localVtable . ST.insertLoopMerge -bindLoopVar :: SimplifiableLore lore => VName -> IntType -> SubExp -> SimpleM lore a -> SimpleM lore a+bindLoopVar :: SimplifiableRep rep => VName -> IntType -> SubExp -> SimpleM rep a -> SimpleM rep a bindLoopVar var it bound = localVtable $ ST.insertLoopVar var it bound @@ -258,14 +258,14 @@ -- them. (This means such hoisting is not worth it unless they are in -- turn hoisted out of a loop somewhere.) protectIfHoisted ::- SimplifiableLore lore =>+ SimplifiableRep rep => -- | Branch condition. SubExp -> -- | Which side of the branch are we -- protecting here? Bool ->- SimpleM lore (a, Stms (Wise lore)) ->- SimpleM lore (a, Stms (Wise lore))+ SimpleM rep (a, Stms (Wise rep)) ->+ SimpleM rep (a, Stms (Wise rep)) protectIfHoisted cond side m = do (x, stms) <- m ops <- asks $ protectHoistedOpS . fst@@ -286,12 +286,12 @@ -- loops, but they most be protected by adding a branch on top of -- them. protectLoopHoisted ::- SimplifiableLore lore =>- [(FParam (Wise lore), SubExp)] ->- [(FParam (Wise lore), SubExp)] ->- LoopForm (Wise lore) ->- SimpleM lore (a, Stms (Wise lore)) ->- SimpleM lore (a, Stms (Wise lore))+ 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 (x, stms) <- m ops <- asks $ protectHoistedOpS . fst@@ -317,9 +317,9 @@ protectIf :: MonadBinder m => Protect m ->- (Exp (Lore m) -> Bool) ->+ (Exp (Rep m) -> Bool) -> SubExp ->- Stm (Lore m) ->+ Stm (Rep m) -> m () protectIf _@@ -362,7 +362,7 @@ protectIf _ _ _ stm = addStm stm -makeSafe :: Exp lore -> Maybe (Exp lore)+makeSafe :: Exp rep -> Maybe (Exp rep) makeSafe (BasicOp (BinOp (SDiv t _) x y)) = Just $ BasicOp (BinOp (SDiv t Safe) x y) makeSafe (BasicOp (BinOp (SDivUp t _) x y)) =@@ -382,7 +382,7 @@ makeSafe _ = Nothing -emptyOfType :: MonadBinder m => [VName] -> Type -> m (Exp (Lore m))+emptyOfType :: MonadBinder m => [VName] -> Type -> m (Exp (Rep m)) emptyOfType _ Mem {} = error "emptyOfType: Cannot hoist non-existential memory." emptyOfType _ Acc {} =@@ -399,21 +399,21 @@ -- | Statements that are not worth hoisting out of loops, because they -- are unsafe, and added safety (by 'protectLoopHoisted') may inhibit -- further optimisation..-notWorthHoisting :: ASTLore lore => BlockPred lore+notWorthHoisting :: ASTRep rep => BlockPred rep notWorthHoisting _ _ (Let pat _ e) = not (safeExp e) && any ((> 0) . arrayRank) (patternTypes pat) hoistStms ::- SimplifiableLore lore =>- RuleBook (Wise lore) ->- BlockPred (Wise lore) ->- ST.SymbolTable (Wise lore) ->+ SimplifiableRep rep =>+ RuleBook (Wise rep) ->+ BlockPred (Wise rep) ->+ ST.SymbolTable (Wise rep) -> UT.UsageTable ->- Stms (Wise lore) ->+ Stms (Wise rep) -> SimpleM- lore- ( Stms (Wise lore),- Stms (Wise lore)+ rep+ ( Stms (Wise rep),+ Stms (Wise rep) ) hoistStms rules block vtable uses orig_stms = do (blocked, hoisted) <- simplifyStmsBottomUp vtable uses orig_stms@@ -465,9 +465,9 @@ return (uses'', stms' ++ stms) blockUnhoistedDeps ::- ASTLore lore =>- [Either (Stm lore) (Stm lore)] ->- [Either (Stm lore) (Stm lore)]+ ASTRep rep =>+ [Either (Stm rep) (Stm rep)] ->+ [Either (Stm rep) (Stm rep)] blockUnhoistedDeps = snd . mapAccumL block mempty where block blocked (Left need) =@@ -478,15 +478,15 @@ | otherwise = (blocked, Right need) -provides :: Stm lore -> [VName]+provides :: Stm rep -> [VName] provides = patternNames . stmPattern expandUsage ::- (ASTLore lore, Aliased lore) =>- (Stm lore -> UT.UsageTable) ->- ST.SymbolTable lore ->+ (ASTRep rep, Aliased rep) =>+ (Stm rep -> UT.UsageTable) ->+ ST.SymbolTable rep -> UT.UsageTable ->- Stm lore ->+ Stm rep -> UT.UsageTable expandUsage usageInStm vtable utable stm@(Let pat _ e) = UT.expand (`ST.lookupAliases` vtable) (usageInStm stm <> usageThroughAliases)@@ -504,47 +504,47 @@ uses <- UT.lookup name utable return $ mconcat $ map (`UT.usage` uses) $ namesToList aliases -type BlockPred lore = ST.SymbolTable lore -> UT.UsageTable -> Stm lore -> Bool+type BlockPred rep = ST.SymbolTable rep -> UT.UsageTable -> Stm rep -> Bool -neverBlocks :: BlockPred lore+neverBlocks :: BlockPred rep neverBlocks _ _ _ = False -alwaysBlocks :: BlockPred lore+alwaysBlocks :: BlockPred rep alwaysBlocks _ _ _ = True -isFalse :: Bool -> BlockPred lore+isFalse :: Bool -> BlockPred rep isFalse b _ _ _ = not b -orIf :: BlockPred lore -> BlockPred lore -> BlockPred lore+orIf :: BlockPred rep -> BlockPred rep -> BlockPred rep orIf p1 p2 body vtable need = p1 body vtable need || p2 body vtable need -andAlso :: BlockPred lore -> BlockPred lore -> BlockPred lore+andAlso :: BlockPred rep -> BlockPred rep -> BlockPred rep andAlso p1 p2 body vtable need = p1 body vtable need && p2 body vtable need -isConsumed :: BlockPred lore+isConsumed :: BlockPred rep isConsumed _ utable = any (`UT.isConsumed` utable) . patternNames . stmPattern -isOp :: BlockPred lore+isOp :: BlockPred rep isOp _ _ (Let _ _ Op {}) = True isOp _ _ _ = False constructBody ::- SimplifiableLore lore =>- Stms (Wise lore) ->+ SimplifiableRep rep =>+ Stms (Wise rep) -> Result ->- SimpleM lore (Body (Wise lore))+ SimpleM rep (Body (Wise rep)) constructBody stms res = fmap fst . runBinder . buildBody_ $ do addStms stms pure res -type SimplifiedBody lore a = ((a, UT.UsageTable), Stms (Wise lore))+type SimplifiedBody rep a = ((a, UT.UsageTable), Stms (Wise rep)) blockIf ::- SimplifiableLore lore =>- BlockPred (Wise lore) ->- SimpleM lore (SimplifiedBody lore a) ->- SimpleM lore ((Stms (Wise lore), a), Stms (Wise lore))+ SimplifiableRep rep =>+ BlockPred (Wise rep) ->+ SimpleM rep (SimplifiedBody rep a) ->+ SimpleM rep ((Stms (Wise rep), a), Stms (Wise rep)) blockIf block m = do ((x, usages), stms) <- m vtable <- askVtable@@ -552,10 +552,10 @@ (blocked, hoisted) <- hoistStms rules block vtable usages stms return ((blocked, x), hoisted) -hasFree :: ASTLore lore => Names -> BlockPred lore+hasFree :: ASTRep rep => Names -> BlockPred rep hasFree ks _ _ need = ks `namesIntersect` freeIn need -isNotSafe :: ASTLore lore => BlockPred lore+isNotSafe :: ASTRep rep => BlockPred rep isNotSafe _ _ = not . safeExp . stmExp isInPlaceBound :: BlockPred m@@ -564,13 +564,13 @@ isUpdate (BasicOp Update {}) = True isUpdate _ = False -isNotCheap :: ASTLore lore => BlockPred lore+isNotCheap :: ASTRep rep => BlockPred rep isNotCheap _ _ = not . cheapStm -cheapStm :: ASTLore lore => Stm lore -> Bool+cheapStm :: ASTRep rep => Stm rep -> Bool cheapStm = cheapExp . stmExp -cheapExp :: ASTLore lore => Exp lore -> Bool+cheapExp :: ASTRep rep => Exp rep -> Bool cheapExp (BasicOp BinOp {}) = True cheapExp (BasicOp SubExp {}) = True cheapExp (BasicOp UnOp {}) = True@@ -587,24 +587,24 @@ cheapExp _ = True -- Used to be False, but -- let's try it out. -stmIs :: (Stm lore -> Bool) -> BlockPred lore+stmIs :: (Stm rep -> Bool) -> BlockPred rep stmIs f _ _ = f -loopInvariantStm :: ASTLore lore => ST.SymbolTable lore -> Stm lore -> Bool+loopInvariantStm :: ASTRep rep => ST.SymbolTable rep -> Stm rep -> Bool loopInvariantStm vtable = all (`nameIn` ST.availableAtClosestLoop vtable) . namesToList . freeIn hoistCommon ::- SimplifiableLore lore =>+ SimplifiableRep rep => SubExp -> IfSort ->- SimplifiedBody lore Result ->- SimplifiedBody lore Result ->+ SimplifiedBody rep Result ->+ SimplifiedBody rep Result -> SimpleM- lore- ( Body (Wise lore),- Body (Wise lore),- Stms (Wise lore)+ rep+ ( Body (Wise rep),+ Body (Wise rep),+ Stms (Wise rep) ) hoistCommon cond ifsort ((res1, usages1), stms1) ((res2, usages2), stms2) = do is_alloc_fun <- asksEngineEnv $ isAllocation . envHoistBlockers@@ -663,10 +663,10 @@ -- | Simplify a single body. The @[Diet]@ only covers the value -- elements, because the context cannot be consumed. simplifyBody ::- SimplifiableLore lore =>+ SimplifiableRep rep => [Diet] ->- Body lore ->- SimpleM lore (SimplifiedBody lore Result)+ Body rep ->+ SimpleM rep (SimplifiedBody rep Result) simplifyBody ds (Body _ bnds res) = simplifyStms bnds $ do res' <- simplifyResult ds res@@ -675,10 +675,10 @@ -- | Simplify a single 'Result'. The @[Diet]@ only covers the value -- elements, because the context cannot be consumed. simplifyResult ::- SimplifiableLore lore =>+ SimplifiableRep rep => [Diet] -> Result ->- SimpleM lore (Result, UT.UsageTable)+ 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@@ -712,10 +712,10 @@ checkForVar _ = mempty simplifyStms ::- SimplifiableLore lore =>- Stms lore ->- SimpleM lore (a, Stms (Wise lore)) ->- SimpleM lore (a, Stms (Wise lore))+ SimplifiableRep rep =>+ Stms rep ->+ SimpleM rep (a, Stms (Wise rep)) ->+ SimpleM rep (a, Stms (Wise rep)) simplifyStms stms m = case stmsHead stms of Nothing -> inspectStms mempty m@@ -729,17 +729,17 @@ simplifyStms stms' m inspectStm ::- SimplifiableLore lore =>- Stm (Wise lore) ->- SimpleM lore (a, Stms (Wise lore)) ->- SimpleM lore (a, Stms (Wise lore))+ SimplifiableRep rep =>+ Stm (Wise rep) ->+ SimpleM rep (a, Stms (Wise rep)) ->+ SimpleM rep (a, Stms (Wise rep)) inspectStm = inspectStms . oneStm inspectStms ::- SimplifiableLore lore =>- Stms (Wise lore) ->- SimpleM lore (a, Stms (Wise lore)) ->- SimpleM lore (a, Stms (Wise lore))+ SimplifiableRep rep =>+ Stms (Wise rep) ->+ SimpleM rep (a, Stms (Wise rep)) ->+ SimpleM rep (a, Stms (Wise rep)) inspectStms stms m = case stmsHead stms of Nothing -> m@@ -753,15 +753,15 @@ (x, stms'') <- localVtable (ST.insertStm stm) $ inspectStms stms' m return (x, oneStm stm <> stms'') -simplifyOp :: Op lore -> SimpleM lore (Op (Wise lore), Stms (Wise lore))+simplifyOp :: Op rep -> SimpleM rep (Op (Wise rep), Stms (Wise rep)) simplifyOp op = do f <- asks $ simplifyOpS . fst f op simplifyExp ::- SimplifiableLore lore =>- Exp lore ->- SimpleM lore (Exp (Wise lore), Stms (Wise lore))+ SimplifiableRep rep =>+ Exp rep ->+ SimpleM rep (Exp (Wise rep), Stms (Wise rep)) simplifyExp (If cond tbranch fbranch (IfDec ts ifsort)) = do -- Here, we have to check whether 'cond' puts a bound on some free -- variable, and if so, chomp it. We should also try to do CSE@@ -862,9 +862,9 @@ return (e', mempty) simplifyExpBase ::- SimplifiableLore lore =>- Exp lore ->- SimpleM lore (Exp (Wise lore))+ SimplifiableRep rep =>+ Exp rep ->+ SimpleM rep (Exp (Wise rep)) simplifyExpBase = mapExpM hoist where hoist =@@ -887,21 +887,21 @@ error "Unhandled Op in simplification engine." } -type SimplifiableLore lore =- ( ASTLore lore,- Simplifiable (LetDec lore),- Simplifiable (FParamInfo lore),- Simplifiable (LParamInfo lore),- Simplifiable (RetType lore),- Simplifiable (BranchType lore),- CanBeWise (Op lore),- ST.IndexOp (OpWithWisdom (Op lore)),- BinderOps (Wise lore),- IsOp (Op lore)+type SimplifiableRep rep =+ ( ASTRep rep,+ Simplifiable (LetDec rep),+ Simplifiable (FParamInfo rep),+ Simplifiable (LParamInfo rep),+ Simplifiable (RetType rep),+ Simplifiable (BranchType rep),+ CanBeWise (Op rep),+ ST.IndexOp (OpWithWisdom (Op rep)),+ BinderOps (Wise rep),+ IsOp (Op rep) ) class Simplifiable e where- simplify :: SimplifiableLore lore => e -> SimpleM lore e+ simplify :: SimplifiableRep rep => e -> SimpleM rep e instance (Simplifiable a, Simplifiable b) => Simplifiable (a, b) where simplify (x, y) = (,) <$> simplify x <*> simplify y@@ -940,15 +940,15 @@ return $ Constant v simplifyPattern ::- (SimplifiableLore lore, Simplifiable dec) =>+ (SimplifiableRep rep, Simplifiable dec) => PatternT dec ->- SimpleM lore (PatternT dec)+ SimpleM rep (PatternT dec) simplifyPattern pat = Pattern <$> mapM inspect (patternContextElements pat) <*> mapM inspect (patternValueElements pat) where- inspect (PatElem name lore) = PatElem name <$> simplify lore+ inspect (PatElem name rep) = PatElem name <$> simplify rep instance Simplifiable () where simplify = pure@@ -992,25 +992,25 @@ simplify (DimSlice i n s) = DimSlice <$> simplify i <*> simplify n <*> simplify s simplifyLambda ::- SimplifiableLore lore =>- Lambda lore ->- SimpleM lore (Lambda (Wise lore), Stms (Wise lore))+ SimplifiableRep rep =>+ Lambda rep ->+ SimpleM rep (Lambda (Wise rep), Stms (Wise rep)) simplifyLambda lam = do par_blocker <- asksEngineEnv $ blockHoistPar . envHoistBlockers simplifyLambdaMaybeHoist par_blocker lam simplifyLambdaNoHoisting ::- SimplifiableLore lore =>- Lambda lore ->- SimpleM lore (Lambda (Wise lore))+ SimplifiableRep rep =>+ Lambda rep ->+ SimpleM rep (Lambda (Wise rep)) simplifyLambdaNoHoisting lam = fst <$> simplifyLambdaMaybeHoist (isFalse False) lam simplifyLambdaMaybeHoist ::- SimplifiableLore lore =>- BlockPred (Wise lore) ->- Lambda lore ->- SimpleM lore (Lambda (Wise lore), Stms (Wise lore))+ SimplifiableRep rep =>+ BlockPred (Wise rep) ->+ Lambda rep ->+ SimpleM rep (Lambda (Wise rep), Stms (Wise rep)) simplifyLambdaMaybeHoist blocked lam@(Lambda params body rettype) = do params' <- mapM (traverse simplify) params let paramnames = namesFromList $ boundByLambda lam@@ -1041,15 +1041,15 @@ _ -> return [idd] insertAllStms ::- SimplifiableLore lore =>- SimpleM lore (SimplifiedBody lore Result) ->- SimpleM lore (Body (Wise lore))+ SimplifiableRep rep =>+ SimpleM rep (SimplifiedBody rep Result) ->+ SimpleM rep (Body (Wise rep)) insertAllStms = uncurry constructBody . fst <=< blockIf (isFalse False) simplifyFun ::- SimplifiableLore lore =>- FunDef lore ->- SimpleM lore (FunDef (Wise lore))+ SimplifiableRep rep =>+ FunDef rep ->+ SimpleM rep (FunDef (Wise rep)) simplifyFun (FunDef entry attrs fname rettype params body) = do rettype' <- simplify rettype params' <- mapM (traverse simplify) params
− src/Futhark/Optimise/Simplify/Lore.hs
@@ -1,284 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}---- | Definition of the lore used by the simplification engine.-module Futhark.Optimise.Simplify.Lore- ( Wise,- VarWisdom (..),- ExpWisdom,- removeStmWisdom,- removeLambdaWisdom,- removeFunDefWisdom,- removeExpWisdom,- removePatternWisdom,- removeBodyWisdom,- removeScopeWisdom,- addScopeWisdom,- addWisdomToPattern,- mkWiseBody,- mkWiseLetStm,- mkWiseExpDec,- CanBeWise (..),- )-where--import Control.Category-import Control.Monad.Identity-import Control.Monad.Reader-import qualified Data.Kind-import qualified Data.Map.Strict as M-import Futhark.Analysis.Rephrase-import Futhark.Binder-import Futhark.IR-import Futhark.IR.Aliases- ( AliasDec (..),- ConsumedInExp,- VarAliases,- unAliases,- )-import qualified Futhark.IR.Aliases as Aliases-import Futhark.IR.Prop.Aliases-import Futhark.Transform.Rename-import Futhark.Transform.Substitute-import Futhark.Util.Pretty-import Prelude hiding (id, (.))--data Wise lore---- | The wisdom of the let-bound variable.-newtype VarWisdom = VarWisdom {varWisdomAliases :: VarAliases}- deriving (Eq, Ord, Show)--instance Rename VarWisdom where- rename = substituteRename--instance Substitute VarWisdom where- substituteNames substs (VarWisdom als) =- VarWisdom (substituteNames substs als)--instance FreeIn VarWisdom where- freeIn' (VarWisdom als) = freeIn' als---- | Wisdom about an expression.-data ExpWisdom = ExpWisdom- { _expWisdomConsumed :: ConsumedInExp,- expWisdomFree :: AliasDec- }- deriving (Eq, Ord, Show)--instance FreeIn ExpWisdom where- freeIn' = mempty--instance FreeDec ExpWisdom where- precomputed = const . fvNames . unAliases . expWisdomFree--instance Substitute ExpWisdom where- substituteNames substs (ExpWisdom cons free) =- ExpWisdom- (substituteNames substs cons)- (substituteNames substs free)--instance Rename ExpWisdom where- rename = substituteRename---- | Wisdom about a body.-data BodyWisdom = BodyWisdom- { bodyWisdomAliases :: [VarAliases],- bodyWisdomConsumed :: ConsumedInExp,- bodyWisdomFree :: AliasDec- }- deriving (Eq, Ord, Show)--instance Rename BodyWisdom where- rename = substituteRename--instance Substitute BodyWisdom where- substituteNames substs (BodyWisdom als cons free) =- BodyWisdom- (substituteNames substs als)- (substituteNames substs cons)- (substituteNames substs free)--instance FreeIn BodyWisdom where- freeIn' (BodyWisdom als cons free) =- freeIn' als <> freeIn' cons <> freeIn' free--instance FreeDec BodyWisdom where- precomputed = const . fvNames . unAliases . bodyWisdomFree--instance- ( Decorations lore,- CanBeWise (Op lore)- ) =>- Decorations (Wise lore)- where- type LetDec (Wise lore) = (VarWisdom, LetDec lore)- type ExpDec (Wise lore) = (ExpWisdom, ExpDec lore)- type BodyDec (Wise lore) = (BodyWisdom, BodyDec lore)- type FParamInfo (Wise lore) = FParamInfo lore- type LParamInfo (Wise lore) = LParamInfo lore- type RetType (Wise lore) = RetType lore- type BranchType (Wise lore) = BranchType lore- type Op (Wise lore) = OpWithWisdom (Op lore)--withoutWisdom ::- (HasScope (Wise lore) m, Monad m) =>- ReaderT (Scope lore) m a ->- m a-withoutWisdom m = do- scope <- asksScope removeScopeWisdom- runReaderT m scope--instance (ASTLore lore, CanBeWise (Op lore)) => ASTLore (Wise lore) where- expTypesFromPattern =- withoutWisdom . expTypesFromPattern . removePatternWisdom--instance Pretty VarWisdom where- ppr _ = ppr ()--instance (PrettyLore lore, CanBeWise (Op lore)) => PrettyLore (Wise lore) where- ppExpLore (_, dec) = ppExpLore dec . removeExpWisdom--instance AliasesOf (VarWisdom, dec) where- aliasesOf = unAliases . varWisdomAliases . fst--instance (ASTLore lore, CanBeWise (Op lore)) => Aliased (Wise lore) where- bodyAliases = map unAliases . bodyWisdomAliases . fst . bodyDec- consumedInBody = unAliases . bodyWisdomConsumed . fst . bodyDec--removeWisdom :: CanBeWise (Op lore) => Rephraser Identity (Wise lore) lore-removeWisdom =- Rephraser- { rephraseExpLore = return . snd,- rephraseLetBoundLore = return . snd,- rephraseBodyLore = return . snd,- rephraseFParamLore = return,- rephraseLParamLore = return,- rephraseRetType = return,- rephraseBranchType = return,- rephraseOp = return . removeOpWisdom- }--removeScopeWisdom :: Scope (Wise lore) -> Scope lore-removeScopeWisdom = M.map unAlias- where- unAlias (LetName (_, dec)) = LetName dec- unAlias (FParamName dec) = FParamName dec- unAlias (LParamName dec) = LParamName dec- unAlias (IndexName it) = IndexName it--addScopeWisdom :: Scope lore -> Scope (Wise lore)-addScopeWisdom = M.map alias- where- alias (LetName dec) = LetName (VarWisdom mempty, dec)- alias (FParamName dec) = FParamName dec- alias (LParamName dec) = LParamName dec- alias (IndexName it) = IndexName it--removeFunDefWisdom :: CanBeWise (Op lore) => FunDef (Wise lore) -> FunDef lore-removeFunDefWisdom = runIdentity . rephraseFunDef removeWisdom--removeStmWisdom :: CanBeWise (Op lore) => Stm (Wise lore) -> Stm lore-removeStmWisdom = runIdentity . rephraseStm removeWisdom--removeLambdaWisdom :: CanBeWise (Op lore) => Lambda (Wise lore) -> Lambda lore-removeLambdaWisdom = runIdentity . rephraseLambda removeWisdom--removeBodyWisdom :: CanBeWise (Op lore) => Body (Wise lore) -> Body lore-removeBodyWisdom = runIdentity . rephraseBody removeWisdom--removeExpWisdom :: CanBeWise (Op lore) => Exp (Wise lore) -> Exp lore-removeExpWisdom = runIdentity . rephraseExp removeWisdom--removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a-removePatternWisdom = runIdentity . rephrasePattern (return . snd)--addWisdomToPattern ::- (ASTLore lore, CanBeWise (Op lore)) =>- Pattern lore ->- Exp (Wise lore) ->- Pattern (Wise lore)-addWisdomToPattern pat e =- Pattern (map f ctx) (map f val)- where- (ctx, val) = Aliases.mkPatternAliases pat e- f pe =- let (als, dec) = patElemDec pe- in pe `setPatElemLore` (VarWisdom als, dec)--mkWiseBody ::- (ASTLore lore, CanBeWise (Op lore)) =>- BodyDec lore ->- Stms (Wise lore) ->- Result ->- Body (Wise lore)-mkWiseBody innerlore bnds res =- Body- ( BodyWisdom aliases consumed (AliasDec $ freeIn $ freeInStmsAndRes bnds res),- innerlore- )- bnds- res- where- (aliases, consumed) = Aliases.mkBodyAliases bnds res--mkWiseLetStm ::- (ASTLore lore, CanBeWise (Op lore)) =>- Pattern lore ->- StmAux (ExpDec lore) ->- Exp (Wise lore) ->- Stm (Wise lore)-mkWiseLetStm pat (StmAux cs attrs dec) e =- let pat' = addWisdomToPattern pat e- in Let pat' (StmAux cs attrs $ mkWiseExpDec pat' dec e) e--mkWiseExpDec ::- (ASTLore lore, CanBeWise (Op lore)) =>- Pattern (Wise lore) ->- ExpDec lore ->- Exp (Wise lore) ->- ExpDec (Wise lore)-mkWiseExpDec pat explore e =- ( ExpWisdom- (AliasDec $ consumedInExp e)- (AliasDec $ freeIn pat <> freeIn explore <> freeIn e),- explore- )--instance- ( Bindable lore,- CanBeWise (Op lore)- ) =>- Bindable (Wise lore)- where- mkExpPat ctx val e =- addWisdomToPattern (mkExpPat ctx val $ removeExpWisdom e) e-- mkExpDec pat e =- mkWiseExpDec pat (mkExpDec (removePatternWisdom pat) $ removeExpWisdom e) e-- mkLetNames names e = do- env <- asksScope removeScopeWisdom- flip runReaderT env $ do- Let pat dec _ <- mkLetNames names $ removeExpWisdom e- return $ mkWiseLetStm pat dec e-- mkBody bnds res =- let Body bodylore _ _ = mkBody (fmap removeStmWisdom bnds) res- in mkWiseBody bodylore bnds res--class- ( AliasedOp (OpWithWisdom op),- IsOp (OpWithWisdom op)- ) =>- CanBeWise op- where- type OpWithWisdom op :: Data.Kind.Type- removeOpWisdom :: OpWithWisdom op -> op--instance CanBeWise () where- type OpWithWisdom () = ()- removeOpWisdom () = ()
+ src/Futhark/Optimise/Simplify/Rep.hs view
@@ -0,0 +1,278 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++-- | Representation used by the simplification engine.+module Futhark.Optimise.Simplify.Rep+ ( Wise,+ VarWisdom (..),+ ExpWisdom,+ removeStmWisdom,+ removeLambdaWisdom,+ removeFunDefWisdom,+ removeExpWisdom,+ removePatternWisdom,+ removeBodyWisdom,+ removeScopeWisdom,+ addScopeWisdom,+ addWisdomToPattern,+ mkWiseBody,+ mkWiseLetStm,+ mkWiseExpDec,+ CanBeWise (..),+ )+where++import Control.Category+import Control.Monad.Identity+import Control.Monad.Reader+import qualified Data.Kind+import qualified Data.Map.Strict as M+import Futhark.Analysis.Rephrase+import Futhark.Binder+import Futhark.IR+import Futhark.IR.Aliases+ ( AliasDec (..),+ ConsumedInExp,+ VarAliases,+ unAliases,+ )+import qualified Futhark.IR.Aliases as Aliases+import Futhark.IR.Prop.Aliases+import Futhark.Transform.Rename+import Futhark.Transform.Substitute+import Futhark.Util.Pretty+import Prelude hiding (id, (.))++data Wise rep++-- | The wisdom of the let-bound variable.+newtype VarWisdom = VarWisdom {varWisdomAliases :: VarAliases}+ deriving (Eq, Ord, Show)++instance Rename VarWisdom where+ rename = substituteRename++instance Substitute VarWisdom where+ substituteNames substs (VarWisdom als) =+ VarWisdom (substituteNames substs als)++instance FreeIn VarWisdom where+ freeIn' (VarWisdom als) = freeIn' als++-- | Wisdom about an expression.+data ExpWisdom = ExpWisdom+ { _expWisdomConsumed :: ConsumedInExp,+ expWisdomFree :: AliasDec+ }+ deriving (Eq, Ord, Show)++instance FreeIn ExpWisdom where+ freeIn' = mempty++instance FreeDec ExpWisdom where+ precomputed = const . fvNames . unAliases . expWisdomFree++instance Substitute ExpWisdom where+ substituteNames substs (ExpWisdom cons free) =+ ExpWisdom+ (substituteNames substs cons)+ (substituteNames substs free)++instance Rename ExpWisdom where+ rename = substituteRename++-- | Wisdom about a body.+data BodyWisdom = BodyWisdom+ { bodyWisdomAliases :: [VarAliases],+ bodyWisdomConsumed :: ConsumedInExp,+ bodyWisdomFree :: AliasDec+ }+ deriving (Eq, Ord, Show)++instance Rename BodyWisdom where+ rename = substituteRename++instance Substitute BodyWisdom where+ substituteNames substs (BodyWisdom als cons free) =+ BodyWisdom+ (substituteNames substs als)+ (substituteNames substs cons)+ (substituteNames substs free)++instance FreeIn BodyWisdom where+ freeIn' (BodyWisdom als cons free) =+ freeIn' als <> freeIn' cons <> freeIn' free++instance FreeDec BodyWisdom where+ precomputed = const . fvNames . unAliases . bodyWisdomFree++instance (RepTypes rep, CanBeWise (Op rep)) => RepTypes (Wise rep) where+ type LetDec (Wise rep) = (VarWisdom, LetDec rep)+ type ExpDec (Wise rep) = (ExpWisdom, ExpDec rep)+ type BodyDec (Wise rep) = (BodyWisdom, BodyDec rep)+ type FParamInfo (Wise rep) = FParamInfo rep+ type LParamInfo (Wise rep) = LParamInfo rep+ type RetType (Wise rep) = RetType rep+ type BranchType (Wise rep) = BranchType rep+ type Op (Wise rep) = OpWithWisdom (Op rep)++withoutWisdom ::+ (HasScope (Wise rep) m, Monad m) =>+ ReaderT (Scope rep) m a ->+ m a+withoutWisdom m = do+ scope <- asksScope removeScopeWisdom+ runReaderT m scope++instance (ASTRep rep, CanBeWise (Op rep)) => ASTRep (Wise rep) where+ expTypesFromPattern =+ withoutWisdom . expTypesFromPattern . removePatternWisdom++instance Pretty VarWisdom where+ ppr _ = ppr ()++instance (PrettyRep rep, CanBeWise (Op rep)) => PrettyRep (Wise rep) where+ ppExpDec (_, dec) = ppExpDec dec . removeExpWisdom++instance AliasesOf (VarWisdom, dec) where+ aliasesOf = unAliases . varWisdomAliases . fst++instance (ASTRep rep, CanBeWise (Op rep)) => Aliased (Wise rep) where+ bodyAliases = map unAliases . bodyWisdomAliases . fst . bodyDec+ consumedInBody = unAliases . bodyWisdomConsumed . fst . bodyDec++removeWisdom :: CanBeWise (Op rep) => Rephraser Identity (Wise rep) rep+removeWisdom =+ Rephraser+ { rephraseExpDec = return . snd,+ rephraseLetBoundDec = return . snd,+ rephraseBodyDec = return . snd,+ rephraseFParamDec = return,+ rephraseLParamDec = return,+ rephraseRetType = return,+ rephraseBranchType = return,+ rephraseOp = return . removeOpWisdom+ }++removeScopeWisdom :: Scope (Wise rep) -> Scope rep+removeScopeWisdom = M.map unAlias+ where+ unAlias (LetName (_, dec)) = LetName dec+ unAlias (FParamName dec) = FParamName dec+ unAlias (LParamName dec) = LParamName dec+ unAlias (IndexName it) = IndexName it++addScopeWisdom :: Scope rep -> Scope (Wise rep)+addScopeWisdom = M.map alias+ where+ alias (LetName dec) = LetName (VarWisdom mempty, dec)+ alias (FParamName dec) = FParamName dec+ alias (LParamName dec) = LParamName dec+ alias (IndexName it) = IndexName it++removeFunDefWisdom :: CanBeWise (Op rep) => FunDef (Wise rep) -> FunDef rep+removeFunDefWisdom = runIdentity . rephraseFunDef removeWisdom++removeStmWisdom :: CanBeWise (Op rep) => Stm (Wise rep) -> Stm rep+removeStmWisdom = runIdentity . rephraseStm removeWisdom++removeLambdaWisdom :: CanBeWise (Op rep) => Lambda (Wise rep) -> Lambda rep+removeLambdaWisdom = runIdentity . rephraseLambda removeWisdom++removeBodyWisdom :: CanBeWise (Op rep) => Body (Wise rep) -> Body rep+removeBodyWisdom = runIdentity . rephraseBody removeWisdom++removeExpWisdom :: CanBeWise (Op rep) => Exp (Wise rep) -> Exp rep+removeExpWisdom = runIdentity . rephraseExp removeWisdom++removePatternWisdom :: PatternT (VarWisdom, a) -> PatternT a+removePatternWisdom = runIdentity . rephrasePattern (return . snd)++addWisdomToPattern ::+ (ASTRep rep, CanBeWise (Op rep)) =>+ Pattern rep ->+ Exp (Wise rep) ->+ Pattern (Wise rep)+addWisdomToPattern pat e =+ Pattern (map f ctx) (map f val)+ where+ (ctx, val) = Aliases.mkPatternAliases pat e+ f pe =+ let (als, dec) = patElemDec pe+ in pe `setPatElemDec` (VarWisdom als, dec)++mkWiseBody ::+ (ASTRep rep, CanBeWise (Op rep)) =>+ BodyDec rep ->+ Stms (Wise rep) ->+ Result ->+ Body (Wise rep)+mkWiseBody dec bnds res =+ Body+ ( BodyWisdom aliases consumed (AliasDec $ freeIn $ freeInStmsAndRes bnds res),+ dec+ )+ bnds+ res+ where+ (aliases, consumed) = Aliases.mkBodyAliases bnds res++mkWiseLetStm ::+ (ASTRep rep, CanBeWise (Op rep)) =>+ Pattern rep ->+ StmAux (ExpDec rep) ->+ Exp (Wise rep) ->+ Stm (Wise rep)+mkWiseLetStm pat (StmAux cs attrs dec) e =+ let pat' = addWisdomToPattern pat e+ in Let pat' (StmAux cs attrs $ mkWiseExpDec pat' dec e) e++mkWiseExpDec ::+ (ASTRep rep, CanBeWise (Op rep)) =>+ Pattern (Wise rep) ->+ ExpDec rep ->+ Exp (Wise rep) ->+ ExpDec (Wise rep)+mkWiseExpDec pat expdec e =+ ( ExpWisdom+ (AliasDec $ consumedInExp e)+ (AliasDec $ freeIn pat <> freeIn expdec <> freeIn e),+ expdec+ )++instance+ ( Bindable rep,+ CanBeWise (Op rep)+ ) =>+ Bindable (Wise rep)+ where+ mkExpPat ctx val e =+ addWisdomToPattern (mkExpPat ctx val $ removeExpWisdom e) e++ mkExpDec pat e =+ mkWiseExpDec pat (mkExpDec (removePatternWisdom pat) $ removeExpWisdom e) e++ mkLetNames names e = do+ env <- asksScope removeScopeWisdom+ flip runReaderT env $ do+ Let pat dec _ <- mkLetNames names $ removeExpWisdom e+ return $ mkWiseLetStm pat dec e++ mkBody bnds res =+ let Body bodyrep _ _ = mkBody (fmap removeStmWisdom bnds) res+ in mkWiseBody bodyrep bnds res++class+ ( AliasedOp (OpWithWisdom op),+ IsOp (OpWithWisdom op)+ ) =>+ CanBeWise op+ where+ type OpWithWisdom op :: Data.Kind.Type+ removeOpWisdom :: OpWithWisdom op -> op++instance CanBeWise () where+ type OpWithWisdom () = ()+ removeOpWisdom () = ()
src/Futhark/Optimise/Simplify/Rule.hs view
@@ -62,18 +62,18 @@ import Futhark.IR -- | The monad in which simplification rules are evaluated.-newtype RuleM lore a = RuleM (BinderT lore (StateT VNameSource Maybe) a)+newtype RuleM rep a = RuleM (BinderT rep (StateT VNameSource Maybe) a) deriving ( Functor, Applicative, Monad, MonadFreshNames,- HasScope lore,- LocalScope lore+ HasScope rep,+ LocalScope rep ) -instance (ASTLore lore, BinderOps lore) => MonadBinder (RuleM lore) where- type Lore (RuleM lore) = lore+instance (ASTRep rep, BinderOps rep) => MonadBinder (RuleM rep) where+ type Rep (RuleM rep) = rep mkExpDecM pat e = RuleM $ mkExpDecM pat e mkBodyM bnds res = RuleM $ mkBodyM bnds res mkLetNamesM pat e = RuleM $ mkLetNamesM pat e@@ -84,141 +84,141 @@ -- | Execute a 'RuleM' action. If succesful, returns the result and a -- list of new bindings. simplify ::- Scope lore ->+ Scope rep -> VNameSource ->- Rule lore ->- Maybe (Stms lore, VNameSource)+ Rule rep ->+ Maybe (Stms rep, VNameSource) simplify _ _ Skip = Nothing simplify scope src (Simplify (RuleM m)) = runStateT (runBinderT_ m scope) src -cannotSimplify :: RuleM lore a+cannotSimplify :: RuleM rep a cannotSimplify = RuleM $ lift $ lift Nothing -liftMaybe :: Maybe a -> RuleM lore a+liftMaybe :: Maybe a -> RuleM rep a liftMaybe Nothing = cannotSimplify liftMaybe (Just x) = return x -- | An efficient way of encoding whether a simplification rule should even be attempted.-data Rule lore+data Rule rep = -- | Give it a shot.- Simplify (RuleM lore ())+ Simplify (RuleM rep ()) | -- | Don't bother. Skip -type RuleGeneric lore a = a -> Stm lore -> Rule lore+type RuleGeneric rep a = a -> Stm rep -> Rule rep -type RuleBasicOp lore a =+type RuleBasicOp rep a = ( a ->- Pattern lore ->- StmAux (ExpDec lore) ->+ Pattern rep ->+ StmAux (ExpDec rep) -> BasicOp ->- Rule lore+ Rule rep ) -type RuleIf lore a =+type RuleIf rep a = a ->- Pattern lore ->- StmAux (ExpDec lore) ->+ Pattern rep ->+ StmAux (ExpDec rep) -> ( SubExp,- BodyT lore,- BodyT lore,- IfDec (BranchType lore)+ BodyT rep,+ BodyT rep,+ IfDec (BranchType rep) ) ->- Rule lore+ Rule rep -type RuleDoLoop lore a =+type RuleDoLoop rep a = a ->- Pattern lore ->- StmAux (ExpDec lore) ->- ( [(FParam lore, SubExp)],- [(FParam lore, SubExp)],- LoopForm lore,- BodyT lore+ Pattern rep ->+ StmAux (ExpDec rep) ->+ ( [(FParam rep, SubExp)],+ [(FParam rep, SubExp)],+ LoopForm rep,+ BodyT rep ) ->- Rule lore+ Rule rep -type RuleOp lore a =+type RuleOp rep a = a ->- Pattern lore ->- StmAux (ExpDec lore) ->- Op lore ->- Rule lore+ Pattern rep ->+ StmAux (ExpDec rep) ->+ Op rep ->+ Rule rep -- | A simplification rule takes some argument and a statement, and -- tries to simplify the statement.-data SimplificationRule lore a- = RuleGeneric (RuleGeneric lore a)- | RuleBasicOp (RuleBasicOp lore a)- | RuleIf (RuleIf lore a)- | RuleDoLoop (RuleDoLoop lore a)- | RuleOp (RuleOp lore a)+data SimplificationRule rep a+ = RuleGeneric (RuleGeneric rep a)+ | RuleBasicOp (RuleBasicOp rep a)+ | RuleIf (RuleIf rep a)+ | RuleDoLoop (RuleDoLoop rep a)+ | RuleOp (RuleOp rep a) -- | A collection of rules grouped by which forms of statements they -- may apply to.-data Rules lore a = Rules- { rulesAny :: [SimplificationRule lore a],- rulesBasicOp :: [SimplificationRule lore a],- rulesIf :: [SimplificationRule lore a],- rulesDoLoop :: [SimplificationRule lore a],- rulesOp :: [SimplificationRule lore a]+data Rules rep a = Rules+ { rulesAny :: [SimplificationRule rep a],+ rulesBasicOp :: [SimplificationRule rep a],+ rulesIf :: [SimplificationRule rep a],+ rulesDoLoop :: [SimplificationRule rep a],+ rulesOp :: [SimplificationRule rep a] } -instance Semigroup (Rules lore a) where+instance Semigroup (Rules rep a) where Rules as1 bs1 cs1 ds1 es1 <> Rules as2 bs2 cs2 ds2 es2 = Rules (as1 <> as2) (bs1 <> bs2) (cs1 <> cs2) (ds1 <> ds2) (es1 <> es2) -instance Monoid (Rules lore a) where+instance Monoid (Rules rep a) where mempty = Rules mempty mempty mempty mempty mempty -- | Context for a rule applied during top-down traversal of the -- program. Takes a symbol table as argument.-type TopDown lore = ST.SymbolTable lore+type TopDown rep = ST.SymbolTable rep -type TopDownRuleGeneric lore = RuleGeneric lore (TopDown lore)+type TopDownRuleGeneric rep = RuleGeneric rep (TopDown rep) -type TopDownRuleBasicOp lore = RuleBasicOp lore (TopDown lore)+type TopDownRuleBasicOp rep = RuleBasicOp rep (TopDown rep) -type TopDownRuleIf lore = RuleIf lore (TopDown lore)+type TopDownRuleIf rep = RuleIf rep (TopDown rep) -type TopDownRuleDoLoop lore = RuleDoLoop lore (TopDown lore)+type TopDownRuleDoLoop rep = RuleDoLoop rep (TopDown rep) -type TopDownRuleOp lore = RuleOp lore (TopDown lore)+type TopDownRuleOp rep = RuleOp rep (TopDown rep) -type TopDownRule lore = SimplificationRule lore (TopDown lore)+type TopDownRule rep = SimplificationRule rep (TopDown rep) -- | Context for a rule applied during bottom-up traversal of the -- program. Takes a symbol table and usage table as arguments.-type BottomUp lore = (ST.SymbolTable lore, UT.UsageTable)+type BottomUp rep = (ST.SymbolTable rep, UT.UsageTable) -type BottomUpRuleGeneric lore = RuleGeneric lore (BottomUp lore)+type BottomUpRuleGeneric rep = RuleGeneric rep (BottomUp rep) -type BottomUpRuleBasicOp lore = RuleBasicOp lore (BottomUp lore)+type BottomUpRuleBasicOp rep = RuleBasicOp rep (BottomUp rep) -type BottomUpRuleIf lore = RuleIf lore (BottomUp lore)+type BottomUpRuleIf rep = RuleIf rep (BottomUp rep) -type BottomUpRuleDoLoop lore = RuleDoLoop lore (BottomUp lore)+type BottomUpRuleDoLoop rep = RuleDoLoop rep (BottomUp rep) -type BottomUpRuleOp lore = RuleOp lore (BottomUp lore)+type BottomUpRuleOp rep = RuleOp rep (BottomUp rep) -type BottomUpRule lore = SimplificationRule lore (BottomUp lore)+type BottomUpRule rep = SimplificationRule rep (BottomUp rep) -- | A collection of top-down rules.-type TopDownRules lore = Rules lore (TopDown lore)+type TopDownRules rep = Rules rep (TopDown rep) -- | A collection of bottom-up rules.-type BottomUpRules lore = Rules lore (BottomUp lore)+type BottomUpRules rep = Rules rep (BottomUp rep) -- | A collection of both top-down and bottom-up rules.-data RuleBook lore = RuleBook- { bookTopDownRules :: TopDownRules lore,- bookBottomUpRules :: BottomUpRules lore+data RuleBook rep = RuleBook+ { bookTopDownRules :: TopDownRules rep,+ bookBottomUpRules :: BottomUpRules rep } -instance Semigroup (RuleBook lore) where+instance Semigroup (RuleBook rep) where RuleBook ts1 bs1 <> RuleBook ts2 bs2 = RuleBook (ts1 <> ts2) (bs1 <> bs2) -instance Monoid (RuleBook lore) where+instance Monoid (RuleBook rep) where mempty = RuleBook mempty mempty -- | Construct a rule book from a collection of rules.@@ -259,11 +259,11 @@ -- of bindings is returned, that bind at least the same names as the -- original binding (and possibly more, for intermediate results). topDownSimplifyStm ::- (MonadFreshNames m, HasScope lore m) =>- RuleBook lore ->- ST.SymbolTable lore ->- Stm lore ->- m (Maybe (Stms lore))+ (MonadFreshNames m, HasScope rep m) =>+ RuleBook rep ->+ ST.SymbolTable rep ->+ Stm rep ->+ m (Maybe (Stms rep)) topDownSimplifyStm = applyRules . bookTopDownRules -- | @simplifyStm uses bnd@ performs simplification of the binding@@ -272,14 +272,14 @@ -- original binding (and possibly more, for intermediate results). -- The first argument is the set of names used after this binding. bottomUpSimplifyStm ::- (MonadFreshNames m, HasScope lore m) =>- RuleBook lore ->- (ST.SymbolTable lore, UT.UsageTable) ->- Stm lore ->- m (Maybe (Stms lore))+ (MonadFreshNames m, HasScope rep m) =>+ RuleBook rep ->+ (ST.SymbolTable rep, UT.UsageTable) ->+ Stm rep ->+ m (Maybe (Stms rep)) bottomUpSimplifyStm = applyRules . bookBottomUpRules -rulesForStm :: Stm lore -> Rules lore a -> [SimplificationRule lore a]+rulesForStm :: Stm rep -> Rules rep a -> [SimplificationRule rep a] rulesForStm stm = case stmExp stm of BasicOp {} -> rulesBasicOp DoLoop {} -> rulesDoLoop@@ -287,7 +287,7 @@ If {} -> rulesIf _ -> rulesAny -applyRule :: SimplificationRule lore a -> a -> Stm lore -> Rule lore+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)) =@@ -300,11 +300,11 @@ Skip applyRules ::- (MonadFreshNames m, HasScope lore m) =>- Rules lore a ->+ (MonadFreshNames m, HasScope rep m) =>+ Rules rep a -> a ->- Stm lore ->- m (Maybe (Stms lore))+ Stm rep ->+ m (Maybe (Stms rep)) applyRules all_rules context stm = do scope <- askScope
src/Futhark/Optimise/Simplify/Rules.hs view
@@ -37,7 +37,7 @@ import Futhark.Optimise.Simplify.Rules.Loop import Futhark.Util -topDownRules :: BinderOps lore => [TopDownRule lore]+topDownRules :: BinderOps rep => [TopDownRule rep] topDownRules = [ RuleGeneric constantFoldPrimFun, RuleIf ruleIf,@@ -45,7 +45,7 @@ RuleGeneric withAccTopDown ] -bottomUpRules :: BinderOps lore => [BottomUpRule lore]+bottomUpRules :: BinderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleIf removeDeadBranchResult, RuleGeneric withAccBottomUp,@@ -55,14 +55,14 @@ -- | A set of standard simplification rules. These assume pure -- functional semantics, and so probably should not be applied after -- memory block merging.-standardRules :: (BinderOps lore, Aliased lore) => RuleBook lore+standardRules :: (BinderOps 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 lore, Aliased lore) => BottomUpRuleBasicOp lore+removeUnnecessaryCopy :: (BinderOps rep, Aliased rep) => BottomUpRuleBasicOp rep removeUnnecessaryCopy (vtable, used) (Pattern [] [d]) _ (Copy v) | not (v `UT.isConsumed` used), (not (v `UT.used` used) && consumable) || not (patElemName d `UT.isConsumed` used) =@@ -84,7 +84,7 @@ pure True removeUnnecessaryCopy _ _ _ _ = Skip -constantFoldPrimFun :: BinderOps lore => TopDownRuleGeneric lore+constantFoldPrimFun :: BinderOps 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,7 +98,7 @@ isConst _ = Nothing constantFoldPrimFun _ _ = Skip -simplifyIndex :: BinderOps lore => BottomUpRuleBasicOp lore+simplifyIndex :: BinderOps rep => BottomUpRuleBasicOp rep simplifyIndex (vtable, used) pat@(Pattern [] [pe]) (StmAux cs attrs _) (Index idd inds) | Just m <- simplifyIndexing vtable seType idd inds consumed = Simplify $ do res <- m@@ -115,7 +115,7 @@ seType (Constant v) = Just $ Prim $ primValueType v simplifyIndex _ _ _ _ = Skip -ruleIf :: BinderOps lore => TopDownRuleIf lore+ruleIf :: BinderOps rep => TopDownRuleIf rep ruleIf _ pat _ (e1, tb, fb, IfDec _ ifsort) | Just branch <- checkBranch, ifsort /= IfFallback || isCt1 e1 = Simplify $ do@@ -194,7 +194,7 @@ -- | 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 lore => TopDownRuleIf lore+hoistBranchInvariant :: BinderOps rep => TopDownRuleIf rep hoistBranchInvariant _ pat _ (cond, tb, fb, IfDec ret ifsort) = Simplify $ do let tses = bodyResult tb fses = bodyResult fb@@ -278,7 +278,7 @@ -- 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 lore => BottomUpRuleIf lore+removeDeadBranchResult :: BinderOps rep => BottomUpRuleIf rep removeDeadBranchResult (_, used) pat _ (e1, tb, fb, IfDec rettype ifsort) | -- Only if there is no existential context... patternSize pat == length rettype,@@ -300,7 +300,7 @@ in Simplify $ letBind (Pattern [] pat') $ If e1 tb' fb' $ IfDec rettype' ifsort | otherwise = Skip -withAccTopDown :: BinderOps lore => TopDownRuleGeneric lore+withAccTopDown :: BinderOps 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@@ -359,7 +359,7 @@ pure $ Just x withAccTopDown _ _ = Skip -withAccBottomUp :: BinderOps lore => BottomUpRuleGeneric lore+withAccBottomUp :: BinderOps rep => BottomUpRuleGeneric rep -- Eliminate dead results. withAccBottomUp (_, utable) (Let pat aux (WithAcc inputs lam)) | not $ all (`UT.used` utable) $ patternNames pat = Simplify $ do
src/Futhark/Optimise/Simplify/Rules/BasicOp.hs view
@@ -35,7 +35,7 @@ | ArgReplicate [SubExp] SubExp | ArgVar VName -toConcatArg :: ST.SymbolTable lore -> VName -> (ConcatArg, Certificates)+toConcatArg :: ST.SymbolTable rep -> VName -> (ConcatArg, Certificates) toConcatArg vtable v = case ST.lookupBasicOp v vtable of Just (ArrayLit ses _, cs) ->@@ -79,7 +79,7 @@ fuseConcatArg xs y = y : xs -simplifyConcat :: BinderOps lore => BottomUpRuleBasicOp lore+simplifyConcat :: BinderOps 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 lore => TopDownRuleBasicOp lore+ruleBasicOp :: BinderOps rep => TopDownRuleBasicOp rep ruleBasicOp vtable pat aux op | Just (op', cs) <- applySimpleRules defOf seType op = Simplify $ certifying (cs <> stmAuxCerts aux) $ letBind pat $ BasicOp op'@@ -375,17 +375,17 @@ ruleBasicOp _ _ _ _ = Skip -topDownRules :: BinderOps lore => [TopDownRule lore]+topDownRules :: BinderOps rep => [TopDownRule rep] topDownRules = [ RuleBasicOp ruleBasicOp ] -bottomUpRules :: BinderOps lore => [BottomUpRule lore]+bottomUpRules :: BinderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleBasicOp simplifyConcat ] -- | A set of simplification rules for 'BasicOp's. Includes rules -- from "Futhark.Optimise.Simplify.Rules.Simple".-basicOpRules :: (BinderOps lore, Aliased lore) => RuleBook lore+basicOpRules :: (BinderOps rep, Aliased rep) => RuleBook rep basicOpRules = ruleBook topDownRules bottomUpRules <> loopRules
src/Futhark/Optimise/Simplify/Rules/ClosedForm.hs view
@@ -39,13 +39,13 @@ -- | @foldClosedForm look foldfun accargs arrargs@ determines whether -- each of the results of @foldfun@ can be expressed in a closed form. foldClosedForm ::- (ASTLore lore, BinderOps lore) =>- VarLookup lore ->- Pattern lore ->- Lambda lore ->+ (ASTRep rep, BinderOps rep) =>+ VarLookup rep ->+ Pattern rep ->+ Lambda rep -> [SubExp] -> [VName] ->- RuleM lore ()+ RuleM rep () foldClosedForm look pat lam accs arrs = do inputsize <- arraysSize 0 <$> mapM lookupType arrs @@ -78,14 +78,14 @@ -- | @loopClosedForm pat respat merge bound bodys@ determines whether -- the do-loop can be expressed in a closed form. loopClosedForm ::- (ASTLore lore, BinderOps lore) =>- Pattern lore ->- [(FParam lore, SubExp)] ->+ (ASTRep rep, BinderOps rep) =>+ Pattern rep ->+ [(FParam rep, SubExp)] -> Names -> IntType -> SubExp ->- Body lore ->- RuleM lore ()+ Body rep ->+ RuleM rep () loopClosedForm pat merge i it bound body = do t <- case patternTypes pat of [Prim t] -> return t@@ -118,7 +118,7 @@ knownBnds = M.fromList $ zip mergenames mergeexp checkResults ::- BinderOps lore =>+ BinderOps rep => [VName] -> SubExp -> Names ->@@ -126,9 +126,9 @@ M.Map VName SubExp -> -- | Lambda-bound [VName] ->- Body lore ->+ Body rep -> [SubExp] ->- RuleM lore (Body lore)+ RuleM rep (Body rep) checkResults pat size untouchable it knownBnds params body accs = do ((), bnds) <- collectStms $@@ -191,8 +191,8 @@ BasicOp $ ConvOp (SIToFP it t) size determineKnownBindings ::- VarLookup lore ->- Lambda lore ->+ VarLookup rep ->+ Lambda rep -> [SubExp] -> [VName] -> M.Map VName SubExp@@ -215,7 +215,7 @@ Just (p, ve) isReplicate _ = Nothing -makeBindMap :: Body lore -> M.Map VName (Exp lore)+makeBindMap :: Body rep -> M.Map VName (Exp rep) makeBindMap = M.fromList . mapMaybe isSingletonStm . stmsToList . bodyStms where isSingletonStm (Let pat _ e) = case patternNames pat of
src/Futhark/Optimise/Simplify/Rules/Index.hs view
@@ -33,7 +33,7 @@ -- | Try to simplify an index operation. simplifyIndexing :: MonadBinder m =>- ST.SymbolTable (Lore m) ->+ ST.SymbolTable (Rep m) -> TypeLookup -> VName -> Slice SubExp ->
src/Futhark/Optimise/Simplify/Rules/Loop.hs view
@@ -25,7 +25,7 @@ -- 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 lore => BottomUpRuleDoLoop lore+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@@ -105,7 +105,7 @@ -- 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 lore => TopDownRuleDoLoop lore+hoistLoopInvariantMergeVariables :: BinderOps rep => TopDownRuleDoLoop rep hoistLoopInvariantMergeVariables vtable pat aux (ctx, val, form, loopbody) = -- Figure out which of the elements of loopresult are -- loop-invariant, and hoist them out.@@ -206,12 +206,12 @@ not (name `nameIn` namesOfMergeParams) || name `nameIn` namesOfInvariant -simplifyClosedFormLoop :: BinderOps lore => TopDownRuleDoLoop lore+simplifyClosedFormLoop :: BinderOps rep => TopDownRuleDoLoop rep simplifyClosedFormLoop _ pat _ ([], val, ForLoop i it bound [], body) = Simplify $ loopClosedForm pat val (oneName i) it bound body simplifyClosedFormLoop _ _ _ _ = Skip -simplifyLoopVariables :: (BinderOps lore, Aliased lore) => TopDownRuleDoLoop lore+simplifyLoopVariables :: (BinderOps rep, Aliased rep) => TopDownRuleDoLoop rep simplifyLoopVariables vtable pat aux (ctx, val, form@(ForLoop i it num_iters loop_vars), body) | simplifiable <- map checkIfSimplifiable loop_vars, not $ all isNothing simplifiable = Simplify $ do@@ -290,7 +290,7 @@ -- 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 lore) => TopDownRuleDoLoop lore+narrowLoopType :: (BinderOps rep) => TopDownRuleDoLoop rep narrowLoopType vtable pat aux (ctx, val, ForLoop i Int64 n [], body) | Just (n', it', cs) <- smallerType = Simplify $ do@@ -315,13 +315,13 @@ narrowLoopType _ _ _ _ = Skip unroll ::- BinderOps lore =>+ BinderOps rep => Integer ->- [(FParam lore, SubExp)] ->+ [(FParam rep, SubExp)] -> (VName, IntType, Integer) ->- [(LParam lore, VName)] ->- Body lore ->- RuleM lore [SubExp]+ [(LParam rep, VName)] ->+ Body rep ->+ RuleM rep [SubExp] unroll n merge (iv, it, i) loop_vars body | i >= n = return $ map snd merge@@ -348,7 +348,7 @@ let merge' = zip (map fst merge) $ bodyResult iter_body' unroll n merge' (iv, it, i + 1) loop_vars body -simplifyKnownIterationLoop :: BinderOps lore => TopDownRuleDoLoop lore+simplifyKnownIterationLoop :: BinderOps rep => TopDownRuleDoLoop rep simplifyKnownIterationLoop _ pat aux (ctx, val, ForLoop i it (Constant iters) loop_vars, body) | IntValue n <- iters, zeroIshInt n || oneIshInt n || "unroll" `inAttrs` stmAuxAttrs aux = Simplify $ do@@ -358,7 +358,7 @@ simplifyKnownIterationLoop _ _ _ _ = Skip -topDownRules :: (BinderOps lore, Aliased lore) => [TopDownRule lore]+topDownRules :: (BinderOps rep, Aliased rep) => [TopDownRule rep] topDownRules = [ RuleDoLoop hoistLoopInvariantMergeVariables, RuleDoLoop simplifyClosedFormLoop,@@ -367,11 +367,11 @@ RuleDoLoop narrowLoopType ] -bottomUpRules :: BinderOps lore => [BottomUpRule lore]+bottomUpRules :: BinderOps rep => [BottomUpRule rep] bottomUpRules = [ RuleDoLoop removeRedundantMergeVariables ] -- | Standard loop simplification rules.-loopRules :: (BinderOps lore, Aliased lore) => RuleBook lore+loopRules :: (BinderOps 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 lore = VName -> Maybe (Exp lore, Certificates)+type VarLookup rep = VName -> Maybe (Exp rep, Certificates) -- | 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 lore = VarLookup lore -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)+type SimpleRule rep = VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates) isCt1 :: SubExp -> Bool isCt1 (Constant v) = oneIsh v@@ -31,7 +31,7 @@ isCt0 (Constant v) = zeroIsh v isCt0 _ = False -simplifyCmpOp :: SimpleRule lore+simplifyCmpOp :: SimpleRule rep simplifyCmpOp _ _ (CmpOp cmp e1 e2) | e1 == e2 = constRes $ BoolValue $@@ -55,7 +55,7 @@ _ -> Just (SubExp (Constant (BoolValue False)), cs) simplifyCmpOp _ _ _ = Nothing -simplifyBinOp :: SimpleRule lore+simplifyBinOp :: SimpleRule rep simplifyBinOp _ _ (BinOp op (Constant v1) (Constant v2)) | Just res <- doBinOp op v1 v2 = constRes res@@ -204,7 +204,7 @@ subExpRes :: SubExp -> Maybe (BasicOp, Certificates) subExpRes = Just . (,mempty) . SubExp -simplifyUnOp :: SimpleRule lore+simplifyUnOp :: SimpleRule rep simplifyUnOp _ _ (UnOp op (Constant v)) = constRes =<< doUnOp op v simplifyUnOp defOf _ (UnOp Not (Var v))@@ -213,7 +213,7 @@ simplifyUnOp _ _ _ = Nothing -simplifyConvOp :: SimpleRule lore+simplifyConvOp :: SimpleRule rep simplifyConvOp _ _ (ConvOp op (Constant v)) = constRes =<< doConvOp op v simplifyConvOp _ _ (ConvOp op se)@@ -244,13 +244,13 @@ Nothing -- If expression is true then just replace assertion.-simplifyAssert :: SimpleRule lore+simplifyAssert :: SimpleRule rep simplifyAssert _ _ (Assert (Constant (BoolValue True)) _ _) = constRes UnitValue simplifyAssert _ _ _ = Nothing -simplifyIdentityReshape :: SimpleRule lore+simplifyIdentityReshape :: SimpleRule rep simplifyIdentityReshape _ seType (Reshape newshape v) | Just t <- seType $ Var v, newDims newshape == arrayDims t -- No-op reshape.@@ -258,19 +258,19 @@ subExpRes $ Var v simplifyIdentityReshape _ _ _ = Nothing -simplifyReshapeReshape :: SimpleRule lore+simplifyReshapeReshape :: SimpleRule rep simplifyReshapeReshape defOf _ (Reshape newshape v) | Just (BasicOp (Reshape oldshape v2), v_cs) <- defOf v = Just (Reshape (fuseReshape oldshape newshape) v2, v_cs) simplifyReshapeReshape _ _ _ = Nothing -simplifyReshapeScratch :: SimpleRule lore+simplifyReshapeScratch :: SimpleRule rep simplifyReshapeScratch defOf _ (Reshape newshape v) | Just (BasicOp (Scratch bt _), v_cs) <- defOf v = Just (Scratch bt $ newDims newshape, v_cs) simplifyReshapeScratch _ _ _ = Nothing -simplifyReshapeReplicate :: SimpleRule lore+simplifyReshapeReplicate :: SimpleRule rep simplifyReshapeReplicate defOf seType (Reshape newshape v) | Just (BasicOp (Replicate _ se), v_cs) <- defOf v, Just oldshape <- arrayShape <$> seType se,@@ -281,7 +281,7 @@ in Just (Replicate (Shape new) se, v_cs) simplifyReshapeReplicate _ _ _ = Nothing -simplifyReshapeIota :: SimpleRule lore+simplifyReshapeIota :: SimpleRule rep simplifyReshapeIota defOf _ (Reshape newshape v) | Just (BasicOp (Iota _ offset stride it), v_cs) <- defOf v, [n] <- newDims newshape =@@ -297,7 +297,7 @@ -- If we are size-coercing a slice, then we might as well just use a -- different slice instead.-simplifyReshapeIndex :: SimpleRule lore+simplifyReshapeIndex :: SimpleRule rep simplifyReshapeIndex defOf _ (Reshape newshape v) | Just ds <- shapeCoercion newshape, Just (BasicOp (Index v' slice), v_cs) <- defOf v,@@ -308,7 +308,7 @@ -- 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 lore+simplifyUpdateReshape :: SimpleRule rep simplifyUpdateReshape defOf seType (Update dest slice (Var v)) | Just (BasicOp (Reshape newshape v'), v_cs) <- defOf v, Just _ <- shapeCoercion newshape,@@ -318,7 +318,7 @@ Just (Update dest slice' $ Var v', v_cs) simplifyUpdateReshape _ _ _ = Nothing -improveReshape :: SimpleRule lore+improveReshape :: SimpleRule rep improveReshape _ seType (Reshape newshape v) | Just t <- seType $ Var v, newshape' <- informReshape (arrayDims t) newshape,@@ -328,7 +328,7 @@ -- | If we are copying a scratch array (possibly indirectly), just turn it into a scratch by -- itself.-copyScratchToScratch :: SimpleRule lore+copyScratchToScratch :: SimpleRule rep copyScratchToScratch defOf seType (Copy src) = do t <- seType $ Var src if isActuallyScratch src@@ -344,7 +344,7 @@ copyScratchToScratch _ _ _ = Nothing -simpleRules :: [SimpleRule lore]+simpleRules :: [SimpleRule rep] simpleRules = [ simplifyBinOp, simplifyCmpOp,@@ -366,7 +366,7 @@ -- and certificates that it must depend on. {-# NOINLINE applySimpleRules #-} applySimpleRules ::- VarLookup lore ->+ VarLookup rep -> TypeLookup -> BasicOp -> Maybe (BasicOp, Certificates)
src/Futhark/Optimise/Sink.hs view
@@ -40,10 +40,10 @@ -- you ever see this pass as being a compilation speed bottleneck, -- start by caching that a bit. ----- This pass is defined on the Kernels representation. This is not--- because we do anything kernel-specific here, but simply because--- more explicit indexing is going on after SOACs are gone.-module Futhark.Optimise.Sink (sinkKernels, sinkMC) where+-- This pass is defined on post-SOACS representations. This is not+-- because we do anything GPU-specific here, but simply because more+-- explicit indexing is going on after SOACs are gone.+module Futhark.Optimise.Sink (sinkGPU, sinkMC) where import Control.Monad.State import Data.Bifunctor@@ -52,28 +52,28 @@ import qualified Futhark.Analysis.Alias as Alias import qualified Futhark.Analysis.SymbolTable as ST import Futhark.IR.Aliases-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.IR.MC import Futhark.Pass -type SymbolTable lore = ST.SymbolTable lore+type SymbolTable rep = ST.SymbolTable rep -type Sinking lore = M.Map VName (Stm lore)+type Sinking rep = M.Map VName (Stm rep) type Sunk = Names -type Sinker lore a = SymbolTable lore -> Sinking lore -> a -> (a, Sunk)+type Sinker rep a = SymbolTable rep -> Sinking rep -> a -> (a, Sunk) -type Constraints lore =- ( ASTLore lore,- Aliased lore,- ST.IndexOp (Op lore)+type Constraints rep =+ ( ASTRep rep,+ Aliased rep,+ ST.IndexOp (Op rep) ) -- | Given a statement, compute how often each of its free variables -- are used. Not accurate: what we care about are only 1, and greater -- than 1.-multiplicity :: Constraints lore => Stm lore -> M.Map VName Int+multiplicity :: Constraints rep => Stm rep -> M.Map VName Int multiplicity stm = case stmExp stm of If cond tbranch fbranch _ ->@@ -86,9 +86,9 @@ comb = M.unionWith (+) optimiseBranch ::- Constraints lore =>- Sinker lore (Op lore) ->- Sinker lore (Body lore)+ Constraints rep =>+ Sinker rep (Op rep) ->+ Sinker rep (Body rep) optimiseBranch onOp vtable sinking (Body dec stms res) = let (stms', stms_sunk) = optimiseStms onOp vtable sinking' (sunk_stms <> stms) $ freeIn res in ( Body dec stms' res,@@ -104,13 +104,13 @@ sunk = namesFromList $ foldMap (patternNames . stmPattern) sunk_stms optimiseStms ::- Constraints lore =>- Sinker lore (Op lore) ->- SymbolTable lore ->- Sinking lore ->- Stms lore ->+ Constraints rep =>+ Sinker rep (Op rep) ->+ SymbolTable rep ->+ Sinking rep ->+ Stms rep -> Names ->- (Stms lore, Sunk)+ (Stms rep, Sunk) optimiseStms onOp init_vtable init_sinking all_stms free_in_res = let (all_stms', sunk) = optimiseStms' init_vtable init_sinking $ stmsToList all_stms@@ -168,25 +168,25 @@ } optimiseBody ::- Constraints lore =>- Sinker lore (Op lore) ->- Sinker lore (Body lore)+ Constraints rep =>+ Sinker rep (Op rep) ->+ Sinker rep (Body rep) optimiseBody onOp vtable sinking (Body attr stms res) = let (stms', sunk) = optimiseStms onOp vtable sinking stms $ freeIn res in (Body attr stms' res, sunk) optimiseKernelBody ::- Constraints lore =>- Sinker lore (Op lore) ->- Sinker lore (KernelBody lore)+ Constraints rep =>+ Sinker rep (Op rep) ->+ Sinker rep (KernelBody rep) optimiseKernelBody onOp vtable sinking (KernelBody attr stms res) = let (stms', sunk) = optimiseStms onOp vtable sinking stms $ freeIn res in (KernelBody attr stms' res, sunk) optimiseSegOp ::- Constraints lore =>- Sinker lore (Op lore) ->- Sinker lore (SegOp lvl lore)+ Constraints rep =>+ Sinker rep (Op rep) ->+ Sinker rep (SegOp lvl rep) optimiseSegOp onOp vtable sinking op = let scope = scopeOfSegSpace $ segSpace op in runState (mapSegOpM (opMapper scope) op) mempty@@ -208,15 +208,15 @@ where op_vtable = ST.fromScope scope <> vtable -type SinkLore lore = Aliases lore+type SinkRep rep = Aliases rep sink ::- ( ASTLore lore,- CanBeAliased (Op lore),- ST.IndexOp (OpWithAliases (Op lore))+ ( ASTRep rep,+ CanBeAliased (Op rep),+ ST.IndexOp (OpWithAliases (Op rep)) ) =>- Sinker (SinkLore lore) (Op (SinkLore lore)) ->- Pass lore lore+ Sinker (SinkRep rep) (Op (SinkRep rep)) ->+ Pass rep rep sink onOp = Pass "sink" "move memory loads closer to their uses" $ fmap removeProgAliases@@ -235,10 +235,10 @@ namesFromList $ M.keys $ scopeOf consts -- | Sinking in GPU kernels.-sinkKernels :: Pass Kernels Kernels-sinkKernels = sink onHostOp+sinkGPU :: Pass GPU GPU+sinkGPU = sink onHostOp where- onHostOp :: Sinker (SinkLore Kernels) (Op (SinkLore Kernels))+ onHostOp :: Sinker (SinkRep GPU) (Op (SinkRep GPU)) onHostOp vtable sinking (SegOp op) = first SegOp $ optimiseSegOp onHostOp vtable sinking op onHostOp _ _ op = (op, mempty)@@ -247,7 +247,7 @@ sinkMC :: Pass MC MC sinkMC = sink onHostOp where- onHostOp :: Sinker (SinkLore MC) (Op (SinkLore MC))+ onHostOp :: Sinker (SinkRep MC) (Op (SinkRep MC)) onHostOp vtable sinking (ParOp par_op op) = let (par_op', par_sunk) = maybe
src/Futhark/Optimise/TileLoops.hs view
@@ -12,7 +12,7 @@ import Data.Maybe (mapMaybe) import qualified Data.Sequence as Seq import qualified Futhark.Analysis.Alias as Alias-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.IR.Prop.Aliases (consumedInStm) import Futhark.MonadFreshNames import Futhark.Optimise.BlkRegTiling@@ -23,7 +23,7 @@ import Prelude hiding (quot) -- | The pass definition.-tileLoops :: Pass Kernels Kernels+tileLoops :: Pass GPU GPU tileLoops = Pass "tile loops" "Tile stream loops inside kernels" $ intraproceduralTransformation onStms@@ -33,16 +33,16 @@ runState $ runReaderT (optimiseStms stms) scope -optimiseBody :: Body Kernels -> TileM (Body Kernels)+optimiseBody :: Body GPU -> TileM (Body GPU) optimiseBody (Body () stms res) = Body () <$> optimiseStms stms <*> pure res -optimiseStms :: Stms Kernels -> TileM (Stms Kernels)+optimiseStms :: Stms GPU -> TileM (Stms GPU) optimiseStms stms = localScope (scopeOf stms) $ mconcat <$> mapM optimiseStm (stmsToList stms) -optimiseStm :: Stm Kernels -> TileM (Stms Kernels)+optimiseStm :: Stm GPU -> TileM (Stms GPU) optimiseStm stm@(Let pat aux (Op (SegOp (SegMap lvl@SegThread {} space ts kbody)))) = do res3dtiling <- doRegTiling3D stm case res3dtiling of@@ -51,7 +51,7 @@ blkRegTiling_res <- mmBlkRegTiling stm case blkRegTiling_res of Just (extra_bnds, stmt') -> return (extra_bnds <> oneStm stmt')- Nothing -> do+ Nothing -> localScope (scopeOfSegSpace space) $ do (host_stms, (lvl', space', kbody')) <- tileInKernelBody mempty initial_variance lvl space ts kbody return $ host_stms <> oneStm (Let pat aux $ Op $ SegOp $ SegMap lvl' space' ts kbody') where@@ -67,8 +67,8 @@ SegLevel -> SegSpace -> [Type] ->- KernelBody Kernels ->- TileM (Stms Kernels, (SegLevel, SegSpace, KernelBody Kernels))+ KernelBody GPU ->+ TileM (Stms GPU, (SegLevel, SegSpace, KernelBody GPU)) tileInKernelBody branch_variant initial_variance lvl initial_kspace ts kbody | Just kbody_res <- mapM isSimpleResult $ kernelBodyResult kbody = do maybe_tiled <-@@ -99,8 +99,8 @@ SegLevel -> SegSpace -> [Type] ->- Body Kernels ->- TileM (Maybe (Stms Kernels, Tiling, TiledBody))+ Body GPU ->+ TileM (Maybe (Stms GPU, Tiling, TiledBody)) tileInBody branch_variant initial_variance initial_lvl initial_space res_ts (Body () initial_kstms stms_res) = descend mempty $ stmsToList initial_kstms where@@ -207,10 +207,10 @@ -- the tiled statement anyway. preludeToPostlude :: VarianceTable ->- Stms Kernels ->- Stm Kernels ->- Stms Kernels ->- (Stms Kernels, Stms Kernels)+ Stms GPU ->+ Stm GPU ->+ Stms GPU ->+ (Stms GPU, Stms GPU) preludeToPostlude variance prelude stm_to_tile postlude = (prelude_used, prelude_not_used <> postlude) where@@ -247,10 +247,10 @@ -- in memory). partitionPrelude :: VarianceTable ->- Stms Kernels ->+ Stms GPU -> Names -> Names ->- (Stms Kernels, Stms Kernels, Stms Kernels)+ (Stms GPU, Stms GPU, Stms GPU) partitionPrelude variance prestms private used_after = (invariant_prestms, precomputed_variant_prestms, recomputed_variant_prestms) where@@ -301,10 +301,10 @@ injectPrelude :: SegSpace -> VarianceTable ->- Stms Kernels ->+ Stms GPU -> Names ->- (Stms Kernels, Tiling, TiledBody) ->- (Stms Kernels, Tiling, TiledBody)+ (Stms GPU, Tiling, TiledBody) ->+ (Stms GPU, Tiling, TiledBody) injectPrelude initial_space variance prestms used (host_stms, tiling, tiledBody) = (host_stms, tiling, tiledBody') where@@ -338,19 +338,19 @@ tileDoLoop :: SegSpace -> VarianceTable ->- Stms Kernels ->+ Stms GPU -> Names ->- (Stms Kernels, Tiling, TiledBody) ->+ (Stms GPU, Tiling, TiledBody) -> [Type] ->- Pattern Kernels ->- StmAux (ExpDec Kernels) ->- [(FParam Kernels, SubExp)] ->+ Pattern GPU ->+ StmAux (ExpDec GPU) ->+ [(FParam GPU, SubExp)] -> VName -> IntType -> SubExp ->- Stms Kernels ->+ Stms GPU -> Result ->- TileM (Stms Kernels, Tiling, TiledBody)+ TileM (Stms GPU, Tiling, TiledBody) tileDoLoop initial_space variance prestms used_in_body (host_stms, tiling, tiledBody) res_ts pat aux merge i it bound poststms poststms_res = do let prestms_used = used_in_body <> freeIn poststms <> freeIn poststms_res ( invariant_prestms,@@ -415,7 +415,7 @@ PrivStms mempty indexMergeParams <> privstms <> inloop_privstms loopbody' <-- runBodyBinder $+ localScope (scopeOfFParams mergeparams') . runBodyBinder $ resultBody . map Var <$> tiledBody private' privstms' accs' <-@@ -432,34 +432,29 @@ filter (`notElem` unSegSpace (tilingSpace tiling)) $ unSegSpace initial_space -doPrelude :: Tiling -> PrivStms -> Stms Kernels -> [VName] -> Binder Kernels [VName]+doPrelude :: Tiling -> PrivStms -> Stms GPU -> [VName] -> Binder 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) $- letTupExp "pre"- =<< eIf- (toExp in_bounds)- ( do- addPrivStms slice privstms- addStms prestms- resultBodyM $ map Var prestms_live- )- (eBody $ map eBlank ts)+ protectOutOfBounds "pre" in_bounds ts $ do+ addPrivStms slice privstms+ addStms prestms+ pure $ map Var prestms_live -liveSet :: FreeIn a => Stms Kernels -> a -> Names+liveSet :: FreeIn a => Stms GPU -> a -> Names liveSet stms after = namesFromList (concatMap (patternNames . stmPattern) stms) `namesIntersection` freeIn after tileable ::- Stm Kernels ->+ Stm GPU -> Maybe ( SubExp, [VName],- (Commutativity, Lambda Kernels, [SubExp], Lambda Kernels)+ (Commutativity, Lambda GPU, [SubExp], Lambda GPU) ) tileable stm | Op (OtherOp (Screma w arrs form)) <- stmExp stm,@@ -521,12 +516,12 @@ -- SegMaps. This is for things that cannot efficiently be computed -- once in advance in the prelude SegMap, primarily (exclusively?) -- array slicing operations.-data PrivStms = PrivStms (Stms Kernels) ReadPrelude+data PrivStms = PrivStms (Stms GPU) ReadPrelude -privStms :: Stms Kernels -> PrivStms+privStms :: Stms GPU -> PrivStms privStms stms = PrivStms stms $ const $ return () -addPrivStms :: Slice SubExp -> PrivStms -> Binder Kernels ()+addPrivStms :: Slice SubExp -> PrivStms -> Binder GPU () addPrivStms local_slice (PrivStms stms readPrelude) = do readPrelude local_slice addStms stms@@ -541,13 +536,13 @@ instance Monoid PrivStms where mempty = privStms mempty -type ReadPrelude = Slice SubExp -> Binder Kernels ()+type ReadPrelude = Slice SubExp -> Binder GPU () data ProcessTileArgs = ProcessTileArgs { processPrivStms :: PrivStms, processComm :: Commutativity,- processRedLam :: Lambda Kernels,- processMapLam :: Lambda Kernels,+ processRedLam :: Lambda GPU,+ processMapLam :: Lambda GPU, processTiles :: [InputTile], processAcc :: [VName], processTileId :: SubExp@@ -556,8 +551,8 @@ data ResidualTileArgs = ResidualTileArgs { residualPrivStms :: PrivStms, residualComm :: Commutativity,- residualRedLam :: Lambda Kernels,- residualMapLam :: Lambda Kernels,+ residualRedLam :: Lambda GPU,+ residualMapLam :: Lambda GPU, residualInput :: [InputArray], residualAcc :: [VName], residualInputSize :: SubExp,@@ -572,8 +567,8 @@ String -> SegLevel -> ResultManifest ->- (PrimExp VName -> Slice SubExp -> Binder Kernels [SubExp]) ->- Binder Kernels [VName],+ (PrimExp VName -> Slice SubExp -> Binder GPU [SubExp]) ->+ Binder GPU [VName], -- The boolean PrimExp indicates whether they are in-bounds. tilingReadTile ::@@ -581,22 +576,22 @@ PrivStms -> SubExp -> [InputArray] ->- Binder Kernels [InputTile],+ Binder GPU [InputTile], tilingProcessTile :: ProcessTileArgs ->- Binder Kernels [VName],+ Binder GPU [VName], tilingProcessResidualTile :: ResidualTileArgs ->- Binder Kernels [VName],- tilingTileReturns :: VName -> Binder Kernels KernelResult,+ Binder GPU [VName],+ tilingTileReturns :: VName -> Binder GPU KernelResult, tilingSpace :: SegSpace, tilingTileShape :: Shape, tilingLevel :: SegLevel,- tilingNumWholeTiles :: Binder Kernels SubExp+ tilingNumWholeTiles :: Binder GPU SubExp } type DoTiling gtids kdims =- SegLevel -> gtids -> kdims -> SubExp -> Binder Kernels Tiling+ SegLevel -> gtids -> kdims -> SubExp -> Binder GPU Tiling scalarLevel :: Tiling -> SegLevel scalarLevel tiling =@@ -608,20 +603,35 @@ String -> PrimExp VName -> [Type] ->- Binder Kernels [SubExp] ->- Binder Kernels [VName]-protectOutOfBounds desc in_bounds ts m =- letTupExp desc =<< eIf (toExp in_bounds) (resultBody <$> m) (eBody $ map eBlank ts)+ Binder GPU [SubExp] ->+ Binder 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+ -- do. By the linear type rules of accumulators, the body returns+ -- 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+ let m_body_free = namesToList $ freeIn m_body+ t_to_v <-+ filter (isAcc . fst)+ <$> (zip <$> mapM lookupType m_body_free <*> pure m_body_free)+ let blank t = maybe (eBlank t) (pure . BasicOp . SubExp . Var) $ lookup t t_to_v+ letTupExp desc =<< eIf (toExp in_bounds) (pure m_body) (eBody $ map blank ts)+ where+ isAcc Acc {} = True+ isAcc _ = False postludeGeneric :: Tiling -> PrivStms ->- Pattern Kernels ->+ Pattern GPU -> [VName] ->- Stms Kernels ->+ Stms GPU -> Result -> [Type] ->- Binder Kernels [VName]+ Binder 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.@@ -640,21 +650,21 @@ addStms poststms return poststms_res -type TiledBody = Names -> PrivStms -> Binder Kernels [VName]+type TiledBody = Names -> PrivStms -> Binder GPU [VName] tileGeneric :: DoTiling gtids kdims -> SegLevel -> [Type] ->- Pattern Kernels ->+ Pattern GPU -> gtids -> kdims -> SubExp ->- (Commutativity, Lambda Kernels, [SubExp], Lambda Kernels) ->+ (Commutativity, Lambda GPU, [SubExp], Lambda GPU) -> [InputArray] ->- Stms Kernels ->+ Stms GPU -> Result ->- TileM (Stms Kernels, Tiling, TiledBody)+ 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 @@ -662,7 +672,7 @@ where (red_comm, red_lam, red_nes, map_lam) = form - tiledBody :: Tiling -> Names -> PrivStms -> Binder Kernels [VName]+ tiledBody :: Tiling -> Names -> PrivStms -> Binder GPU [VName] tiledBody tiling _private privstms = do let tile_shape = tilingTileShape tiling @@ -723,14 +733,14 @@ arr_t <- lookupType arr letBindNames [v] $ BasicOp $ Index arr $ fullSlice arr_t slice -tileReturns :: [(VName, SubExp)] -> [(SubExp, SubExp)] -> VName -> Binder Kernels KernelResult+tileReturns :: [(VName, SubExp)] -> [(SubExp, SubExp)] -> VName -> Binder GPU KernelResult tileReturns dims_on_top dims arr = do let unit_dims = replicate (length dims_on_top) (intConst Int64 1)+ arr_t <- lookupType arr arr' <-- if null dims_on_top+ if null dims_on_top || null (arrayDims arr_t) -- Second check is for accumulators. then return arr else do- arr_t <- lookupType arr 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@@ -743,34 +753,12 @@ | otherwise = InputDontTile arr -segMap1D ::- String ->- SegLevel ->- ResultManifest ->- (VName -> Binder Kernels [SubExp]) ->- Binder Kernels [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) <- runBinder $ do- res <- f ltid- ts <- mapM subExpType res- return (ts, res)- Body _ stms' res' <- renameBody $ mkBody stms res-- letTupExp desc $- Op $- SegOp $- SegMap lvl space ts $ KernelBody () stms' $ map (Returns manifest) res'- reconstructGtids1D :: Count GroupSize SubExp -> VName -> VName -> VName ->- Binder Kernels ()+ Binder GPU () reconstructGtids1D group_size gtid gid ltid = letBindNames [gtid] =<< toExp (le64 gid * pe64 (unCount group_size) + le64 ltid)@@ -785,7 +773,7 @@ PrivStms -> SubExp -> [InputArray] ->- Binder Kernels [InputTile]+ Binder GPU [InputTile] readTile1D tile_size gid gtid num_groups group_size kind privstms tile_id inputs = fmap (inputsToTiles inputs) . segMap1D "full_tile" lvl ResultNoSimplify@@ -826,7 +814,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ProcessTileArgs ->- Binder Kernels [VName]+ Binder 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@@ -870,7 +858,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ResidualTileArgs ->- Binder Kernels [VName]+ Binder 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.@@ -1001,7 +989,7 @@ (VName, VName) -> (VName, VName) -> (VName, VName) ->- Binder Kernels ()+ Binder 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]@@ -1020,7 +1008,7 @@ PrivStms -> SubExp -> [InputArray] ->- Binder Kernels [InputTile]+ Binder 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@@ -1075,7 +1063,7 @@ TileFull -> mapM readTileElem arrs_and_perms -findTileSize :: HasScope lore m => [InputTile] -> m SubExp+findTileSize :: HasScope rep m => [InputTile] -> m SubExp findTileSize tiles = case mapMaybe isTiled tiles of v : _ -> arraySize 0 <$> lookupType v@@ -1092,7 +1080,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ProcessTileArgs ->- Binder Kernels [VName]+ Binder 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@@ -1148,7 +1136,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> ResidualTileArgs ->- Binder Kernels [VName]+ Binder GPU [VName] processResidualTile2D gids gtids
@@ -1,5 +1,6 @@ module Futhark.Optimise.TileLoops.Shared ( TileM,+ segMap1D, segMap2D, segMap3D, segScatter2D,@@ -13,29 +14,51 @@ import Control.Monad.State import Data.List (foldl', zip4) import qualified Data.Map as M-import Futhark.IR.Kernels+import Futhark.IR.GPU import Futhark.MonadFreshNames import Futhark.Tools import Futhark.Transform.Rename -type TileM = ReaderT (Scope Kernels) (State VNameSource)+type TileM = ReaderT (Scope GPU) (State VNameSource) +segMap1D ::+ String ->+ SegLevel ->+ ResultManifest ->+ (VName -> Binder GPU [SubExp]) ->+ Binder 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+ res <- f ltid+ ts <- mapM subExpType res+ return (ts, res)+ Body _ stms' res' <- renameBody $ mkBody stms res++ letTupExp desc $+ Op $+ SegOp $+ SegMap lvl space ts $ KernelBody () stms' $ map (Returns manifest) res'+ segMap2D :: String -> -- desc SegLevel -> -- lvl ResultManifest -> -- manifest (SubExp, SubExp) -> -- (dim_x, dim_y) ( (VName, VName) -> -- f- Binder Kernels [SubExp]+ Binder GPU [SubExp] ) ->- Binder Kernels [VName]+ Binder 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) <- runBinder $ do+ ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBinder $ do res <- f (ltid_yy, ltid_xx) ts <- mapM subExpType res return (ts, res)@@ -51,9 +74,9 @@ ResultManifest -> -- manifest (SubExp, SubExp, SubExp) -> -- (dim_z, dim_y, dim_x) ( (VName, VName, VName) -> -- f- Binder Kernels [SubExp]+ Binder GPU [SubExp] ) ->- Binder Kernels [VName]+ Binder GPU [VName] segMap3D desc lvl manifest (dim_z, dim_y, dim_x) f = do ltid_x <- newVName "ltid_x" ltid_flat <- newVName "ltid_flat"@@ -61,7 +84,7 @@ 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) <- runBinder $ do+ ((ts, res), stms) <- localScope (scopeOfSegSpace segspace) . runBinder $ do res <- f (ltid_z, ltid_y, ltid_x) ts <- mapM subExpType res return (ts, res)@@ -77,8 +100,8 @@ VName -> SegLevel -> -- lvl (SubExp, SubExp) -> -- (dim_y, dim_x)- ((VName, VName) -> Binder Kernels (SubExp, SubExp)) -> -- f- Binder Kernels [VName]+ ((VName, VName) -> Binder GPU (SubExp, SubExp)) -> -- f+ Binder 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"@@ -103,11 +126,11 @@ type VarianceTable = M.Map VName Names isTileableRedomap ::- Stm Kernels ->+ Stm GPU -> Maybe ( SubExp, [VName],- (Commutativity, Lambda Kernels, [SubExp], Lambda Kernels)+ (Commutativity, Lambda GPU, [SubExp], Lambda GPU) ) isTileableRedomap stm | Op (OtherOp (Screma w arrs form)) <- stmExp stm,@@ -123,7 +146,7 @@ | otherwise = Nothing -defVarianceInStm :: VarianceTable -> Stm Kernels -> VarianceTable+defVarianceInStm :: VarianceTable -> Stm GPU -> VarianceTable defVarianceInStm variance bnd = foldl' add variance $ patternNames $ stmPattern bnd where@@ -133,7 +156,7 @@ -- just in case you need the Screma being treated differently than -- by default; previously Cosmin had to enhance it when dealing with stream.-varianceInStm :: VarianceTable -> Stm Kernels -> VarianceTable+varianceInStm :: VarianceTable -> Stm GPU -> VarianceTable varianceInStm v0 bnd@(Let _ _ (Op (OtherOp Screma {}))) | Just (_, arrs, (_, red_lam, red_nes, map_lam)) <- isTileableRedomap bnd = let v = defVarianceInStm v0 bnd@@ -156,5 +179,5 @@ in varianceInStms v' stm_lam varianceInStm v0 bnd = defVarianceInStm v0 bnd -varianceInStms :: VarianceTable -> Stms Kernels -> VarianceTable+varianceInStms :: VarianceTable -> Stms GPU -> VarianceTable varianceInStms = foldl' varianceInStm
src/Futhark/Optimise/Unstream.hs view
@@ -18,13 +18,13 @@ -- simplified away, but only *before* they are turned into loops. In -- principle this pass could be split into multiple, but for now it is -- kept together.-module Futhark.Optimise.Unstream (unstreamKernels, unstreamMC) where+module Futhark.Optimise.Unstream (unstreamGPU, unstreamMC) where import Control.Monad.Reader import Control.Monad.State-import Futhark.IR.Kernels-import qualified Futhark.IR.Kernels as Kernels-import Futhark.IR.Kernels.Simplify (simplifyKernels)+import Futhark.IR.GPU+import qualified Futhark.IR.GPU as GPU+import Futhark.IR.GPU.Simplify (simplifyGPU) import Futhark.IR.MC import qualified Futhark.IR.MC as MC import Futhark.MonadFreshNames@@ -33,8 +33,8 @@ import qualified Futhark.Transform.FirstOrderTransform as FOT -- | The pass for GPU kernels.-unstreamKernels :: Pass Kernels Kernels-unstreamKernels = unstream onHostOp simplifyKernels+unstreamGPU :: Pass GPU GPU+unstreamGPU = unstream onHostOp simplifyGPU -- | The pass for multicore. unstreamMC :: Pass MC MC@@ -43,10 +43,10 @@ data Stage = SeqStreams | SeqAll unstream ::- ASTLore lore =>- (Stage -> OnOp lore) ->- (Prog lore -> PassM (Prog lore)) ->- Pass lore lore+ ASTRep rep =>+ (Stage -> OnOp rep) ->+ (Prog rep -> PassM (Prog rep)) ->+ Pass rep rep unstream onOp simplify = Pass "unstream" "sequentialise remaining SOACs" $ intraproceduralTransformation (optimise SeqStreams)@@ -58,33 +58,33 @@ runState $ runReaderT (optimiseStms (onOp stage) stms) scope -type UnstreamM lore = ReaderT (Scope lore) (State VNameSource)+type UnstreamM rep = ReaderT (Scope rep) (State VNameSource) -type OnOp lore =- Pattern lore -> StmAux (ExpDec lore) -> Op lore -> UnstreamM lore [Stm lore]+type OnOp rep =+ Pattern rep -> StmAux (ExpDec rep) -> Op rep -> UnstreamM rep [Stm rep] optimiseStms ::- ASTLore lore =>- OnOp lore ->- Stms lore ->- UnstreamM lore (Stms lore)+ ASTRep rep =>+ OnOp rep ->+ Stms rep ->+ UnstreamM rep (Stms rep) optimiseStms onOp stms = localScope (scopeOf stms) $ stmsFromList . concat <$> mapM (optimiseStm onOp) (stmsToList stms) optimiseBody ::- ASTLore lore =>- OnOp lore ->- Body lore ->- UnstreamM lore (Body lore)+ ASTRep rep =>+ OnOp rep ->+ Body rep ->+ UnstreamM rep (Body rep) optimiseBody onOp (Body aux stms res) = Body aux <$> optimiseStms onOp stms <*> pure res optimiseKernelBody ::- ASTLore lore =>- OnOp lore ->- KernelBody lore ->- UnstreamM lore (KernelBody lore)+ ASTRep rep =>+ OnOp rep ->+ KernelBody rep ->+ UnstreamM rep (KernelBody rep) optimiseKernelBody onOp (KernelBody attr stms res) = localScope (scopeOf stms) $ KernelBody attr@@ -92,19 +92,19 @@ <*> pure res optimiseLambda ::- ASTLore lore =>- OnOp lore ->- Lambda lore ->- UnstreamM lore (Lambda lore)+ ASTRep rep =>+ OnOp rep ->+ Lambda rep ->+ UnstreamM rep (Lambda rep) optimiseLambda onOp lam = localScope (scopeOfLParams $ lambdaParams lam) $ do body <- optimiseBody onOp $ lambdaBody lam return lam {lambdaBody = body} optimiseStm ::- ASTLore lore =>- OnOp lore ->- Stm lore ->- UnstreamM lore [Stm lore]+ ASTRep rep =>+ OnOp rep ->+ Stm rep ->+ UnstreamM rep [Stm rep] optimiseStm onOp (Let pat aux (Op op)) = onOp pat aux op optimiseStm onOp (Let pat aux e) =@@ -117,10 +117,10 @@ } optimiseSegOp ::- ASTLore lore =>- OnOp lore ->- SegOp lvl lore ->- UnstreamM lore (SegOp lvl lore)+ ASTRep rep =>+ OnOp rep ->+ SegOp lvl rep ->+ UnstreamM rep (SegOp lvl rep) optimiseSegOp onOp op = localScope (scopeOfSegSpace $ segSpace op) $ mapSegOpM optimise op where@@ -150,13 +150,13 @@ { mapOnSOACLambda = optimiseLambda (onMCOp stage) } -sequentialise :: Stage -> SOAC lore -> Bool+sequentialise :: Stage -> SOAC rep -> Bool sequentialise SeqStreams Stream {} = True sequentialise SeqStreams _ = False sequentialise SeqAll _ = True -onHostOp :: Stage -> OnOp Kernels-onHostOp stage pat aux (Kernels.OtherOp soac)+onHostOp :: Stage -> OnOp GPU+onHostOp stage pat aux (GPU.OtherOp soac) | sequentialise stage soac = do stms <- runBinder_ $ FOT.transformSOAC pat soac fmap concat $@@ -164,7 +164,7 @@ mapM (optimiseStm (onHostOp stage)) $ stmsToList stms | otherwise = -- Still sequentialise whatever's inside.- pure <$> (Let pat aux . Op . Kernels.OtherOp <$> mapSOACM optimise soac)+ pure <$> (Let pat aux . Op . GPU.OtherOp <$> mapSOACM optimise soac) where optimise = identitySOACMapper
src/Futhark/Pass.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE Strict #-} -- | Definition of a polymorphic (generic) pass that can work with--- programs of any lore.+-- programs of any rep. module Futhark.Pass ( PassM, runPassM,@@ -58,9 +58,9 @@ liftEitherM :: Show err => PassM (Either err a) -> PassM a liftEitherM m = liftEither =<< m --- | A compiler pass transforming a 'Prog' of a given lore to a 'Prog'--- of another lore.-data Pass fromlore tolore = Pass+-- | A compiler pass transforming a 'Prog' of a given rep to a 'Prog'+-- of another rep.+data Pass fromrep torep = Pass { -- | Name of the pass. Keep this short and simple. It will -- be used to automatically generate a command-line option -- name via 'passLongOption'.@@ -68,12 +68,12 @@ -- | A slightly longer description, which will show up in the -- command-line help text. passDescription :: String,- passFunction :: Prog fromlore -> PassM (Prog tolore)+ passFunction :: Prog fromrep -> PassM (Prog torep) } -- | Take the name of the pass, turn spaces into dashes, and make all -- characters lowercase.-passLongOption :: Pass fromlore tolore -> String+passLongOption :: Pass fromrep torep -> String passLongOption = map (spaceToDash . toLower) . passName where spaceToDash ' ' = '-'@@ -101,10 +101,10 @@ -- The function definition transformations are run in parallel (with -- 'parPass'), since they cannot affect each other. intraproceduralTransformationWithConsts ::- (Stms fromlore -> PassM (Stms tolore)) ->- (Stms tolore -> FunDef fromlore -> PassM (FunDef tolore)) ->- Prog fromlore ->- PassM (Prog tolore)+ (Stms fromrep -> PassM (Stms torep)) ->+ (Stms torep -> FunDef fromrep -> PassM (FunDef torep)) ->+ Prog fromrep ->+ PassM (Prog torep) intraproceduralTransformationWithConsts ct ft (Prog consts funs) = do consts' <- ct consts funs' <- parPass (ft consts') funs@@ -113,9 +113,9 @@ -- | Like 'intraproceduralTransformationWithConsts', but do not change -- the top-level constants, and simply pass along their 'Scope'. intraproceduralTransformation ::- (Scope lore -> Stms lore -> PassM (Stms lore)) ->- Prog lore ->- PassM (Prog lore)+ (Scope rep -> Stms rep -> PassM (Stms rep)) ->+ Prog rep ->+ PassM (Prog rep) intraproceduralTransformation f = intraproceduralTransformationWithConsts (f mempty) f' where
src/Futhark/Pass/ExpandAllocations.hs view
@@ -16,15 +16,15 @@ import qualified Futhark.Analysis.SymbolTable as ST import Futhark.Error import Futhark.IR-import qualified Futhark.IR.Kernels.Simplify as Kernels-import Futhark.IR.KernelsMem+import qualified Futhark.IR.GPU.Simplify as GPU+import Futhark.IR.GPUMem import qualified Futhark.IR.Mem.IxFun as IxFun import Futhark.MonadFreshNames-import Futhark.Optimise.Simplify.Lore (addScopeWisdom)+import Futhark.Optimise.Simplify.Rep (addScopeWisdom) import Futhark.Pass-import Futhark.Pass.ExplicitAllocations.Kernels (explicitAllocationsInStms)+import Futhark.Pass.ExplicitAllocations.GPU (explicitAllocationsInStms) import Futhark.Pass.ExtractKernels.BlockedKernel (nonSegRed)-import Futhark.Pass.ExtractKernels.ToKernels (segThread)+import Futhark.Pass.ExtractKernels.ToGPU (segThread) import Futhark.Tools import Futhark.Transform.CopyPropagate (copyPropagateInFun) import Futhark.Transform.Rename (renameStm)@@ -33,7 +33,7 @@ import Prelude hiding (quot) -- | The memory expansion pass definition.-expandAllocations :: Pass KernelsMem KernelsMem+expandAllocations :: Pass GPUMem GPUMem expandAllocations = Pass "expand allocations" "Expand allocations" $ \(Prog consts funs) -> do@@ -45,19 +45,19 @@ -- duplicate size keys (which are not fixed by renamer, and size -- keys must currently be globally unique). -type ExpandM = ReaderT (Scope KernelsMem) (StateT VNameSource (Either String))+type ExpandM = ReaderT (Scope GPUMem) (StateT VNameSource (Either String)) limitationOnLeft :: Either String a -> a limitationOnLeft = either compilerLimitationS id transformFunDef ::- Scope KernelsMem ->- FunDef KernelsMem ->- PassM (FunDef KernelsMem)+ Scope GPUMem ->+ FunDef GPUMem ->+ PassM (FunDef GPUMem) transformFunDef scope fundec = do body' <- modifyNameSource $ limitationOnLeft . runStateT (runReaderT m mempty) copyPropagateInFun- simpleKernelsMem+ simpleGPUMem (ST.fromScope (addScopeWisdom scope)) fundec {funDefBody = body'} where@@ -66,20 +66,20 @@ inScopeOf fundec $ transformBody $ funDefBody fundec -transformBody :: Body KernelsMem -> ExpandM (Body KernelsMem)+transformBody :: Body GPUMem -> ExpandM (Body GPUMem) transformBody (Body () stms res) = Body () <$> transformStms stms <*> pure res -transformLambda :: Lambda KernelsMem -> ExpandM (Lambda KernelsMem)+transformLambda :: Lambda GPUMem -> ExpandM (Lambda GPUMem) transformLambda (Lambda params body ret) = Lambda params <$> localScope (scopeOfLParams params) (transformBody body) <*> pure ret -transformStms :: Stms KernelsMem -> ExpandM (Stms KernelsMem)+transformStms :: Stms GPUMem -> ExpandM (Stms GPUMem) transformStms stms = inScopeOf stms $ mconcat <$> mapM transformStm (stmsToList stms) -transformStm :: Stm KernelsMem -> ExpandM (Stms KernelsMem)+transformStm :: Stm GPUMem -> ExpandM (Stms GPUMem) -- It is possible that we are unable to expand allocations in some -- code versions. If so, we can remove the offending branch. Only if -- both versions fail do we propagate the error.@@ -110,7 +110,7 @@ { mapOnBody = \scope -> localScope scope . transformBody } -transformExp :: Exp KernelsMem -> ExpandM (Stms KernelsMem, Exp KernelsMem)+transformExp :: Exp GPUMem -> ExpandM (Stms GPUMem, Exp GPUMem) transformExp (Op (Inner (SegOp (SegMap lvl space ts kbody)))) = do (alloc_stms, (_, kbody')) <- transformScanRed lvl space [] kbody return@@ -190,9 +190,9 @@ transformScanRed :: SegLevel -> SegSpace ->- [Lambda KernelsMem] ->- KernelBody KernelsMem ->- ExpandM (Stms KernelsMem, ([Lambda KernelsMem], KernelBody KernelsMem))+ [Lambda GPUMem] ->+ KernelBody GPUMem ->+ ExpandM (Stms GPUMem, ([Lambda GPUMem], KernelBody GPUMem)) transformScanRed lvl space ops kbody = do bound_outside <- asks $ namesFromList . M.keys let user = (lvl, [le64 $ segFlat space])@@ -230,7 +230,7 @@ namesFromList (M.keys $ scopeOfSegSpace space) <> boundInKernelBody kbody -boundInKernelBody :: KernelBody KernelsMem -> Names+boundInKernelBody :: KernelBody GPUMem -> Names boundInKernelBody = namesFromList . M.keys . scopeOf . kernelBodyStms allocsForBody ::@@ -238,8 +238,8 @@ Extraction -> SegLevel -> SegSpace ->- KernelBody KernelsMem ->- (Stms KernelsMem -> KernelBody KernelsMem -> OffsetM b) ->+ KernelBody GPUMem ->+ (Stms GPUMem -> KernelBody GPUMem -> OffsetM b) -> ExpandM b allocsForBody variant_allocs invariant_allocs lvl space kbody' m = do (alloc_offsets, alloc_stms) <-@@ -260,10 +260,10 @@ memoryRequirements :: SegLevel -> SegSpace ->- Stms KernelsMem ->+ Stms GPUMem -> Extraction -> Extraction ->- ExpandM (RebaseMap, Stms KernelsMem)+ ExpandM (RebaseMap, Stms GPUMem) memoryRequirements lvl space kstms variant_allocs invariant_allocs = do (num_threads, num_threads_stms) <- runBinder . letSubExp "num_threads" . BasicOp $@@ -305,8 +305,8 @@ User -> Names -> Names ->- KernelBody KernelsMem ->- ( KernelBody KernelsMem,+ KernelBody GPUMem ->+ ( KernelBody GPUMem, Extraction ) extractKernelBodyAllocations lvl bound_outside bound_kernel =@@ -317,8 +317,8 @@ User -> Names -> Names ->- Body KernelsMem ->- (Body KernelsMem, Extraction)+ Body GPUMem ->+ (Body GPUMem, Extraction) extractBodyAllocations user bound_outside bound_kernel = extractGenericBodyAllocations user bound_outside bound_kernel bodyStms $ \stms body -> body {bodyStms = stms}@@ -327,8 +327,8 @@ User -> Names -> Names ->- Lambda KernelsMem ->- (Lambda KernelsMem, Extraction)+ Lambda GPUMem ->+ (Lambda GPUMem, Extraction) extractLambdaAllocations user bound_outside bound_kernel lam = (lam {lambdaBody = body'}, allocs) where (body', allocs) = extractBodyAllocations user bound_outside bound_kernel $ lambdaBody lam@@ -337,8 +337,8 @@ User -> Names -> Names ->- (body -> Stms KernelsMem) ->- (Stms KernelsMem -> body -> body) ->+ (body -> Stms GPUMem) ->+ (Stms GPUMem -> body -> body) -> body -> ( body, Extraction@@ -363,8 +363,8 @@ User -> Names -> Names ->- Stm KernelsMem ->- Writer Extraction (Maybe (Stm KernelsMem))+ Stm GPUMem ->+ Writer Extraction (Maybe (Stm GPUMem)) extractStmAllocations user bound_outside bound_kernel (Let (Pattern [] [patElem]) _ (Op (Alloc size space))) | expandable space && expandableSize size -- FIXME: the '&& notScalar space' part is a hack because we@@ -417,7 +417,7 @@ return lam {lambdaBody = body} genericExpandedInvariantAllocations ::- (User -> (Shape, [TPrimExp Int64 VName])) -> Extraction -> ExpandM (Stms KernelsMem, RebaseMap)+ (User -> (Shape, [TPrimExp Int64 VName])) -> Extraction -> ExpandM (Stms GPUMem, RebaseMap) genericExpandedInvariantAllocations getNumUsers invariant_allocs = do -- We expand the invariant allocations by adding an inner dimension -- equal to the number of kernel threads.@@ -459,7 +459,7 @@ Count NumGroups SubExp -> Count GroupSize SubExp -> Extraction ->- ExpandM (Stms KernelsMem, RebaseMap)+ ExpandM (Stms GPUMem, RebaseMap) expandedInvariantAllocations num_threads (Count num_groups) (Count group_size) = genericExpandedInvariantAllocations getNumUsers where@@ -471,9 +471,9 @@ expandedVariantAllocations :: SubExp -> SegSpace ->- Stms KernelsMem ->+ Stms GPUMem -> Extraction ->- ExpandM (Stms KernelsMem, RebaseMap)+ ExpandM (Stms GPUMem, RebaseMap) expandedVariantAllocations _ _ _ variant_allocs | null variant_allocs = return (mempty, mempty) expandedVariantAllocations num_threads kspace kstms variant_allocs = do@@ -538,7 +538,7 @@ newtype OffsetM a = OffsetM ( ReaderT- (Scope KernelsMem)+ (Scope GPUMem) (ReaderT RebaseMap (Either String)) a )@@ -546,12 +546,12 @@ ( Applicative, Functor, Monad,- HasScope KernelsMem,- LocalScope KernelsMem,+ HasScope GPUMem,+ LocalScope GPUMem, MonadError String ) -runOffsetM :: Scope KernelsMem -> RebaseMap -> OffsetM a -> Either String a+runOffsetM :: Scope GPUMem -> RebaseMap -> OffsetM a -> Either String a runOffsetM scope offsets (OffsetM m) = runReaderT (runReaderT m scope) offsets @@ -563,7 +563,7 @@ offsets <- askRebaseMap return $ ($ x) <$> M.lookup name offsets -offsetMemoryInKernelBody :: KernelBody KernelsMem -> OffsetM (KernelBody KernelsMem)+offsetMemoryInKernelBody :: KernelBody GPUMem -> OffsetM (KernelBody GPUMem) offsetMemoryInKernelBody kbody = do scope <- askScope stms' <-@@ -574,7 +574,7 @@ (stmsToList $ kernelBodyStms kbody) return kbody {kernelBodyStms = stms'} -offsetMemoryInBody :: Body KernelsMem -> OffsetM (Body KernelsMem)+offsetMemoryInBody :: Body GPUMem -> OffsetM (Body GPUMem) offsetMemoryInBody (Body dec stms res) = do scope <- askScope stms' <-@@ -585,7 +585,7 @@ (stmsToList stms) return $ Body dec stms' res -offsetMemoryInStm :: Stm KernelsMem -> OffsetM (Scope KernelsMem, Stm KernelsMem)+offsetMemoryInStm :: Stm GPUMem -> OffsetM (Scope GPUMem, Stm GPUMem) offsetMemoryInStm (Let pat dec e) = do pat' <- offsetMemoryInPattern pat e' <- localScope (scopeOfPattern pat') $ offsetMemoryInExp e@@ -618,7 +618,7 @@ inst Ext {} = Nothing inst (Free x) = return x -offsetMemoryInPattern :: Pattern KernelsMem -> OffsetM (Pattern KernelsMem)+offsetMemoryInPattern :: Pattern GPUMem -> OffsetM (Pattern GPUMem) offsetMemoryInPattern (Pattern ctx vals) = do mapM_ inspectCtx ctx Pattern ctx <$> mapM inspectVal vals@@ -664,12 +664,12 @@ IxFun.rebase (fmap (fmap Free) new_base') ixfun offsetMemoryInBodyReturns br = return br -offsetMemoryInLambda :: Lambda KernelsMem -> OffsetM (Lambda KernelsMem)+offsetMemoryInLambda :: Lambda GPUMem -> OffsetM (Lambda GPUMem) offsetMemoryInLambda lam = inScopeOf lam $ do body <- offsetMemoryInBody $ lambdaBody lam return $ lam {lambdaBody = body} -offsetMemoryInExp :: Exp KernelsMem -> OffsetM (Exp KernelsMem)+offsetMemoryInExp :: Exp GPUMem -> OffsetM (Exp GPUMem) offsetMemoryInExp (DoLoop ctx val form body) = do let (ctxparams, ctxinit) = unzip ctx (valparams, valinit) = unzip val@@ -698,8 +698,8 @@ ---- Slicing allocation sizes out of a kernel. -unAllocKernelsStms :: Stms KernelsMem -> Either String (Stms Kernels.Kernels)-unAllocKernelsStms = unAllocStms False+unAllocGPUStms :: Stms GPUMem -> Either String (Stms GPU.GPU)+unAllocGPUStms = unAllocStms False where unAllocBody (Body dec stms res) = Body dec <$> unAllocStms True stms <*> pure res@@ -765,7 +765,7 @@ unMem (MemAcc acc ispace ts u) = Just $ Acc acc ispace ts u unMem MemMem {} = Nothing -unAllocScope :: Scope KernelsMem -> Scope Kernels.Kernels+unAllocScope :: Scope GPUMem -> Scope GPU.GPU unAllocScope = M.mapMaybe unInfo where unInfo (LetName dec) = LetName <$> unMem dec@@ -784,10 +784,10 @@ SubExp -> [SubExp] -> SegSpace ->- Stms KernelsMem ->- ExpandM (Stms Kernels.Kernels, [VName], [VName])+ Stms GPUMem ->+ ExpandM (Stms GPU.GPU, [VName], [VName]) sliceKernelSizes num_threads sizes space kstms = do- kstms' <- either throwError return $ unAllocKernelsStms kstms+ kstms' <- either throwError return $ unAllocGPUStms kstms let num_sizes = length sizes i64s = replicate num_sizes $ Prim int64 @@ -825,7 +825,7 @@ return sizes localScope (scopeOfSegSpace space) $- Kernels.simplifyLambda (Lambda [flat_gtid_lparam] (Body () stms zs) i64s)+ GPU.simplifyLambda (Lambda [flat_gtid_lparam] (Body () stms zs) i64s) ((maxes_per_thread, size_sums), slice_stms) <- flip runBinderT kernels_scope $ do pat <-
src/Futhark/Pass/ExplicitAllocations.hs view
@@ -54,7 +54,7 @@ import Futhark.MonadFreshNames import Futhark.Optimise.Simplify.Engine (SimpleOps (..)) import qualified Futhark.Optimise.Simplify.Engine as Engine-import Futhark.Optimise.Simplify.Lore (mkWiseBody)+import Futhark.Optimise.Simplify.Rep (mkWiseBody) import Futhark.Pass import Futhark.Tools import Futhark.Util (splitAt3, splitFromEnd, takeLast)@@ -66,7 +66,7 @@ deriving (Eq, Ord, Show) bindAllocStm ::- (MonadBinder m, Op (Lore m) ~ MemOp inner) =>+ (MonadBinder m, Op (Rep m) ~ MemOp inner) => AllocStm -> m () bindAllocStm (SizeComputation name pe) =@@ -77,15 +77,15 @@ letBindNames [name] $ BasicOp $ Copy src class- (MonadFreshNames m, LocalScope lore m, Mem lore) =>- Allocator lore m+ (MonadFreshNames m, LocalScope rep m, Mem rep) =>+ Allocator rep m where addAllocStm :: AllocStm -> m () askDefaultSpace :: m Space default addAllocStm ::- ( Allocable fromlore lore,- m ~ AllocM fromlore lore+ ( Allocable fromrep rep,+ m ~ AllocM fromrep rep ) => AllocStm -> m ()@@ -100,7 +100,7 @@ -- allocate space for. See 'ChunkMap' comment. dimAllocationSize :: SubExp -> m SubExp default dimAllocationSize ::- m ~ AllocM fromlore lore =>+ m ~ AllocM fromrep rep => SubExp -> m SubExp dimAllocationSize (Var v) =@@ -113,11 +113,11 @@ -- | Get those names that are known to be constants at run-time. askConsts :: m (S.Set VName) - expHints :: Exp lore -> m [ExpHint]+ expHints :: Exp rep -> m [ExpHint] expHints = defaultExpHints allocateMemory ::- Allocator lore m =>+ Allocator rep m => String -> SubExp -> Space ->@@ -128,7 +128,7 @@ return v computeSize ::- Allocator lore m =>+ Allocator rep m => String -> PrimExp VName -> m SubExp@@ -137,19 +137,19 @@ addAllocStm $ SizeComputation v se return $ Var v -type Allocable fromlore tolore =- ( PrettyLore fromlore,- PrettyLore tolore,- Mem tolore,- FParamInfo fromlore ~ DeclType,- LParamInfo fromlore ~ Type,- BranchType fromlore ~ ExtType,- RetType fromlore ~ DeclExtType,- BodyDec fromlore ~ (),- BodyDec tolore ~ (),- ExpDec tolore ~ (),- SizeSubst (Op tolore),- BinderOps tolore+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 ) -- | A mapping from chunk names to their maximum size. XXX FIXME@@ -158,7 +158,7 @@ -- analysis yet (it should). type ChunkMap = M.Map VName SubExp -data AllocEnv fromlore tolore = AllocEnv+data AllocEnv fromrep torep = AllocEnv { chunkMap :: ChunkMap, -- | Aggressively try to reuse memory in do-loops - -- should be True inside kernels, False outside.@@ -170,28 +170,28 @@ -- | The set of names that are known to be constants at -- kernel compile time. envConsts :: S.Set VName,- allocInOp :: Op fromlore -> AllocM fromlore tolore (Op tolore),- envExpHints :: Exp tolore -> AllocM fromlore tolore [ExpHint]+ allocInOp :: Op fromrep -> AllocM fromrep torep (Op torep),+ envExpHints :: Exp torep -> AllocM fromrep torep [ExpHint] } -- | Monad for adding allocations to an entire program.-newtype AllocM fromlore tolore a- = AllocM (BinderT tolore (ReaderT (AllocEnv fromlore tolore) (State VNameSource)) a)+newtype AllocM fromrep torep a+ = AllocM (BinderT torep (ReaderT (AllocEnv fromrep torep) (State VNameSource)) a) deriving ( Applicative, Functor, Monad, MonadFreshNames,- HasScope tolore,- LocalScope tolore,- MonadReader (AllocEnv fromlore tolore)+ HasScope torep,+ LocalScope torep,+ MonadReader (AllocEnv fromrep torep) ) instance- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>- MonadBinder (AllocM fromlore tolore)+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ MonadBinder (AllocM fromrep torep) where- type Lore (AllocM fromlore tolore) = tolore+ type Rep (AllocM fromrep torep) = torep mkExpDecM _ _ = return () @@ -205,8 +205,8 @@ collectStms (AllocM m) = AllocM $ collectStms m instance- (Allocable fromlore tolore) =>- Allocator tolore (AllocM fromlore tolore)+ (Allocable fromrep torep) =>+ Allocator torep (AllocM fromrep torep) where expHints e = do f <- asks envExpHints@@ -217,9 +217,9 @@ runAllocM :: MonadFreshNames m =>- (Op fromlore -> AllocM fromlore tolore (Op tolore)) ->- (Exp tolore -> AllocM fromlore tolore [ExpHint]) ->- AllocM fromlore tolore a ->+ (Op fromrep -> AllocM fromrep torep (Op torep)) ->+ (Exp torep -> AllocM fromrep torep [ExpHint]) ->+ AllocM fromrep torep a -> m a runAllocM handleOp hints (AllocM m) = fmap fst $ modifyNameSource $ runState $ runReaderT (runBinderT m mempty) env@@ -235,10 +235,10 @@ } -- | Monad for adding allocations to a single pattern.-newtype PatAllocM lore a+newtype PatAllocM rep a = PatAllocM ( RWS- (Scope lore)+ (Scope rep) [AllocStm] VNameSource a@@ -247,13 +247,13 @@ ( Applicative, Functor, Monad,- HasScope lore,- LocalScope lore,+ HasScope rep,+ LocalScope rep, MonadWriter [AllocStm], MonadFreshNames ) -instance Mem lore => Allocator lore (PatAllocM lore) where+instance Mem rep => Allocator rep (PatAllocM rep) where addAllocStm = tell . pure dimAllocationSize = return askDefaultSpace = return DefaultSpace@@ -261,8 +261,8 @@ runPatAllocM :: MonadFreshNames m =>- PatAllocM lore a ->- Scope lore ->+ PatAllocM rep a ->+ Scope rep -> m (a, [AllocStm]) runPatAllocM (PatAllocM m) mems = modifyNameSource $ frob . runRWS m mems@@ -276,19 +276,22 @@ arraySizeInBytesExp t = untyped $ foldl' (*) (elemSize t) $ map pe64 (arrayDims t) -arraySizeInBytesExpM :: Allocator lore m => Type -> m (PrimExp VName)+arraySizeInBytesExpM :: Allocator rep m => Type -> m (PrimExp VName) arraySizeInBytesExpM t = do dims <- mapM dimAllocationSize (arrayDims t)- let dim_prod = product $ map pe64 dims- elm_size = elemSize t- return $ untyped $ dim_prod * elm_size+ let dim_prod_i64 = product $ map pe64 dims+ elm_size_i64 = elemSize t+ return $+ BinOpExp (SMax Int64) (ValueExp $ IntValue $ Int64Value 0) $+ untyped $+ dim_prod_i64 * elm_size_i64 -arraySizeInBytes :: Allocator lore m => Type -> m SubExp+arraySizeInBytes :: Allocator rep m => Type -> m SubExp arraySizeInBytes = computeSize "bytes" <=< arraySizeInBytesExpM -- | Allocate memory for a value of the given type. allocForArray ::- Allocator lore m =>+ Allocator rep m => Type -> Space -> m VName@@ -297,11 +300,11 @@ allocateMemory "mem" size space allocsForStm ::- (Allocator lore m, ExpDec lore ~ ()) =>+ (Allocator rep m, ExpDec rep ~ ()) => [Ident] -> [Ident] ->- Exp lore ->- m (Stm lore)+ Exp rep ->+ m (Stm rep) allocsForStm sizeidents validents e = do rts <- expReturns e hints <- expHints e@@ -309,10 +312,10 @@ return $ Let (Pattern ctxElems valElems) (defAux ()) e patternWithAllocations ::- (Allocator lore m, ExpDec lore ~ ()) =>+ (Allocator rep m, ExpDec rep ~ ()) => [VName] ->- Exp lore ->- m (Pattern lore)+ Exp rep ->+ m (Pattern rep) patternWithAllocations names e = do (ts', sizes) <- instantiateShapes' =<< expExtType e let identForBindage name t =@@ -321,14 +324,14 @@ stmPattern <$> allocsForStm sizes vals e allocsForPattern ::- Allocator lore m =>+ Allocator rep m => [Ident] -> [Ident] -> [ExpReturns] -> [ExpHint] -> m- ( [PatElem lore],- [PatElem lore]+ ( [PatElem rep],+ [PatElem rep] ) allocsForPattern sizeidents validents rts hints = do let sizes' = [PatElem size $ MemPrim int64 | size <- map identName sizeidents]@@ -432,7 +435,7 @@ inst (Free x) = return x summaryForBindage ::- Allocator lore m =>+ Allocator rep m => Type -> ExpHint -> m (MemBound NoUniqueness)@@ -456,7 +459,7 @@ m <- allocateMemory "mem" bytes space return $ MemArray pt (arrayShape t) NoUniqueness $ ArrayIn m ixfun -lookupMemSpace :: (HasScope lore m, Monad m) => VName -> m Space+lookupMemSpace :: (HasScope rep m, Monad m) => VName -> m Space lookupMemSpace v = do t <- lookupType v case t of@@ -469,10 +472,10 @@ in MemArray bt shape u $ ArrayIn mem ixf allocInFParams ::- (Allocable fromlore tolore) =>- [(FParam fromlore, Space)] ->- ([FParam tolore] -> AllocM fromlore tolore a) ->- AllocM fromlore tolore a+ (Allocable fromrep torep) =>+ [(FParam fromrep, Space)] ->+ ([FParam torep] -> AllocM fromrep torep a) ->+ AllocM fromrep torep a allocInFParams params m = do (valparams, (ctxparams, memparams)) <- runWriterT $ mapM (uncurry allocInFParam) params@@ -481,13 +484,13 @@ localScope summary $ m params' allocInFParam ::- (Allocable fromlore tolore) =>- FParam fromlore ->+ (Allocable fromrep torep) =>+ FParam fromrep -> Space -> WriterT- ([FParam tolore], [FParam tolore])- (AllocM fromlore tolore)- (FParam tolore)+ ([FParam torep], [FParam torep])+ (AllocM fromrep torep)+ (FParam torep) allocInFParam param pspace = case paramDeclType param of Array pt shape u -> do@@ -504,16 +507,16 @@ return param {paramDec = MemAcc acc ispace ts u} allocInMergeParams ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) =>- [(FParam fromlore, SubExp)] ->- ( [FParam tolore] ->- [FParam tolore] ->- ([SubExp] -> AllocM fromlore tolore ([SubExp], [SubExp])) ->- AllocM fromlore tolore a+ [(FParam fromrep, SubExp)] ->+ ( [FParam torep] ->+ [FParam torep] ->+ ([SubExp] -> AllocM fromrep torep ([SubExp], [SubExp])) ->+ AllocM fromrep torep a ) ->- AllocM fromlore tolore a+ AllocM fromrep torep a allocInMergeParams merge m = do ((valparams, handle_loop_subexps), (ctx_params, mem_params)) <- runWriterT $ unzip <$> mapM allocInMergeParam merge@@ -528,12 +531,12 @@ localScope summary $ m (ctx_params <> mem_params) valparams mk_loop_res where allocInMergeParam ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => (Param DeclType, SubExp) -> WriterT- ([FParam tolore], [FParam tolore])- (AllocM fromlore tolore)- (FParam tolore, SubExp -> WriterT ([SubExp], [SubExp]) (AllocM fromlore tolore) SubExp)+ ([FParam torep], [FParam torep])+ (AllocM fromrep torep)+ (FParam torep, SubExp -> WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp) allocInMergeParam (mergeparam, Var v) | Array pt shape u <- paramDeclType mergeparam = do (mem', _) <- lift $ lookupArraySummary v@@ -577,10 +580,10 @@ -- Returns the existentialized index function, the list of substituted values and the memory location. existentializeArray ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => Space -> VName ->- AllocM fromlore tolore (SubExp, ExtIxFun, [TPrimExp Int64 VName], 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')@@ -599,12 +602,12 @@ return (subexp, fromJust ext_ixfun, substs, mem) ensureArrayIn ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) => Space -> SubExp ->- WriterT ([SubExp], [SubExp]) (AllocM fromlore tolore) SubExp+ WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp ensureArrayIn _ (Constant v) = error $ "ensureArrayIn: " ++ pretty v ++ " cannot be an array." ensureArrayIn space (Var v) = do@@ -623,12 +626,12 @@ return sub_exp ensureDirectArray ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) => Maybe Space -> VName ->- AllocM fromlore tolore (VName, SubExp)+ AllocM fromrep torep (VName, SubExp) ensureDirectArray space_ok v = do (mem, ixfun) <- lookupArraySummary v mem_space <- lookupMemSpace mem@@ -643,11 +646,11 @@ allocLinearArray space (baseString v) v allocLinearArray ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => Space -> String -> VName ->- AllocM fromlore tolore (VName, SubExp)+ AllocM fromrep torep (VName, SubExp) allocLinearArray space s v = do t <- lookupType v case t of@@ -662,11 +665,11 @@ error $ "allocLinearArray: " ++ pretty t funcallArgs ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) => [(SubExp, Diet)] ->- AllocM fromlore tolore [(SubExp, Diet)]+ AllocM fromrep torep [(SubExp, Diet)] funcallArgs args = do (valargs, (ctx_args, mem_and_size_args)) <- runWriterT $ forM args $ \(arg, d) -> do@@ -677,13 +680,13 @@ return $ map (,Observe) (ctx_args <> mem_and_size_args) <> valargs linearFuncallArg ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) => Type -> Space -> SubExp ->- WriterT ([SubExp], [SubExp]) (AllocM fromlore tolore) SubExp+ WriterT ([SubExp], [SubExp]) (AllocM fromrep torep) SubExp linearFuncallArg Array {} space (Var v) = do (mem, arg') <- lift $ ensureDirectArray (Just space) v tell ([], [Var mem])@@ -692,12 +695,12 @@ return arg explicitAllocationsGeneric ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) =>- (Op fromlore -> AllocM fromlore tolore (Op tolore)) ->- (Exp tolore -> AllocM fromlore tolore [ExpHint]) ->- Pass fromlore tolore+ (Op fromrep -> AllocM fromrep torep (Op torep)) ->+ (Exp torep -> AllocM fromrep torep [ExpHint]) ->+ Pass fromrep torep explicitAllocationsGeneric handleOp hints = Pass "explicit allocations" "Transform program to explicit memory representation" $ intraproceduralTransformationWithConsts onStms allocInFun@@ -717,13 +720,13 @@ explicitAllocationsInStmsGeneric :: ( MonadFreshNames m,- HasScope tolore m,- Allocable fromlore tolore+ HasScope torep m,+ Allocable fromrep torep ) =>- (Op fromlore -> AllocM fromlore tolore (Op tolore)) ->- (Exp tolore -> AllocM fromlore tolore [ExpHint]) ->- Stms fromlore ->- m (Stms tolore)+ (Op fromrep -> AllocM fromrep torep (Op torep)) ->+ (Exp torep -> AllocM fromrep torep [ExpHint]) ->+ Stms fromrep ->+ m (Stms torep) explicitAllocationsInStmsGeneric handleOp hints stms = do scope <- askScope runAllocM handleOp hints $@@ -749,9 +752,9 @@ startOfFreeIDRange = S.size . shapeContext bodyReturnMemCtx ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => SubExp ->- AllocM fromlore tolore [SubExp]+ AllocM fromrep torep [SubExp] bodyReturnMemCtx Constant {} = return [] bodyReturnMemCtx (Var v) = do@@ -763,10 +766,10 @@ MemArray _ _ _ (ArrayIn mem _) -> return [Var mem] allocInFunBody ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => [Maybe Space] ->- Body fromlore ->- AllocM fromlore tolore (Body tolore)+ Body fromrep ->+ AllocM fromrep torep (Body torep) allocInFunBody space_oks (Body _ bnds res) = buildBody_ . allocInStms bnds $ do res' <- zipWithM ensureDirect space_oks' res@@ -778,10 +781,10 @@ space_oks' = replicate (length res - num_vals) Nothing ++ space_oks ensureDirect ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => Maybe Space -> SubExp ->- AllocM fromlore tolore SubExp+ AllocM fromrep torep SubExp ensureDirect space_ok se = do se_info <- subExpMemInfo se case (se_info, se) of@@ -792,10 +795,10 @@ return se allocInStms ::- (Allocable fromlore tolore) =>- Stms fromlore ->- AllocM fromlore tolore a ->- AllocM fromlore tolore a+ (Allocable fromrep torep) =>+ Stms fromrep ->+ AllocM fromrep torep a ->+ AllocM fromrep torep a allocInStms origstms m = allocInStms' $ stmsToList origstms where allocInStms' [] = m@@ -812,9 +815,9 @@ local f $ allocInStms' stms allocInStm ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>- Stm fromlore ->- AllocM fromlore tolore ()+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ Stm fromrep ->+ AllocM fromrep torep () allocInStm (Let (Pattern sizeElems valElems) _ e) = do e' <- allocInExp e let sizeidents = map patElemIdent sizeElems@@ -823,18 +826,18 @@ addStm bnd allocInLambda ::- Allocable fromlore tolore =>- [LParam tolore] ->- Body fromlore ->- AllocM fromlore tolore (Lambda tolore)+ Allocable fromrep torep =>+ [LParam torep] ->+ Body fromrep ->+ AllocM fromrep torep (Lambda torep) allocInLambda params body = mkLambda params . allocInStms (bodyStms body) $ pure $ bodyResult body allocInExp ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>- Exp fromlore ->- AllocM fromlore tolore (Exp tolore)+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) =>+ Exp fromrep ->+ AllocM fromrep torep (Exp torep) allocInExp (DoLoop ctx val form (Body () bodybnds bodyres)) = allocInMergeParams ctx $ \_ ctxparams' _ -> allocInMergeParams val $@@ -920,10 +923,10 @@ selectSub f (Just (ixfn, m)) = Just (ixfn, map f m) selectSub _ Nothing = Nothing allocInIfBody ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => Int ->- Body fromlore ->- AllocM fromlore tolore (Body tolore, [Maybe IxFun])+ 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@@ -995,9 +998,9 @@ } subExpIxFun ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => SubExp ->- AllocM fromlore tolore (Maybe IxFun)+ AllocM fromrep torep (Maybe IxFun) subExpIxFun Constant {} = return Nothing subExpIxFun (Var v) = do info <- lookupMemInfo v@@ -1006,12 +1009,12 @@ _ -> return Nothing addResCtxInIfBody ::- (Allocable fromlore tolore, Allocator tolore (AllocM fromlore tolore)) =>+ (Allocable fromrep torep, Allocator torep (AllocM fromrep torep)) => [ExtType] ->- Body tolore ->+ Body torep -> [Maybe Space] -> [Maybe (ExtIxFun, [TPrimExp Int64 VName])] ->- AllocM fromlore tolore (Body tolore, [BodyReturns])+ 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@@ -1090,9 +1093,9 @@ adjustExtPE k = fmap (adjustExtV k) mkSpaceOks ::- (Mem tolore, LocalScope tolore m) =>+ (Mem torep, LocalScope torep m) => Int ->- Body tolore ->+ Body torep -> m [Maybe Space] mkSpaceOks num_vals (Body _ stms res) = inScopeOf stms $@@ -1110,11 +1113,11 @@ mkSpaceOK _ = return Nothing allocInLoopForm ::- ( Allocable fromlore tolore,- Allocator tolore (AllocM fromlore tolore)+ ( Allocable fromrep torep,+ Allocator torep (AllocM fromrep torep) ) =>- LoopForm fromlore ->- AllocM fromlore tolore (LoopForm tolore)+ LoopForm fromrep ->+ AllocM fromrep torep (LoopForm torep) allocInLoopForm (WhileLoop v) = return $ WhileLoop v allocInLoopForm (ForLoop i it n loopvars) = ForLoop i it n <$> mapM allocInLoopVar loopvars@@ -1150,41 +1153,41 @@ opIsConst (Inner op) = opIsConst op opIsConst _ = False -sizeSubst :: SizeSubst (Op lore) => Stm lore -> ChunkMap+sizeSubst :: SizeSubst (Op rep) => Stm rep -> ChunkMap sizeSubst (Let pat _ (Op op)) = opSizeSubst pat op sizeSubst _ = mempty -stmConsts :: SizeSubst (Op lore) => Stm lore -> S.Set VName+stmConsts :: SizeSubst (Op rep) => Stm rep -> S.Set VName stmConsts (Let pat _ (Op op)) | opIsConst op = S.fromList $ patternNames pat stmConsts _ = mempty mkLetNamesB' ::- ( Op (Lore m) ~ MemOp inner,+ ( Op (Rep m) ~ MemOp inner, MonadBinder m,- ExpDec (Lore m) ~ (),- Allocator (Lore m) (PatAllocM (Lore m))+ ExpDec (Rep m) ~ (),+ Allocator (Rep m) (PatAllocM (Rep m)) ) =>- ExpDec (Lore m) ->+ ExpDec (Rep m) -> [VName] ->- Exp (Lore m) ->- m (Stm (Lore m))+ 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 mkLetNamesB'' ::- ( Op (Lore m) ~ MemOp inner,- ExpDec lore ~ (),- HasScope (Engine.Wise lore) m,- Allocator lore (PatAllocM lore),+ ( Op (Rep m) ~ MemOp inner,+ ExpDec rep ~ (),+ HasScope (Engine.Wise rep) m,+ Allocator rep (PatAllocM rep), MonadBinder m,- Engine.CanBeWise (Op lore)+ Engine.CanBeWise (Op rep) ) => [VName] ->- Exp (Engine.Wise lore) ->- m (Stm (Engine.Wise lore))+ 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@@ -1194,15 +1197,15 @@ return $ Let pat' (defAux dec) e simplifiable ::- ( Engine.SimplifiableLore lore,- ExpDec lore ~ (),- BodyDec lore ~ (),- Op lore ~ MemOp inner,- Allocator lore (PatAllocM lore)+ ( Engine.SimplifiableRep rep,+ ExpDec rep ~ (),+ BodyDec rep ~ (),+ Op rep ~ MemOp inner,+ Allocator rep (PatAllocM rep) ) => (Engine.OpWithWisdom inner -> UT.UsageTable) ->- (inner -> Engine.SimpleM lore (Engine.OpWithWisdom inner, Stms (Engine.Wise lore))) ->- SimpleOps lore+ (inner -> Engine.SimpleM rep (Engine.OpWithWisdom inner, Stms (Engine.Wise rep))) ->+ SimpleOps rep simplifiable innerUsage simplifyInnerOp = SimpleOps mkExpDecS' mkBodyS' protectOp opUsage simplifyOp where@@ -1235,14 +1238,14 @@ bindPatternWithAllocations :: ( MonadBinder m,- ExpDec lore ~ (),- Op (Lore m) ~ MemOp inner,- Allocator lore (PatAllocM lore)+ ExpDec rep ~ (),+ Op (Rep m) ~ MemOp inner,+ Allocator rep (PatAllocM rep) ) =>- Scope lore ->+ Scope rep -> [VName] ->- Exp lore ->- m (Pattern lore)+ Exp rep ->+ m (Pattern rep) bindPatternWithAllocations types names e = do (pat, prebnds) <- runPatAllocM (patternWithAllocations names e) types mapM_ bindAllocStm prebnds@@ -1252,5 +1255,5 @@ = NoHint | Hint IxFun Space -defaultExpHints :: (Monad m, ASTLore lore) => Exp lore -> m [ExpHint]+defaultExpHints :: (Monad m, ASTRep rep) => Exp rep -> m [ExpHint] defaultExpHints e = return $ replicate (expExtTypeSize e) NoHint
+ src/Futhark/Pass/ExplicitAllocations/GPU.hs view
@@ -0,0 +1,192 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-- | Facilities for converting a 'GPU' program to 'GPUMem'.+module Futhark.Pass.ExplicitAllocations.GPU+ ( explicitAllocations,+ explicitAllocationsInStms,+ )+where++import qualified Data.Map as M+import qualified Data.Set as S+import Futhark.IR.GPU+import Futhark.IR.GPUMem+import qualified Futhark.IR.Mem.IxFun as IxFun+import Futhark.Pass.ExplicitAllocations+import Futhark.Pass.ExplicitAllocations.SegOp++instance SizeSubst (HostOp rep op) where+ opSizeSubst (Pattern _ [size]) (SizeOp (SplitSpace _ _ _ elems_per_thread)) =+ M.singleton (patElemName size) elems_per_thread+ opSizeSubst _ _ = mempty++ opIsConst (SizeOp GetSize {}) = True+ opIsConst (SizeOp GetSizeMax {}) = True+ opIsConst _ = False++allocAtLevel :: SegLevel -> AllocM fromrep trep a -> AllocM fromrep trep a+allocAtLevel lvl = local $ \env ->+ env+ { allocSpace = space,+ aggressiveReuse = True+ }+ where+ space = case lvl of+ SegThread {} -> DefaultSpace+ SegGroup {} -> Space "local"++handleSegOp ::+ SegOp SegLevel GPU ->+ AllocM GPU GPUMem (SegOp SegLevel GPUMem)+handleSegOp op = do+ num_threads <-+ letSubExp "num_threads" $+ BasicOp $+ BinOp+ (Mul Int64 OverflowUndef)+ (unCount (segNumGroups lvl))+ (unCount (segGroupSize lvl))+ allocAtLevel lvl $ mapSegOpM (mapper num_threads) op+ where+ scope = scopeOfSegSpace $ segSpace op+ lvl = segLevel op+ mapper num_threads =+ identitySegOpMapper+ { mapOnSegOpBody =+ localScope scope . local f . allocInKernelBody,+ mapOnSegOpLambda =+ local inThread+ . allocInBinOpLambda num_threads (segSpace op)+ }+ f = case segLevel op of+ SegThread {} -> inThread+ SegGroup {} -> inGroup+ inThread env = env {envExpHints = inThreadExpHints}+ inGroup env = env {envExpHints = inGroupExpHints}++handleHostOp ::+ HostOp GPU (SOAC GPU) ->+ AllocM GPU GPUMem (MemOp (HostOp GPUMem ()))+handleHostOp (SizeOp op) =+ return $ Inner $ SizeOp op+handleHostOp (OtherOp op) =+ error $ "Cannot allocate memory in SOAC: " ++ pretty op+handleHostOp (SegOp op) =+ Inner . SegOp <$> handleSegOp op++kernelExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+kernelExpHints (BasicOp (Manifest perm v)) = do+ dims <- arrayDims <$> lookupType v+ let perm_inv = rearrangeInverse perm+ dims' = rearrangeShape perm dims+ ixfun = IxFun.permute (IxFun.iota $ map pe64 dims') perm_inv+ return [Hint ixfun DefaultSpace]+kernelExpHints (Op (Inner (SegOp (SegMap lvl@SegThread {} space ts body)))) =+ zipWithM (mapResultHint lvl space) ts $ kernelBodyResult body+kernelExpHints (Op (Inner (SegOp (SegRed lvl@SegThread {} space reds ts body)))) =+ (map (const NoHint) red_res <>) <$> zipWithM (mapResultHint lvl space) (drop num_reds ts) map_res+ where+ num_reds = segBinOpResults reds+ (red_res, map_res) = splitAt num_reds $ kernelBodyResult body+kernelExpHints e =+ return $ replicate (expExtTypeSize e) NoHint++mapResultHint ::+ Allocator rep m =>+ SegLevel ->+ SegSpace ->+ Type ->+ KernelResult ->+ m ExpHint+mapResultHint lvl space = hint+ where+ num_threads =+ pe64 (unCount $ segNumGroups lvl) * pe64 (unCount $ segGroupSize lvl)++ -- Heuristic: do not rearrange for returned arrays that are+ -- sufficiently small.+ coalesceReturnOfShape _ [] = False+ coalesceReturnOfShape bs [Constant (IntValue (Int64Value d))] = bs * d > 4+ coalesceReturnOfShape _ _ = True++ hint t Returns {}+ | coalesceReturnOfShape (primByteSize (elemType t)) $ arrayDims t = do+ let space_dims = segSpaceDims space+ t_dims <- mapM dimAllocationSize $ arrayDims t+ return $ Hint (innermost space_dims t_dims) DefaultSpace+ hint t (ConcatReturns SplitStrided {} w _ _) = do+ t_dims <- mapM dimAllocationSize $ arrayDims t+ return $ Hint (innermost [w] t_dims) DefaultSpace+ 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]+ return $ Hint ixfun DefaultSpace+ hint _ _ = return NoHint++innermost :: [SubExp] -> [SubExp] -> IxFun+innermost space_dims t_dims =+ let r = length t_dims+ dims = space_dims ++ t_dims+ perm =+ [length space_dims .. length space_dims + r -1]+ ++ [0 .. length space_dims -1]+ perm_inv = rearrangeInverse perm+ dims_perm = rearrangeShape perm dims+ ixfun_base = IxFun.iota $ map pe64 dims_perm+ ixfun_rearranged = IxFun.permute ixfun_base perm_inv+ in ixfun_rearranged++semiStatic :: S.Set VName -> SubExp -> Bool+semiStatic _ Constant {} = True+semiStatic consts (Var v) = v `S.member` consts++inGroupExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+inGroupExpHints (Op (Inner (SegOp (SegMap _ space ts body))))+ | any private $ kernelBodyResult body = do+ consts <- askConsts+ return $ do+ (t, r) <- zip ts $ kernelBodyResult body+ return $+ if private r && all (semiStatic consts) (arrayDims t)+ then+ let seg_dims = map pe64 $ segSpaceDims space+ dims = seg_dims ++ map pe64 (arrayDims t)+ nilSlice d = DimSlice 0 d 0+ in Hint+ ( IxFun.slice (IxFun.iota dims) $+ fullSliceNum dims $ map nilSlice seg_dims+ )+ $ ScalarSpace (arrayDims t) $ elemType t+ else NoHint+ where+ private (Returns ResultPrivate _) = True+ private _ = False+inGroupExpHints e = return $ replicate (expExtTypeSize e) NoHint++inThreadExpHints :: Allocator GPUMem m => Exp GPUMem -> m [ExpHint]+inThreadExpHints e = do+ consts <- askConsts+ 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+ | otherwise =+ return NoHint++-- | The pass from 'GPU' to 'GPUMem'.+explicitAllocations :: Pass GPU GPUMem+explicitAllocations = explicitAllocationsGeneric handleHostOp kernelExpHints++-- | Convert some 'GPU' stms to 'GPUMem'.+explicitAllocationsInStms ::+ (MonadFreshNames m, HasScope GPUMem m) =>+ Stms GPU ->+ m (Stms GPUMem)+explicitAllocationsInStms = explicitAllocationsInStmsGeneric handleHostOp kernelExpHints
− src/Futhark/Pass/ExplicitAllocations/Kernels.hs
@@ -1,192 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---- | Facilities for converting a 'Kernels' program to 'KernelsMem'.-module Futhark.Pass.ExplicitAllocations.Kernels- ( explicitAllocations,- explicitAllocationsInStms,- )-where--import qualified Data.Map as M-import qualified Data.Set as S-import Futhark.IR.Kernels-import Futhark.IR.KernelsMem-import qualified Futhark.IR.Mem.IxFun as IxFun-import Futhark.Pass.ExplicitAllocations-import Futhark.Pass.ExplicitAllocations.SegOp--instance SizeSubst (HostOp lore op) where- opSizeSubst (Pattern _ [size]) (SizeOp (SplitSpace _ _ _ elems_per_thread)) =- M.singleton (patElemName size) elems_per_thread- opSizeSubst _ _ = mempty-- opIsConst (SizeOp GetSize {}) = True- opIsConst (SizeOp GetSizeMax {}) = True- opIsConst _ = False--allocAtLevel :: SegLevel -> AllocM fromlore tlore a -> AllocM fromlore tlore a-allocAtLevel lvl = local $ \env ->- env- { allocSpace = space,- aggressiveReuse = True- }- where- space = case lvl of- SegThread {} -> DefaultSpace- SegGroup {} -> Space "local"--handleSegOp ::- SegOp SegLevel Kernels ->- AllocM Kernels KernelsMem (SegOp SegLevel KernelsMem)-handleSegOp op = do- num_threads <-- letSubExp "num_threads" $- BasicOp $- BinOp- (Mul Int64 OverflowUndef)- (unCount (segNumGroups lvl))- (unCount (segGroupSize lvl))- allocAtLevel lvl $ mapSegOpM (mapper num_threads) op- where- scope = scopeOfSegSpace $ segSpace op- lvl = segLevel op- mapper num_threads =- identitySegOpMapper- { mapOnSegOpBody =- localScope scope . local f . allocInKernelBody,- mapOnSegOpLambda =- local inThread- . allocInBinOpLambda num_threads (segSpace op)- }- f = case segLevel op of- SegThread {} -> inThread- SegGroup {} -> inGroup- inThread env = env {envExpHints = inThreadExpHints}- inGroup env = env {envExpHints = inGroupExpHints}--handleHostOp ::- HostOp Kernels (SOAC Kernels) ->- AllocM Kernels KernelsMem (MemOp (HostOp KernelsMem ()))-handleHostOp (SizeOp op) =- return $ Inner $ SizeOp op-handleHostOp (OtherOp op) =- error $ "Cannot allocate memory in SOAC: " ++ pretty op-handleHostOp (SegOp op) =- Inner . SegOp <$> handleSegOp op--kernelExpHints :: Allocator KernelsMem m => Exp KernelsMem -> m [ExpHint]-kernelExpHints (BasicOp (Manifest perm v)) = do- dims <- arrayDims <$> lookupType v- let perm_inv = rearrangeInverse perm- dims' = rearrangeShape perm dims- ixfun = IxFun.permute (IxFun.iota $ map pe64 dims') perm_inv- return [Hint ixfun DefaultSpace]-kernelExpHints (Op (Inner (SegOp (SegMap lvl@SegThread {} space ts body)))) =- zipWithM (mapResultHint lvl space) ts $ kernelBodyResult body-kernelExpHints (Op (Inner (SegOp (SegRed lvl@SegThread {} space reds ts body)))) =- (map (const NoHint) red_res <>) <$> zipWithM (mapResultHint lvl space) (drop num_reds ts) map_res- where- num_reds = segBinOpResults reds- (red_res, map_res) = splitAt num_reds $ kernelBodyResult body-kernelExpHints e =- return $ replicate (expExtTypeSize e) NoHint--mapResultHint ::- Allocator lore m =>- SegLevel ->- SegSpace ->- Type ->- KernelResult ->- m ExpHint-mapResultHint lvl space = hint- where- num_threads =- pe64 (unCount $ segNumGroups lvl) * pe64 (unCount $ segGroupSize lvl)-- -- Heuristic: do not rearrange for returned arrays that are- -- sufficiently small.- coalesceReturnOfShape _ [] = False- coalesceReturnOfShape bs [Constant (IntValue (Int64Value d))] = bs * d > 4- coalesceReturnOfShape _ _ = True-- hint t Returns {}- | coalesceReturnOfShape (primByteSize (elemType t)) $ arrayDims t = do- let space_dims = segSpaceDims space- t_dims <- mapM dimAllocationSize $ arrayDims t- return $ Hint (innermost space_dims t_dims) DefaultSpace- hint t (ConcatReturns SplitStrided {} w _ _) = do- t_dims <- mapM dimAllocationSize $ arrayDims t- return $ Hint (innermost [w] t_dims) DefaultSpace- 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]- return $ Hint ixfun DefaultSpace- hint _ _ = return NoHint--innermost :: [SubExp] -> [SubExp] -> IxFun-innermost space_dims t_dims =- let r = length t_dims- dims = space_dims ++ t_dims- perm =- [length space_dims .. length space_dims + r -1]- ++ [0 .. length space_dims -1]- perm_inv = rearrangeInverse perm- dims_perm = rearrangeShape perm dims- ixfun_base = IxFun.iota $ map pe64 dims_perm- ixfun_rearranged = IxFun.permute ixfun_base perm_inv- in ixfun_rearranged--semiStatic :: S.Set VName -> SubExp -> Bool-semiStatic _ Constant {} = True-semiStatic consts (Var v) = v `S.member` consts--inGroupExpHints :: Allocator KernelsMem m => Exp KernelsMem -> m [ExpHint]-inGroupExpHints (Op (Inner (SegOp (SegMap _ space ts body))))- | any private $ kernelBodyResult body = do- consts <- askConsts- return $ do- (t, r) <- zip ts $ kernelBodyResult body- return $- if private r && all (semiStatic consts) (arrayDims t)- then- let seg_dims = map pe64 $ segSpaceDims space- dims = seg_dims ++ map pe64 (arrayDims t)- nilSlice d = DimSlice 0 d 0- in Hint- ( IxFun.slice (IxFun.iota dims) $- fullSliceNum dims $ map nilSlice seg_dims- )- $ ScalarSpace (arrayDims t) $ elemType t- else NoHint- where- private (Returns ResultPrivate _) = True- private _ = False-inGroupExpHints e = return $ replicate (expExtTypeSize e) NoHint--inThreadExpHints :: Allocator KernelsMem m => Exp KernelsMem -> m [ExpHint]-inThreadExpHints e = do- consts <- askConsts- 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- | otherwise =- return NoHint---- | The pass from 'Kernels' to 'KernelsMem'.-explicitAllocations :: Pass Kernels KernelsMem-explicitAllocations = explicitAllocationsGeneric handleHostOp kernelExpHints---- | Convert some 'Kernels' stms to 'KernelsMem'.-explicitAllocationsInStms ::- (MonadFreshNames m, HasScope KernelsMem m) =>- Stms Kernels ->- m (Stms KernelsMem)-explicitAllocationsInStms = explicitAllocationsInStmsGeneric handleHostOp kernelExpHints
src/Futhark/Pass/ExplicitAllocations/MC.hs view
@@ -10,7 +10,7 @@ import Futhark.Pass.ExplicitAllocations import Futhark.Pass.ExplicitAllocations.SegOp -instance SizeSubst (MCOp lore op) where+instance SizeSubst (MCOp rep op) where opSizeSubst _ _ = mempty handleSegOp :: SegOp () MC -> AllocM MC MCMem (SegOp () MCMem)
src/Futhark/Pass/ExplicitAllocations/SegOp.hs view
@@ -9,38 +9,38 @@ ) where -import Futhark.IR.KernelsMem+import Futhark.IR.GPUMem import qualified Futhark.IR.Mem.IxFun as IxFun import Futhark.Pass.ExplicitAllocations -instance SizeSubst (SegOp lvl lore) where+instance SizeSubst (SegOp lvl rep) where opSizeSubst _ _ = mempty allocInKernelBody ::- Allocable fromlore tolore =>- KernelBody fromlore ->- AllocM fromlore tolore (KernelBody tolore)+ Allocable fromrep torep =>+ KernelBody fromrep ->+ AllocM fromrep torep (KernelBody torep) allocInKernelBody (KernelBody () stms res) = uncurry (flip (KernelBody ())) <$> collectStms (allocInStms stms (pure res)) allocInLambda ::- Allocable fromlore tolore =>- [LParam tolore] ->- Body fromlore ->- AllocM fromlore tolore (Lambda tolore)+ Allocable fromrep torep =>+ [LParam torep] ->+ Body fromrep ->+ AllocM fromrep torep (Lambda torep) allocInLambda params body = mkLambda params . allocInStms (bodyStms body) $ pure $ bodyResult body allocInBinOpParams ::- Allocable fromlore tolore =>+ Allocable fromrep torep => SubExp -> TPrimExp Int64 VName -> TPrimExp Int64 VName ->- [LParam fromlore] ->- [LParam fromlore] ->- AllocM fromlore tolore ([LParam tolore], [LParam tolore])+ [LParam fromrep] ->+ [LParam fromrep] ->+ AllocM fromrep torep ([LParam torep], [LParam torep]) allocInBinOpParams num_threads my_id other_id xs ys = unzip <$> zipWithM alloc xs ys where alloc x y =@@ -83,11 +83,11 @@ ) allocInBinOpLambda ::- Allocable fromlore tolore =>+ Allocable fromrep torep => SubExp -> SegSpace ->- Lambda fromlore ->- AllocM fromlore tolore (Lambda tolore)+ Lambda fromrep ->+ AllocM fromrep torep (Lambda torep) allocInBinOpLambda num_threads (SegSpace flat _) lam = do let (acc_params, arr_params) = splitAt (length (lambdaParams lam) `div` 2) $ lambdaParams lam
src/Futhark/Pass/ExtractKernels.hs view
@@ -165,8 +165,8 @@ import Control.Monad.Reader import Data.Bifunctor (first) import Data.Maybe-import qualified Futhark.IR.Kernels as Out-import Futhark.IR.Kernels.Kernel+import qualified Futhark.IR.GPU as Out+import Futhark.IR.GPU.Kernel import Futhark.IR.SOACS import Futhark.IR.SOACS.Simplify (simplifyStms) import Futhark.MonadFreshNames@@ -177,7 +177,7 @@ import Futhark.Pass.ExtractKernels.ISRWIM import Futhark.Pass.ExtractKernels.Intragroup import Futhark.Pass.ExtractKernels.StreamKernel-import Futhark.Pass.ExtractKernels.ToKernels+import Futhark.Pass.ExtractKernels.ToGPU import Futhark.Tools import qualified Futhark.Transform.FirstOrderTransform as FOT import Futhark.Transform.Rename@@ -186,7 +186,7 @@ -- | Transform a program using SOACs to a program using explicit -- kernels, using the kernel extraction transformation.-extractKernels :: Pass SOACS Out.Kernels+extractKernels :: Pass SOACS Out.GPU extractKernels = Pass { passName = "extract kernels",@@ -194,7 +194,7 @@ passFunction = transformProg } -transformProg :: Prog SOACS -> PassM (Prog Out.Kernels)+transformProg :: Prog SOACS -> PassM (Prog Out.GPU) transformProg (Prog consts funs) = do consts' <- runDistribM $ transformStms mempty $ stmsToList consts funs' <- mapM (transformFunDef $ scopeOf consts') funs@@ -208,13 +208,13 @@ stateThresholdCounter :: Int } -newtype DistribM a = DistribM (RWS (Scope Out.Kernels) Log State a)+newtype DistribM a = DistribM (RWS (Scope Out.GPU) Log State a) deriving ( Functor, Applicative, Monad,- HasScope Out.Kernels,- LocalScope Out.Kernels,+ HasScope Out.GPU,+ LocalScope Out.GPU, MonadState State, MonadLogger )@@ -236,23 +236,23 @@ transformFunDef :: (MonadFreshNames m, MonadLogger m) =>- Scope Out.Kernels ->+ Scope Out.GPU -> FunDef SOACS ->- m (Out.FunDef Out.Kernels)+ m (Out.FunDef Out.GPU) transformFunDef scope (FunDef entry attrs name rettype params body) = runDistribM $ do body' <- localScope (scope <> scopeOfFParams params) $ transformBody mempty body return $ FunDef entry attrs name rettype params body' -type KernelsStms = Stms Out.Kernels+type GPUStms = Stms Out.GPU -transformBody :: KernelPath -> Body -> DistribM (Out.Body Out.Kernels)+transformBody :: KernelPath -> Body -> DistribM (Out.Body Out.GPU) transformBody path body = do bnds <- transformStms path $ stmsToList $ bodyStms body return $ mkBody bnds $ bodyResult body -transformStms :: KernelPath -> [Stm] -> DistribM KernelsStms+transformStms :: KernelPath -> [Stm] -> DistribM GPUStms transformStms _ [] = return mempty transformStms path (bnd : bnds) =@@ -308,7 +308,7 @@ String -> Out.SizeClass -> [SubExp] ->- DistribM ((SubExp, Name), Out.Stms Out.Kernels)+ DistribM ((SubExp, Name), Out.Stms Out.GPU) cmpSizeLe desc size_class to_what = do x <- gets stateThresholdCounter modify $ \s -> s {stateThresholdCounter = x + 1}@@ -321,11 +321,11 @@ return (cmp_res, size_key) kernelAlternatives ::- (MonadFreshNames m, HasScope Out.Kernels m) =>- Out.Pattern Out.Kernels ->- Out.Body Out.Kernels ->- [(SubExp, Out.Body Out.Kernels)] ->- m (Out.Stms Out.Kernels)+ (MonadFreshNames m, HasScope Out.GPU m) =>+ Out.Pattern Out.GPU ->+ Out.Body Out.GPU ->+ [(SubExp, Out.Body Out.GPU)] ->+ m (Out.Stms Out.GPU) kernelAlternatives pat default_body [] = runBinder_ $ do ses <- bodyBind default_body forM_ (zip (patternNames pat) ses) $ \(name, se) ->@@ -343,13 +343,13 @@ If cond alt alt_body $ IfDec (staticShapes (patternTypes pat)) IfEquiv -transformLambda :: KernelPath -> Lambda -> DistribM (Out.Lambda Out.Kernels)+transformLambda :: KernelPath -> Lambda -> DistribM (Out.Lambda Out.GPU) transformLambda path (Lambda params body ret) = Lambda params <$> localScope (scopeOfLParams params) (transformBody path body) <*> pure ret -transformStm :: KernelPath -> Stm -> DistribM KernelsStms+transformStm :: KernelPath -> Stm -> DistribM GPUStms transformStm _ stm | "sequential" `inAttrs` stmAuxAttrs (stmAux stm) = runBinder_ $ FOT.transformStmRecursively stm@@ -366,7 +366,7 @@ <$> (WithAcc (map transformInput inputs) <$> transformLambda path lam) where transformInput (shape, arrs, op) =- (shape, arrs, fmap (first soacsLambdaToKernels) op)+ (shape, arrs, fmap (first soacsLambdaToGPU) op) transformStm path (Let pat aux (DoLoop ctx val form body)) = localScope ( castScope (scopeOf form)@@ -392,9 +392,9 @@ | Just (scans, map_lam) <- isScanomapSOAC form = runBinder_ $ do scan_ops <- forM scans $ \(Scan scan_lam nes) -> do (scan_lam', nes', shape) <- determineReduceOp scan_lam nes- let scan_lam'' = soacsLambdaToKernels scan_lam'+ let scan_lam'' = soacsLambdaToGPU scan_lam' return $ SegBinOp Noncommutative scan_lam'' nes' shape- let map_lam_sequential = soacsLambdaToKernels map_lam+ let map_lam_sequential = soacsLambdaToGPU map_lam lvl <- segThreadCapped [w] "segscan" $ NoRecommendation SegNoVirt addStms . fmap (certify cs) =<< segScan lvl res_pat w scan_ops map_lam_sequential arrs [] []@@ -415,9 +415,9 @@ let comm' | commutativeLambda red_lam' = Commutative | otherwise = comm- red_lam'' = soacsLambdaToKernels red_lam'+ red_lam'' = soacsLambdaToGPU red_lam' return $ SegBinOp comm' red_lam'' nes' shape- let map_lam_sequential = soacsLambdaToKernels map_lam+ let map_lam_sequential = soacsLambdaToGPU map_lam lvl <- segThreadCapped [w] "segred" $ NoRecommendation SegNoVirt addStms . fmap (certify cs) =<< nonSegRed lvl pat w red_ops map_lam_sequential arrs@@ -482,7 +482,7 @@ | not $ all primType $ lambdaReturnType red_fun = do -- Split into a chunked map and a reduction, with the latter -- further transformed.- let fold_fun' = soacsLambdaToKernels fold_fun+ let fold_fun' = soacsLambdaToGPU fold_fun let (red_pat_elems, concat_pat_elems) = splitAt (length nes) $ patternValueElements pat@@ -509,8 +509,8 @@ Op (Screma num_threads red_results reduce_soac) ) | otherwise = do- let red_fun_sequential = soacsLambdaToKernels red_fun- fold_fun_sequential = soacsLambdaToKernels fold_fun+ let red_fun_sequential = soacsLambdaToGPU red_fun+ fold_fun_sequential = soacsLambdaToGPU fold_fun fmap (certify cs) <$> streamRed segThreadCapped@@ -551,7 +551,7 @@ 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- let lam' = soacsLambdaToKernels lam+ let lam' = soacsLambdaToGPU lam write_i <- newVName "write_i" let (as_ws, _, _) = unzip3 as kstms = bodyStms $ lambdaBody lam'@@ -574,7 +574,7 @@ addStms stms letBind pat $ Op $ SegOp kernel transformStm _ (Let orig_pat (StmAux cs _ _) (Op (Hist w ops bucket_fun imgs))) = do- let bfun' = soacsLambdaToKernels bucket_fun+ let bfun' = soacsLambdaToGPU bucket_fun -- It is important not to launch unnecessarily many threads for -- histograms, because it may mean we unnecessarily need to reduce@@ -583,7 +583,7 @@ lvl <- segThreadCapped [w] "seghist" $ NoRecommendation SegNoVirt addStms =<< histKernel onLambda lvl orig_pat [] [] cs w ops bfun' imgs where- onLambda = pure . soacsLambdaToKernels+ onLambda = pure . soacsLambdaToGPU transformStm _ bnd = runBinder_ $ FOT.transformStmRecursively bnd @@ -592,7 +592,7 @@ [SubExp] -> KernelPath -> Maybe Int64 ->- DistribM ((SubExp, Name), Out.Stms Out.Kernels)+ DistribM ((SubExp, Name), Out.Stms Out.GPU) sufficientParallelism desc ws path def = cmpSizeLe desc (Out.SizeThreshold path def) ws @@ -654,6 +654,8 @@ 0 -- Basically a map. | DoLoop _ _ ForLoop {} body <- stmExp stm = bodyInterest body * 10+ | WithAcc _ withacc_lam <- stmExp stm =+ bodyInterest (lambdaBody withacc_lam) | Op (Screma _ _ form@(ScremaForm _ _ lam')) <- stmExp stm = 1 + bodyInterest (lambdaBody lam') +@@ -672,11 +674,11 @@ onTopLevelStms :: KernelPath -> Stms SOACS ->- DistNestT Out.Kernels DistribM KernelsStms+ DistNestT Out.GPU DistribM GPUStms onTopLevelStms path stms = liftInner $ transformStms path $ stmsToList stms -onMap :: KernelPath -> MapLoop -> DistribM KernelsStms+onMap :: KernelPath -> MapLoop -> DistribM GPUStms onMap path (MapLoop pat aux w lam arrs) = do types <- askScope let loopnest = MapNesting pat aux w $ zip (lambdaParams lam) arrs@@ -685,20 +687,20 @@ { distNest = singleNesting (Nesting mempty loopnest), distScope = scopeOfPattern pat- <> scopeForKernels (scopeOf lam)+ <> scopeForGPU (scopeOf lam) <> types, distOnInnerMap = onInnerMap path', distOnTopLevelStms = onTopLevelStms path', distSegLevel = segThreadCapped,- distOnSOACSStms = pure . oneStm . soacsStmToKernels,- distOnSOACSLambda = pure . soacsLambdaToKernels+ distOnSOACSStms = pure . oneStm . soacsStmToGPU,+ distOnSOACSLambda = pure . soacsLambdaToGPU } exploitInnerParallelism path' = runDistNestT (env path') $ distributeMapBodyStms acc (bodyStms $ lambdaBody lam) let exploitOuterParallelism path' = do- let lam' = soacsLambdaToKernels lam+ let lam' = soacsLambdaToGPU lam runDistNestT (env path') $ distribute $ addStmsToAcc (bodyStms $ lambdaBody lam') acc@@ -736,11 +738,11 @@ onMap' :: KernelNest -> KernelPath ->- (KernelPath -> DistribM (Out.Stms Out.Kernels)) ->- (KernelPath -> DistribM (Out.Stms Out.Kernels)) ->+ (KernelPath -> DistribM (Out.Stms Out.GPU)) ->+ (KernelPath -> DistribM (Out.Stms Out.GPU)) -> Pattern -> Lambda ->- DistribM (Out.Stms Out.Kernels)+ DistribM (Out.Stms Out.GPU) onMap' loopnest path mk_seq_stms mk_par_stms pat lam = do -- Some of the control flow here looks a bit convoluted because we -- are trying to avoid generating unneeded threshold parameters,@@ -865,8 +867,8 @@ onInnerMap :: KernelPath -> MapLoop ->- DistAcc Out.Kernels ->- DistNestT Out.Kernels DistribM (DistAcc Out.Kernels)+ DistAcc Out.GPU ->+ DistNestT Out.GPU DistribM (DistAcc Out.GPU) onInnerMap path maploop@(MapLoop pat aux w lam arrs) acc | unbalancedLambda lam, lambdaContainsParallelism lam =@@ -920,7 +922,7 @@ -- versioning does not take place down that branch (it currently -- does not). (sequentialised_kernel, nestw_bnds) <- localScope extra_scope $ do- let sequentialised_lam = soacsLambdaToKernels lam'+ let sequentialised_lam = soacsLambdaToGPU lam' constructKernel segThreadCapped nest' $ lambdaBody sequentialised_lam let outer_pat = loopNestingPattern $ fst nest
src/Futhark/Pass/ExtractKernels/BlockedKernel.hs view
@@ -3,7 +3,7 @@ {-# LANGUAGE TypeFamilies #-} module Futhark.Pass.ExtractKernels.BlockedKernel- ( DistLore,+ ( DistRep, MkSegLevel, ThreadRecommendation (..), segRed,@@ -31,32 +31,32 @@ import Prelude hiding (quot) -- | Constraints pertinent to performing distribution/flattening.-type DistLore lore =- ( Bindable lore,- HasSegOp lore,- BinderOps lore,- LetDec lore ~ Type,- ExpDec lore ~ (),- BodyDec lore ~ (),- CanBeAliased (Op lore)+type DistRep rep =+ ( Bindable rep,+ HasSegOp rep,+ BinderOps rep,+ LetDec rep ~ Type,+ ExpDec rep ~ (),+ BodyDec rep ~ (),+ CanBeAliased (Op rep) ) data ThreadRecommendation = ManyThreads | NoRecommendation SegVirt -type MkSegLevel lore m =- [SubExp] -> String -> ThreadRecommendation -> BinderT lore m (SegOpLevel lore)+type MkSegLevel rep m =+ [SubExp] -> String -> ThreadRecommendation -> BinderT rep m (SegOpLevel rep) mkSegSpace :: MonadFreshNames m => [(VName, SubExp)] -> m SegSpace mkSegSpace dims = SegSpace <$> newVName "phys_tid" <*> pure dims prepareRedOrScan ::- (MonadBinder m, DistLore (Lore m)) =>+ (MonadBinder m, DistRep (Rep m)) => SubExp ->- Lambda (Lore m) ->+ Lambda (Rep m) -> [VName] -> [(VName, SubExp)] -> [KernelInput] ->- m (SegSpace, KernelBody (Lore m))+ m (SegSpace, KernelBody (Rep m)) prepareRedOrScan w map_lam arrs ispace inps = do gtid <- newVName "gtid" space <- mkSegSpace $ ispace ++ [(gtid, w)]@@ -64,25 +64,24 @@ runBinder $ localScope (scopeOfSegSpace space) $ do mapM_ readKernelInput inps- forM_ (zip (lambdaParams map_lam) arrs) $ \(p, arr) -> do- arr_t <- lookupType arr- letBindNames [paramName p] $- BasicOp $ Index arr $ fullSlice arr_t [DimFix $ Var gtid]+ 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) return (space, kbody) segRed ::- (MonadFreshNames m, DistLore lore, HasScope lore m) =>- SegOpLevel lore ->- Pattern lore ->+ (MonadFreshNames m, DistRep rep, HasScope rep m) =>+ SegOpLevel rep ->+ Pattern rep -> SubExp -> -- segment size- [SegBinOp lore] ->- Lambda lore ->+ [SegBinOp rep] ->+ Lambda rep -> [VName] -> [(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 lore)+ m (Stms rep) segRed lvl pat w ops map_lam arrs ispace inps = runBinder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $@@ -91,16 +90,16 @@ SegRed lvl kspace ops (lambdaReturnType map_lam) kbody segScan ::- (MonadFreshNames m, DistLore lore, HasScope lore m) =>- SegOpLevel lore ->- Pattern lore ->+ (MonadFreshNames m, DistRep rep, HasScope rep m) =>+ SegOpLevel rep ->+ Pattern rep -> SubExp -> -- segment size- [SegBinOp lore] ->- Lambda lore ->+ [SegBinOp rep] ->+ Lambda rep -> [VName] -> [(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 lore)+ m (Stms rep) segScan lvl pat w ops map_lam arrs ispace inps = runBinder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $@@ -109,15 +108,15 @@ SegScan lvl kspace ops (lambdaReturnType map_lam) kbody segMap ::- (MonadFreshNames m, DistLore lore, HasScope lore m) =>- SegOpLevel lore ->- Pattern lore ->+ (MonadFreshNames m, DistRep rep, HasScope rep m) =>+ SegOpLevel rep ->+ Pattern rep -> SubExp -> -- segment size- Lambda lore ->+ 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 lore)+ m (Stms rep) segMap lvl pat w map_lam arrs ispace inps = runBinder_ $ do (kspace, kbody) <- prepareRedOrScan w map_lam arrs ispace inps letBind pat $@@ -126,9 +125,9 @@ SegMap lvl kspace (lambdaReturnType map_lam) kbody dummyDim ::- (MonadFreshNames m, MonadBinder m, DistLore (Lore m)) =>- Pattern (Lore m) ->- m (Pattern (Lore m), [(VName, SubExp)], m ())+ (MonadFreshNames m, MonadBinder m, DistRep (Rep m)) =>+ Pattern (Rep m) ->+ m (Pattern (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.@@ -153,31 +152,31 @@ ) nonSegRed ::- (MonadFreshNames m, DistLore lore, HasScope lore m) =>- SegOpLevel lore ->- Pattern lore ->+ (MonadFreshNames m, DistRep rep, HasScope rep m) =>+ SegOpLevel rep ->+ Pattern rep -> SubExp ->- [SegBinOp lore] ->- Lambda lore ->+ [SegBinOp rep] ->+ Lambda rep -> [VName] ->- m (Stms lore)+ m (Stms rep) nonSegRed lvl pat w ops map_lam arrs = runBinder_ $ do (pat', ispace, read_dummy) <- dummyDim pat addStms =<< segRed lvl pat' w ops map_lam arrs ispace [] read_dummy segHist ::- (DistLore lore, MonadFreshNames m, HasScope lore m) =>- SegOpLevel lore ->- Pattern lore ->+ (DistRep rep, MonadFreshNames m, HasScope rep m) =>+ SegOpLevel rep ->+ Pattern rep -> SubExp -> -- | Segment indexes and sizes. [(VName, SubExp)] -> [KernelInput] ->- [HistOp lore] ->- Lambda lore ->+ [HistOp rep] ->+ Lambda rep -> [VName] ->- m (Stms lore)+ m (Stms rep) segHist lvl pat arr_w ispace inps ops lam arrs = runBinder_ $ do gtid <- newVName "gtid" space <- mkSegSpace $ ispace ++ [(gtid, arr_w)]@@ -195,10 +194,10 @@ letBind pat $ Op $ segOp $ SegHist lvl space ops (lambdaReturnType lam) kbody mapKernelSkeleton ::- (DistLore lore, HasScope lore m, MonadFreshNames m) =>+ (DistRep rep, HasScope rep m, MonadFreshNames m) => [(VName, SubExp)] -> [KernelInput] ->- m (SegSpace, Stms lore)+ m (SegSpace, Stms rep) mapKernelSkeleton ispace inputs = do read_input_bnds <- runBinder_ $ mapM readKernelInput inputs @@ -206,13 +205,13 @@ return (space, read_input_bnds) mapKernel ::- (DistLore lore, HasScope lore m, MonadFreshNames m) =>- MkSegLevel lore m ->+ (DistRep rep, HasScope rep m, MonadFreshNames m) =>+ MkSegLevel rep m -> [(VName, SubExp)] -> [KernelInput] -> [Type] ->- KernelBody lore ->- m (SegOp (SegOpLevel lore) lore, Stms lore)+ KernelBody rep ->+ m (SegOp (SegOpLevel rep) rep, Stms rep) mapKernel mk_lvl ispace inputs rts (KernelBody () kstms krets) = runBinderT' $ do (space, read_input_stms) <- mapKernelSkeleton ispace inputs @@ -238,7 +237,7 @@ deriving (Show) readKernelInput ::- (DistLore (Lore m), MonadBinder m) =>+ (DistRep (Rep m), MonadBinder m) => KernelInput -> m () readKernelInput inp = do
src/Futhark/Pass/ExtractKernels/DistributeNests.hs view
@@ -62,7 +62,7 @@ import Futhark.Util import Futhark.Util.Log -scopeForSOACs :: SameScope lore SOACS => Scope lore -> Scope SOACS+scopeForSOACs :: SameScope rep SOACS => Scope rep -> Scope SOACS scopeForSOACs = castScope data MapLoop = MapLoop SOACS.Pattern (StmAux ()) SubExp SOACS.Lambda [VName]@@ -71,80 +71,80 @@ mapLoopStm (MapLoop pat aux w lam arrs) = Let pat aux $ Op $ Screma w arrs $ mapSOAC lam -data DistEnv lore m = DistEnv+data DistEnv rep m = DistEnv { distNest :: Nestings,- distScope :: Scope lore,- distOnTopLevelStms :: Stms SOACS -> DistNestT lore m (Stms lore),+ distScope :: Scope rep,+ distOnTopLevelStms :: Stms SOACS -> DistNestT rep m (Stms rep), distOnInnerMap :: MapLoop ->- DistAcc lore ->- DistNestT lore m (DistAcc lore),- distOnSOACSStms :: Stm SOACS -> Binder lore (Stms lore),- distOnSOACSLambda :: Lambda SOACS -> Binder lore (Lambda lore),- distSegLevel :: MkSegLevel lore m+ DistAcc rep ->+ DistNestT rep m (DistAcc rep),+ distOnSOACSStms :: Stm SOACS -> Binder rep (Stms rep),+ distOnSOACSLambda :: Lambda SOACS -> Binder rep (Lambda rep),+ distSegLevel :: MkSegLevel rep m } -data DistAcc lore = DistAcc+data DistAcc rep = DistAcc { distTargets :: Targets,- distStms :: Stms lore+ distStms :: Stms rep } -data DistRes lore = DistRes- { accPostStms :: PostStms lore,+data DistRes rep = DistRes+ { accPostStms :: PostStms rep, accLog :: Log } -instance Semigroup (DistRes lore) where+instance Semigroup (DistRes rep) where DistRes ks1 log1 <> DistRes ks2 log2 = DistRes (ks1 <> ks2) (log1 <> log2) -instance Monoid (DistRes lore) where+instance Monoid (DistRes rep) where mempty = DistRes mempty mempty -newtype PostStms lore = PostStms {unPostStms :: Stms lore}+newtype PostStms rep = PostStms {unPostStms :: Stms rep} -instance Semigroup (PostStms lore) where+instance Semigroup (PostStms rep) where PostStms xs <> PostStms ys = PostStms $ ys <> xs -instance Monoid (PostStms lore) where+instance Monoid (PostStms rep) where mempty = PostStms mempty -typeEnvFromDistAcc :: DistLore lore => DistAcc lore -> Scope lore+typeEnvFromDistAcc :: DistRep rep => DistAcc rep -> Scope rep typeEnvFromDistAcc = scopeOfPattern . fst . outerTarget . distTargets -addStmsToAcc :: Stms lore -> DistAcc lore -> DistAcc lore+addStmsToAcc :: Stms rep -> DistAcc rep -> DistAcc rep addStmsToAcc stms acc = acc {distStms = stms <> distStms acc} addStmToAcc ::- (MonadFreshNames m, DistLore lore) =>+ (MonadFreshNames m, DistRep rep) => Stm SOACS ->- DistAcc lore ->- DistNestT lore m (DistAcc lore)+ DistAcc rep ->+ DistNestT rep m (DistAcc rep) addStmToAcc stm acc = do onSoacs <- asks distOnSOACSStms (stm', _) <- runBinder $ onSoacs stm return acc {distStms = stm' <> distStms acc} soacsLambda ::- (MonadFreshNames m, DistLore lore) =>+ (MonadFreshNames m, DistRep rep) => Lambda SOACS ->- DistNestT lore m (Lambda lore)+ DistNestT rep m (Lambda rep) soacsLambda lam = do onLambda <- asks distOnSOACSLambda fst <$> runBinder (onLambda lam) -newtype DistNestT lore m a- = DistNestT (ReaderT (DistEnv lore m) (WriterT (DistRes lore) m) a)+newtype DistNestT rep m a+ = DistNestT (ReaderT (DistEnv rep m) (WriterT (DistRes rep) m) a) deriving ( Functor, Applicative, Monad,- MonadReader (DistEnv lore m),- MonadWriter (DistRes lore)+ MonadReader (DistEnv rep m),+ MonadWriter (DistRes rep) ) -liftInner :: (LocalScope lore m, DistLore lore) => m a -> DistNestT lore m a+liftInner :: (LocalScope rep m, DistRep rep) => m a -> DistNestT rep m a liftInner m = do outer_scope <- askScope DistNestT $@@ -153,25 +153,25 @@ inner_scope <- askScope localScope (outer_scope `M.difference` inner_scope) m -instance MonadFreshNames m => MonadFreshNames (DistNestT lore m) where+instance MonadFreshNames m => MonadFreshNames (DistNestT rep m) where getNameSource = DistNestT $ lift getNameSource putNameSource = DistNestT . lift . putNameSource -instance (Monad m, ASTLore lore) => HasScope lore (DistNestT lore m) where+instance (Monad m, ASTRep rep) => HasScope rep (DistNestT rep m) where askScope = asks distScope -instance (Monad m, ASTLore lore) => LocalScope lore (DistNestT lore m) where+instance (Monad m, ASTRep rep) => LocalScope rep (DistNestT rep m) where localScope types = local $ \env -> env {distScope = types <> distScope env} -instance Monad m => MonadLogger (DistNestT lore m) where+instance Monad m => MonadLogger (DistNestT rep m) where addLog msgs = tell mempty {accLog = msgs} runDistNestT ::- (MonadLogger m, DistLore lore) =>- DistEnv lore m ->- DistNestT lore m (DistAcc lore) ->- m (Stms lore)+ (MonadLogger m, DistRep rep) =>+ DistEnv rep m ->+ DistNestT rep m (DistAcc rep) ->+ m (Stms rep) runDistNestT env (DistNestT m) = do (acc, res) <- runWriterT $ runReaderT m env addLog $ accLog res@@ -200,17 +200,17 @@ BasicOp $ Replicate (Shape [loopNestingWidth outermost]) se -addPostStms :: Monad m => PostStms lore -> DistNestT lore m ()+addPostStms :: Monad m => PostStms rep -> DistNestT rep m () addPostStms ks = tell $ mempty {accPostStms = ks} -postStm :: Monad m => Stms lore -> DistNestT lore m ()+postStm :: Monad m => Stms rep -> DistNestT rep m () postStm stms = addPostStms $ PostStms stms withStm ::- (Monad m, DistLore lore) =>+ (Monad m, DistRep rep) => Stm SOACS ->- DistNestT lore m a ->- DistNestT lore m a+ DistNestT rep m a ->+ DistNestT rep m a withStm stm = local $ \env -> env { distScope =@@ -223,9 +223,9 @@ provided = namesFromList $ patternNames $ stmPattern stm leavingNesting ::- (MonadFreshNames m, DistLore lore) =>- DistAcc lore ->- DistNestT lore m (DistAcc lore)+ (MonadFreshNames m, DistRep rep) =>+ DistAcc rep ->+ DistNestT rep m (DistAcc rep) leavingNesting acc = case popInnerTarget $ distTargets acc of Nothing ->@@ -278,14 +278,14 @@ return $ acc {distTargets = newtargets, distStms = stms} mapNesting ::- (MonadFreshNames m, DistLore lore) =>+ (MonadFreshNames m, DistRep rep) => PatternT Type -> StmAux () -> SubExp -> Lambda SOACS -> [VName] ->- DistNestT lore m (DistAcc lore) ->- DistNestT lore m (DistAcc lore)+ DistNestT rep m (DistAcc rep) ->+ DistNestT rep m (DistAcc rep) mapNesting pat aux w lam arrs m = local extend $ leavingNesting =<< m where@@ -300,10 +300,10 @@ } inNesting ::- (Monad m, DistLore lore) =>+ (Monad m, DistRep rep) => KernelNest ->- DistNestT lore m a ->- DistNestT lore m a+ DistNestT rep m a ->+ DistNestT rep m a inNesting (outer, nests) = local $ \env -> env { distNest = (inner, nests'),@@ -334,10 +334,10 @@ lambdaContainsParallelism = bodyContainsParallelism . lambdaBody distributeMapBodyStms ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistAcc lore ->+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistAcc rep -> Stms SOACS ->- DistNestT lore m (DistAcc lore)+ DistNestT rep m (DistAcc rep) distributeMapBodyStms orig_acc = distribute <=< onStms orig_acc . stmsToList where onStms acc [] = return acc@@ -354,21 +354,21 @@ -- situation that stm is in scope of itself. withStm stm $ maybeDistributeStm stm =<< onStms acc stms -onInnerMap :: Monad m => MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)+onInnerMap :: Monad m => MapLoop -> DistAcc rep -> DistNestT rep m (DistAcc rep) onInnerMap loop acc = do f <- asks distOnInnerMap f loop acc -onTopLevelStms :: Monad m => Stms SOACS -> DistNestT lore m ()+onTopLevelStms :: Monad m => Stms SOACS -> DistNestT rep m () onTopLevelStms stms = do f <- asks distOnTopLevelStms postStm =<< f stms maybeDistributeStm ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => Stm SOACS ->- DistAcc lore ->- DistNestT lore m (DistAcc lore)+ DistAcc rep ->+ DistNestT rep m (DistAcc rep) maybeDistributeStm stm acc | "sequential" `inAttrs` stmAuxAttrs (stmAux stm) = addStmToAcc stm acc@@ -650,12 +650,12 @@ addStmToAcc bnd acc distributeSingleUnaryStm ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistAcc lore ->+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistAcc rep -> Stm SOACS -> VName ->- (KernelNest -> PatternT Type -> VName -> DistNestT lore m (Stms lore)) ->- DistNestT lore m (DistAcc lore)+ (KernelNest -> PatternT 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')@@ -682,15 +682,15 @@ False distribute ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistAcc lore ->- DistNestT lore m (DistAcc lore)+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistAcc rep ->+ DistNestT rep m (DistAcc rep) distribute acc = fromMaybe acc <$> distributeIfPossible acc mkSegLevel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistNestT lore m (MkSegLevel lore (DistNestT lore m))+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistNestT rep m (MkSegLevel rep (DistNestT rep m)) mkSegLevel = do mk_lvl <- asks distSegLevel return $ \w desc r -> do@@ -699,9 +699,9 @@ return lvl distributeIfPossible ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistAcc lore ->- DistNestT lore m (Maybe (DistAcc lore))+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistAcc rep ->+ DistNestT rep m (Maybe (DistAcc rep)) distributeIfPossible acc = do nest <- asks distNest mk_lvl <- mkSegLevel@@ -717,17 +717,17 @@ } distributeSingleStm ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>- DistAcc lore ->+ (MonadFreshNames m, LocalScope rep m, DistRep rep) =>+ DistAcc rep -> Stm SOACS -> DistNestT- lore+ rep m ( Maybe- ( PostStms lore,+ ( PostStms rep, Result, KernelNest,- DistAcc lore+ DistAcc rep ) ) distributeSingleStm acc bnd = do@@ -751,16 +751,16 @@ ) segmentedScatterKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> PatternT Type -> Certificates -> SubExp ->- Lambda lore ->+ Lambda rep -> [VName] -> [(Shape, Int, VName)] ->- DistNestT lore m (Stms lore)+ DistNestT rep m (Stms rep) segmentedScatterKernel nest perm scatter_pat cs scatter_w lam ivs dests = do -- We replicate some of the checking done by 'isSegmentedOp', but -- things are different because a scatter is not a reduction or@@ -833,14 +833,14 @@ (gtids, ws) = unzip ispace segmentedUpdateKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> Certificates -> VName -> Slice SubExp -> VName ->- DistNestT lore m (Stms lore)+ DistNestT rep m (Stms rep) segmentedUpdateKernel nest perm cs arr slice v = do (base_ispace, kernel_inps) <- flatKernel nest let slice_dims = sliceDims slice@@ -889,12 +889,12 @@ letBind pat $ Op $ segOp k segmentedGatherKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> Certificates -> VName -> Slice SubExp ->- DistNestT lore m (Stms lore)+ DistNestT rep m (Stms rep) segmentedGatherKernel nest cs arr slice = do let slice_dims = sliceDims slice slice_gtids <- replicateM (length slice_dims) (newVName "gtid_slice")@@ -925,15 +925,15 @@ letBind pat $ Op $ segOp k segmentedHistKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> Certificates -> SubExp -> [SOACS.HistOp SOACS] ->- Lambda lore ->+ Lambda rep -> [VName] ->- DistNestT lore m (Stms lore)+ DistNestT rep m (Stms rep) segmentedHistKernel nest perm cs hist_w ops lam arrs = do -- We replicate some of the checking done by 'isSegmentedOp', but -- things are different because a Hist is not a reduction or@@ -970,18 +970,18 @@ bad = error "Ill-typed nested Hist encountered." histKernel ::- (MonadBinder m, DistLore (Lore m)) =>- (Lambda SOACS -> m (Lambda (Lore m))) ->- SegOpLevel (Lore m) ->+ (MonadBinder m, DistRep (Rep m)) =>+ (Lambda SOACS -> m (Lambda (Rep m))) ->+ SegOpLevel (Rep m) -> PatternT Type -> [(VName, SubExp)] -> [KernelInput] -> Certificates -> SubExp -> [SOACS.HistOp SOACS] ->- Lambda (Lore m) ->+ Lambda (Rep m) -> [VName] ->- m (Stms (Lore m))+ m (Stms (Rep m)) histKernel onLambda lvl orig_pat ispace inputs cs hist_w ops lam arrs = runBinderT'_ $ do ops' <- forM ops $ \(SOACS.HistOp num_bins rf dests nes op) -> do (op', nes', shape) <- determineReduceOp op nes@@ -1029,15 +1029,15 @@ | otherwise = (mempty, lam) segmentedScanomapKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> SubExp ->- Lambda lore ->- Lambda lore ->+ Lambda rep ->+ Lambda rep -> [SubExp] -> [VName] ->- DistNestT lore m (Maybe (Stms lore))+ DistNestT rep m (Maybe (Stms rep)) segmentedScanomapKernel nest perm segment_size lam map_lam nes arrs = do mk_lvl <- asks distSegLevel isSegmentedOp nest perm (freeIn lam) (freeIn map_lam) nes [] $@@ -1048,16 +1048,16 @@ =<< segScan lvl pat segment_size [scan_op] map_lam arrs ispace inps regularSegmentedRedomapKernel ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> SubExp -> Commutativity ->- Lambda lore ->- Lambda lore ->+ Lambda rep ->+ Lambda rep -> [SubExp] -> [VName] ->- DistNestT lore m (Maybe (Stms lore))+ DistNestT rep m (Maybe (Stms rep)) regularSegmentedRedomapKernel nest perm segment_size comm lam map_lam nes arrs = do mk_lvl <- asks distSegLevel isSegmentedOp nest perm (freeIn lam) (freeIn map_lam) nes [] $@@ -1068,7 +1068,7 @@ =<< segRed lvl pat segment_size [red_op] map_lam arrs ispace inps isSegmentedOp ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => KernelNest -> [Int] -> Names ->@@ -1080,9 +1080,9 @@ [KernelInput] -> [SubExp] -> [VName] ->- BinderT lore m ()+ BinderT rep m () ) ->- DistNestT lore m (Maybe (Stms lore))+ DistNestT rep m (Maybe (Stms rep)) isSegmentedOp nest perm free_in_op _free_in_fold_op nes arrs m = runMaybeT $ do -- We must verify that array inputs to the operation are inputs to -- the outermost loop nesting or free in the loop nest. Nothing@@ -1181,14 +1181,14 @@ } kernelOrNot ::- (MonadFreshNames m, DistLore lore) =>+ (MonadFreshNames m, DistRep rep) => Certificates -> Stm SOACS ->- DistAcc lore ->- PostStms lore ->- DistAcc lore ->- Maybe (Stms lore) ->- DistNestT lore m (DistAcc lore)+ DistAcc rep ->+ PostStms rep ->+ DistAcc rep ->+ Maybe (Stms rep) ->+ DistNestT rep m (DistAcc rep) kernelOrNot cs bnd acc _ _ Nothing = addStmToAcc (certify cs bnd) acc kernelOrNot cs _ _ kernels acc' (Just bnds) = do@@ -1197,10 +1197,10 @@ return acc' distributeMap ::- (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+ (MonadFreshNames m, LocalScope rep m, DistRep rep) => MapLoop ->- DistAcc lore ->- DistNestT lore m (DistAcc lore)+ DistAcc rep ->+ DistNestT rep m (DistAcc rep) distributeMap (MapLoop pat aux w lam arrs) acc = distribute =<< mapNesting
src/Futhark/Pass/ExtractKernels/Distribution.hs view
@@ -53,7 +53,7 @@ import Futhark.IR.SegOp import Futhark.MonadFreshNames import Futhark.Pass.ExtractKernels.BlockedKernel- ( DistLore,+ ( DistRep, KernelInput (..), MkSegLevel, mapKernel,@@ -112,10 +112,10 @@ x : xs -> Just (t, Targets x $ reverse xs) [] -> Nothing -targetScope :: DistLore lore => Target -> Scope lore+targetScope :: DistRep rep => Target -> Scope rep targetScope = scopeOfPattern . fst -targetsScope :: DistLore lore => Targets -> Scope lore+targetsScope :: DistRep rep => Targets -> Scope rep targetsScope (Targets t ts) = mconcat $ map targetScope $ t : ts data LoopNesting = MapNesting@@ -126,7 +126,7 @@ } deriving (Show) -scopeOfLoopNesting :: DistLore lore => LoopNesting -> Scope lore+scopeOfLoopNesting :: DistRep rep => LoopNesting -> Scope rep scopeOfLoopNesting = scopeOfLParams . map fst . loopNestingParamsAndArrs ppLoopNesting :: LoopNesting -> String@@ -249,11 +249,11 @@ kernelNestWidths = map loopNestingWidth . kernelNestLoops constructKernel ::- (DistLore lore, MonadFreshNames m, LocalScope lore m) =>- MkSegLevel lore m ->+ (DistRep rep, MonadFreshNames m, LocalScope rep m) =>+ MkSegLevel rep m -> KernelNest ->- Body lore ->- m (Stm lore, Stms lore)+ Body rep ->+ m (Stm rep, Stms rep) constructKernel mk_lvl kernel_nest inner_body = runBinderT' $ do (ispace, inps) <- flatKernel kernel_nest let aux = loopNestingAux first_nest@@ -331,9 +331,9 @@ distributionInnerPattern = fst . innerTarget . distributionTarget distributionBodyFromStms ::- ASTLore lore =>+ ASTRep rep => Targets ->- Stms lore ->+ Stms rep -> (DistributionBody, Result) distributionBodyFromStms (Targets (inner_pat, inner_res) targets) stms = let bound_by_stms = namesFromList $ M.keys $ scopeOf stms@@ -349,16 +349,16 @@ ) distributionBodyFromStm ::- ASTLore lore =>+ ASTRep rep => Targets ->- Stm lore ->+ Stm rep -> (DistributionBody, Result) distributionBodyFromStm targets bnd = distributionBodyFromStms targets $ oneStm bnd createKernelNest ::- forall lore m.- (MonadFreshNames m, HasScope lore m) =>+ forall rep m.+ (MonadFreshNames m, HasScope rep m) => Nestings -> DistributionBody -> m (Maybe (Targets, KernelNest))@@ -551,16 +551,16 @@ in (pat', res', identity_map, expand_target) tryDistribute ::- ( DistLore lore,+ ( DistRep rep, MonadFreshNames m,- LocalScope lore m,+ LocalScope rep m, MonadLogger m ) =>- MkSegLevel lore m ->+ MkSegLevel rep m -> Nestings -> Targets ->- Stms lore ->- m (Maybe (Targets, Stms lore))+ Stms rep ->+ m (Maybe (Targets, Stms rep)) tryDistribute _ _ targets stms | null stms = -- No point in distributing an empty kernel.@@ -590,10 +590,10 @@ (dist_body, inner_body_res) = distributionBodyFromStms targets stms tryDistributeStm ::- (MonadFreshNames m, HasScope t m, ASTLore lore) =>+ (MonadFreshNames m, HasScope t m, ASTRep rep) => Nestings -> Targets ->- Stm lore ->+ Stm rep -> m (Maybe (Result, Targets, KernelNest)) tryDistributeStm nest targets bnd = fmap addRes <$> createKernelNest nest dist_body
src/Futhark/Pass/ExtractKernels/ISRWIM.hs view
@@ -18,7 +18,7 @@ -- | Interchange Scan With Inner Map. Tries to turn a @scan(map)@ into a -- @map(scan) iswim ::- (MonadBinder m, Lore m ~ SOACS) =>+ (MonadBinder m, Rep m ~ SOACS) => Pattern -> SubExp -> Lambda ->@@ -81,7 +81,7 @@ -- | Interchange Reduce With Inner Map. Tries to turn a @reduce(map)@ into a -- @map(reduce) irwim ::- (MonadBinder m, Lore m ~ SOACS) =>+ (MonadBinder m, Rep m ~ SOACS) => Pattern -> SubExp -> Commutativity ->
src/Futhark/Pass/ExtractKernels/Interchange.hs view
@@ -185,7 +185,7 @@ Let pat (defAux ()) $ WithAcc inputs lam interchangeWithAcc1 ::- (MonadBinder m, Lore m ~ SOACS) =>+ (MonadBinder m, Rep m ~ SOACS) => WithAccStm -> LoopNesting -> m WithAccStm@@ -193,21 +193,30 @@ (WithAccStm perm _withacc_pat inputs acc_lam) (MapNesting map_pat map_aux w params_and_arrs) = do inputs' <- mapM onInput inputs- let lam_params = lambdaParams acc_lam+ lam_params' <- newAccLamParams $ lambdaParams acc_lam iota_p <- newParam "iota_p" $ Prim int64- acc_lam' <- trLam (Var (paramName iota_p)) <=< mkLambda lam_params $ do+ acc_lam' <- trLam (Var (paramName iota_p)) <=< mkLambda lam_params' $ do+ let acc_params = drop (length inputs) lam_params'+ orig_acc_params = drop (length inputs) $ lambdaParams acc_lam iota_w <- letExp "acc_inter_iota" . BasicOp $ Iota w (intConst Int64 0) (intConst Int64 1) Int64 let (params, arrs) = unzip params_and_arrs maplam_ret = lambdaReturnType acc_lam- maplam = Lambda (iota_p : params) (lambdaBody acc_lam) maplam_ret+ maplam = Lambda (iota_p : orig_acc_params ++ params) (lambdaBody acc_lam) maplam_ret auxing map_aux . letTupExp' "withacc_inter" $- Op $ Screma w (iota_w : arrs) (mapSOAC maplam)+ 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] pure $ WithAccStm perm' pat inputs' acc_lam' where+ newAccLamParams ps = do+ let (cert_ps, acc_ps) = splitAt (length ps `div` 2) ps+ -- Should not rename the certificates.+ acc_ps' <- forM acc_ps $ \(Param v t) ->+ newParam (baseString v) t+ pure $ cert_ps <> acc_ps'+ num_accs = length inputs acc_certs = map paramName $ take num_accs $ lambdaParams acc_lam onArr v =
src/Futhark/Pass/ExtractKernels/Intragroup.hs view
@@ -13,14 +13,14 @@ import qualified Data.Map.Strict as M import qualified Data.Set as S import Futhark.Analysis.PrimExp.Convert-import qualified Futhark.IR.Kernels as Out-import Futhark.IR.Kernels.Kernel hiding (HistOp)+import qualified Futhark.IR.GPU as Out+import Futhark.IR.GPU.Kernel hiding (HistOp) import Futhark.IR.SOACS import Futhark.MonadFreshNames import Futhark.Pass.ExtractKernels.BlockedKernel import Futhark.Pass.ExtractKernels.DistributeNests import Futhark.Pass.ExtractKernels.Distribution-import Futhark.Pass.ExtractKernels.ToKernels+import Futhark.Pass.ExtractKernels.ToGPU import Futhark.Tools import qualified Futhark.Transform.FirstOrderTransform as FOT import Futhark.Util.Log@@ -39,7 +39,7 @@ -- We distinguish between "minimum group size" and "maximum -- exploitable parallelism". intraGroupParallelise ::- (MonadFreshNames m, LocalScope Out.Kernels m) =>+ (MonadFreshNames m, LocalScope Out.GPU m) => KernelNest -> Lambda -> m@@ -47,8 +47,8 @@ ( (SubExp, SubExp), SubExp, Log,- Out.Stms Out.Kernels,- Out.Stms Out.Kernels+ Out.Stms Out.GPU,+ Out.Stms Out.GPU ) ) intraGroupParallelise knest lam = runMaybeT $ do@@ -136,7 +136,7 @@ aux = loopNestingAux first_nest readGroupKernelInput ::- (DistLore (Lore m), MonadBinder m) =>+ (DistRep (Rep m), MonadBinder m) => KernelInput -> m () readGroupKernelInput inp@@ -161,15 +161,15 @@ mempty = IntraAcc mempty mempty mempty type IntraGroupM =- BinderT Out.Kernels (RWS () IntraAcc VNameSource)+ BinderT Out.GPU (RWS () IntraAcc VNameSource) instance MonadLogger IntraGroupM where addLog log = tell mempty {accLog = log} runIntraGroupM ::- (MonadFreshNames m, HasScope Out.Kernels m) =>+ (MonadFreshNames m, HasScope Out.GPU m) => IntraGroupM () ->- m (IntraAcc, Out.Stms Out.Kernels)+ m (IntraAcc, Out.Stms Out.GPU) runIntraGroupM m = do scope <- castScope <$> askScope modifyNameSource $ \src ->@@ -184,7 +184,7 @@ accAvailPar = S.singleton ws } -intraGroupBody :: SegLevel -> Body -> IntraGroupM (Out.Body Out.Kernels)+intraGroupBody :: SegLevel -> Body -> IntraGroupM (Out.Body Out.GPU) intraGroupBody lvl body = do stms <- collectStms_ $ intraGroupStms lvl $ bodyStms body return $ mkBody stms $ bodyResult body@@ -223,7 +223,7 @@ singleNesting $ Nesting mempty loopnest, distScope = scopeOfPattern pat- <> scopeForKernels (scopeOf lam)+ <> scopeForGPU (scopeOf lam) <> scope, distOnInnerMap = distributeMap,@@ -233,9 +233,9 @@ lift $ parallelMin minw return lvl, distOnSOACSStms =- pure . oneStm . soacsStmToKernels,+ pure . oneStm . soacsStmToGPU, distOnSOACSLambda =- pure . soacsLambdaToKernels+ pure . soacsLambdaToGPU } acc = DistAcc@@ -248,26 +248,26 @@ Op (Screma w arrs form) | Just (scans, mapfun) <- isScanomapSOAC form, Scan scanfun nes <- singleScan scans -> do- let scanfun' = soacsLambdaToKernels scanfun- mapfun' = soacsLambdaToKernels mapfun+ let scanfun' = soacsLambdaToGPU scanfun+ mapfun' = soacsLambdaToGPU mapfun certifying (stmAuxCerts aux) $ addStms =<< segScan lvl' pat w [SegBinOp Noncommutative scanfun' nes mempty] mapfun' arrs [] [] parallelMin [w] Op (Screma w arrs form) | Just (reds, map_lam) <- isRedomapSOAC form, Reduce comm red_lam nes <- singleReduce reds -> do- let red_lam' = soacsLambdaToKernels red_lam- map_lam' = soacsLambdaToKernels map_lam+ let red_lam' = soacsLambdaToGPU red_lam+ map_lam' = soacsLambdaToGPU map_lam certifying (stmAuxCerts aux) $ addStms =<< segRed lvl' pat w [SegBinOp comm red_lam' nes mempty] map_lam' arrs [] [] parallelMin [w] Op (Hist w ops bucket_fun arrs) -> do ops' <- forM ops $ \(HistOp num_bins rf dests nes op) -> do (op', nes', shape) <- determineReduceOp op nes- let op'' = soacsLambdaToKernels op'+ let op'' = soacsLambdaToGPU op' return $ Out.HistOp num_bins rf dests nes' shape op'' - let bucket_fun' = soacsLambdaToKernels bucket_fun+ let bucket_fun' = soacsLambdaToGPU bucket_fun certifying (stmAuxCerts aux) $ addStms =<< segHist lvl' pat w [] [] ops' bucket_fun' arrs parallelMin [w]@@ -285,7 +285,7 @@ write_i <- newVName "write_i" space <- mkSegSpace [(write_i, w)] - let lam' = soacsLambdaToKernels lam+ let lam' = soacsLambdaToGPU lam (dests_ws, _, _) = unzip3 dests krets = do (a_w, a, is_vs) <-@@ -307,16 +307,16 @@ parallelMin [w] _ ->- addStm $ soacsStmToKernels stm+ addStm $ soacsStmToGPU stm intraGroupStms :: SegLevel -> Stms SOACS -> IntraGroupM () intraGroupStms lvl = mapM_ (intraGroupStm lvl) intraGroupParalleliseBody ::- (MonadFreshNames m, HasScope Out.Kernels m) =>+ (MonadFreshNames m, HasScope Out.GPU m) => SegLevel -> Body ->- m ([[SubExp]], [[SubExp]], Log, Out.KernelBody Out.Kernels)+ m ([[SubExp]], [[SubExp]], Log, Out.KernelBody Out.GPU) intraGroupParalleliseBody lvl body = do (IntraAcc min_ws avail_ws log, kstms) <- runIntraGroupM $ intraGroupStms lvl $ bodyStms body
src/Futhark/Pass/ExtractKernels/StreamKernel.hs view
@@ -14,7 +14,7 @@ import Data.List () import Futhark.Analysis.PrimExp import Futhark.IR-import Futhark.IR.Kernels hiding+import Futhark.IR.GPU hiding ( BasicOp, Body, Exp,@@ -30,7 +30,7 @@ ) import Futhark.MonadFreshNames import Futhark.Pass.ExtractKernels.BlockedKernel-import Futhark.Pass.ExtractKernels.ToKernels+import Futhark.Pass.ExtractKernels.ToGPU import Futhark.Tools import Prelude hiding (quot) @@ -43,7 +43,7 @@ deriving (Eq, Ord, Show) numberOfGroups ::- (MonadBinder m, Op (Lore m) ~ HostOp (Lore m) inner) =>+ (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) => String -> SubExp -> SubExp ->@@ -59,7 +59,7 @@ return (num_groups, num_threads) blockedKernelSize ::- (MonadBinder m, Lore m ~ Kernels) =>+ (MonadBinder m, Rep m ~ GPU) => String -> SubExp -> m KernelSize@@ -75,7 +75,7 @@ return $ KernelSize per_thread_elements num_threads splitArrays ::- (MonadBinder m, Lore m ~ Kernels) =>+ (MonadBinder m, Rep m ~ GPU) => VName -> [VName] -> SplitOrdering ->@@ -113,12 +113,12 @@ error "partitionChunkedKernelFoldParameters: lambda takes too few parameters" blockedPerThread ::- (MonadBinder m, Lore m ~ Kernels) =>+ (MonadBinder m, Rep m ~ GPU) => VName -> SubExp -> KernelSize -> StreamOrd ->- Lambda (Lore m) ->+ Lambda (Rep m) -> Int -> [VName] -> m ([PatElemT Type], [PatElemT Type])@@ -172,8 +172,8 @@ kerneliseLambda :: MonadFreshNames m => [SubExp] ->- Lambda Kernels ->- m (Lambda Kernels)+ Lambda GPU ->+ m (Lambda GPU) kerneliseLambda nes lam = do thread_index <- newVName "thread_index" let thread_index_param = Param thread_index $ Prim int64@@ -197,15 +197,15 @@ } prepareStream ::- (MonadBinder m, Lore m ~ Kernels) =>+ (MonadBinder m, Rep m ~ GPU) => KernelSize -> [(VName, SubExp)] -> SubExp -> Commutativity ->- Lambda Kernels ->+ Lambda GPU -> [SubExp] -> [VName] ->- m (SubExp, SegSpace, [Type], KernelBody Kernels)+ m (SubExp, SegSpace, [Type], KernelBody GPU) prepareStream size ispace w comm fold_lam nes arrs = do let (KernelSize elems_per_thread num_threads) = size let (ordering, split_ordering) =@@ -235,16 +235,16 @@ return (num_threads, space, ts, kbody) streamRed ::- (MonadFreshNames m, HasScope Kernels m) =>- MkSegLevel Kernels m ->- Pattern Kernels ->+ (MonadFreshNames m, HasScope GPU m) =>+ MkSegLevel GPU m ->+ Pattern GPU -> SubExp -> Commutativity ->- Lambda Kernels ->- Lambda Kernels ->+ Lambda GPU ->+ Lambda GPU -> [SubExp] -> [VName] ->- m (Stms Kernels)+ m (Stms GPU) streamRed mk_lvl pat w comm red_lam fold_lam nes arrs = runBinderT'_ $ do -- The strategy here is to rephrase the stream reduction as a -- non-segmented SegRed that does explicit chunking within its body.@@ -272,16 +272,16 @@ -- Similar to streamRed, but without the last reduction. streamMap ::- (MonadFreshNames m, HasScope Kernels m) =>- MkSegLevel Kernels m ->+ (MonadFreshNames m, HasScope GPU m) =>+ MkSegLevel GPU m -> [String] ->- [PatElem Kernels] ->+ [PatElem GPU] -> SubExp -> Commutativity ->- Lambda Kernels ->+ Lambda GPU -> [SubExp] -> [VName] ->- m ((SubExp, [VName]), Stms Kernels)+ m ((SubExp, [VName]), Stms GPU) streamMap mk_lvl out_desc mapout_pes w comm fold_lam nes arrs = runBinderT' $ do size <- blockedKernelSize "stream_map" w @@ -301,7 +301,7 @@ -- | Like 'segThread', but cap the thread count to the input size. -- This is more efficient for small kernels, e.g. summing a small -- array.-segThreadCapped :: MonadFreshNames m => MkSegLevel Kernels m+segThreadCapped :: MonadFreshNames m => MkSegLevel GPU m segThreadCapped ws desc r = do w <- letSubExp "nest_size"
+ src/Futhark/Pass/ExtractKernels/ToGPU.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++module Futhark.Pass.ExtractKernels.ToGPU+ ( getSize,+ segThread,+ soacsLambdaToGPU,+ soacsStmToGPU,+ scopeForGPU,+ scopeForSOACs,+ injectSOACS,+ )+where++import Control.Monad.Identity+import Data.List ()+import Futhark.Analysis.Rephrase+import Futhark.IR+import Futhark.IR.GPU+import Futhark.IR.SOACS (SOACS)+import qualified Futhark.IR.SOACS.SOAC as SOAC+import Futhark.Tools++getSize ::+ (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) =>+ String ->+ SizeClass ->+ m SubExp+getSize desc size_class = do+ size_key <- nameFromString . pretty <$> newVName desc+ letSubExp desc $ Op $ SizeOp $ GetSize size_key size_class++segThread ::+ (MonadBinder m, Op (Rep m) ~ HostOp (Rep m) inner) =>+ String ->+ m SegLevel+segThread desc =+ SegThread+ <$> (Count <$> getSize (desc ++ "_num_groups") SizeNumGroups)+ <*> (Count <$> getSize (desc ++ "_group_size") SizeGroup)+ <*> pure SegVirt++injectSOACS ::+ ( Monad m,+ SameScope from to,+ ExpDec from ~ ExpDec to,+ BodyDec from ~ BodyDec to,+ RetType from ~ RetType to,+ BranchType from ~ BranchType to,+ Op from ~ SOAC from+ ) =>+ (SOAC to -> Op to) ->+ Rephraser m from to+injectSOACS f =+ Rephraser+ { rephraseExpDec = return,+ rephraseBodyDec = return,+ rephraseLetBoundDec = return,+ rephraseFParamDec = return,+ rephraseLParamDec = return,+ rephraseOp = fmap f . onSOAC,+ rephraseRetType = return,+ rephraseBranchType = return+ }+ where+ onSOAC = SOAC.mapSOACM mapper+ mapper =+ SOAC.SOACMapper+ { SOAC.mapOnSOACSubExp = return,+ SOAC.mapOnSOACVName = return,+ SOAC.mapOnSOACLambda = rephraseLambda $ injectSOACS f+ }++soacsStmToGPU :: Stm SOACS -> Stm GPU+soacsStmToGPU = runIdentity . rephraseStm (injectSOACS OtherOp)++soacsLambdaToGPU :: Lambda SOACS -> Lambda GPU+soacsLambdaToGPU = runIdentity . rephraseLambda (injectSOACS OtherOp)++scopeForSOACs :: Scope GPU -> Scope SOACS+scopeForSOACs = castScope++scopeForGPU :: Scope SOACS -> Scope GPU+scopeForGPU = castScope
− src/Futhark/Pass/ExtractKernels/ToKernels.hs
@@ -1,85 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}--module Futhark.Pass.ExtractKernels.ToKernels- ( getSize,- segThread,- soacsLambdaToKernels,- soacsStmToKernels,- scopeForKernels,- scopeForSOACs,- injectSOACS,- )-where--import Control.Monad.Identity-import Data.List ()-import Futhark.Analysis.Rephrase-import Futhark.IR-import Futhark.IR.Kernels-import Futhark.IR.SOACS (SOACS)-import qualified Futhark.IR.SOACS.SOAC as SOAC-import Futhark.Tools--getSize ::- (MonadBinder m, Op (Lore m) ~ HostOp (Lore m) inner) =>- String ->- SizeClass ->- m SubExp-getSize desc size_class = do- size_key <- nameFromString . pretty <$> newVName desc- letSubExp desc $ Op $ SizeOp $ GetSize size_key size_class--segThread ::- (MonadBinder m, Op (Lore m) ~ HostOp (Lore m) inner) =>- String ->- m SegLevel-segThread desc =- SegThread- <$> (Count <$> getSize (desc ++ "_num_groups") SizeNumGroups)- <*> (Count <$> getSize (desc ++ "_group_size") SizeGroup)- <*> pure SegVirt--injectSOACS ::- ( Monad m,- SameScope from to,- ExpDec from ~ ExpDec to,- BodyDec from ~ BodyDec to,- RetType from ~ RetType to,- BranchType from ~ BranchType to,- Op from ~ SOAC from- ) =>- (SOAC to -> Op to) ->- Rephraser m from to-injectSOACS f =- Rephraser- { rephraseExpLore = return,- rephraseBodyLore = return,- rephraseLetBoundLore = return,- rephraseFParamLore = return,- rephraseLParamLore = return,- rephraseOp = fmap f . onSOAC,- rephraseRetType = return,- rephraseBranchType = return- }- where- onSOAC = SOAC.mapSOACM mapper- mapper =- SOAC.SOACMapper- { SOAC.mapOnSOACSubExp = return,- SOAC.mapOnSOACVName = return,- SOAC.mapOnSOACLambda = rephraseLambda $ injectSOACS f- }--soacsStmToKernels :: Stm SOACS -> Stm Kernels-soacsStmToKernels = runIdentity . rephraseStm (injectSOACS OtherOp)--soacsLambdaToKernels :: Lambda SOACS -> Lambda Kernels-soacsLambdaToKernels = runIdentity . rephraseLambda (injectSOACS OtherOp)--scopeForSOACs :: Scope Kernels -> Scope SOACS-scopeForSOACs = castScope--scopeForKernels :: Scope SOACS -> Scope Kernels-scopeForKernels = castScope
src/Futhark/Pass/ExtractMulticore.hs view
@@ -25,7 +25,7 @@ import qualified Futhark.IR.SOACS.Simplify as SOACS import Futhark.Pass import Futhark.Pass.ExtractKernels.DistributeNests-import Futhark.Pass.ExtractKernels.ToKernels (injectSOACS)+import Futhark.Pass.ExtractKernels.ToGPU (injectSOACS) import Futhark.Tools import qualified Futhark.Transform.FirstOrderTransform as FOT import Futhark.Transform.Rename (Rename, renameSomething)
src/Futhark/Pass/FirstOrderTransform.hs view
@@ -24,10 +24,10 @@ import Futhark.IR.SOACS (SOACS, scopeOf) import Futhark.Pass-import Futhark.Transform.FirstOrderTransform (FirstOrderLore, transformConsts, transformFunDef)+import Futhark.Transform.FirstOrderTransform (FirstOrderRep, transformConsts, transformFunDef) -- | The first-order transformation pass.-firstOrderTransform :: FirstOrderLore lore => Pass SOACS lore+firstOrderTransform :: FirstOrderRep rep => Pass SOACS rep firstOrderTransform = Pass "first order transform"
src/Futhark/Pass/KernelBabysitting.hs view
@@ -11,7 +11,7 @@ import qualified Data.Map.Strict as M import Data.Maybe import Futhark.IR-import Futhark.IR.Kernels hiding+import Futhark.IR.GPU hiding ( BasicOp, Body, Exp,@@ -31,7 +31,7 @@ import Futhark.Util -- | The pass definition.-babysitKernels :: Pass Kernels Kernels+babysitKernels :: Pass GPU GPU babysitKernels = Pass "babysit kernels"@@ -42,12 +42,12 @@ let m = localScope scope $ transformStms mempty stms fmap fst $ modifyNameSource $ runState (runBinderT m M.empty) -type BabysitM = Binder Kernels+type BabysitM = Binder GPU -transformStms :: ExpMap -> Stms Kernels -> BabysitM (Stms Kernels)+transformStms :: ExpMap -> Stms GPU -> BabysitM (Stms GPU) transformStms expmap stms = collectStms_ $ foldM_ transformStm expmap stms -transformBody :: ExpMap -> Body Kernels -> BabysitM (Body Kernels)+transformBody :: ExpMap -> Body GPU -> BabysitM (Body GPU) transformBody expmap (Body () stms res) = do stms' <- transformStms expmap stms return $ Body () stms' res@@ -57,7 +57,7 @@ -- funky in memory (and we'd prefer it not to be). If we cannot find -- it in the map, we just assume it's all good. HACK and FIXME, I -- suppose. We really should do this at the memory level.-type ExpMap = M.Map VName (Stm Kernels)+type ExpMap = M.Map VName (Stm GPU) nonlinearInMemory :: VName -> ExpMap -> Maybe (Maybe [Int]) nonlinearInMemory name m =@@ -80,7 +80,7 @@ return $ Just $ rearrangeInverse $ [inner_r .. inner_r + outer_r -1] ++ [0 .. inner_r -1] | otherwise = Nothing -transformStm :: ExpMap -> Stm Kernels -> BabysitM ExpMap+transformStm :: ExpMap -> Stm GPU -> BabysitM ExpMap transformStm expmap (Let pat aux (Op (SegOp op))) -- FIXME: We only make coalescing optimisations for SegThread -- SegOps, because that's what the analysis assumes. For SegGroup@@ -102,7 +102,7 @@ addStm bnd' return $ M.fromList [(name, bnd') | name <- patternNames pat] <> expmap -transform :: ExpMap -> Mapper Kernels Kernels BabysitM+transform :: ExpMap -> Mapper GPU GPU BabysitM transform expmap = identityMapper {mapOnBody = \scope -> localScope scope . transformBody expmap} @@ -110,8 +110,8 @@ ExpMap -> SegLevel -> SegSpace ->- KernelBody Kernels ->- BabysitM (KernelBody Kernels)+ KernelBody GPU ->+ BabysitM (KernelBody GPU) transformKernelBody expmap lvl space kbody = do -- Go spelunking for accesses to arrays that are defined outside the -- kernel body and where the indices are kernel thread indices.@@ -143,7 +143,7 @@ (VName -> Bool) -> -- thread local? (VName -> SubExp -> Bool) -> -- variant to a certain gid (given as first param)? (SubExp -> Maybe SubExp) -> -- split substitution?- Scope Kernels -> -- type environment+ Scope GPU -> -- type environment VName -> Slice SubExp -> m (Maybe (VName, Slice SubExp))@@ -152,10 +152,10 @@ (Applicative f, Monad f) => Names -> Names ->- Scope Kernels ->+ Scope GPU -> ArrayIndexTransform f ->- KernelBody Kernels ->- f (KernelBody Kernels)+ KernelBody GPU ->+ f (KernelBody GPU) traverseKernelBodyArrayIndexes free_ker_vars thread_variant outer_scope f (KernelBody () kstms kres) = KernelBody () . stmsFromList <$> mapM@@ -513,10 +513,10 @@ type VarianceTable = M.Map VName Names -varianceInStms :: VarianceTable -> Stms Kernels -> VarianceTable+varianceInStms :: VarianceTable -> Stms GPU -> VarianceTable varianceInStms t = foldl varianceInStm t . stmsToList -varianceInStm :: VarianceTable -> Stm Kernels -> VarianceTable+varianceInStm :: VarianceTable -> Stm GPU -> VarianceTable varianceInStm variance bnd = foldl' add variance $ patternNames $ stmPattern bnd where
src/Futhark/Pass/Simplify.hs view
@@ -5,15 +5,15 @@ simplifySOACS, simplifySeq, simplifyMC,- simplifyKernels,- simplifyKernelsMem,+ simplifyGPU,+ simplifyGPUMem, simplifySeqMem, simplifyMCMem, ) where -import qualified Futhark.IR.Kernels.Simplify as Kernels-import qualified Futhark.IR.KernelsMem as KernelsMem+import qualified Futhark.IR.GPU.Simplify as GPU+import qualified Futhark.IR.GPUMem as GPUMem import qualified Futhark.IR.MC as MC import qualified Futhark.IR.MCMem as MCMem import qualified Futhark.IR.SOACS.Simplify as SOACS@@ -23,15 +23,15 @@ import Futhark.Pass simplify ::- (Prog lore -> PassM (Prog lore)) ->- Pass lore lore+ (Prog rep -> PassM (Prog rep)) ->+ Pass rep rep simplify = Pass "simplify" "Perform simple enabling optimisations." simplifySOACS :: Pass SOACS.SOACS SOACS.SOACS simplifySOACS = simplify SOACS.simplifySOACS -simplifyKernels :: Pass Kernels.Kernels Kernels.Kernels-simplifyKernels = simplify Kernels.simplifyKernels+simplifyGPU :: Pass GPU.GPU GPU.GPU+simplifyGPU = simplify GPU.simplifyGPU simplifySeq :: Pass Seq.Seq Seq.Seq simplifySeq = simplify Seq.simplifyProg@@ -39,8 +39,8 @@ simplifyMC :: Pass MC.MC MC.MC simplifyMC = simplify MC.simplifyProg -simplifyKernelsMem :: Pass KernelsMem.KernelsMem KernelsMem.KernelsMem-simplifyKernelsMem = simplify KernelsMem.simplifyProg+simplifyGPUMem :: Pass GPUMem.GPUMem GPUMem.GPUMem+simplifyGPUMem = simplify GPUMem.simplifyProg simplifySeqMem :: Pass SeqMem.SeqMem SeqMem.SeqMem simplifySeqMem = simplify SeqMem.simplifyProg
src/Futhark/Passes.hs view
@@ -13,8 +13,8 @@ where import Control.Category ((>>>))-import Futhark.IR.Kernels (Kernels)-import Futhark.IR.KernelsMem (KernelsMem)+import Futhark.IR.GPU (GPU)+import Futhark.IR.GPUMem (GPUMem) import Futhark.IR.MC (MC) import Futhark.IR.MCMem (MCMem) import Futhark.IR.SOACS (SOACS)@@ -25,11 +25,12 @@ import Futhark.Optimise.Fusion import Futhark.Optimise.InPlaceLowering import Futhark.Optimise.InliningDeadFun+import qualified Futhark.Optimise.ReuseAllocations as ReuseAllocations import Futhark.Optimise.Sink import Futhark.Optimise.TileLoops import Futhark.Optimise.Unstream import Futhark.Pass.ExpandAllocations-import qualified Futhark.Pass.ExplicitAllocations.Kernels as Kernels+import qualified Futhark.Pass.ExplicitAllocations.GPU as GPU import qualified Futhark.Pass.ExplicitAllocations.MC as MC import qualified Futhark.Pass.ExplicitAllocations.Seq as Seq import Futhark.Pass.ExtractKernels@@ -57,19 +58,19 @@ removeDeadFunctions ] -kernelsPipeline :: Pipeline SOACS Kernels+kernelsPipeline :: Pipeline SOACS GPU kernelsPipeline = standardPipeline >>> onePass extractKernels >>> passes- [ simplifyKernels,+ [ simplifyGPU, babysitKernels, tileLoops,- unstreamKernels,+ unstreamGPU, performCSE True,- simplifyKernels,- sinkKernels,- inPlaceLoweringKernels+ simplifyGPU,+ sinkGPU,+ inPlaceLoweringGPU ] sequentialPipeline :: Pipeline SOACS Seq@@ -91,18 +92,20 @@ simplifySeqMem ] -gpuPipeline :: Pipeline SOACS KernelsMem+gpuPipeline :: Pipeline SOACS GPUMem gpuPipeline = kernelsPipeline- >>> onePass Kernels.explicitAllocations+ >>> onePass GPU.explicitAllocations >>> passes- [ simplifyKernelsMem,+ [ simplifyGPUMem, performCSE False,- simplifyKernelsMem,- doubleBufferKernels,- simplifyKernelsMem,+ simplifyGPUMem,+ doubleBufferGPU,+ simplifyGPUMem,+ ReuseAllocations.optimise,+ simplifyGPUMem, expandAllocations,- simplifyKernelsMem+ simplifyGPUMem ] mcPipeline :: Pipeline SOACS MC
src/Futhark/Pipeline.hs view
@@ -37,7 +37,7 @@ import Data.Time.Clock import qualified Futhark.Analysis.Alias as Alias import Futhark.Error-import Futhark.IR (PrettyLore, Prog)+import Futhark.IR (PrettyRep, Prog) import Futhark.MonadFreshNames import Futhark.Pass import Futhark.TypeCheck@@ -103,10 +103,10 @@ newEnv = FutharkEnv verbose -- | A compilation always ends with some kind of action.-data Action lore = Action+data Action rep = Action { actionName :: String, actionDescription :: String,- actionProcedure :: Prog lore -> FutharkM ()+ actionProcedure :: Prog rep -> FutharkM () } -- | Configuration object for running a compiler pipeline.@@ -118,7 +118,7 @@ -- | A compiler pipeline is conceptually a function from programs to -- programs, where the actual representation may change. Pipelines -- can be composed using their 'Category' instance.-newtype Pipeline fromlore tolore = Pipeline {unPipeline :: PipelineConfig -> Prog fromlore -> FutharkM (Prog tolore)}+newtype Pipeline fromrep torep = Pipeline {unPipeline :: PipelineConfig -> Prog fromrep -> FutharkM (Prog torep)} instance Category Pipeline where id = Pipeline $ const return@@ -129,17 +129,17 @@ -- | Run the pipeline on the given program. runPipeline ::- Pipeline fromlore tolore ->+ Pipeline fromrep torep -> PipelineConfig ->- Prog fromlore ->- FutharkM (Prog tolore)+ Prog fromrep ->+ FutharkM (Prog torep) runPipeline = unPipeline -- | Construct a pipeline from a single compiler pass. onePass ::- Checkable tolore =>- Pass fromlore tolore ->- Pipeline fromlore tolore+ Checkable torep =>+ Pass fromrep torep ->+ Pipeline fromrep torep onePass pass = Pipeline perform where perform cfg prog = do@@ -156,15 +156,15 @@ -- | Create a pipeline from a list of passes. passes ::- Checkable lore =>- [Pass lore lore] ->- Pipeline lore lore+ Checkable rep =>+ [Pass rep rep] ->+ Pipeline rep rep passes = foldl (>>>) id . map onePass validationError ::- PrettyLore lore =>- Pass fromlore tolore ->- Prog lore ->+ PrettyRep rep =>+ Pass fromrep torep ->+ Prog rep -> String -> FutharkM a validationError pass prog err =@@ -173,9 +173,9 @@ msg = "Type error after pass '" <> T.pack (passName pass) <> "':\n" <> T.pack err runPass ::- Pass fromlore tolore ->- Prog fromlore ->- FutharkM (Prog tolore)+ Pass fromrep torep ->+ Prog fromrep ->+ FutharkM (Prog torep) runPass pass prog = do (prog', logged) <- runPassM (passFunction pass prog) verb <- asks $ (>= VeryVerbose) . futharkVerbose
src/Futhark/Script.hs view
@@ -34,8 +34,6 @@ where import Control.Monad.Except-import qualified Data.Binary as Bin-import qualified Data.ByteString.Lazy.Char8 as LBS import Data.Char import Data.Foldable (toList) import Data.Functor@@ -46,13 +44,12 @@ import qualified Data.Text as T import Data.Traversable import Data.Void+import qualified Futhark.Data.Parser as V import Futhark.Server+import Futhark.Server.Values (getValue, putValue) import qualified Futhark.Test.Values as V-import qualified Futhark.Test.Values.Parser as V import Futhark.Util (nubOrd) import Futhark.Util.Pretty hiding (float, line, sep, string, (</>), (<|>))-import System.IO-import System.IO.Temp import Text.Megaparsec import Text.Megaparsec.Char.Lexer (charLiteral) @@ -69,9 +66,9 @@ -- | Start a server, execute an action, then shut down the server. -- Similar to 'withServer'.-withScriptServer :: FilePath -> [FilePath] -> (ScriptServer -> IO a) -> IO a-withScriptServer prog options f =- withServer prog options $ flip withScriptServer' f+withScriptServer :: ServerCfg -> (ScriptServer -> IO a) -> IO a+withScriptServer cfg f =+ withServer cfg $ flip withScriptServer' f -- | A function called in a 'Call' expression can be either a Futhark -- function or a builtin function.@@ -101,7 +98,7 @@ instance Pretty Exp where ppr = pprPrec 0 pprPrec _ (ServerVar _ v) = "$" <> ppr v- pprPrec _ (Const v) = ppr v+ pprPrec _ (Const v) = strictText $ V.valueText v pprPrec i (Let pat e1 e2) = parensIf (i > 0) $ "let" <+> pat' <+> equals <+> ppr e1 <+> "in" <+> ppr e2 where@@ -137,11 +134,8 @@ <*> pPattern <* lexeme sep "=" <*> parseExp sep <* lexeme sep "in" <*> parseExp sep,- inParens sep (mkTuple <$> (parseExp sep `sepBy` pComma)),- inBraces sep (Record <$> (pField `sepBy` pComma)),- Call <$> parseFunc <*> many (parseExp sep),- Const <$> V.parseValue sep,- StringLit . T.pack <$> lexeme sep ("\"" *> manyTill charLiteral "\"")+ try $ Call <$> parseFunc <*> many pAtom,+ pAtom ] <?> "expression" where@@ -151,6 +145,16 @@ mkTuple [v] = v mkTuple vs = Tuple vs + pAtom =+ choice+ [ try $ inParens sep (mkTuple <$> (parseExp sep `sepBy` pComma)),+ inParens sep $ parseExp sep,+ inBraces sep (Record <$> (pField `sepBy` pComma)),+ Const <$> V.parseValue sep,+ StringLit . T.pack <$> lexeme sep ("\"" *> manyTill charLiteral "\""),+ Call <$> parseFunc <*> pure []+ ]+ pPattern = choice [ inParens sep $ pVarName `sepBy` pComma,@@ -172,35 +176,13 @@ where constituent c = isAlphaNum c || c == '_' -prettyFailure :: CmdFailure -> T.Text-prettyFailure (CmdFailure bef aft) =- T.unlines $ bef ++ aft- readVar :: (MonadError T.Text m, MonadIO m) => Server -> VarName -> m V.Value readVar server v =- either throwError pure <=< liftIO $- withSystemTempFile "futhark-server-read" $ \tmpf tmpf_h -> do- hClose tmpf_h- store_res <- cmdStore server tmpf [v]- case store_res of- Just err -> pure $ Left $ prettyFailure err- Nothing -> do- s <- LBS.readFile tmpf- case V.readValues s of- Just [val] -> pure $ Right val- Just [] -> pure $ Left "Cannot read opaque value from Futhark server."- _ -> pure $ Left "Invalid data file produced by Futhark server."+ either throwError pure =<< liftIO (getValue server v) writeVar :: (MonadError T.Text m, MonadIO m) => Server -> VarName -> V.Value -> m () writeVar server v val =- cmdMaybe . liftIO . withSystemTempFile "futhark-server-write" $ \tmpf tmpf_h -> do- LBS.hPutStr tmpf_h $ Bin.encode val- hClose tmpf_h- -- We are not using prettyprinting for the type, because we don't- -- want the sizes of the dimensions.- let V.ValueType dims t = V.valueType val- t' = mconcat (map (const "[]") dims) <> prettyText t- cmdRestore server tmpf [(v, t')]+ cmdMaybe $ liftIO (putValue server v val) -- | A ScriptValue is either a base value or a partially applied -- function. We don't have real first-class functions in@@ -327,7 +309,7 @@ valToInterVal :: V.CompoundValue -> ExpValue valToInterVal = fmap $ \v ->- SValue (V.prettyValueTypeNoDims (V.valueType v)) $ VVal v+ SValue (V.valueTypeTextNoDims (V.valueType v)) $ VVal v simpleType (V.ValueAtom (STValue _)) = True simpleType _ = False@@ -355,8 +337,8 @@ throwError $ "Locally bound name cannot be invoked as a function: " <> prettyText name pure e evalExp' vtable (Call (FuncFut name) es) = do- in_types <- cmdEither $ cmdInputs server name- out_types <- cmdEither $ cmdOutputs server name+ in_types <- fmap (map inputType) $ cmdEither $ cmdInputs server name+ out_types <- fmap (map outputType) $ cmdEither $ cmdOutputs server name es' <- mapM (evalExp' vtable) es let es_types = map (fmap scriptValueType) es'@@ -382,17 +364,17 @@ then do outs <- replicateM (length out_types) $ newVar "out" void $ cmdEither $ cmdCall server name outs ins- pure $ V.mkCompound $ zipWith SValue out_types $ map VVar outs+ pure $ V.mkCompound $ map V.ValueAtom $ zipWith SValue out_types $ map VVar outs else pure . V.ValueAtom . SFun name in_types out_types $ zipWith SValue in_types $ map VVar ins evalExp' _ (StringLit s) = case V.putValue s of Just s' ->- pure $ V.ValueAtom $ SValue (prettyText (V.valueType s')) $ VVal s'+ pure $ V.ValueAtom $ SValue (V.valueTypeText (V.valueType s')) $ VVal s' Nothing -> error $ "Unable to write value " ++ pretty s evalExp' _ (Const val) =- pure $ V.ValueAtom $ SValue (V.prettyValueTypeNoDims (V.valueType val)) $ VVal val+ pure $ V.ValueAtom $ SValue (V.valueTypeTextNoDims (V.valueType val)) $ VVal val evalExp' vtable (Tuple es) = V.ValueTuple <$> mapM (evalExp' vtable) es evalExp' vtable e@(Record m) = do
− src/Futhark/Server.hs
@@ -1,211 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}---- | Haskell code for interacting with a Futhark server program (a--- program compiled with @--server@).-module Futhark.Server- ( Server,- withServer,- CmdFailure (..),- VarName,- TypeName,- EntryName,- cmdRestore,- cmdStore,- cmdCall,- cmdFree,- cmdRename,- cmdInputs,- cmdOutputs,- cmdClear,- cmdReport,- cmdMaybe,- cmdEither,- )-where--import Control.Exception-import Control.Monad-import Control.Monad.Except-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.IO as T-import Futhark.Util (isEnvVarAtLeast)-import System.Directory (removeFile)-import System.Exit-import System.IO hiding (stdin, stdout)-import System.IO.Temp-import qualified System.Process as P---- | A handle to a running server.-data Server = Server- { serverStdin :: Handle,- serverStdout :: Handle,- serverErrLog :: FilePath,- serverProc :: P.ProcessHandle,- serverDebug :: Bool- }--startServer :: FilePath -> [FilePath] -> IO Server-startServer prog options = do- tmpdir <- getCanonicalTemporaryDirectory- (err_log_f, err_log_h) <- openTempFile tmpdir "futhark-server-stderr.log"- (Just stdin, Just stdout, Nothing, phandle) <-- P.createProcess- ( (P.proc prog options)- { P.std_err = P.UseHandle err_log_h,- P.std_in = P.CreatePipe,- P.std_out = P.CreatePipe- }- )-- code <- P.getProcessExitCode phandle- case code of- Just (ExitFailure e) ->- error $ "Cannot start " ++ prog ++ ": error " ++ show e- _ -> do- let server =- Server- { serverStdin = stdin,- serverStdout = stdout,- serverProc = phandle,- serverDebug = isEnvVarAtLeast "FUTHARK_COMPILER_DEBUGGING" 1,- serverErrLog = err_log_f- }- void (responseLines server) `catch` onStartupError server- pure server- where- onStartupError :: Server -> IOError -> IO a- onStartupError s _ = do- code <- P.waitForProcess $ serverProc s- stderr_s <- readFile $ serverErrLog s- removeFile $ serverErrLog s- error $- "Command failed with " ++ show code ++ ":\n"- ++ unwords (prog : options)- ++ "\nStderr:\n"- ++ stderr_s--stopServer :: Server -> IO ()-stopServer s = do- hClose $ serverStdin s- void $ P.waitForProcess $ serverProc s- removeFile $ serverErrLog s---- | Start a server, execute an action, then shut down the server.-withServer :: FilePath -> [FilePath] -> (Server -> IO a) -> IO a-withServer prog options = bracket (startServer prog options) stopServer---- Read lines of response until the next %%% OK (which is what--- indicates that the server is ready for new instructions).-responseLines :: Server -> IO [Text]-responseLines s = do- l <- T.hGetLine $ serverStdout s- when (serverDebug s) $- T.hPutStrLn stderr $ "<<< " <> l- case l of- "%%% OK" -> pure []- _ -> (l :) <$> responseLines s---- | The command failed, and this is why. The first 'Text' is any--- output before the failure indincator, and the second Text is the--- output after the indicator.-data CmdFailure = CmdFailure {failureLog :: [Text], failureMsg :: [Text]}- deriving (Eq, Ord, Show)---- Figure out whether the response is a failure, and if so, return the--- failure message.-checkForFailure :: [Text] -> Either CmdFailure [Text]-checkForFailure [] = Right []-checkForFailure ("%%% FAILURE" : ls) = Left $ CmdFailure mempty ls-checkForFailure (l : ls) =- case checkForFailure ls of- Left (CmdFailure xs ys) -> Left $ CmdFailure (l : xs) ys- Right ls' -> Right $ l : ls'---- Words with spaces in them must be quoted.-quoteWord :: Text -> Text-quoteWord t- | Just _ <- T.find (== ' ') t =- "\"" <> t <> "\""- | otherwise = t--sendCommand :: Server -> [Text] -> IO (Either CmdFailure [Text])-sendCommand s command = do- let command' = T.unwords $ map quoteWord command-- when (serverDebug s) $- T.hPutStrLn stderr $ ">>> " <> command'-- T.hPutStrLn (serverStdin s) command'- hFlush $ serverStdin s- checkForFailure <$> responseLines s `catch` onError- where- onError :: IOError -> IO a- onError e = do- code <- P.getProcessExitCode $ serverProc s- let code_msg =- case code of- Just (ExitFailure x) ->- "\nServer process exited unexpectedly with exit code: " ++ show x- _ -> mempty- stderr_s <- readFile $ serverErrLog s- error $- "After sending command " ++ show command ++ " to server process:"- ++ show e- ++ code_msg- ++ "\nServer stderr:\n"- ++ stderr_s---- | The name of a server-side variable.-type VarName = Text---- | The name of a server-side type.-type TypeName = Text---- | The name of an entry point.-type EntryName = Text--helpCmd :: Server -> [Text] -> IO (Maybe CmdFailure)-helpCmd s cmd =- either Just (const Nothing) <$> sendCommand s cmd--cmdRestore :: Server -> FilePath -> [(VarName, TypeName)] -> IO (Maybe CmdFailure)-cmdRestore s fname vars = helpCmd s $ "restore" : T.pack fname : concatMap f vars- where- f (v, t) = [v, t]--cmdStore :: Server -> FilePath -> [VarName] -> IO (Maybe CmdFailure)-cmdStore s fname vars = helpCmd s $ "store" : T.pack fname : vars--cmdCall :: Server -> EntryName -> [VarName] -> [VarName] -> IO (Either CmdFailure [T.Text])-cmdCall s entry outs ins =- sendCommand s $ "call" : entry : outs ++ ins--cmdFree :: Server -> [VarName] -> IO (Maybe CmdFailure)-cmdFree s vs = helpCmd s $ "free" : vs--cmdRename :: Server -> VarName -> VarName -> IO (Maybe CmdFailure)-cmdRename s oldname newname = helpCmd s ["rename", oldname, newname]--cmdInputs :: Server -> EntryName -> IO (Either CmdFailure [TypeName])-cmdInputs s entry =- sendCommand s ["inputs", entry]--cmdOutputs :: Server -> EntryName -> IO (Either CmdFailure [TypeName])-cmdOutputs s entry =- sendCommand s ["outputs", entry]--cmdClear :: Server -> IO (Maybe CmdFailure)-cmdClear s = helpCmd s ["clear"]--cmdReport :: Server -> IO (Either CmdFailure [T.Text])-cmdReport s = sendCommand s ["report"]---- | Turn a 'Maybe'-producing command into a monadic action.-cmdMaybe :: (MonadError T.Text m, MonadIO m) => IO (Maybe CmdFailure) -> m ()-cmdMaybe = maybe (pure ()) (throwError . T.unlines . failureMsg) <=< liftIO---- | Turn an 'Either'-producing command into a monadic action.-cmdEither :: (MonadError T.Text m, MonadIO m) => IO (Either CmdFailure a) -> m a-cmdEither = either (throwError . T.unlines . failureMsg) pure <=< liftIO
src/Futhark/Test.hs view
@@ -15,7 +15,7 @@ getValues, getValuesBS, valuesAsVars,- compareValues,+ V.compareValues, checkResult, testRunReferenceOutput, getExpectedResult,@@ -25,7 +25,8 @@ ensureReferenceOutput, determineTuning, binaryName,- Mismatch,+ futharkServerCfg,+ V.Mismatch, ProgramTest (..), StructureTest (..), StructurePipeline (..),@@ -37,7 +38,8 @@ ExpectedResult (..), Success (..), Values (..),- Value,+ V.Value,+ V.valueText, ) where @@ -62,15 +64,14 @@ import qualified Data.Text.IO as T import Data.Void import Futhark.Analysis.Metrics.Type-import Futhark.IR.Primitive (floatByteSize, intByteSize)+import Futhark.Data.Parser+import qualified Futhark.Data.Parser as V import qualified Futhark.Script as Script import Futhark.Server-import Futhark.Test.Values-import Futhark.Test.Values.Parser-import Futhark.Util (directoryContents, pmapIO)-import Futhark.Util.Pretty (pretty, prettyOneLine, prettyText, prettyTextOneLine)-import Language.Futhark.Prop (primByteSize, primValueType)-import Language.Futhark.Syntax (PrimType (..), PrimValue (..))+import Futhark.Server.Values+import qualified Futhark.Test.Values as V+import Futhark.Util (directoryContents, isEnvVarAtLeast, pmapIO)+import Futhark.Util.Pretty (prettyOneLine, prettyText, prettyTextOneLine) import System.Directory import System.Exit import System.FilePath@@ -151,7 +152,7 @@ -- | Several values - either literally, or by reference to a file, or -- to be generated on demand. All paths are relative to test program. data Values- = Values [Value]+ = Values [V.Value] | InFile FilePath | GenValues [GenValue] | ScriptValues Script.Exp@@ -161,18 +162,18 @@ data GenValue = -- | Generate a value of the given rank and primitive -- type. Scalars are considered 0-ary arrays.- GenValue ValueType+ GenValue V.ValueType | -- | A fixed non-randomised primitive value.- GenPrim PrimValue+ GenPrim V.Value deriving (Show) -- | A prettyprinted representation of type of value produced by a -- 'GenValue'. genValueType :: GenValue -> String-genValueType (GenValue (ValueType ds t)) =- concatMap (\d -> "[" ++ show d ++ "]") ds ++ pretty t+genValueType (GenValue (V.ValueType ds t)) =+ concatMap (\d -> "[" ++ show d ++ "]") ds ++ T.unpack (V.primTypeText t) genValueType (GenPrim v) =- pretty v+ T.unpack $ V.valueText v -- | How a test case is expected to terminate. data ExpectedResult values@@ -309,7 +310,7 @@ -- Turn linebreaks into space. "#" ++ show i ++ " (\"" ++ unwords (lines vs') ++ "\")" where- vs' = case unwords (map pretty vs) of+ vs' = case unwords $ map (T.unpack . V.valueText) vs of s | length s > 50 -> take 50 s ++ "..." | otherwise -> s@@ -352,7 +353,7 @@ parseGenValue = choice [ GenValue <$> lexeme parseType,- GenPrim <$> lexeme parsePrimValue+ GenPrim <$> lexeme V.parsePrimValue ] parseValues :: Parser Values@@ -481,9 +482,9 @@ -- | Try to parse a several values from a byte string. The 'String' -- parameter is used for error messages.-valuesFromByteString :: String -> BS.ByteString -> Either String [Value]+valuesFromByteString :: String -> BS.ByteString -> Either String [V.Value] valuesFromByteString srcname =- maybe (Left $ "Cannot parse values from '" ++ srcname ++ "'") Right . readValues+ maybe (Left $ "Cannot parse values from '" ++ srcname ++ "'") Right . V.readValues -- | The @futhark@ executable we are using. This is merely a wrapper -- around the underlying file path, because we will be using a lot of@@ -495,7 +496,7 @@ -- specification. The first 'FilePath' is the path of the @futhark@ -- executable, and the second is the directory which file paths are -- read relative to.-getValues :: (MonadFail m, MonadIO m) => FutharkExe -> FilePath -> Values -> m [Value]+getValues :: (MonadFail m, MonadIO m) => FutharkExe -> FilePath -> Values -> m [V.Value] getValues _ _ (Values vs) = return vs getValues futhark dir v = do@@ -521,7 +522,7 @@ -- guarantee that the resulting byte string yields a readable value. getValuesBS :: (MonadFail m, MonadIO m) => FutharkExe -> FilePath -> Values -> m BS.ByteString getValuesBS _ _ (Values vs) =- return $ BS.fromStrict $ T.encodeUtf8 $ T.unlines $ map prettyText vs+ return $ BS.fromStrict $ T.encodeUtf8 $ T.unlines $ map V.valueText vs getValuesBS _ dir (InFile file) = case takeExtension file of ".gz" -> liftIO $ do@@ -543,14 +544,10 @@ (MonadError T.Text m, MonadIO m) => Server -> VarName ->- TypeName ->- Value ->+ V.Value -> m ()-valueAsVar server v t val = do- cmdMaybe . withSystemTempFile "futhark-input" $ \tmpf tmpf_h -> do- BS.hPutStr tmpf_h $ Bin.encode val- hClose tmpf_h- cmdRestore server tmpf [(v, t)]+valueAsVar server v val =+ cmdMaybe $ putValue server v val -- Frees the expression on error. scriptValueAsVars ::@@ -560,24 +557,24 @@ Script.ExpValue -> m () scriptValueAsVars server names_and_types val- | vals <- unCompound val,+ | vals <- V.unCompound val, length names_and_types == length vals, Just loads <- zipWithM f names_and_types vals = sequence_ loads where- f (v, t0) (ValueAtom (Script.SValue t1 sval))+ f (v, t0) (V.ValueAtom (Script.SValue t1 sval)) | t0 == t1 = Just $ case sval of Script.VVar oldname -> cmdMaybe $ cmdRename server oldname v Script.VVal sval' ->- valueAsVar server v t0 sval'+ valueAsVar server v sval' f _ _ = Nothing scriptValueAsVars server names_and_types val = do cmdMaybe $ cmdFree server $ S.toList $ Script.serverVarsInValue val throwError $ "Expected value of type: "- <> prettyTextOneLine (mkCompound (map snd names_and_types))+ <> prettyTextOneLine (V.mkCompound (map (V.ValueAtom . snd) names_and_types)) <> "\nBut got value of type: " <> prettyTextOneLine (fmap Script.scriptValueType val) <> notes@@ -703,16 +700,12 @@ genFileSize = genSize where header_size = 1 + 1 + 1 + 4 -- 'b' <version> <num_dims> <type>- genSize (GenValue (ValueType ds t)) =- header_size + toInteger (length ds) * 8- + product (map toInteger ds) * primSize t+ genSize (GenValue (V.ValueType ds t)) =+ toInteger $+ header_size + length ds * 8+ + product ds * V.primTypeBytes t genSize (GenPrim v) =- header_size + primByteSize (primValueType v)-- primSize (Signed it) = intByteSize it- primSize (Unsigned it) = intByteSize it- primSize (FloatType ft) = floatByteSize ft- primSize Bool = 1+ toInteger $ header_size + product (V.valueShape v) * V.primTypeBytes (V.valueElemType v) -- | When/if generating a reference output file for this run, what -- should it be called? Includes the "data/" folder.@@ -737,7 +730,7 @@ FilePath -> T.Text -> TestRun ->- m (ExpectedResult [Value])+ m (ExpectedResult [V.Value]) getExpectedResult futhark prog entry tr = case runExpectedResult tr of (Succeeds (Just (SuccessValues vals))) ->@@ -821,23 +814,9 @@ (MonadIO m, MonadError T.Text m) => Server -> [VarName] ->- FilePath ->- m [Value]-readResults server outs program =- join . liftIO . withSystemTempFile "futhark-output" $ \outputf outputh -> do- hClose outputh- store_r <- cmdStore server outputf outs- case store_r of- Just (CmdFailure _ err) ->- pure $ throwError $ T.unlines err- Nothing -> do- bytes <- BS.readFile outputf- case valuesFromByteString "output" bytes of- Left e -> do- let actualf = program `addExtension` "actual"- liftIO $ BS.writeFile actualf bytes- pure $ throwError $ T.pack e <> "\n(See " <> T.pack actualf <> ")"- Right vs -> pure $ pure vs+ m [V.Value]+readResults server =+ mapM (either throwError pure <=< liftIO . getValue server) -- | Ensure that any reference output files exist, or create them (by -- compiling the program with the reference compiler and running it on@@ -910,11 +889,11 @@ checkResult :: (MonadError T.Text m, MonadIO m) => FilePath ->- [Value] ->- [Value] ->+ [V.Value] ->+ [V.Value] -> m () checkResult program expected_vs actual_vs =- case compareValues actual_vs expected_vs of+ case V.compareSeveralValues (V.Tolerance 0.002) actual_vs expected_vs of mismatch : mismatches -> do let actualf = program <.> "actual" expectedf = program <.> "expected"@@ -929,3 +908,11 @@ else "\n...and " <> prettyText (length mismatches) <> " other mismatches." [] -> return ()++-- | Create a Futhark server configuration suitable for use when+-- testing/benchmarking Futhark programs.+futharkServerCfg :: FilePath -> [String] -> ServerCfg+futharkServerCfg prog opts =+ (newServerCfg prog opts)+ { cfgDebug = isEnvVarAtLeast "FUTHARK_COMPILER_DEBUGGING" 1+ }
src/Futhark/Test/Values.hs view
@@ -1,203 +1,34 @@ {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Strict #-} {-# LANGUAGE Trustworthy #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} --- | This module defines an efficient value representation as well as--- parsing and comparison functions. This is because the standard--- Futhark parser is not able to cope with large values (like arrays--- that are tens of megabytes in size). The representation defined--- here does not support tuples, so don't use those as input/output--- for your test programs.+-- | This module provides an efficient value representation as well as+-- parsing and comparison functions. module Futhark.Test.Values- ( Value (..),+ ( module Futhark.Data,+ module Futhark.Data.Compare,+ module Futhark.Data.Reader, Compound (..), CompoundValue,- Vector,-- -- * Reading Values- readValues,-- -- * Types of values- ValueType (..),- prettyValueTypeNoDims,- valueType,- valueShape,-- -- * Manipulating values- valueElems, mkCompound, unCompound,-- -- * Comparing Values- compareValues,- Mismatch,-- -- * Converting values- GetValue (..),- PutValue (..), ) where -import Control.Monad-import Control.Monad.ST-import Data.Binary-import Data.Binary.Get-import Data.Binary.Put-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy.Char8 as LBS-import Data.Char (chr, isSpace, ord)-import Data.Int (Int16, Int32, Int64, Int8)-import Data.List (intercalate) import qualified Data.Map as M import qualified Data.Text as T-import qualified Data.Text.Encoding as T import Data.Traversable-import Data.Vector.Generic (freeze)-import qualified Data.Vector.Storable as SVec-import Data.Vector.Storable.ByteString (byteStringToVector, vectorToByteString)-import qualified Data.Vector.Unboxed as UVec-import qualified Data.Vector.Unboxed.Mutable as UMVec-import Futhark.IR.Primitive (PrimValue)-import Futhark.IR.Prop.Constants (IsValue (..))-import Futhark.IR.Prop.Reshape (unflattenIndex)-import Futhark.Util.IntegralExp-import Futhark.Util.Loc (Pos (..))+import Futhark.Data+import Futhark.Data.Compare+import Futhark.Data.Reader import Futhark.Util.Pretty-import qualified Futhark.Util.Pretty as PP-import Language.Futhark.Parser.Lexer-import Language.Futhark.Pretty ()-import qualified Language.Futhark.Syntax as F -type STVector s = UMVec.STVector s---- | The value vector type.-type Vector = SVec.Vector---- | An efficiently represented Futhark value. Use 'pretty' to get a--- human-readable representation, and v'put' to obtain binary a--- representation.-data Value- = Int8Value (Vector Int) (Vector Int8)- | Int16Value (Vector Int) (Vector Int16)- | Int32Value (Vector Int) (Vector Int32)- | Int64Value (Vector Int) (Vector Int64)- | Word8Value (Vector Int) (Vector Word8)- | Word16Value (Vector Int) (Vector Word16)- | Word32Value (Vector Int) (Vector Word32)- | Word64Value (Vector Int) (Vector Word64)- | Float32Value (Vector Int) (Vector Float)- | Float64Value (Vector Int) (Vector Double)- | BoolValue (Vector Int) (Vector Bool)- deriving (Show)--binaryFormatVersion :: Word8-binaryFormatVersion = 2--instance Binary Value where- put (Int8Value shape vs) = putBinaryValue " i8" shape vs- put (Int16Value shape vs) = putBinaryValue " i16" shape vs- put (Int32Value shape vs) = putBinaryValue " i32" shape vs- put (Int64Value shape vs) = putBinaryValue " i64" shape vs- put (Word8Value shape vs) = putBinaryValue " u8" shape vs- put (Word16Value shape vs) = putBinaryValue " u16" shape vs- put (Word32Value shape vs) = putBinaryValue " u32" shape vs- put (Word64Value shape vs) = putBinaryValue " u64" shape vs- put (Float32Value shape vs) = putBinaryValue " f32" shape vs- put (Float64Value shape vs) = putBinaryValue " f64" shape vs- -- Bool must be treated specially because the Storable instance- -- uses four bytes.- put (BoolValue shape vs) = putBinaryValue "bool" shape $ SVec.map boolToInt8 vs- where- boolToInt8 True = 1 :: Int8- boolToInt8 False = 0-- get = do- first <- getInt8- version <- getWord8- rank <- getInt8-- unless (chr (fromIntegral first) == 'b') $- fail "Input does not begin with ASCII 'b'."- unless (version == binaryFormatVersion) $- fail $ "Expecting binary format version 1; found version: " ++ show version- unless (rank >= 0) $- fail $ "Rank must be non-negative, but is: " ++ show rank-- type_f <- getLazyByteString 4-- shape <- replicateM (fromIntegral rank) $ fromIntegral <$> getInt64le- let num_elems = product shape- shape' = SVec.fromList shape-- case LBS.unpack type_f of- " i8" -> get' (Int8Value shape') num_elems 1- " i16" -> get' (Int16Value shape') num_elems 2- " i32" -> get' (Int32Value shape') num_elems 4- " i64" -> get' (Int64Value shape') num_elems 8- " u8" -> get' (Word8Value shape') num_elems 1- " u16" -> get' (Word16Value shape') num_elems 2- " u32" -> get' (Word32Value shape') num_elems 4- " u64" -> get' (Word64Value shape') num_elems 8- " f32" -> get' (Float32Value shape') num_elems 4- " f64" -> get' (Float64Value shape') num_elems 8- -- Bool must be treated specially because the Storable instance- -- uses four bytes.- "bool" -> BoolValue shape' . SVec.map int8ToBool . byteStringToVector . BS.copy <$> getByteString num_elems- s -> fail $ "Cannot parse binary values of type " ++ show s- where- -- The copy is to ensure that the bytestring is properly- -- aligned.- get' mk num_elems elem_size =- mk . byteStringToVector . BS.copy <$> getByteString (num_elems * elem_size)-- int8ToBool :: Int8 -> Bool- int8ToBool = (/= 0)--putBinaryValue ::- SVec.Storable a =>- String ->- Vector Int ->- Vector a ->- Put-putBinaryValue tstr shape vs = do- putInt8 $ fromIntegral $ ord 'b'- putWord8 binaryFormatVersion- putWord8 $ fromIntegral $ SVec.length shape- mapM_ (putInt8 . fromIntegral . ord) tstr- putByteString $ vectorToByteString shape- putByteString $ vectorToByteString vs--instance PP.Pretty Value where- ppr v- | product (valueShape v) == 0 =- text "empty"- <> parens (dims <> ppr (valueElemType v))- where- dims = mconcat $ map (brackets . ppr) $ valueShape v- ppr (Int8Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Int16Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Int32Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Int64Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Word8Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Word16Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Word32Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Word64Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Float32Value shape vs) = pprArray (SVec.toList shape) vs- ppr (Float64Value shape vs) = pprArray (SVec.toList shape) vs- ppr (BoolValue shape vs) = pprArray (SVec.toList shape) vs+instance Pretty Value where+ ppr = strictText . valueText -pprArray :: (SVec.Storable a, F.IsPrimValue a) => [Int] -> SVec.Vector a -> Doc-pprArray [] vs =- ppr $ F.primValue $ SVec.head vs-pprArray (d : ds) vs =- brackets $ cat $ punctuate separator $ map (pprArray ds . slice) [0 .. d -1]- where- slice_size = product ds- slice i = SVec.slice (i * slice_size) slice_size vs- separator- | null ds = comma <> space- | otherwise = comma <> line+instance Pretty ValueType where+ ppr = strictText . valueTypeText -- | The structure of a compound value, parameterised over the actual -- values. For most cases you probably want 'CompoundValue'.@@ -227,9 +58,9 @@ field (k, v) = ppr k <> equals <> ppr v -- | Create a tuple for a non-unit list, and otherwise a 'ValueAtom'-mkCompound :: [v] -> Compound v-mkCompound [v] = ValueAtom v-mkCompound vs = ValueTuple $ map ValueAtom vs+mkCompound :: [Compound v] -> Compound v+mkCompound [v] = v+mkCompound vs = ValueTuple vs -- | If the value is a tuple, extract the components, otherwise return -- a singleton list of the value.@@ -241,633 +72,3 @@ -- supported by raw values. You cannot parse or read these in -- standard ways, and they cannot be elements of arrays. type CompoundValue = Compound Value---- | A representation of the simple values we represent in this module.-data ValueType = ValueType [Int] F.PrimType- deriving (Eq, Ord, Show)--instance PP.Pretty ValueType where- ppr (ValueType ds t) = mconcat (map pprDim ds) <> ppr t- where- pprDim d = brackets $ ppr d---- | Prettyprint a value type with empty dimensions. This is needed--- for Futhark server programs, whose types are un-sized.-prettyValueTypeNoDims :: ValueType -> T.Text-prettyValueTypeNoDims (ValueType dims t) =- mconcat (replicate (length dims) "[]") <> prettyText t---- | Get the type of a value.-valueType :: Value -> ValueType-valueType v = ValueType (valueShape v) $ valueElemType v--valueElemType :: Value -> F.PrimType-valueElemType Int8Value {} = F.Signed F.Int8-valueElemType Int16Value {} = F.Signed F.Int16-valueElemType Int32Value {} = F.Signed F.Int32-valueElemType Int64Value {} = F.Signed F.Int64-valueElemType Word8Value {} = F.Unsigned F.Int8-valueElemType Word16Value {} = F.Unsigned F.Int16-valueElemType Word32Value {} = F.Unsigned F.Int32-valueElemType Word64Value {} = F.Unsigned F.Int64-valueElemType Float32Value {} = F.FloatType F.Float32-valueElemType Float64Value {} = F.FloatType F.Float64-valueElemType BoolValue {} = F.Bool---- | The shape of a value. Empty list in case of a scalar.-valueShape :: Value -> [Int]-valueShape (Int8Value shape _) = SVec.toList shape-valueShape (Int16Value shape _) = SVec.toList shape-valueShape (Int32Value shape _) = SVec.toList shape-valueShape (Int64Value shape _) = SVec.toList shape-valueShape (Word8Value shape _) = SVec.toList shape-valueShape (Word16Value shape _) = SVec.toList shape-valueShape (Word32Value shape _) = SVec.toList shape-valueShape (Word64Value shape _) = SVec.toList shape-valueShape (Float32Value shape _) = SVec.toList shape-valueShape (Float64Value shape _) = SVec.toList shape-valueShape (BoolValue shape _) = SVec.toList shape---- | Produce a list of the immediate elements of the value. That is,--- a 2D array will produce a list of 1D values. While lists are of--- course inefficient, the actual values are just slices of the--- original value, which makes them fairly efficient.-valueElems :: Value -> [Value]-valueElems v- | n : ns <- valueShape v =- let k = product ns- slices mk vs =- [ mk (SVec.fromList ns) $- SVec.slice (k * i) k vs- | i <- [0 .. n -1]- ]- in case v of- Int8Value _ vs -> slices Int8Value vs- Int16Value _ vs -> slices Int16Value vs- Int32Value _ vs -> slices Int32Value vs- Int64Value _ vs -> slices Int64Value vs- Word8Value _ vs -> slices Word8Value vs- Word16Value _ vs -> slices Word16Value vs- Word32Value _ vs -> slices Word32Value vs- Word64Value _ vs -> slices Word64Value vs- Float32Value _ vs -> slices Float32Value vs- Float64Value _ vs -> slices Float64Value vs- BoolValue _ vs -> slices BoolValue vs- | otherwise =- []---- The parser--dropRestOfLine, dropSpaces :: LBS.ByteString -> LBS.ByteString-dropRestOfLine = LBS.drop 1 . LBS.dropWhile (/= '\n')-dropSpaces t = case LBS.dropWhile isSpace t of- t'- | "--" `LBS.isPrefixOf` t' -> dropSpaces $ dropRestOfLine t'- | otherwise -> t'--type ReadValue v = LBS.ByteString -> Maybe (v, LBS.ByteString)--symbol :: Char -> LBS.ByteString -> Maybe LBS.ByteString-symbol c t- | Just (c', t') <- LBS.uncons t, c' == c = Just $ dropSpaces t'- | otherwise = Nothing--lexeme :: LBS.ByteString -> LBS.ByteString -> Maybe LBS.ByteString-lexeme l t- | l `LBS.isPrefixOf` t = Just $ dropSpaces $ LBS.drop (LBS.length l) t- | otherwise = Nothing---- (Used elements, shape, elements, remaining input)-type State s v = (Int, Vector Int, STVector s v, LBS.ByteString)--readArrayElemsST ::- UMVec.Unbox v =>- Int ->- Int ->- ReadValue v ->- State s v ->- ST s (Maybe (Int, State s v))-readArrayElemsST j r rv s = do- ms <- readRankedArrayOfST r rv s- case ms of- Just (i, shape, arr, t)- | Just t' <- symbol ',' t -> do- next <- readArrayElemsST (j + 1) r rv (i, shape, arr, t')- -- Not OK to have zero values after a comma.- case next of- Just (0, _) -> return Nothing- _ -> return next- | otherwise -> return $ Just (j, (i, shape, arr, t))- _ ->- return $ Just (0, s)--updateShape :: Int -> Int -> Vector Int -> Maybe (Vector Int)-updateShape d n shape- | old_n < 0 = Just $ shape SVec.// [(r - d, n)]- | old_n == n = Just shape- | otherwise = Nothing- where- r = SVec.length shape- old_n = shape SVec.! (r - d)--growIfFilled :: UVec.Unbox v => Int -> STVector s v -> ST s (STVector s v)-growIfFilled i arr =- if i >= capacity- then UMVec.grow arr capacity- else return arr- where- capacity = UMVec.length arr--readRankedArrayOfST ::- UMVec.Unbox v =>- Int ->- ReadValue v ->- State s v ->- ST s (Maybe (State s v))-readRankedArrayOfST 0 rv (i, shape, arr, t)- | Just (v, t') <- rv t = do- arr' <- growIfFilled i arr- UMVec.write arr' i v- return $ Just (i + 1, shape, arr', t')-readRankedArrayOfST r rv (i, shape, arr, t)- | Just t' <- symbol '[' t = do- ms <- readArrayElemsST 1 (r -1) rv (i, shape, arr, t')- return $ do- (j, s) <- ms- closeArray r j s-readRankedArrayOfST _ _ _ =- return Nothing--closeArray :: Int -> Int -> State s v -> Maybe (State s v)-closeArray r j (i, shape, arr, t) = do- t' <- symbol ']' t- shape' <- updateShape r j shape- return (i, shape', arr, t')--readRankedArrayOf ::- (UMVec.Unbox v, SVec.Storable v) =>- Int ->- ReadValue v ->- LBS.ByteString ->- Maybe (Vector Int, Vector v, LBS.ByteString)-readRankedArrayOf r rv t = runST $ do- arr <- UMVec.new 1024- ms <- readRankedArrayOfST r rv (0, SVec.replicate r (-1), arr, t)- case ms of- Just (i, shape, arr', t') -> do- arr'' <- freeze (UMVec.slice 0 i arr')- return $ Just (shape, UVec.convert arr'', t')- Nothing ->- return Nothing---- | A character that can be part of a value. This doesn't work for--- string and character literals.-constituent :: Char -> Bool-constituent ',' = False-constituent ']' = False-constituent ')' = False-constituent c = not $ isSpace c--readIntegral :: Integral int => (Token -> Maybe int) -> ReadValue int-readIntegral f t = do- v <- case fst <$> scanTokens (Pos "" 1 1 0) a of- Right [L _ NEGATE, L _ (INTLIT x)] -> Just $ negate $ fromIntegral x- Right [L _ (INTLIT x)] -> Just $ fromIntegral x- Right [L _ tok] -> f tok- Right [L _ NEGATE, L _ tok] -> negate <$> f tok- _ -> Nothing- return (v, dropSpaces b)- where- (a, b) = LBS.span constituent t--readInt8 :: ReadValue Int8-readInt8 = readIntegral f- where- f (I8LIT x) = Just x- f _ = Nothing--readInt16 :: ReadValue Int16-readInt16 = readIntegral f- where- f (I16LIT x) = Just x- f _ = Nothing--readInt32 :: ReadValue Int32-readInt32 = readIntegral f- where- f (I32LIT x) = Just x- f _ = Nothing--readInt64 :: ReadValue Int64-readInt64 = readIntegral f- where- f (I64LIT x) = Just x- f _ = Nothing--readWord8 :: ReadValue Word8-readWord8 = readIntegral f- where- f (U8LIT x) = Just x- f _ = Nothing--readWord16 :: ReadValue Word16-readWord16 = readIntegral f- where- f (U16LIT x) = Just x- f _ = Nothing--readWord32 :: ReadValue Word32-readWord32 = readIntegral f- where- f (U32LIT x) = Just x- f _ = Nothing--readWord64 :: ReadValue Word64-readWord64 = readIntegral f- where- f (U64LIT x) = Just x- f _ = Nothing--readFloat :: RealFloat float => ([Token] -> Maybe float) -> ReadValue float-readFloat f t = do- v <- case map unLoc . fst <$> scanTokens (Pos "" 1 1 0) a of- Right [NEGATE, FLOATLIT x] -> Just $ negate $ fromDouble x- Right [FLOATLIT x] -> Just $ fromDouble x- Right (NEGATE : toks) -> negate <$> f toks- Right toks -> f toks- _ -> Nothing- return (v, dropSpaces b)- where- (a, b) = LBS.span constituent t- fromDouble = uncurry encodeFloat . decodeFloat- unLoc (L _ x) = x--readFloat32 :: ReadValue Float-readFloat32 = readFloat lexFloat32- where- lexFloat32 [F32LIT x] = Just x- lexFloat32 [ID "f32", DOT, ID "inf"] = Just $ 1 / 0- lexFloat32 [ID "f32", DOT, ID "nan"] = Just $ 0 / 0- lexFloat32 _ = Nothing--readFloat64 :: ReadValue Double-readFloat64 = readFloat lexFloat64- where- lexFloat64 [F64LIT x] = Just x- lexFloat64 [ID "f64", DOT, ID "inf"] = Just $ 1 / 0- lexFloat64 [ID "f64", DOT, ID "nan"] = Just $ 0 / 0- lexFloat64 _ = Nothing--readBool :: ReadValue Bool-readBool t = do- v <- case fst <$> scanTokens (Pos "" 1 1 0) a of- Right [L _ TRUE] -> Just True- Right [L _ FALSE] -> Just False- _ -> Nothing- return (v, dropSpaces b)- where- (a, b) = LBS.span constituent t--readPrimType :: ReadValue String-readPrimType t = do- pt <- case fst <$> scanTokens (Pos "" 1 1 0) a of- Right [L _ (ID s)] -> Just $ F.nameToString s- _ -> Nothing- return (pt, dropSpaces b)- where- (a, b) = LBS.span constituent t--readEmptyArrayOfShape :: [Int] -> LBS.ByteString -> Maybe (Value, LBS.ByteString)-readEmptyArrayOfShape shape t- | Just t' <- symbol '[' t,- Just (d, t'') <- readIntegral (const Nothing) t',- Just t''' <- symbol ']' t'' =- readEmptyArrayOfShape (shape ++ [d]) t'''- | otherwise = do- (pt, t') <- readPrimType t- guard $ elem 0 shape- v <- case pt of- "i8" -> Just $ Int8Value (SVec.fromList shape) SVec.empty- "i16" -> Just $ Int16Value (SVec.fromList shape) SVec.empty- "i32" -> Just $ Int32Value (SVec.fromList shape) SVec.empty- "i64" -> Just $ Int64Value (SVec.fromList shape) SVec.empty- "u8" -> Just $ Word8Value (SVec.fromList shape) SVec.empty- "u16" -> Just $ Word16Value (SVec.fromList shape) SVec.empty- "u32" -> Just $ Word32Value (SVec.fromList shape) SVec.empty- "u64" -> Just $ Word64Value (SVec.fromList shape) SVec.empty- "f32" -> Just $ Float32Value (SVec.fromList shape) SVec.empty- "f64" -> Just $ Float64Value (SVec.fromList shape) SVec.empty- "bool" -> Just $ BoolValue (SVec.fromList shape) SVec.empty- _ -> Nothing- return (v, t')--readEmptyArray :: LBS.ByteString -> Maybe (Value, LBS.ByteString)-readEmptyArray t = do- t' <- symbol '(' =<< lexeme "empty" t- (v, t'') <- readEmptyArrayOfShape [] t'- t''' <- symbol ')' t''- return (v, t''')--readValue :: LBS.ByteString -> Maybe (Value, LBS.ByteString)-readValue full_t- | Right (t', _, v) <- decodeOrFail full_t =- Just (v, dropSpaces t')- | otherwise = readEmptyArray full_t `mplus` insideBrackets 0 full_t- where- insideBrackets r t = maybe (tryValueAndReadValue r t) (insideBrackets (r + 1)) $ symbol '[' t- tryWith f mk r t- | Just _ <- f t = do- (shape, arr, rest_t) <- readRankedArrayOf r f full_t- return (mk shape arr, rest_t)- | otherwise = Nothing- tryValueAndReadValue r t =- -- 32-bit signed integers come first such that we parse- -- unsuffixed integer constants as of that type.- tryWith readInt32 Int32Value r t- `mplus` tryWith readInt8 Int8Value r t- `mplus` tryWith readInt16 Int16Value r t- `mplus` tryWith readInt64 Int64Value r t- `mplus` tryWith readWord8 Word8Value r t- `mplus` tryWith readWord16 Word16Value r t- `mplus` tryWith readWord32 Word32Value r t- `mplus` tryWith readWord64 Word64Value r t- `mplus` tryWith readFloat64 Float64Value r t- `mplus` tryWith readFloat32 Float32Value r t- `mplus` tryWith readBool BoolValue r t---- | Parse Futhark values from the given bytestring.-readValues :: LBS.ByteString -> Maybe [Value]-readValues = readValues' . dropSpaces- where- readValues' t- | LBS.null t = Just []- | otherwise = do- (a, t') <- readValue t- (a :) <$> readValues' t'---- Comparisons---- | Two values differ in some way. The 'Show' instance produces a--- human-readable explanation.-data Mismatch- = -- | The position the value number and a flat index- -- into the array.- PrimValueMismatch Int [Int] PrimValue PrimValue- | ArrayShapeMismatch Int [Int] [Int]- | TypeMismatch Int String String- | ValueCountMismatch Int Int--instance Show Mismatch where- show (PrimValueMismatch vi [] got expected) =- explainMismatch (show vi) "" got expected- show (PrimValueMismatch vi js got expected) =- explainMismatch (show vi ++ " index [" ++ intercalate "," (map show js) ++ "]") "" got expected- show (ArrayShapeMismatch i got expected) =- explainMismatch (show i) "array of shape " got expected- show (TypeMismatch i got expected) =- explainMismatch (show i) "value of type " got expected- show (ValueCountMismatch got expected) =- "Expected " ++ show expected ++ " values, got " ++ show got---- | A human-readable description of how two values are not the same.-explainMismatch :: (PP.Pretty a) => String -> String -> a -> a -> String-explainMismatch i what got expected =- "Value #" ++ i ++ ": expected " ++ what ++ PP.pretty expected ++ ", got " ++ PP.pretty got---- | Compare two sets of Futhark values for equality. Shapes and--- types must also match.-compareValues :: [Value] -> [Value] -> [Mismatch]-compareValues got expected- | n /= m = [ValueCountMismatch n m]- | otherwise = concat $ zipWith3 compareValue [0 ..] got expected- where- n = length got- m = length expected--compareValue :: Int -> Value -> Value -> [Mismatch]-compareValue i got_v expected_v- | valueShape got_v == valueShape expected_v =- case (got_v, expected_v) of- (Int8Value _ got_vs, Int8Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Int16Value _ got_vs, Int16Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Int32Value _ got_vs, Int32Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Int64Value _ got_vs, Int64Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Word8Value _ got_vs, Word8Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Word16Value _ got_vs, Word16Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Word32Value _ got_vs, Word32Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Word64Value _ got_vs, Word64Value _ expected_vs) ->- compareNum 1 got_vs expected_vs- (Float32Value _ got_vs, Float32Value _ expected_vs) ->- compareFloat (tolerance expected_vs) got_vs expected_vs- (Float64Value _ got_vs, Float64Value _ expected_vs) ->- compareFloat (tolerance expected_vs) got_vs expected_vs- (BoolValue _ got_vs, BoolValue _ expected_vs) ->- compareGen compareBool got_vs expected_vs- _ ->- [TypeMismatch i (pretty $ valueElemType got_v) (pretty $ valueElemType expected_v)]- | otherwise =- [ArrayShapeMismatch i (valueShape got_v) (valueShape expected_v)]- where- unflatten =- map wrappedValue . unflattenIndex (map Wrapped (valueShape got_v)) . Wrapped-- {-# INLINE compareGen #-}- {-# INLINE compareNum #-}- {-# INLINE compareFloat #-}- {-# INLINE compareFloatElement #-}- {-# INLINE compareElement #-}- compareNum tol = compareGen $ compareElement tol- compareFloat tol = compareGen $ compareFloatElement tol-- compareGen cmp got expected =- let l = SVec.length got- check acc j- | j < l =- case cmp j (got SVec.! j) (expected SVec.! j) of- Just mismatch ->- check (mismatch : acc) (j + 1)- Nothing ->- check acc (j + 1)- | otherwise =- acc- in reverse $ check [] 0-- compareElement tol j got expected- | comparePrimValue tol got expected = Nothing- | otherwise = Just $ PrimValueMismatch i (unflatten j) (value got) (value expected)-- compareFloatElement tol j got expected- | isNaN got,- isNaN expected =- Nothing- | isInfinite got,- isInfinite expected,- signum got == signum expected =- Nothing- | otherwise =- compareElement tol j got expected-- compareBool j got expected- | got == expected = Nothing- | otherwise = Just $ PrimValueMismatch i (unflatten j) (value got) (value expected)--comparePrimValue ::- (Ord num, Num num) =>- num ->- num ->- num ->- Bool-comparePrimValue tol x y =- diff < tol- where- diff = abs $ x - y--minTolerance :: Fractional a => a-minTolerance = 0.002 -- 0.2%--tolerance :: (RealFloat a, SVec.Storable a) => Vector a -> a-tolerance = SVec.foldl tolerance' minTolerance . SVec.filter (not . nanOrInf)- where- tolerance' t v = max t $ minTolerance * v- nanOrInf x = isInfinite x || isNaN x---- | A class for Haskell values that can be retrieved from 'Value'.--- This is a convenience facility - don't expect it to be fast.-class GetValue t where- getValue :: Value -> Maybe t--instance GetValue t => GetValue [t] where- getValue = mapM getValue . valueElems--instance GetValue Bool where- getValue (BoolValue shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Int8 where- getValue (Int8Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Int16 where- getValue (Int16Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Int32 where- getValue (Int32Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Int64 where- getValue (Int64Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Word8 where- getValue (Word8Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Word16 where- getValue (Word16Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Word32 where- getValue (Word32Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing--instance GetValue Word64 where- getValue (Word64Value shape vs)- | [] <- SVec.toList shape =- Just $ vs SVec.! 0- getValue _ = Nothing---- | A class for Haskell values that can be converted to 'Value'.--- This is a convenience facility - don't expect it to be fast.-class PutValue t where- -- | This may fail for cases such as irregular arrays.- putValue :: t -> Maybe Value--instance PutValue Word8 where- putValue = Just . Word8Value mempty . SVec.singleton--instance PutValue F.PrimValue where- putValue (F.SignedValue (F.Int8Value x)) =- Just $ Int8Value mempty $ SVec.singleton x- putValue (F.SignedValue (F.Int16Value x)) =- Just $ Int16Value mempty $ SVec.singleton x- putValue (F.SignedValue (F.Int32Value x)) =- Just $ Int32Value mempty $ SVec.singleton x- putValue (F.SignedValue (F.Int64Value x)) =- Just $ Int64Value mempty $ SVec.singleton x- putValue (F.UnsignedValue (F.Int8Value x)) =- Just $ Word8Value mempty $ SVec.singleton $ fromIntegral x- putValue (F.UnsignedValue (F.Int16Value x)) =- Just $ Word16Value mempty $ SVec.singleton $ fromIntegral x- putValue (F.UnsignedValue (F.Int32Value x)) =- Just $ Word32Value mempty $ SVec.singleton $ fromIntegral x- putValue (F.UnsignedValue (F.Int64Value x)) =- Just $ Word64Value mempty $ SVec.singleton $ fromIntegral x- putValue (F.FloatValue (F.Float32Value x)) =- Just $ Float32Value mempty $ SVec.singleton x- putValue (F.FloatValue (F.Float64Value x)) =- Just $ Float64Value mempty $ SVec.singleton x- putValue (F.BoolValue b) =- Just $ BoolValue mempty $ SVec.singleton b--instance PutValue [Value] where- putValue [] = Nothing- putValue (x : xs) = do- let res_shape = SVec.fromList $ length (x : xs) : valueShape x- guard $ all ((== valueType x) . valueType) xs- Just $ case x of- Int8Value {} -> Int8Value res_shape $ foldMap getVec (x : xs)- Int16Value {} -> Int16Value res_shape $ foldMap getVec (x : xs)- Int32Value {} -> Int32Value res_shape $ foldMap getVec (x : xs)- Int64Value {} -> Int64Value res_shape $ foldMap getVec (x : xs)- Word8Value {} -> Word8Value res_shape $ foldMap getVec (x : xs)- Word16Value {} -> Word16Value res_shape $ foldMap getVec (x : xs)- Word32Value {} -> Word32Value res_shape $ foldMap getVec (x : xs)- Word64Value {} -> Word64Value res_shape $ foldMap getVec (x : xs)- Float32Value {} -> Float32Value res_shape $ foldMap getVec (x : xs)- Float64Value {} -> Float64Value res_shape $ foldMap getVec (x : xs)- BoolValue {} -> BoolValue res_shape $ foldMap getVec (x : xs)- where- getVec (Int8Value _ vec) = SVec.unsafeCast vec- getVec (Int16Value _ vec) = SVec.unsafeCast vec- getVec (Int32Value _ vec) = SVec.unsafeCast vec- getVec (Int64Value _ vec) = SVec.unsafeCast vec- getVec (Word8Value _ vec) = SVec.unsafeCast vec- getVec (Word16Value _ vec) = SVec.unsafeCast vec- getVec (Word32Value _ vec) = SVec.unsafeCast vec- getVec (Word64Value _ vec) = SVec.unsafeCast vec- getVec (Float32Value _ vec) = SVec.unsafeCast vec- getVec (Float64Value _ vec) = SVec.unsafeCast vec- getVec (BoolValue _ vec) = SVec.unsafeCast vec--instance PutValue T.Text where- putValue = putValue . T.encodeUtf8--instance PutValue BS.ByteString where- putValue bs =- Just $ Word8Value size $ byteStringToVector bs- where- size = SVec.fromList [fromIntegral (BS.length bs)]
− src/Futhark/Test/Values/Parser.hs
@@ -1,167 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- | Megaparsec-based parser for primitive 'Value's. The difference--- between this and the parser defined in "Futhark.Test.Values" is--- that we don't try to handle both the textual and binary format ---- only the former. On the other hand, this parser has (much) better--- error messages and can be easily used by other parsers (like the--- ones for FutharkScript or test blocks.-module Futhark.Test.Values.Parser- ( parsePrimType,- parseType,- parsePrimValue,- parseValue,- )-where--import Control.Monad.Except-import Data.Functor-import qualified Data.Set as S-import qualified Data.Text as T-import qualified Data.Vector.Storable as SVec-import Data.Void-import Futhark.Test.Values-import qualified Language.Futhark.Syntax as F-import Text.Megaparsec-import Text.Megaparsec.Char.Lexer- ( binary,- decimal,- float,- hexadecimal,- signed,- )--type Parser = Parsec Void T.Text---- | Parse the name of a primitive type. Does *not* consume any--- trailing whitespace, nor does it permit any internal whitespace.-parsePrimType :: Parser F.PrimType-parsePrimType =- choice- [ "i8" $> F.Signed F.Int8,- "i16" $> F.Signed F.Int16,- "i32" $> F.Signed F.Int32,- "i64" $> F.Signed F.Int64,- "u8" $> F.Unsigned F.Int8,- "u16" $> F.Unsigned F.Int16,- "u32" $> F.Unsigned F.Int32,- "u64" $> F.Unsigned F.Int64,- "f32" $> F.FloatType F.Float32,- "f64" $> F.FloatType F.Float64,- "bool" $> F.Bool- ]--parseInteger :: Parser Integer-parseInteger =- signed (pure ()) $- choice- [ "0b" *> binary,- "0x" *> hexadecimal,- decimal- ]--parseIntConst :: Parser F.PrimValue-parseIntConst = do- x <- parseInteger- notFollowedBy $ "f32" <|> "f64" <|> "." <|> "e"- choice- [ signedV F.Int8Value x "i8",- signedV F.Int16Value x "i16",- signedV F.Int32Value x "i32",- signedV F.Int64Value x "i64",- unsignedV F.Int8Value x "u8",- unsignedV F.Int16Value x "u16",- unsignedV F.Int32Value x "u32",- unsignedV F.Int64Value x "u64",- signedV F.Int32Value x ""- ]- where- signedV mk x suffix =- suffix $> F.SignedValue (mk (fromInteger x))- unsignedV mk x suffix =- suffix $> F.UnsignedValue (mk (fromInteger x))--parseFloatConst :: Parser F.PrimValue-parseFloatConst =- choice- [ "f32.nan" $> F.FloatValue (F.Float32Value (0 / 0)),- "f64.nan" $> F.FloatValue (F.Float64Value (0 / 0)),- "f32.inf" $> F.FloatValue (F.Float32Value (1 / 0)),- "f64.inf" $> F.FloatValue (F.Float64Value (1 / 0)),- "-f32.inf" $> F.FloatValue (F.Float32Value (-1 / 0)),- "-f64.inf" $> F.FloatValue (F.Float64Value (-1 / 0)),- numeric- ]- where- numeric = do- x <-- signed (pure ()) $ choice [try float, fromInteger <$> decimal]- choice- [ floatV F.Float32Value x "f32",- floatV F.Float64Value x "f64",- floatV F.Float64Value x ""- ]-- floatV mk x suffix =- suffix $> F.FloatValue (mk (realToFrac (x :: Double)))---- | Parse a primitive value. Does *not* consume any trailing--- whitespace, nor does it permit any internal whitespace.-parsePrimValue :: Parser F.PrimValue-parsePrimValue =- choice- [ try parseIntConst,- parseFloatConst,- "true" $> F.BoolValue True,- "false" $> F.BoolValue False- ]--lexeme :: Parser () -> Parser a -> Parser a-lexeme sep p = p <* sep--inBrackets :: Parser () -> Parser a -> Parser a-inBrackets sep = between (lexeme sep "[") (lexeme sep "]")---- | Parse a type. Does *not* consume any trailing whitespace, nor--- does it permit any internal whitespace.-parseType :: Parser ValueType-parseType = ValueType <$> many parseDim <*> parsePrimType- where- parseDim = fromInteger <$> ("[" *> parseInteger <* "]")--parseEmpty :: Parser Value-parseEmpty = do- ValueType dims t <- parseType- unless (product dims == 0) $ fail "Expected at least one empty dimension"- pure $ case t of- F.Signed F.Int8 -> Int8Value (SVec.fromList dims) mempty- F.Signed F.Int16 -> Int16Value (SVec.fromList dims) mempty- F.Signed F.Int32 -> Int32Value (SVec.fromList dims) mempty- F.Signed F.Int64 -> Int64Value (SVec.fromList dims) mempty- F.Unsigned F.Int8 -> Word8Value (SVec.fromList dims) mempty- F.Unsigned F.Int16 -> Word16Value (SVec.fromList dims) mempty- F.Unsigned F.Int32 -> Word32Value (SVec.fromList dims) mempty- F.Unsigned F.Int64 -> Word64Value (SVec.fromList dims) mempty- F.FloatType F.Float32 -> Float32Value (SVec.fromList dims) mempty- F.FloatType F.Float64 -> Float64Value (SVec.fromList dims) mempty- F.Bool -> BoolValue (SVec.fromList dims) mempty---- | Parse a value, given a post-lexeme parser for whitespace.-parseValue :: Parser () -> Parser Value-parseValue sep =- choice- [ putValue' $ lexeme sep parsePrimValue,- putValue' $ inBrackets sep (parseValue sep `sepBy` lexeme sep ","),- lexeme sep $ "empty(" *> parseEmpty <* ")"- ]- where- putValue' :: PutValue v => Parser v -> Parser Value- putValue' p = do- o <- getOffset- x <- p- case putValue x of- Nothing ->- parseError . FancyError o . S.singleton $- ErrorFail "array is irregular or has elements of multiple types."- Just v ->- pure v
src/Futhark/Tools.hs view
@@ -31,19 +31,19 @@ -- Only handles a pattern with an empty 'patternContextElements'. redomapToMapAndReduce :: ( MonadFreshNames m,- Bindable lore,- ExpDec lore ~ (),- Op lore ~ SOAC lore+ Bindable rep,+ ExpDec rep ~ (),+ Op rep ~ SOAC rep ) =>- Pattern lore ->+ Pattern rep -> ( SubExp, Commutativity,- LambdaT lore,- LambdaT lore,+ LambdaT rep,+ LambdaT rep, [SubExp], [VName] ) ->- m (Stm lore, Stm lore)+ m (Stm rep, Stm rep) redomapToMapAndReduce (Pattern [] patelems) (w, comm, redlam, map_lam, accs, arrs) = do@@ -62,7 +62,7 @@ (Typed dec, MonadFreshNames m) => [PatElemT dec] -> SubExp ->- LambdaT lore ->+ LambdaT rep -> [SubExp] -> m ([Ident], PatternT dec, [(SubExp, VName)]) splitScanOrRedomap patelems w map_lam accs = do@@ -84,12 +84,12 @@ -- In essense, what happens is the opposite of horisontal fusion. dissectScrema :: ( MonadBinder m,- Op (Lore m) ~ SOAC (Lore m),- Bindable (Lore m)+ Op (Rep m) ~ SOAC (Rep m),+ Bindable (Rep m) ) =>- Pattern (Lore m) ->+ Pattern (Rep m) -> SubExp ->- ScremaForm (Lore m) ->+ ScremaForm (Rep m) -> [VName] -> m () dissectScrema pat w (ScremaForm scans reds map_lam) arrs = do@@ -110,11 +110,11 @@ -- | Turn a stream SOAC into statements that apply the stream lambda -- to the entire input. sequentialStreamWholeArray ::- (MonadBinder m, Bindable (Lore m)) =>- Pattern (Lore m) ->+ (MonadBinder m, Bindable (Rep m)) =>+ Pattern (Rep m) -> SubExp -> [SubExp] ->- LambdaT (Lore m) ->+ LambdaT (Rep m) -> [VName] -> m () sequentialStreamWholeArray pat w nes lam arrs = do
src/Futhark/Transform/CopyPropagate.hs view
@@ -15,31 +15,31 @@ import Futhark.IR import Futhark.MonadFreshNames import Futhark.Optimise.Simplify-import Futhark.Optimise.Simplify.Lore (Wise)+import Futhark.Optimise.Simplify.Rep (Wise) import Futhark.Pass -- | Run copy propagation on an entire program. copyPropagateInProg ::- SimplifiableLore lore =>- SimpleOps lore ->- Prog lore ->- PassM (Prog lore)+ SimplifiableRep rep =>+ SimpleOps rep ->+ Prog rep ->+ PassM (Prog rep) copyPropagateInProg simpl = simplifyProg simpl mempty neverHoist -- | Run copy propagation on some statements. copyPropagateInStms ::- (MonadFreshNames m, SimplifiableLore lore) =>- SimpleOps lore ->- Scope lore ->- Stms lore ->- m (ST.SymbolTable (Wise lore), Stms lore)+ (MonadFreshNames m, SimplifiableRep rep) =>+ SimpleOps rep ->+ Scope rep ->+ Stms rep ->+ m (ST.SymbolTable (Wise rep), Stms rep) copyPropagateInStms simpl = simplifyStms simpl mempty neverHoist -- | Run copy propagation on a function. copyPropagateInFun ::- (MonadFreshNames m, SimplifiableLore lore) =>- SimpleOps lore ->- ST.SymbolTable (Wise lore) ->- FunDef lore ->- m (FunDef lore)+ (MonadFreshNames m, SimplifiableRep rep) =>+ SimpleOps rep ->+ ST.SymbolTable (Wise rep) ->+ FunDef rep ->+ m (FunDef rep) copyPropagateInFun simpl = simplifyFun simpl mempty neverHoist
src/Futhark/Transform/FirstOrderTransform.hs view
@@ -10,7 +10,7 @@ module Futhark.Transform.FirstOrderTransform ( transformFunDef, transformConsts,- FirstOrderLore,+ FirstOrderRep, Transformer, transformStmRecursively, transformLambda,@@ -30,23 +30,23 @@ import Futhark.Tools import Futhark.Util (chunks, splitAt3) --- | The constraints that must hold for a lore in order to be the+-- | The constraints that must hold for a rep in order to be the -- target of first-order transformation.-type FirstOrderLore lore =- ( Bindable lore,- BinderOps lore,- LetDec SOACS ~ LetDec lore,- LParamInfo SOACS ~ LParamInfo lore,- CanBeAliased (Op lore)+type FirstOrderRep rep =+ ( Bindable rep,+ BinderOps rep,+ LetDec SOACS ~ LetDec rep,+ LParamInfo SOACS ~ LParamInfo rep,+ CanBeAliased (Op rep) ) -- | First-order-transform a single function, with the given scope -- provided by top-level constants. transformFunDef ::- (MonadFreshNames m, FirstOrderLore tolore) =>- Scope tolore ->+ (MonadFreshNames m, FirstOrderRep torep) =>+ Scope torep -> FunDef SOACS ->- m (AST.FunDef tolore)+ m (AST.FunDef torep) transformFunDef consts_scope (FunDef entry attrs fname rettype params body) = do (body', _) <- modifyNameSource $ runState $ runBinderT m consts_scope return $ FunDef entry attrs fname rettype params body'@@ -55,9 +55,9 @@ -- | First-order-transform these top-level constants. transformConsts ::- (MonadFreshNames m, FirstOrderLore tolore) =>+ (MonadFreshNames m, FirstOrderRep torep) => Stms SOACS ->- m (AST.Stms tolore)+ m (AST.Stms torep) transformConsts stms = fmap snd $ modifyNameSource $ runState $ runBinderT m mempty where@@ -67,17 +67,17 @@ -- first-order transformation. type Transformer m = ( MonadBinder m,- LocalScope (Lore m) m,- Bindable (Lore m),- BinderOps (Lore m),- LParamInfo SOACS ~ LParamInfo (Lore m),- CanBeAliased (Op (Lore m))+ LocalScope (Rep m) m,+ Bindable (Rep m),+ BinderOps (Rep m),+ LParamInfo SOACS ~ LParamInfo (Rep m),+ CanBeAliased (Op (Rep m)) ) transformBody ::- (Transformer m, LetDec (Lore m) ~ LetDec SOACS) =>+ (Transformer m, LetDec (Rep m) ~ LetDec SOACS) => Body ->- m (AST.Body (Lore m))+ m (AST.Body (Rep m)) transformBody (Body () stms res) = buildBody_ $ do mapM_ transformStmRecursively stms pure res@@ -85,7 +85,7 @@ -- | First transform any nested t'Body' or t'Lambda' elements, then -- apply 'transformSOAC' if the expression is a SOAC. transformStmRecursively ::- (Transformer m, LetDec (Lore m) ~ LetDec SOACS) =>+ (Transformer m, LetDec (Rep m) ~ LetDec SOACS) => Stm -> m () transformStmRecursively (Let pat aux (Op soac)) =@@ -119,11 +119,11 @@ -- | Transform a single 'SOAC' into a do-loop. The body of the lambda -- is untouched, and may or may not contain further 'SOAC's depending--- on the given lore.+-- on the given rep. transformSOAC :: Transformer m =>- AST.Pattern (Lore m) ->- SOAC (Lore m) ->+ AST.Pattern (Rep m) ->+ SOAC (Rep m) -> m () transformSOAC pat (Screma w arrs form@(ScremaForm scans reds map_lam)) = do -- See Note [Translation of Screma].@@ -360,15 +360,15 @@ -- | Recursively first-order-transform a lambda. transformLambda :: ( MonadFreshNames m,- Bindable lore,- BinderOps lore,- LocalScope somelore m,- SameScope somelore lore,- LetDec lore ~ LetDec SOACS,- CanBeAliased (Op lore)+ Bindable rep,+ BinderOps rep,+ LocalScope somerep m,+ SameScope somerep rep,+ LetDec rep ~ LetDec SOACS,+ CanBeAliased (Op rep) ) => Lambda ->- m (AST.Lambda lore)+ m (AST.Lambda rep) transformLambda (Lambda params body rettype) = do body' <- runBodyBinder $@@ -389,8 +389,8 @@ bindLambda :: Transformer m =>- AST.Lambda (Lore m) ->- [AST.Exp (Lore m)] ->+ AST.Lambda (Rep m) ->+ [AST.Exp (Rep m)] -> m [SubExp] bindLambda (Lambda params body _) args = do forM_ (zip params args) $ \(param, arg) ->
src/Futhark/Transform/Rename.hs view
@@ -53,9 +53,9 @@ -- correct to begin with. In particular, the renaming may make an -- invalid program valid. renameProg ::- (Renameable lore, MonadFreshNames m) =>- Prog lore ->- m (Prog lore)+ (Renameable rep, MonadFreshNames m) =>+ Prog rep ->+ m (Prog rep) renameProg prog = modifyNameSource $ runRenamer $ renamingStms (progConsts prog) $ \consts -> do@@ -67,9 +67,9 @@ -- expression was correct to begin with. Any free variables are left -- untouched. renameExp ::- (Renameable lore, MonadFreshNames m) =>- Exp lore ->- m (Exp lore)+ (Renameable rep, MonadFreshNames m) =>+ Exp rep ->+ m (Exp rep) renameExp = modifyNameSource . runRenamer . rename -- | Rename bound variables such that each is unique. The semantics@@ -77,9 +77,9 @@ -- binding was correct to begin with. Any free variables are left -- untouched, as are the names in the pattern of the binding. renameStm ::- (Renameable lore, MonadFreshNames m) =>- Stm lore ->- m (Stm lore)+ (Renameable rep, MonadFreshNames m) =>+ Stm rep ->+ m (Stm rep) renameStm binding = do e <- renameExp $ stmExp binding return binding {stmExp = e}@@ -88,9 +88,9 @@ -- of the body is unaffected, under the assumption that the body was -- correct to begin with. Any free variables are left untouched. renameBody ::- (Renameable lore, MonadFreshNames m) =>- Body lore ->- m (Body lore)+ (Renameable rep, MonadFreshNames m) =>+ Body rep ->+ m (Body rep) renameBody = modifyNameSource . runRenamer . rename -- | Rename bound variables such that each is unique. The semantics@@ -98,9 +98,9 @@ -- correct to begin with. Any free variables are left untouched. -- Note in particular that the parameters of the lambda are renamed. renameLambda ::- (Renameable lore, MonadFreshNames m) =>- Lambda lore ->- m (Lambda lore)+ (Renameable rep, MonadFreshNames m) =>+ Lambda rep ->+ m (Lambda rep) renameLambda = modifyNameSource . runRenamer . rename -- | Produce an equivalent pattern but with each pattern element given@@ -196,7 +196,7 @@ -- | Rename some statements, then execute an action with the name -- substitutions induced by the statements active.-renamingStms :: Renameable lore => Stms lore -> (Stms lore -> RenameM a) -> RenameM a+renamingStms :: Renameable rep => Stms rep -> (Stms rep -> RenameM a) -> RenameM a renamingStms stms m = descend mempty stms where descend stms' rem_stms = case stmsHead rem_stms of@@ -205,7 +205,7 @@ stm' <- rename stm descend (stms' <> oneStm stm') rem_stms' -instance Renameable lore => Rename (FunDef lore) where+instance Renameable rep => Rename (FunDef rep) where rename (FunDef entry attrs fname ret params body) = bind (map paramName params) $ do params' <- mapM rename params@@ -236,16 +236,16 @@ rename (StmAux cs attrs dec) = StmAux <$> rename cs <*> rename attrs <*> rename dec -instance Renameable lore => Rename (Body lore) where+instance Renameable rep => Rename (Body rep) where rename (Body dec stms res) = do dec' <- rename dec renamingStms stms $ \stms' -> Body dec' stms' <$> rename res -instance Renameable lore => Rename (Stm lore) where- rename (Let pat elore e) = Let <$> rename pat <*> rename elore <*> rename e+instance Renameable rep => Rename (Stm rep) where+ rename (Let pat dec e) = Let <$> rename pat <*> rename dec <*> rename e -instance Renameable lore => Rename (Exp lore) where+instance Renameable rep => Rename (Exp rep) where rename (WithAcc inputs lam) = WithAcc <$> rename inputs <*> rename lam rename (DoLoop ctx val form loopbody) = do@@ -315,7 +315,7 @@ rename (Acc acc ispace ts u) = Acc <$> rename acc <*> rename ispace <*> rename ts <*> pure u -instance Renameable lore => Rename (Lambda lore) where+instance Renameable rep => Rename (Lambda rep) where rename (Lambda params body ret) = bind (map paramName params) $ do params' <- mapM rename params@@ -343,14 +343,14 @@ rename (DimFix i) = DimFix <$> rename i rename (DimSlice i n s) = DimSlice <$> rename i <*> rename n <*> rename s --- | Lores in which all annotations are renameable.-type Renameable lore =- ( Rename (LetDec lore),- Rename (ExpDec lore),- Rename (BodyDec lore),- Rename (FParamInfo lore),- Rename (LParamInfo lore),- Rename (RetType lore),- Rename (BranchType lore),- Rename (Op lore)+-- | Representations in which all decorations are renameable.+type Renameable rep =+ ( Rename (LetDec rep),+ Rename (ExpDec rep),+ Rename (BodyDec rep),+ Rename (FParamInfo rep),+ Rename (LParamInfo rep),+ Rename (RetType rep),+ Rename (BranchType rep),+ Rename (Op rep) )
src/Futhark/Transform/Substitute.hs view
@@ -37,7 +37,7 @@ instance Substitute a => Substitute [a] where substituteNames substs = map $ substituteNames substs -instance Substitute (Stm lore) => Substitute (Stms lore) where+instance Substitute (Stm rep) => Substitute (Stms rep) where substituteNames substs = fmap $ substituteNames substs instance (Substitute a, Substitute b) => Substitute (a, b) where@@ -72,7 +72,7 @@ substituteNames substs (Var v) = Var $ substituteNames substs v substituteNames _ (Constant v) = Constant v -instance Substitutable lore => Substitute (Exp lore) where+instance Substitutable rep => Substitute (Exp rep) where substituteNames substs = mapExp $ replace substs instance Substitute dec => Substitute (PatElemT dec) where@@ -103,21 +103,21 @@ substituteNames substs (Certificates cs) = Certificates $ substituteNames substs cs -instance Substitutable lore => Substitute (Stm lore) where+instance Substitutable rep => Substitute (Stm rep) where substituteNames substs (Let pat annot e) = Let (substituteNames substs pat) (substituteNames substs annot) (substituteNames substs e) -instance Substitutable lore => Substitute (Body lore) where+instance Substitutable rep => Substitute (Body rep) where substituteNames substs (Body dec stms res) = Body (substituteNames substs dec) (substituteNames substs stms) (substituteNames substs res) -replace :: Substitutable lore => M.Map VName VName -> Mapper lore lore Identity+replace :: Substitutable rep => M.Map VName VName -> Mapper rep rep Identity replace substs = Mapper { mapOnVName = return . substituteNames substs,@@ -164,7 +164,7 @@ substituteNames _ (Mem space) = Mem space -instance Substitutable lore => Substitute (Lambda lore) where+instance Substitutable rep => Substitute (Lambda rep) where substituteNames substs (Lambda params body rettype) = Lambda (substituteNames substs params)@@ -191,7 +191,7 @@ substituteNames substs = TPrimExp . fmap (substituteNames substs) . untyped -instance Substitutable lore => Substitute (NameInfo lore) where+instance Substitutable rep => Substitute (NameInfo rep) where substituteNames subst (LetName dec) = LetName $ substituteNames subst dec substituteNames subst (FParamName dec) =@@ -204,16 +204,16 @@ instance Substitute FV where substituteNames subst = fvNames . substituteNames subst . freeIn --- | Lores in which all annotations support name+-- | Representations in which all annotations support name -- substitution.-type Substitutable lore =- ( Decorations lore,- Substitute (ExpDec lore),- Substitute (BodyDec lore),- Substitute (LetDec lore),- Substitute (FParamInfo lore),- Substitute (LParamInfo lore),- Substitute (RetType lore),- Substitute (BranchType lore),- Substitute (Op lore)+type Substitutable rep =+ ( RepTypes rep,+ Substitute (ExpDec rep),+ Substitute (BodyDec rep),+ Substitute (LetDec rep),+ Substitute (FParamInfo rep),+ Substitute (LParamInfo rep),+ Substitute (RetType rep),+ Substitute (BranchType rep),+ Substitute (Op rep) )
src/Futhark/TypeCheck.hs view
@@ -70,14 +70,14 @@ -- | Information about an error during type checking. The 'Show' -- instance for this type produces a human-readable description.-data ErrorCase lore+data ErrorCase rep = TypeError String- | UnexpectedType (Exp lore) Type [Type]+ | UnexpectedType (Exp rep) Type [Type] | ReturnTypeError Name [ExtType] [ExtType] | DupDefinitionError Name | DupParamError Name VName | DupPatternError VName- | InvalidPatternError (Pattern (Aliases lore)) [ExtType] (Maybe String)+ | InvalidPatternError (Pattern (Aliases rep)) [ExtType] (Maybe String) | UnknownVariableError VName | UnknownFunctionError Name | ParameterMismatch (Maybe Name) [Type] [Type]@@ -88,7 +88,7 @@ | NotAnArray VName Type | PermutationError [Int] Int (Maybe VName) -instance Checkable lore => Show (ErrorCase lore) where+instance Checkable rep => Show (ErrorCase rep) where show (TypeError msg) = "Type error:\n" ++ msg show (UnexpectedType e _ []) =@@ -177,9 +177,9 @@ name' = maybe "" ((++ " ") . pretty) name -- | A type error.-data TypeError lore = Error [String] (ErrorCase lore)+data TypeError rep = Error [String] (ErrorCase rep) -instance Checkable lore => Show (TypeError lore) where+instance Checkable rep => Show (TypeError rep) where show (Error [] err) = show err show (Error msgs err) =@@ -187,9 +187,9 @@ -- | A tuple of a return type and a list of parameters, possibly -- named.-type FunBinding lore = ([RetType (Aliases lore)], [FParam (Aliases lore)])+type FunBinding rep = ([RetType (Aliases rep)], [FParam (Aliases rep)]) -type VarBinding lore = NameInfo (Aliases lore)+type VarBinding rep = NameInfo (Aliases rep) data Usage = Consumed@@ -271,10 +271,10 @@ -- function table is only initialised at the very beginning, but the -- variable table will be extended during type-checking when -- let-expressions are encountered.-data Env lore = Env- { envVtable :: M.Map VName (VarBinding lore),- envFtable :: M.Map Name (FunBinding lore),- envCheckOp :: OpWithAliases (Op lore) -> TypeM lore (),+data Env rep = Env+ { envVtable :: M.Map VName (VarBinding rep),+ envFtable :: M.Map Name (FunBinding rep),+ envCheckOp :: OpWithAliases (Op rep) -> TypeM rep (), envContext :: [String] } @@ -284,24 +284,24 @@ } -- | The type checker runs in this monad.-newtype TypeM lore a+newtype TypeM rep a = TypeM ( ReaderT- (Env lore)- (StateT TState (Either (TypeError lore)))+ (Env rep)+ (StateT TState (Either (TypeError rep))) a ) deriving ( Monad, Functor, Applicative,- MonadReader (Env lore),+ MonadReader (Env rep), MonadState TState ) instance- Checkable lore =>- HasScope (Aliases lore) (TypeM lore)+ Checkable rep =>+ HasScope (Aliases rep) (TypeM rep) where lookupType = fmap typeOf . lookupVar askScope = asks $ M.fromList . mapMaybe varType . M.toList . envVtable@@ -309,18 +309,18 @@ varType (name, dec) = Just (name, dec) runTypeM ::- Env lore ->- TypeM lore a ->- Either (TypeError lore) (a, Consumption)+ Env rep ->+ TypeM rep a ->+ Either (TypeError rep) (a, Consumption) runTypeM env (TypeM m) = second stateCons <$> runStateT (runReaderT m env) (TState mempty mempty) -bad :: ErrorCase lore -> TypeM lore a+bad :: ErrorCase rep -> TypeM rep a bad e = do messages <- asks envContext TypeM $ lift $ lift $ Left $ Error (reverse messages) e -tell :: Consumption -> TypeM lore ()+tell :: Consumption -> TypeM rep () tell cons = modify $ \s -> s {stateCons = stateCons s <> cons} -- | Add information about what is being type-checked to the current@@ -329,8 +329,8 @@ -- 'bad'. context :: String ->- TypeM lore a ->- TypeM lore a+ TypeM rep a ->+ TypeM rep a context s = local $ \env -> env {envContext = s : envContext env} message ::@@ -344,35 +344,35 @@ -- | Mark a name as bound. If the name has been bound previously in -- the program, report a type error.-bound :: VName -> TypeM lore ()+bound :: VName -> TypeM rep () bound name = do already_seen <- gets $ nameIn name . stateNames when already_seen $ bad $ TypeError $ "Name " ++ pretty name ++ " bound twice" modify $ \s -> s {stateNames = oneName name <> stateNames s} -occur :: Occurences -> TypeM lore ()+occur :: Occurences -> TypeM rep () occur = tell . Consumption . filter (not . nullOccurence) -- | Proclaim that we have made read-only use of the given variable. -- No-op unless the variable is array-typed. observe ::- Checkable lore =>+ Checkable rep => VName ->- TypeM lore ()+ TypeM rep () observe name = do dec <- lookupVar name unless (primType $ typeOf dec) $ occur [observation $ oneName name <> aliases dec] -- | Proclaim that we have written to the given variables.-consume :: Checkable lore => Names -> TypeM lore ()+consume :: Checkable rep => Names -> TypeM rep () consume als = do scope <- askScope let isArray = maybe False (not . primType . typeOf) . (`M.lookup` scope) occur [consumption $ namesFromList $ filter isArray $ namesToList als] -collectOccurences :: TypeM lore a -> TypeM lore (a, Occurences)+collectOccurences :: TypeM rep a -> TypeM rep (a, Occurences) collectOccurences m = do old <- gets stateCons modify $ \s -> s {stateCons = mempty}@@ -383,16 +383,16 @@ pure (x, o) checkOpWith ::- (OpWithAliases (Op lore) -> TypeM lore ()) ->- TypeM lore a ->- TypeM lore a+ (OpWithAliases (Op rep) -> TypeM rep ()) ->+ TypeM rep a ->+ TypeM rep a checkOpWith checker = local $ \env -> env {envCheckOp = checker} -checkConsumption :: Consumption -> TypeM lore Occurences+checkConsumption :: Consumption -> TypeM rep Occurences checkConsumption (ConsumptionError e) = bad $ TypeError e checkConsumption (Consumption os) = return os -alternative :: TypeM lore a -> TypeM lore b -> TypeM lore (a, b)+alternative :: TypeM rep a -> TypeM rep b -> TypeM rep (a, b) alternative m1 m2 = do (x, os1) <- collectOccurences m1 (y, os2) <- collectOccurences m2@@ -403,7 +403,7 @@ -- names is consumed, the consumption will be rewritten to be a -- consumption of the corresponding alias set. Consumption of -- anything else will result in a type error.-consumeOnlyParams :: [(VName, Names)] -> TypeM lore a -> TypeM lore a+consumeOnlyParams :: [(VName, Names)] -> TypeM rep a -> TypeM rep a consumeOnlyParams consumable m = do (x, os) <- collectOccurences m tell . Consumption =<< mapM inspect os@@ -427,7 +427,7 @@ -- | Given the immediate aliases, compute the full transitive alias -- set (including the immediate aliases).-expandAliases :: Names -> Env lore -> Names+expandAliases :: Names -> Env rep -> Names expandAliases names env = names <> aliasesOfAliases where aliasesOfAliases = mconcat . map look . namesToList $ names@@ -436,10 +436,10 @@ _ -> mempty binding ::- Checkable lore =>- Scope (Aliases lore) ->- TypeM lore a ->- TypeM lore a+ Checkable rep =>+ Scope (Aliases rep) ->+ TypeM rep a ->+ TypeM rep a binding bnds = check . local (`bindVars` bnds) where bindVars = M.foldlWithKey' bindVar@@ -464,14 +464,14 @@ tell $ Consumption $ unOccur (namesFromList boundnames) os return a -lookupVar :: VName -> TypeM lore (NameInfo (Aliases lore))+lookupVar :: VName -> TypeM rep (NameInfo (Aliases rep)) lookupVar name = do bnd <- asks $ M.lookup name . envVtable case bnd of Nothing -> bad $ UnknownVariableError name Just dec -> return dec -lookupAliases :: Checkable lore => VName -> TypeM lore Names+lookupAliases :: Checkable rep => VName -> TypeM rep Names lookupAliases name = do info <- lookupVar name return $@@ -479,19 +479,19 @@ then mempty else oneName name <> aliases info -aliases :: NameInfo (Aliases lore) -> Names+aliases :: NameInfo (Aliases rep) -> Names aliases (LetName (als, _)) = unAliases als aliases _ = mempty -subExpAliasesM :: Checkable lore => SubExp -> TypeM lore Names+subExpAliasesM :: Checkable rep => SubExp -> TypeM rep Names subExpAliasesM Constant {} = return mempty subExpAliasesM (Var v) = lookupAliases v lookupFun ::- Checkable lore =>+ Checkable rep => Name -> [SubExp] ->- TypeM lore ([RetType lore], [DeclType])+ TypeM rep ([RetType rep], [DeclType]) lookupFun fname args = do bnd <- asks $ M.lookup fname . envFtable case bnd of@@ -510,27 +510,27 @@ String -> Type -> Type ->- TypeM lore ()+ TypeM rep () checkAnnotation desc t1 t2 | t2 == t1 = return () | otherwise = bad $ BadAnnotation desc t1 t2 -- | @require ts se@ causes a '(TypeError vn)' if the type of @se@ is -- not a subtype of one of the types in @ts@.-require :: Checkable lore => [Type] -> SubExp -> TypeM lore ()+require :: Checkable rep => [Type] -> SubExp -> TypeM rep () require ts se = do t <- checkSubExp se unless (t `elem` ts) $ bad $ UnexpectedType (BasicOp $ SubExp se) t ts -- | Variant of 'require' working on variable names.-requireI :: Checkable lore => [Type] -> VName -> TypeM lore ()+requireI :: Checkable rep => [Type] -> VName -> TypeM rep () requireI ts ident = require ts $ Var ident checkArrIdent ::- Checkable lore =>+ Checkable rep => VName ->- TypeM lore Type+ TypeM rep Type checkArrIdent v = do t <- lookupType v case t of@@ -538,9 +538,9 @@ _ -> bad $ NotAnArray v t checkAccIdent ::- Checkable lore =>+ Checkable rep => VName ->- TypeM lore (Shape, [Type])+ TypeM rep (Shape, [Type]) checkAccIdent v = do t <- lookupType v case t of@@ -556,9 +556,9 @@ -- yielding either a type error or a program with complete type -- information. checkProg ::- Checkable lore =>- Prog (Aliases lore) ->- Either (TypeError lore) ()+ Checkable rep =>+ Prog (Aliases rep) ->+ Either (TypeError rep) () checkProg (Prog consts funs) = do let typeenv = Env@@ -588,8 +588,8 @@ return $ M.insert name (ret, params) ftable initialFtable ::- Checkable lore =>- TypeM lore (M.Map Name (FunBinding lore))+ Checkable rep =>+ TypeM rep (M.Map Name (FunBinding rep)) initialFtable = fmap M.fromList $ mapM addBuiltin $ M.toList builtInFunctions where addBuiltin (fname, (t, ts)) = do@@ -598,9 +598,9 @@ name = VName (nameFromString "x") 0 checkFun ::- Checkable lore =>- FunDef (Aliases lore) ->- TypeM lore ()+ Checkable rep =>+ FunDef (Aliases rep) ->+ TypeM rep () checkFun (FunDef _ _ fname rettype params body) = context ("In function " ++ nameToString fname) $ checkFun'@@ -621,40 +621,40 @@ ] funParamsToNameInfos ::- [FParam lore] ->- [(VName, NameInfo (Aliases lore))]-funParamsToNameInfos = map nameTypeAndLore+ [FParam rep] ->+ [(VName, NameInfo (Aliases rep))]+funParamsToNameInfos = map nameTypeAndDec where- nameTypeAndLore fparam =+ nameTypeAndDec fparam = ( paramName fparam, FParamName $ paramDec fparam ) checkFunParams ::- Checkable lore =>- [FParam lore] ->- TypeM lore ()+ Checkable rep =>+ [FParam rep] ->+ TypeM rep () checkFunParams = mapM_ $ \param -> context ("In function parameter " ++ pretty param) $- checkFParamLore (paramName param) (paramDec param)+ checkFParamDec (paramName param) (paramDec param) checkLambdaParams ::- Checkable lore =>- [LParam lore] ->- TypeM lore ()+ Checkable rep =>+ [LParam rep] ->+ TypeM rep () checkLambdaParams = mapM_ $ \param -> context ("In lambda parameter " ++ pretty param) $- checkLParamLore (paramName param) (paramDec param)+ checkLParamDec (paramName param) (paramDec param) checkFun' ::- Checkable lore =>+ Checkable rep => ( Name, [DeclExtType],- [(VName, NameInfo (Aliases lore))]+ [(VName, NameInfo (Aliases rep))] ) -> Maybe [(VName, Names)] ->- TypeM lore [Names] ->- TypeM lore ()+ TypeM rep [Names] ->+ TypeM rep () checkFun' (fname, rettype, params) consumable check = do checkNoDuplicateParams binding (M.fromList params) $@@ -698,7 +698,7 @@ zip (reverse (map uniqueness expected) ++ repeat Nonunique) $ reverse got -checkSubExp :: Checkable lore => SubExp -> TypeM lore Type+checkSubExp :: Checkable rep => SubExp -> TypeM rep Type checkSubExp (Constant val) = return $ Prim $ primValueType val checkSubExp (Var ident) = context ("In subexp " ++ pretty ident) $ do@@ -706,10 +706,10 @@ lookupType ident checkStms ::- Checkable lore =>- Stms (Aliases lore) ->- TypeM lore a ->- TypeM lore a+ Checkable rep =>+ Stms (Aliases rep) ->+ TypeM rep a ->+ TypeM rep a checkStms origbnds m = delve $ stmsToList origbnds where delve (stm@(Let pat _ e) : bnds) = do@@ -721,18 +721,18 @@ m checkResult ::- Checkable lore =>+ Checkable rep => Result ->- TypeM lore ()+ TypeM rep () checkResult = mapM_ checkSubExp checkFunBody ::- Checkable lore =>- [RetType lore] ->- Body (Aliases lore) ->- TypeM lore [Names]-checkFunBody rt (Body (_, lore) bnds res) = do- checkBodyLore lore+ Checkable rep =>+ [RetType rep] ->+ Body (Aliases rep) ->+ TypeM rep [Names]+checkFunBody rt (Body (_, rep) bnds res) = do+ checkBodyDec rep checkStms bnds $ do context "When checking body result" $ checkResult res context "When matching declared return type to result of body" $@@ -742,12 +742,12 @@ bound_here = namesFromList $ M.keys $ scopeOf bnds checkLambdaBody ::- Checkable lore =>+ Checkable rep => [Type] ->- Body (Aliases lore) ->- TypeM lore [Names]-checkLambdaBody ret (Body (_, lore) bnds res) = do- checkBodyLore lore+ Body (Aliases rep) ->+ TypeM rep [Names]+checkLambdaBody ret (Body (_, rep) bnds res) = do+ checkBodyDec rep checkStms bnds $ do checkLambdaResult ret res map (`namesSubtract` bound_here) <$> mapM subExpAliasesM res@@ -755,10 +755,10 @@ bound_here = namesFromList $ M.keys $ scopeOf bnds checkLambdaResult ::- Checkable lore =>+ Checkable rep => [Type] -> Result ->- TypeM lore ()+ TypeM rep () checkLambdaResult ts es | length ts /= length es = bad $@@ -780,18 +780,18 @@ ++ pretty t checkBody ::- Checkable lore =>- Body (Aliases lore) ->- TypeM lore [Names]-checkBody (Body (_, lore) bnds res) = do- checkBodyLore lore+ Checkable rep =>+ Body (Aliases rep) ->+ TypeM rep [Names]+checkBody (Body (_, rep) bnds res) = do+ checkBodyDec rep checkStms bnds $ do checkResult res map (`namesSubtract` bound_here) <$> mapM subExpAliasesM res where bound_here = namesFromList $ M.keys $ scopeOf bnds -checkBasicOp :: Checkable lore => BasicOp -> TypeM lore ()+checkBasicOp :: Checkable rep => BasicOp -> TypeM rep () checkBasicOp (SubExp es) = void $ checkSubExp es checkBasicOp (Opaque es) =@@ -934,11 +934,11 @@ consume =<< lookupAliases acc matchLoopResultExt ::- Checkable lore =>+ Checkable rep => [Param DeclType] -> [Param DeclType] -> [SubExp] ->- TypeM lore ()+ TypeM rep () matchLoopResultExt ctx val loopres = do let rettype_ext = existentialiseExtTypes (map paramName ctx) $@@ -962,9 +962,9 @@ (staticShapes bodyt) checkExp ::- Checkable lore =>- Exp (Aliases lore) ->- TypeM lore ()+ Checkable rep =>+ Exp (Aliases rep) ->+ TypeM rep () checkExp (BasicOp op) = checkBasicOp op checkExp (If e1 e2 e3 info) = do require [Prim Bool] e1@@ -1016,7 +1016,7 @@ (Just consumable) $ do checkFunParams mergepat- checkBodyLore $ snd $ bodyDec loopbody+ checkBodyDec $ snd $ bodyDec loopbody checkStms (bodyStms loopbody) $ do checkResult $ bodyResult loopbody@@ -1037,7 +1037,7 @@ observe a case peelArray 1 a_t of Just a_t_r -> do- checkLParamLore (paramName p) $ paramDec p+ checkLParamDec (paramName p) $ paramDec p unless (a_t_r `subtypeOf` typeOf (paramDec p)) $ bad $ TypeError $@@ -1127,10 +1127,10 @@ checker op checkSOACArrayArgs ::- Checkable lore =>+ Checkable rep => SubExp -> [VName] ->- TypeM lore [Arg]+ TypeM rep [Arg] checkSOACArrayArgs width = mapM checkSOACArrayArg where checkSOACArrayArg v = do@@ -1151,9 +1151,9 @@ "SOAC argument " ++ pretty v ++ " is not an array" checkType ::- Checkable lore =>+ Checkable rep => TypeBase Shape u ->- TypeM lore ()+ TypeM rep () checkType (Mem (ScalarSpace d _)) = mapM_ (require [Prim int64]) d checkType (Acc cert shape ts _) = do requireI [Prim Unit] cert@@ -1162,20 +1162,20 @@ checkType t = mapM_ checkSubExp $ arrayDims t checkExtType ::- Checkable lore =>+ Checkable rep => TypeBase ExtShape u ->- TypeM lore ()+ TypeM rep () checkExtType = mapM_ checkExtDim . shapeDims . arrayShape where checkExtDim (Free se) = void $ checkSubExp se checkExtDim (Ext _) = return () checkCmpOp ::- Checkable lore =>+ Checkable rep => CmpOp -> SubExp -> SubExp ->- TypeM lore ()+ TypeM rep () checkCmpOp (CmpEq t) x y = do require [Prim t] x require [Prim t] y@@ -1189,38 +1189,38 @@ checkCmpOp CmpLle x y = checkBinOpArgs Bool x y checkBinOpArgs ::- Checkable lore =>+ Checkable rep => PrimType -> SubExp -> SubExp ->- TypeM lore ()+ TypeM rep () checkBinOpArgs t e1 e2 = do require [Prim t] e1 require [Prim t] e2 checkPatElem ::- Checkable lore =>- PatElemT (LetDec lore) ->- TypeM lore ()+ Checkable rep =>+ PatElemT (LetDec rep) ->+ TypeM rep () checkPatElem (PatElem name dec) = context ("When checking pattern element " ++ pretty name) $- checkLetBoundLore name dec+ checkLetBoundDec name dec checkDimIndex ::- Checkable lore =>+ Checkable rep => DimIndex SubExp ->- TypeM lore ()+ TypeM rep () checkDimIndex (DimFix i) = require [Prim int64] i checkDimIndex (DimSlice i n s) = mapM_ (require [Prim int64]) [i, n, s] checkStm ::- Checkable lore =>- Stm (Aliases lore) ->- TypeM lore a ->- TypeM lore a+ Checkable rep =>+ Stm (Aliases rep) ->+ TypeM rep a ->+ TypeM rep a checkStm stm@(Let pat (StmAux (Certificates cs) _ (_, dec)) e) m = do context "When checking certificates" $ mapM_ (requireI [Prim Unit]) cs- context "When checking expression annotation" $ checkExpLore dec+ context "When checking expression annotation" $ checkExpDec dec context ("When matching\n" ++ message " " pat ++ "\nwith\n" ++ message " " e) $ matchPattern pat e binding (maybeWithoutAliases $ scopeOf stm) $ do@@ -1242,37 +1242,37 @@ withoutAliases info = info matchExtPattern ::- Checkable lore =>- Pattern (Aliases lore) ->+ Checkable rep =>+ Pattern (Aliases rep) -> [ExtType] ->- TypeM lore ()+ TypeM rep () matchExtPattern pat ts = unless (expExtTypesFromPattern pat == ts) $ bad $ InvalidPatternError pat ts Nothing matchExtReturnType ::- Checkable lore =>+ Checkable rep => [ExtType] -> Result ->- TypeM lore ()+ TypeM rep () matchExtReturnType rettype res = do ts <- mapM subExpType res matchExtReturns rettype res ts matchExtBranchType ::- Checkable lore =>+ Checkable rep => [ExtType] ->- Body (Aliases lore) ->- TypeM lore ()+ Body (Aliases rep) ->+ TypeM rep () matchExtBranchType rettype (Body _ stms res) = do ts <- extendedScope (traverse subExpType res) stmscope matchExtReturns rettype res ts where stmscope = scopeOf stms -matchExtReturns :: [ExtType] -> Result -> [Type] -> TypeM lore ()+matchExtReturns :: [ExtType] -> Result -> [Type] -> TypeM rep () matchExtReturns rettype res ts = do- let problem :: TypeM lore a+ let problem :: TypeM rep a problem = bad $ TypeError $@@ -1337,9 +1337,9 @@ noArgAliases (t, _) = (t, mempty) checkArg ::- Checkable lore =>+ Checkable rep => SubExp ->- TypeM lore Arg+ TypeM rep Arg checkArg arg = do argt <- checkSubExp arg als <- subExpAliasesM arg@@ -1349,7 +1349,7 @@ Maybe Name -> [DeclType] -> [Arg] ->- TypeM lore ()+ TypeM rep () checkFuncall fname paramts args = do let argts = map argType args unless (validApply paramts argts) $@@ -1359,7 +1359,7 @@ consumeArgs :: [DeclType] -> [Arg] ->- TypeM lore ()+ TypeM rep () consumeArgs paramts args = forM_ (zip (map diet paramts) args) $ \(d, (_, als)) -> occur [consumption (consumeArg als d)]@@ -1370,7 +1370,7 @@ -- The boolean indicates whether we only allow consumption of -- parameters. checkAnyLambda ::- Checkable lore => Bool -> Lambda (Aliases lore) -> [Arg] -> TypeM lore ()+ Checkable rep => Bool -> Lambda (Aliases rep) -> [Arg] -> TypeM rep () checkAnyLambda soac (Lambda params body rettype) args = do let fname = nameFromString "<anonymous>" if length params == length args@@ -1407,10 +1407,10 @@ ++ show (length args) ++ " arguments." -checkLambda :: Checkable lore => Lambda (Aliases lore) -> [Arg] -> TypeM lore ()+checkLambda :: Checkable rep => Lambda (Aliases rep) -> [Arg] -> TypeM rep () checkLambda = checkAnyLambda True -checkPrimExp :: Checkable lore => PrimExp VName -> TypeM lore ()+checkPrimExp :: Checkable rep => PrimExp VName -> TypeM rep () checkPrimExp ValueExp {} = return () checkPrimExp (LeafExp v pt) = requireI [Prim pt] v checkPrimExp (BinOpExp op x y) = do@@ -1442,7 +1442,7 @@ ++ pretty h_ret zipWithM_ requirePrimExp h_ts args -requirePrimExp :: Checkable lore => PrimType -> PrimExp VName -> TypeM lore ()+requirePrimExp :: Checkable rep => PrimType -> PrimExp VName -> TypeM rep () requirePrimExp t e = context ("in PrimExp " ++ pretty e) $ do checkPrimExp e unless (primExpType e == t) $@@ -1450,62 +1450,62 @@ TypeError $ pretty e ++ " must have type " ++ pretty t -class ASTLore lore => CheckableOp lore where- checkOp :: OpWithAliases (Op lore) -> TypeM lore ()+class ASTRep rep => CheckableOp rep where+ checkOp :: OpWithAliases (Op rep) -> TypeM rep () -- ^ Used at top level; can be locally changed with 'checkOpWith'. --- | The class of lores that can be type-checked.-class (ASTLore lore, CanBeAliased (Op lore), CheckableOp lore) => Checkable lore where- checkExpLore :: ExpDec lore -> TypeM lore ()- checkBodyLore :: BodyDec lore -> TypeM lore ()- checkFParamLore :: VName -> FParamInfo lore -> TypeM lore ()- checkLParamLore :: VName -> LParamInfo lore -> TypeM lore ()- checkLetBoundLore :: VName -> LetDec lore -> TypeM lore ()- checkRetType :: [RetType lore] -> TypeM lore ()- matchPattern :: Pattern (Aliases lore) -> Exp (Aliases lore) -> TypeM lore ()- primFParam :: VName -> PrimType -> TypeM lore (FParam (Aliases lore))- matchReturnType :: [RetType lore] -> Result -> TypeM lore ()- matchBranchType :: [BranchType lore] -> Body (Aliases lore) -> TypeM lore ()+-- | The class of representations that can be type-checked.+class (ASTRep rep, CanBeAliased (Op rep), CheckableOp rep) => Checkable rep where+ checkExpDec :: ExpDec rep -> TypeM rep ()+ checkBodyDec :: BodyDec rep -> TypeM rep ()+ checkFParamDec :: VName -> FParamInfo rep -> TypeM rep ()+ 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 ()+ 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 lore)] ->- [FParam (Aliases lore)] ->+ [FParam (Aliases rep)] ->+ [FParam (Aliases rep)] -> [SubExp] ->- TypeM lore ()+ TypeM rep () - default checkExpLore :: ExpDec lore ~ () => ExpDec lore -> TypeM lore ()- checkExpLore = return+ default checkExpDec :: ExpDec rep ~ () => ExpDec rep -> TypeM rep ()+ checkExpDec = return - default checkBodyLore :: BodyDec lore ~ () => BodyDec lore -> TypeM lore ()- checkBodyLore = return+ default checkBodyDec :: BodyDec rep ~ () => BodyDec rep -> TypeM rep ()+ checkBodyDec = return - default checkFParamLore :: FParamInfo lore ~ DeclType => VName -> FParamInfo lore -> TypeM lore ()- checkFParamLore _ = checkType+ default checkFParamDec :: FParamInfo rep ~ DeclType => VName -> FParamInfo rep -> TypeM rep ()+ checkFParamDec _ = checkType - default checkLParamLore :: LParamInfo lore ~ Type => VName -> LParamInfo lore -> TypeM lore ()- checkLParamLore _ = checkType+ default checkLParamDec :: LParamInfo rep ~ Type => VName -> LParamInfo rep -> TypeM rep ()+ checkLParamDec _ = checkType - default checkLetBoundLore :: LetDec lore ~ Type => VName -> LetDec lore -> TypeM lore ()- checkLetBoundLore _ = checkType+ default checkLetBoundDec :: LetDec rep ~ Type => VName -> LetDec rep -> TypeM rep ()+ checkLetBoundDec _ = checkType - default checkRetType :: RetType lore ~ DeclExtType => [RetType lore] -> TypeM lore ()+ default checkRetType :: RetType rep ~ DeclExtType => [RetType rep] -> TypeM rep () checkRetType = mapM_ $ checkExtType . declExtTypeOf - default matchPattern :: Pattern (Aliases lore) -> Exp (Aliases lore) -> TypeM lore ()+ default matchPattern :: Pattern (Aliases rep) -> Exp (Aliases rep) -> TypeM rep () matchPattern pat = matchExtPattern pat <=< expExtType - default primFParam :: FParamInfo lore ~ DeclType => VName -> PrimType -> TypeM lore (FParam (Aliases lore))+ default primFParam :: FParamInfo rep ~ DeclType => VName -> PrimType -> TypeM rep (FParam (Aliases rep)) primFParam name t = return $ Param name (Prim t) - default matchReturnType :: RetType lore ~ DeclExtType => [RetType lore] -> Result -> TypeM lore ()+ default matchReturnType :: RetType rep ~ DeclExtType => [RetType rep] -> Result -> TypeM rep () matchReturnType = matchExtReturnType . map fromDecl - default matchBranchType :: BranchType lore ~ ExtType => [BranchType lore] -> Body (Aliases lore) -> TypeM lore ()+ default matchBranchType :: BranchType rep ~ ExtType => [BranchType rep] -> Body (Aliases rep) -> TypeM rep () matchBranchType = matchExtBranchType default matchLoopResult ::- FParamInfo lore ~ DeclType =>- [FParam (Aliases lore)] ->- [FParam (Aliases lore)] ->+ FParamInfo rep ~ DeclType =>+ [FParam (Aliases rep)] ->+ [FParam (Aliases rep)] -> [SubExp] ->- TypeM lore ()+ TypeM rep () matchLoopResult = matchLoopResultExt
src/Futhark/Util.hs view
@@ -50,22 +50,30 @@ EncodedString, zEncodeString, atMostChars,+ invertMap, ) where +import Control.Arrow (first) import Control.Concurrent import Control.Exception import Control.Monad import qualified Data.ByteString as BS 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 Data.Maybe+import Data.Set (Set)+import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Encoding.Error as T import qualified Data.Text.IO as T+import Data.Tuple (swap) import Numeric import qualified System.Directory.Tree as Dir import System.Environment@@ -431,3 +439,9 @@ atMostChars n s | length s > n = take (n -3) s ++ "..." | otherwise = s++invertMap :: (Ord v, Ord k) => Map k v -> Map v (Set k)+invertMap m =+ Map.toList m+ & fmap (swap . first Set.singleton)+ & foldr (uncurry $ Map.insertWith (<>)) mempty
src/Futhark/Util/Loc.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE Trustworthy #-}- -- | A Safe Haskell-trusted re-export of the @srcloc@ package. module Futhark.Util.Loc (module Data.Loc) where
src/Futhark/Util/Pretty.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE Trustworthy #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | A re-export of the prettyprinting library, along with some convenience functions.
src/Language/Futhark/Core.hs view
@@ -7,7 +7,6 @@ -- representation. module Language.Futhark.Core ( Uniqueness (..),- Commutativity (..), -- * Location utilities SrcLoc,@@ -28,7 +27,6 @@ baseTag, baseName, baseString,- pretty, quote, pquote, @@ -75,19 +73,6 @@ instance Pretty Uniqueness where ppr Unique = star ppr Nonunique = empty---- | Whether some operator is commutative or not. The 'Monoid'--- instance returns the least commutative of its arguments.-data Commutativity- = Noncommutative- | Commutative- deriving (Eq, Ord, Show)--instance Semigroup Commutativity where- (<>) = min--instance Monoid Commutativity where- mempty = Commutative -- | The name of the default program entry point (main). defaultEntryPoint :: Name
src/Language/Futhark/Syntax.hs view
@@ -12,6 +12,7 @@ -- module may be a little hard to understand. module Language.Futhark.Syntax ( module Language.Futhark.Core,+ pretty, -- * Types Uniqueness (..),
unittests/Futhark/IR/Syntax/CoreTests.hs view
@@ -4,7 +4,7 @@ module Futhark.IR.Syntax.CoreTests (tests) where import Control.Applicative-import Futhark.IR.Pretty ()+import Futhark.IR.Pretty (pretty) import Futhark.IR.PrimitiveTests () import Futhark.IR.Syntax.Core import Language.Futhark.CoreTests ()
+ unittests/Futhark/Optimise/ReuseAllocations/GreedyColoringTests.hs view
@@ -0,0 +1,70 @@+module Futhark.Optimise.ReuseAllocations.GreedyColoringTests+ ( tests,+ )+where++import Control.Arrow ((***))+import Data.Function ((&))+import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Futhark.Optimise.ReuseAllocations.GreedyColoring as GreedyColoring+import Test.Tasty+import Test.Tasty.HUnit++tests :: TestTree+tests =+ testGroup+ "GreedyColoringTests"+ [psumTest, allIntersect, emptyGraph, noIntersections, differentSpaces]++psumTest :: TestTree+psumTest =+ testCase "psumTest" $+ assertEqual+ "Color simple 1-2-3 using two colors"+ ([(0, "local"), (1, "local")], [(1 :: Int, 0), (2, 1), (3, 0)])+ $ (Map.toList *** Map.toList) $+ GreedyColoring.colorGraph+ (Map.fromList [(1, "local"), (2, "local"), (3, "local")])+ $ Set.fromList [(1, 2), (2, 3)]++allIntersect :: TestTree+allIntersect =+ testCase "allIntersect" $+ 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) $+ GreedyColoring.colorGraph+ (Map.fromList [(1, "local"), (2, "local"), (3, "local")])+ $ Set.fromList [(1, 2), (2, 3), (1, 3)]++emptyGraph :: TestTree+emptyGraph =+ testCase "emptyGraph" $+ assertEqual+ "Color an empty graph"+ ([] :: [(Int, Char)], [] :: [(Int, Int)])+ $ (Map.toList *** Map.toList) $ GreedyColoring.colorGraph Map.empty $ Set.fromList []++noIntersections :: TestTree+noIntersections =+ GreedyColoring.colorGraph+ (Map.fromList [(1, "local"), (2, "local"), (3, "local")])+ (Set.fromList [])+ & Map.toList *** Map.toList+ & assertEqual+ "Color nodes with no intersections"+ ([(0, "local")], [(1, 0), (2, 0), (3, 0)] :: [(Int, Int)])+ & testCase "noIntersections"++differentSpaces :: TestTree+differentSpaces =+ GreedyColoring.colorGraph+ (Map.fromList [(1, "a"), (2, "b"), (3, "c")])+ (Set.fromList [])+ & Map.toList *** Map.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)])+ & testCase "differentSpaces"
unittests/futhark_tests.hs view
@@ -5,6 +5,7 @@ import qualified Futhark.IR.PrimitiveTests import qualified Futhark.IR.PropTests import qualified Futhark.IR.Syntax.CoreTests+import qualified Futhark.Optimise.ReuseAllocations.GreedyColoringTests import qualified Futhark.Pkg.SolveTests import qualified Language.Futhark.SyntaxTests import Test.Tasty@@ -19,7 +20,8 @@ Futhark.IR.Syntax.CoreTests.tests, Futhark.Pkg.SolveTests.tests, Futhark.IR.Mem.IxFunTests.tests,- Futhark.IR.PrimitiveTests.tests+ Futhark.IR.PrimitiveTests.tests,+ Futhark.Optimise.ReuseAllocations.GreedyColoringTests.tests ] main :: IO ()