packages feed

accelerate-llvm-native 1.2.0.1 → 1.3.0.0

raw patch · 46 files changed

+3250/−3273 lines, 46 filesdep +deepseqdep −Cabaldep −timedep ~acceleratedep ~accelerate-llvmdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: deepseq

Dependencies removed: Cabal, time

Dependency ranges changed: accelerate, accelerate-llvm, base, bytestring, llvm-hs, llvm-hs-pure

API changes (from Hackage documentation)

- Data.Array.Accelerate.LLVM.Native: balancedParIO :: Int -> Strategy
- Data.Array.Accelerate.LLVM.Native: instance Data.Array.Accelerate.LLVM.Native.RunAsync (GHC.Types.IO (Data.Array.Accelerate.Async.Async b))
- Data.Array.Accelerate.LLVM.Native: instance Data.Array.Accelerate.LLVM.Native.RunAsync b => Data.Array.Accelerate.LLVM.Native.RunAsync (a -> b)
- Data.Array.Accelerate.LLVM.Native: type Strategy = Gang -> Executable
- Data.Array.Accelerate.LLVM.Native: unbalancedParIO :: Strategy
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AGPL :: Maybe Version -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AbiTag :: String -> AbiTag
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AllRightsReserved :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AllowAmbiguousTypes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AnyVersion :: VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AnyVersionF :: VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Apache :: Maybe Version -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ApplicativeDo :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Arrows :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: AutoDeriveTypeable :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BSD2 :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BSD3 :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BSD4 :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BangPatterns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BinaryLiterals :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: BlockArguments :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: CApiFFI :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: CPP :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Compiler :: CompilerId -> AbiTag -> [CompilerId] -> [(Language, Flag)] -> [(Extension, Maybe Flag)] -> Map String String -> Compiler
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: CompilerId :: CompilerFlavor -> Version -> CompilerId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: CompilerInfo :: CompilerId -> AbiTag -> Maybe [CompilerId] -> Maybe [Language] -> Maybe [Extension] -> CompilerInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ConstrainedClassMethods :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ConstraintKinds :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DataKinds :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DatatypeContexts :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DefaultSignatures :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Dependency :: PackageName -> VersionRange -> Dependency
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveAnyClass :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveDataTypeable :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveFoldable :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveFunctor :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveGeneric :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveLift :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DeriveTraversable :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DerivingStrategies :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DisableExtension :: KnownExtension -> Extension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DisambiguateRecordFields :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DoAndIfThenElse :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DoRec :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: DuplicateRecordFields :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: EarlierVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: EarlierVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: EmptyCase :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: EmptyDataDecls :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: EnableExtension :: KnownExtension -> Extension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Eta :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExclusiveBound :: Bound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExistentialQuantification :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExplicitForAll :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExplicitNamespaces :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExtendedDefaultRules :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ExtensibleRecords :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: FlexibleContexts :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: FlexibleInstances :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ForeignFunctionInterface :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: FunctionalDependencies :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GADTSyntax :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GADTs :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GHCForeignImportPrim :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GHCJS :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GPL :: Maybe Version -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GeneralizedNewtypeDeriving :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Generics :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: GlobalPackageDB :: PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: HBC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Haskell2010 :: Language
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Haskell98 :: Language
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: HaskellSuite :: String -> CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Helium :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: HereDocuments :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: HexFloatLiterals :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Hugs :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ISC :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ImplicitParams :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ImplicitPrelude :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ImpredicativeTypes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: InclusiveBound :: Bound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: IncoherentInstances :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: InstanceSigs :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: InterruptibleFFI :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: IntersectVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: IntersectVersionRangesF :: a -> a -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: JHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: JavaScriptFFI :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: KindSignatures :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LGPL :: Maybe Version -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LambdaCase :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LaterVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LaterVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LiberalTypeSynonyms :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: LowerBound :: Version -> !Bound -> LowerBound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MIT :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MPL :: Version -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MagicHash :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MajorBoundVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MajorBoundVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MaximalDebugInfo :: DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MaximumOptimisation :: OptimisationLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MinimalDebugInfo :: DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Module :: DefUnitId -> ModuleName -> Module
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MonadComprehensions :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MonadFailDesugaring :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MonoLocalBinds :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MonoPatBinds :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MonomorphismRestriction :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MultiParamTypeClasses :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: MultiWayIf :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NPlusKPatterns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NamedFieldPuns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NamedWildCards :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NegativeLiterals :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NewQualifiedOperators :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NoAbiTag :: AbiTag
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NoDebugInfo :: DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NoOptimisation :: OptimisationLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NoUpperBound :: UpperBound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NondecreasingIndentation :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NormalDebugInfo :: DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NormalOptimisation :: OptimisationLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NullaryTypeClasses :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NumDecimals :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: NumericUnderscores :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OrEarlierVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OrEarlierVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OrLaterVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OrLaterVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OtherCompiler :: String -> CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OtherLicense :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OverlappingInstances :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OverloadedLabels :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OverloadedLists :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: OverloadedStrings :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PackageIdentifier :: PackageName -> Version -> PackageIdentifier
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PackageImports :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ParallelArrays :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ParallelListComp :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PartialTypeSignatures :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PatternGuards :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PatternSignatures :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PatternSynonyms :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PolyKinds :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PolymorphicComponents :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PostfixOperators :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailAllFunctions :: ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailDefault :: ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailExportedFunctions :: ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailNone :: ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailOther :: String -> ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ProfDetailToplevelFunctions :: ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: PublicDomain :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: QuantifiedConstraints :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: QuasiQuotes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Rank2Types :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RankNTypes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RebindableSyntax :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RecordPuns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RecordWildCards :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RecursiveDo :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RegularPatterns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RelaxedPolyRec :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RestrictedTypeSynonyms :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: RoleAnnotations :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Safe :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: SafeImports :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ScopedTypeVariables :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: SpecificPackageDB :: FilePath -> PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: StandaloneDeriving :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: StarIsType :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: StaticPointers :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Strict :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: StrictData :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TemplateHaskell :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TemplateHaskellQuotes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ThisVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ThisVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TraditionalRecordSyntax :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TransformListComp :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Trustworthy :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TupleSections :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeApplications :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeFamilies :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeFamilyDependencies :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeInType :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeOperators :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: TypeSynonymInstances :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnboxedSums :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnboxedTuples :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UndecidableInstances :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UndecidableSuperClasses :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnicodeSyntax :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnionVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnionVersionRangesF :: a -> a -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnknownExtension :: String -> Extension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnknownLanguage :: String -> Language
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnknownLicense :: String -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnliftedFFITypes :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: Unsafe :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UnspecifiedLicense :: License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UpperBound :: Version -> !Bound -> UpperBound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UserHooks :: (Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()) -> IO (Maybe GenericPackageDescription) -> [PPSuffixHandler] -> [Program] -> (Args -> ConfigFlags -> IO HookedBuildInfo) -> ((GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo) -> (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BuildFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()) -> (Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> ReplFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()) -> (Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> CleanFlags -> IO HookedBuildInfo) -> (PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()) -> (Args -> CleanFlags -> PackageDescription -> () -> IO ()) -> (Args -> CopyFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()) -> (Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> InstallFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()) -> (Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> SDistFlags -> IO HookedBuildInfo) -> (PackageDescription -> Maybe LocalBuildInfo -> UserHooks -> SDistFlags -> IO ()) -> (Args -> SDistFlags -> PackageDescription -> Maybe LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> RegisterFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()) -> (Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HscolourFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()) -> (Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> DoctestFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()) -> (Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> HaddockFlags -> IO HookedBuildInfo) -> (PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()) -> (Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> TestFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()) -> (Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> (Args -> BenchmarkFlags -> IO HookedBuildInfo) -> (Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()) -> (Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()) -> UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: UserPackageDB :: PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: VersionRangeParens :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: VersionRangeParensF :: a -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: ViewPatterns :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: WildcardVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: WildcardVersionF :: Version -> VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: XmlSyntax :: KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: YHC :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [benchHook] :: UserHooks -> Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> BenchmarkFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [buildHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [cleanHook] :: UserHooks -> PackageDescription -> () -> UserHooks -> CleanFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerAbiTag] :: Compiler -> AbiTag
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerCompat] :: Compiler -> [CompilerId]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerExtensions] :: Compiler -> [(Extension, Maybe Flag)]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerId] :: Compiler -> CompilerId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerInfoAbiTag] :: CompilerInfo -> AbiTag
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerInfoCompat] :: CompilerInfo -> Maybe [CompilerId]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerInfoExtensions] :: CompilerInfo -> Maybe [Extension]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerInfoId] :: CompilerInfo -> CompilerId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerInfoLanguages] :: CompilerInfo -> Maybe [Language]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerLanguages] :: Compiler -> [(Language, Flag)]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [compilerProperties] :: Compiler -> Map String String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [confHook] :: UserHooks -> (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [copyHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [doctestHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> DoctestFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [haddockHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> HaddockFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [hookedPreProcessors] :: UserHooks -> [PPSuffixHandler]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [hookedPrograms] :: UserHooks -> [Program]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [hscolourHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> HscolourFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [instHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [pkgName] :: PackageIdentifier -> PackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [pkgVersion] :: PackageIdentifier -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postBench] :: UserHooks -> Args -> BenchmarkFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postBuild] :: UserHooks -> Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postClean] :: UserHooks -> Args -> CleanFlags -> PackageDescription -> () -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postConf] :: UserHooks -> Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postCopy] :: UserHooks -> Args -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postDoctest] :: UserHooks -> Args -> DoctestFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postHaddock] :: UserHooks -> Args -> HaddockFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postHscolour] :: UserHooks -> Args -> HscolourFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postInst] :: UserHooks -> Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postReg] :: UserHooks -> Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postRepl] :: UserHooks -> Args -> ReplFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postSDist] :: UserHooks -> Args -> SDistFlags -> PackageDescription -> Maybe LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postTest] :: UserHooks -> Args -> TestFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [postUnreg] :: UserHooks -> Args -> RegisterFlags -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preBench] :: UserHooks -> Args -> BenchmarkFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preBuild] :: UserHooks -> Args -> BuildFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preClean] :: UserHooks -> Args -> CleanFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preConf] :: UserHooks -> Args -> ConfigFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preCopy] :: UserHooks -> Args -> CopyFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preDoctest] :: UserHooks -> Args -> DoctestFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preHaddock] :: UserHooks -> Args -> HaddockFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preHscolour] :: UserHooks -> Args -> HscolourFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preInst] :: UserHooks -> Args -> InstallFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preReg] :: UserHooks -> Args -> RegisterFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preRepl] :: UserHooks -> Args -> ReplFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preSDist] :: UserHooks -> Args -> SDistFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preTest] :: UserHooks -> Args -> TestFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [preUnreg] :: UserHooks -> Args -> RegisterFlags -> IO HookedBuildInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [readDesc] :: UserHooks -> IO (Maybe GenericPackageDescription)
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [regHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [replHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [runTests] :: UserHooks -> Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [sDistHook] :: UserHooks -> PackageDescription -> Maybe LocalBuildInfo -> UserHooks -> SDistFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [testHook] :: UserHooks -> Args -> PackageDescription -> LocalBuildInfo -> UserHooks -> TestFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: [unregHook] :: UserHooks -> PackageDescription -> LocalBuildInfo -> UserHooks -> RegisterFlags -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: abiTagString :: AbiTag -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: absolutePackageDBPath :: PackageDB -> NoCallStackIO PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: absolutePackageDBPaths :: PackageDBStack -> NoCallStackIO PackageDBStack
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: alterVersion :: ([Int] -> [Int]) -> Version -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: anaVersionRange :: () => (a -> VersionRangeF a) -> a -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: anyVersion :: VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: arResponseFilesSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: asVersionIntervals :: VersionRange -> [VersionInterval]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: autoconfUserHooks :: UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: backpackSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: betweenVersionsInclusive :: Version -> Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: buildCompilerFlavor :: CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: buildCompilerId :: CompilerId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: cataVersionRange :: () => (VersionRangeF a -> a) -> VersionRange -> a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: class HasMungedPackageId pkg
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: class Package pkg => HasUnitId pkg
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: class Package pkg
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: class HasUnitId pkg => PackageInstalled pkg
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: classifyCompilerFlavor :: String -> CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: classifyExtension :: String -> Extension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: classifyLanguage :: String -> Language
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: compilerCompatFlavor :: CompilerFlavor -> Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: compilerCompatVersion :: CompilerFlavor -> Compiler -> Maybe Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: compilerFlavor :: Compiler -> CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: compilerInfo :: Compiler -> CompilerInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: compilerVersion :: Compiler -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: coverageSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data AbiHash
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data AbiTag
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Bound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Compiler
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data CompilerId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data CompilerInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data ComponentId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data DefUnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Dependency
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Extension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data KnownExtension
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Language
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data LowerBound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Module
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data OptimisationLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data PackageIdentifier
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data PackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data PkgconfigName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data UpperBound
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: data VersionRangeF a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultCompilerFlavor :: Maybe CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultHookedPackageDesc :: IO (Maybe FilePath)
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMain :: IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainArgs :: [String] -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainNoRead :: GenericPackageDescription -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainWithHooks :: UserHooks -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainWithHooksArgs :: UserHooks -> [String] -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainWithHooksNoRead :: UserHooks -> GenericPackageDescription -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultMainWithHooksNoReadArgs :: UserHooks -> GenericPackageDescription -> [String] -> IO ()
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: defaultUserHooks :: UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: depPkgName :: Dependency -> PackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: depVerRange :: Dependency -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: deprecatedExtensions :: [(Extension, Maybe Extension)]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: differenceVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: earlierVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: embedVersionRange :: VersionRangeF VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: emptyUserHooks :: UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: extensionsToFlags :: Compiler -> [Extension] -> [Flag]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: flagToDebugInfoLevel :: Maybe String -> DebugInfoLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: flagToOptimisationLevel :: Maybe String -> OptimisationLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: flagToProfDetailLevel :: String -> ProfDetailLevel
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: foldVersionRange :: () => a -> (Version -> a) -> (Version -> a) -> (Version -> a) -> (a -> a -> a) -> (a -> a -> a) -> VersionRange -> a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: foldVersionRange' :: () => a -> (Version -> a) -> (Version -> a) -> (Version -> a) -> (Version -> a) -> (Version -> a) -> (Version -> Version -> a) -> (Version -> Version -> a) -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> VersionRange -> a
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: fromVersionIntervals :: VersionIntervals -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: getHSLibraryName :: UnitId -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: hasLowerBound :: VersionRange -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: hasUpperBound :: VersionRange -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: hyloVersionRange :: (VersionRangeF VersionRange -> VersionRange) -> (VersionRange -> VersionRangeF VersionRange) -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: installedDepends :: PackageInstalled pkg => pkg -> [UnitId]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: installedPackageId :: HasUnitId pkg => pkg -> UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: installedUnitId :: HasUnitId pkg => pkg -> UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: intersectVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: intersectVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: invertVersionIntervals :: VersionIntervals -> VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: invertVersionRange :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: isAnyVersion :: VersionRange -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: isNoVersion :: VersionRange -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: isSpecificVersion :: VersionRange -> Maybe Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: knownCompilerFlavors :: [CompilerFlavor]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: knownExtensions :: [KnownExtension]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: knownLanguages :: [Language]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: knownLicenses :: [License]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: knownProfDetailLevels :: [(String, [String], ProfDetailLevel)]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: languageToFlags :: Compiler -> Maybe Language -> [Flag]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: laterVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: libraryDynDirSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: licenseFromSPDX :: License -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: licenseToSPDX :: License -> License
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: majorBoundVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: majorUpperBound :: Version -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkAbiHash :: String -> AbiHash
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkComponentId :: String -> ComponentId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkLegacyUnitId :: PackageId -> UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkPackageName :: String -> PackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkPkgconfigName :: String -> PkgconfigName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkUnitId :: String -> UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkVersion :: [Int] -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkVersion' :: Version -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mkVersionIntervals :: [VersionInterval] -> VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mungedId :: HasMungedPackageId pkg => pkg -> MungedPackageId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mungedName' :: HasMungedPackageId pkg => pkg -> MungedPackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: mungedVersion' :: HasMungedPackageId munged => munged -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: newSimpleUnitId :: ComponentId -> UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: noVersion :: VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: normaliseVersionRange :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: notThisPackageVersion :: PackageIdentifier -> Dependency
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: notThisVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: nullVersion :: Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: orEarlierVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: orLaterVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: packageId :: Package pkg => pkg -> PackageIdentifier
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: packageKeySupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: packageName :: Package pkg => pkg -> PackageName
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: packageVersion :: Package pkg => pkg -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: parmakeSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: parseCompilerFlavorCompat :: () => ReadP r CompilerFlavor
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: profilingSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: projectVersionRange :: VersionRange -> VersionRangeF VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: reexportedModulesSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: registrationPackageDB :: PackageDBStack -> PackageDB
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: removeLowerBound :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: removeUpperBound :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: renamingPackageFlagsSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: showCompilerId :: Compiler -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: showCompilerIdWithAbi :: Compiler -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: showProfDetailLevel :: ProfDetailLevel -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: showVersion :: Version -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: simpleUserHooks :: UserHooks
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: simplifyDependency :: Dependency -> Dependency
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: simplifyVersionRange :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: stripParensVersionRange :: VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: thisPackageVersion :: PackageIdentifier -> Dependency
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: thisVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: toVersionIntervals :: VersionRange -> VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: type Args = [String]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: type InstalledPackageId = UnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: type PackageDBStack = [PackageDB]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: type PackageId = PackageIdentifier
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: type VersionInterval = (LowerBound, UpperBound)
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unAbiHash :: AbiHash -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unComponentId :: ComponentId -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unPackageName :: PackageName -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unPkgconfigName :: PkgconfigName -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unUnitId :: UnitId -> String
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unifiedIPIDRequired :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unionVersionIntervals :: VersionIntervals -> VersionIntervals -> VersionIntervals
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unionVersionRanges :: VersionRange -> VersionRange -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unitIdSupported :: Compiler -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unknownCompilerInfo :: CompilerId -> AbiTag -> CompilerInfo
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unsafeMkDefUnitId :: UnitId -> DefUnitId
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unsupportedExtensions :: Compiler -> [Extension] -> [Extension]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: unsupportedLanguages :: Compiler -> [Language] -> [Language]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: version0 :: Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: versionIntervals :: VersionIntervals -> [VersionInterval]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: versionNumbers :: Version -> [Int]
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: wildcardUpperBound :: Version -> Version
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: withinIntervals :: Version -> VersionIntervals -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: withinRange :: Version -> VersionRange -> Bool
- Data.Array.Accelerate.LLVM.Native.Distribution.Simple: withinVersion :: Version -> VersionRange
- Data.Array.Accelerate.LLVM.Native.Foreign: [fillP] :: Native -> {-# UNPACK #-} !Executable
- Data.Array.Accelerate.LLVM.Native.Foreign: [fillS] :: Native -> {-# UNPACK #-} !Executable
- Data.Array.Accelerate.LLVM.Native.Foreign: [gangSize] :: Native -> {-# UNPACK #-} !Int
- Data.Array.Accelerate.LLVM.Native.Foreign: [segmentOffset] :: Native -> !Bool
- Data.Array.Accelerate.LLVM.Native.Foreign: instance Data.Array.Accelerate.Array.Sugar.Foreign Data.Array.Accelerate.LLVM.Native.Foreign.ForeignAcc
- Data.Array.Accelerate.LLVM.Native.Foreign: instance Data.Array.Accelerate.Array.Sugar.Foreign Data.Array.Accelerate.LLVM.Native.Foreign.ForeignExp
+ Data.Array.Accelerate.LLVM.Native: instance (Data.Array.Accelerate.Sugar.Array.Arrays a, Data.Array.Accelerate.LLVM.Native.RunAsync b) => Data.Array.Accelerate.LLVM.Native.RunAsync (a -> b)
+ Data.Array.Accelerate.LLVM.Native: instance Data.Array.Accelerate.Sugar.Array.Arrays b => Data.Array.Accelerate.LLVM.Native.RunAsync (GHC.Types.IO (Data.Array.Accelerate.Async.Async b))
+ Data.Array.Accelerate.LLVM.Native.Foreign: -- stack with the LLVM monad at the base.
+ Data.Array.Accelerate.LLVM.Native.Foreign: -- | Parallel computations can communicate via futures.
+ Data.Array.Accelerate.LLVM.Native.Foreign: Blocked :: !Seq (a -> IO ()) -> IVar a
+ Data.Array.Accelerate.LLVM.Native.Foreign: Empty :: IVar a
+ Data.Array.Accelerate.LLVM.Native.Foreign: Full :: !a -> IVar a
+ Data.Array.Accelerate.LLVM.Native.Foreign: Future :: {-# UNPACK #-} !IORef (IVar a) -> Future a
+ Data.Array.Accelerate.LLVM.Native.Foreign: [workers] :: Native -> !Workers
+ Data.Array.Accelerate.LLVM.Native.Foreign: block :: (Async arch, HasCallStack) => FutureR arch a -> Par arch a
+ Data.Array.Accelerate.LLVM.Native.Foreign: class Monad Par arch => Async arch where {
+ Data.Array.Accelerate.LLVM.Native.Foreign: data Future a
+ Data.Array.Accelerate.LLVM.Native.Foreign: data IVar a
+ Data.Array.Accelerate.LLVM.Native.Foreign: data family Par arch :: Type -> Type;
+ Data.Array.Accelerate.LLVM.Native.Foreign: evalPar :: Par Native a -> LLVM Native a
+ Data.Array.Accelerate.LLVM.Native.Foreign: fork :: Async arch => Par arch () -> Par arch ()
+ Data.Array.Accelerate.LLVM.Native.Foreign: get :: (Async arch, HasCallStack) => FutureR arch a -> Par arch a
+ Data.Array.Accelerate.LLVM.Native.Foreign: getArrays :: Async arch => ArraysR a -> FutureArraysR arch a -> Par arch a
+ Data.Array.Accelerate.LLVM.Native.Foreign: instance Data.Array.Accelerate.Sugar.Foreign.Foreign Data.Array.Accelerate.LLVM.Native.Foreign.ForeignAcc
+ Data.Array.Accelerate.LLVM.Native.Foreign: instance Data.Array.Accelerate.Sugar.Foreign.Foreign Data.Array.Accelerate.LLVM.Native.Foreign.ForeignExp
+ Data.Array.Accelerate.LLVM.Native.Foreign: liftPar :: (Async arch, HasCallStack) => LLVM arch a -> Par arch a
+ Data.Array.Accelerate.LLVM.Native.Foreign: new :: (Async arch, HasCallStack) => Par arch (FutureR arch a)
+ Data.Array.Accelerate.LLVM.Native.Foreign: newFull :: (Async arch, HasCallStack) => a -> Par arch (FutureR arch a)
+ Data.Array.Accelerate.LLVM.Native.Foreign: put :: (Async arch, HasCallStack) => FutureR arch a -> a -> Par arch ()
+ Data.Array.Accelerate.LLVM.Native.Foreign: putIO :: HasCallStack => Workers -> Future a -> a -> IO ()
+ Data.Array.Accelerate.LLVM.Native.Foreign: spawn :: (Async arch, HasCallStack) => Par arch a -> Par arch a
+ Data.Array.Accelerate.LLVM.Native.Foreign: type family FutureR arch :: Type -> Type;
+ Data.Array.Accelerate.LLVM.Native.Foreign: }
- Data.Array.Accelerate.LLVM.Native: cancel :: () => Async a -> IO ()
+ Data.Array.Accelerate.LLVM.Native: cancel :: Async a -> IO ()
- Data.Array.Accelerate.LLVM.Native: class (Typeable a, Typeable ArrRepr a) => Arrays a
+ Data.Array.Accelerate.LLVM.Native: class Arrays a
- Data.Array.Accelerate.LLVM.Native: createTarget :: [Int] -> Strategy -> IO Native
+ Data.Array.Accelerate.LLVM.Native: createTarget :: [Int] -> IO Native
- Data.Array.Accelerate.LLVM.Native: poll :: () => Async a -> IO (Maybe a)
+ Data.Array.Accelerate.LLVM.Native: poll :: Async a -> IO (Maybe a)
- Data.Array.Accelerate.LLVM.Native: runNAsync :: (Afunction f, RunAsync r, AfunctionR f ~ RunAsyncR r) => f -> r
+ Data.Array.Accelerate.LLVM.Native: runNAsync :: (Afunction f, RunAsync r, ArraysFunctionR f ~ RunAsyncR r) => f -> r
- Data.Array.Accelerate.LLVM.Native: runNAsyncWith :: (Afunction f, RunAsync r, AfunctionR f ~ RunAsyncR r) => Native -> f -> r
+ Data.Array.Accelerate.LLVM.Native: runNAsyncWith :: (Afunction f, RunAsync r, ArraysFunctionR f ~ RunAsyncR r) => Native -> f -> r
- Data.Array.Accelerate.LLVM.Native: runNWith :: Afunction f => Native -> f -> AfunctionR f
+ Data.Array.Accelerate.LLVM.Native: runNWith :: forall f. Afunction f => Native -> f -> AfunctionR f
- Data.Array.Accelerate.LLVM.Native: type family AfunctionR f :: Type
+ Data.Array.Accelerate.LLVM.Native: type family AfunctionR f
- Data.Array.Accelerate.LLVM.Native: wait :: () => Async a -> IO a
+ Data.Array.Accelerate.LLVM.Native: wait :: Async a -> IO a
- Data.Array.Accelerate.LLVM.Native.Foreign: Native :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !LinkCache -> {-# UNPACK #-} !Executable -> {-# UNPACK #-} !Executable -> !Bool -> Native
+ Data.Array.Accelerate.LLVM.Native.Foreign: Native :: !LinkCache -> !Workers -> Native
- Data.Array.Accelerate.LLVM.Native.Foreign: [ForeignAcc] :: String -> (a -> LLVM Native b) -> ForeignAcc (a -> b)
+ Data.Array.Accelerate.LLVM.Native.Foreign: [ForeignAcc] :: String -> (a -> Par Native (Future b)) -> ForeignAcc (a -> b)
- Data.Array.Accelerate.LLVM.Native.Foreign: [linkCache] :: Native -> {-# UNPACK #-} !LinkCache
+ Data.Array.Accelerate.LLVM.Native.Foreign: [linkCache] :: Native -> !LinkCache
- Data.Array.Accelerate.LLVM.Native.Foreign: cloneArray :: (Shape sh, Elt e) => Array sh e -> LLVM Native (Array sh e)
+ Data.Array.Accelerate.LLVM.Native.Foreign: cloneArray :: ArrayR (Array sh e) -> Array sh e -> LLVM Native (Array sh e)

Files

CHANGELOG.md view
@@ -6,69 +6,78 @@ project adheres to the [Haskell Package Versioning Policy (PVP)](https://pvp.haskell.org) -## [1.2.0.1] - 2019-04-29-### Added- * support for GHC-8.6- * support for LLVM-7- * support for LLVM-8+## [1.3.0.0] - 2018-08-27+### Changed+  * Switch the thread scheduler to static, rather than dynamic, work stealing+  * Thread scheduler is no longer block-synchronous+  * Code generation improvements, in particular for >=2-dimensional operations +### Fixed+  * Stability improvements+  * Race condition in thread scheduler ([accelerate-llvm#49])+  ### Contributors  Special thanks to those who contributed patches as part of this release: - * Trevor L. McDonell (@tmcdonell)- * Viktor Kronvall (@considerate)+  * Trevor L. McDonell (@tmcdonell)+  * Josh Meredith (@JoshMeredith)+  * Ivo Gabe de Wolff (@ivogabe)+  * Lars van den Haak (@sakehl)+  * Joshua Meredith (@JoshMeredith)+   ## [1.2.0.0] - 2018-04-03 ### Fixed- * LLVM native throws "SIGSEGV: invalid address" due to fused FP operation ([#409])+  * LLVM native throws "SIGSEGV: invalid address" due to fused FP operation ([#409])  ### Added- * support for half-precision floats- * support for struct-of-array-of-struct representations- * support for LLVM-6.0- * support for GHC-8.4+  * support for half-precision floats+  * support for struct-of-array-of-struct representations+  * support for LLVM-6.0+  * support for GHC-8.4  ### Contributors  Special thanks to those who contributed patches as part of this release: - * Trevor L. McDonell (@tmcdonell)- * @samft- * Ryan Scott (@ryanglscott)- * Jesse Sigal (@jasigal)- * Moritz Kiefer (@cocreature)+  * Trevor L. McDonell (@tmcdonell)+  * @samft+  * Ryan Scott (@ryanglscott)+  * Jesse Sigal (@jasigal)+  * Moritz Kiefer (@cocreature)   ## [1.1.0.1] - 2017-10-04 ### Fixed- * fix for `runQ*` generating multiple declarations with the same name+  * fix for `runQ*` generating multiple declarations with the same name   ## [1.1.0.0] - 2017-09-21 ### Added- * support for GHC-8.2- * caching of compilation results ([accelerate-llvm#17])- * new runtime linker; this fixes the annoying "forkOS_entry: interrupted" error. Note that currently this only supports x86_64 macOS and linux- * support for ahead-of-time compilation (`runQ` and `runQAsync`)+  * support for GHC-8.2+  * caching of compilation results ([accelerate-llvm#17])+  * new runtime linker; this fixes the annoying "forkOS_entry: interrupted" error. Note that currently this only supports x86_64 macOS and linux+  * support for ahead-of-time compilation (`runQ` and `runQAsync`)  ### Changed- * generalise `run1*` to polyvariadic `runN*`- * programs run using all cores by default; the environment variable-   `ACCELERATE_LLVM_NATIVE_THREADS` is used to set the number of worker threads-   rather than `+RTS -N`+  * generalise `run1*` to polyvariadic `runN*`+  * programs run using all cores by default; the environment variable+    `ACCELERATE_LLVM_NATIVE_THREADS` is used to set the number of worker threads+    rather than `+RTS -N`   ## [1.0.0.0] - 2017-03-31- * initial release+  * initial release  -[1.2.0.1]:              https://github.com/AccelerateHS/accelerate-llvm/compare/v1.2.0.0...v1.2.0.1-[1.2.0.0]:              https://github.com/AccelerateHS/accelerate-llvm/compare/1.1.0.1-native...v1.2.0.0+[1.3.0.0]:              https://github.com/AccelerateHS/accelerate-llvm/compare/1.2.0.0...v1.3.0.0+[1.2.0.0]:              https://github.com/AccelerateHS/accelerate-llvm/compare/1.1.0.1-native...1.2.0.0 [1.1.0.1]:              https://github.com/AccelerateHS/accelerate-llvm/compare/1.1.0.0...1.1.0.1-native [1.1.0.0]:              https://github.com/AccelerateHS/accelerate-llvm/compare/1.0.0.0...1.1.0.0 [1.0.0.0]:              https://github.com/AccelerateHS/accelerate-llvm/compare/be7f91295f77434b2103c70aa1cabb6a4f2b09a8...1.0.0.0  [#409]:                 https://github.com/AccelerateHS/accelerate/issues/409 [accelerate-llvm#17]:   https://github.com/AccelerateHS/accelerate-llvm/issues/17+[accelerate-llvm#49]:   https://github.com/AccelerateHS/accelerate-llvm/pull/49 
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) [2014..2017] The Accelerate Team.  All rights reserved.+Copyright (c) [2014..2020] The Accelerate Team.  All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
README.md view
@@ -1,14 +1,20 @@-An LLVM backend for the Accelerate Array Language-=================================================+<div align="center">+<img width="450" src="https://github.com/AccelerateHS/accelerate/raw/master/images/accelerate-logo-text-v.png?raw=true" alt="henlo, my name is Theia"/> -[![Travis](https://img.shields.io/travis/AccelerateHS/accelerate-llvm/master.svg?label=linux)](https://travis-ci.org/AccelerateHS/accelerate-llvm)-[![AppVeyor](https://img.shields.io/appveyor/ci/tmcdonell/accelerate-llvm/master.svg?label=windows)](https://ci.appveyor.com/project/tmcdonell/accelerate-llvm)+# LLVM backends for the Accelerate array language++[![GitHub CI](https://github.com/tmcdonell/accelerate-llvm/workflows/CI/badge.svg)](https://github.com/tmcdonell/accelerate-llvm/actions)+[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/AccelerateHS/Lobby)+<br> [![Stackage LTS](https://stackage.org/package/accelerate-llvm/badge/lts)](https://stackage.org/lts/package/accelerate-llvm) [![Stackage Nightly](https://stackage.org/package/accelerate-llvm/badge/nightly)](https://stackage.org/nightly/package/accelerate-llvm) [![Hackage](https://img.shields.io/hackage/v/accelerate-llvm.svg)](https://hackage.haskell.org/package/accelerate-llvm)+<br> [![Docker Automated build](https://img.shields.io/docker/automated/tmcdonell/accelerate-llvm.svg)](https://hub.docker.com/r/tmcdonell/accelerate-llvm/) [![Docker status](https://images.microbadger.com/badges/image/tmcdonell/accelerate-llvm.svg)](https://microbadger.com/images/tmcdonell/accelerate-llvm) +</div>+ This package compiles Accelerate code to LLVM IR, and executes that code on multicore CPUs as well as NVIDIA GPUs. This avoids the need to go through `nvcc` or `clang`. For details on Accelerate, refer to the [main repository][GitHub].@@ -67,7 +73,7 @@ Example using [Homebrew](http://brew.sh) on macOS:  ```sh-$ brew install llvm-hs/llvm/llvm-8+$ brew install llvm-hs/llvm/llvm-9 ```  ## Debian/Ubuntu@@ -78,17 +84,17 @@ then:  ```sh-$ apt-get install llvm-8-dev+$ apt-get install llvm-9-dev ```  ## Building from source  If your OS does not have an appropriate LLVM distribution available, you can also build from source. Detailed build instructions are available on the [LLVM.org website](http://releases.llvm.org/6.0.0/docs/CMake.html). Note that you will require at least [CMake 3.4.3](http://www.cmake.org/cmake/resources/software.html) and a recent C++ compiler; at least Clang 3.1, GCC 4.8, or Visual Studio 2015 (update 3). -  1. Download and unpack the [LLVM-8.0 source code](http://releases.llvm.org/8.0.0/llvm-8.0.0.src.tar.xz). We'll refer to+  1. Download and unpack the [LLVM-9 source code](https://github.com/llvm/llvm-project/releases/download/llvmorg-9.0.1/llvm-9.0.1.src.tar.xz). We'll refer to      the path that the source tree was unpacked to as `LLVM_SRC`. Only the main      LLVM source tree is required, but you can optionally add other components-     such as the Clang compiler or Polly loop optimiser. See the [LLVM releases](http://releases.llvm.org/download.html#8.0.0)+     such as the Clang compiler or Polly loop optimiser. See the [LLVM releases](http://releases.llvm.org/download.html#9.0.1)      page for the complete list.    2. Create a temporary build directory and `cd` into it, for example:@@ -116,7 +122,7 @@      to [System Integrity Protection](https://en.wikipedia.org/wiki/System_Integrity_Protection):      ```sh      cd $INSTALL_PREFIX/lib-     ln -s libLLVM.dylib libLLVM-8.0.dylib+     ln -s libLLVM.dylib libLLVM-9.dylib      install_name_tool -id $PWD/libLTO.dylib libLTO.dylib      install_name_tool -id $PWD/libLLVM.dylib libLLVM.dylib      install_name_tool -change '@rpath/libLLVM.dylib' $PWD/libLLVM.dylib libLTO.dylib@@ -131,13 +137,13 @@ For example, installation using [`stack`](http://docs.haskellstack.org/en/stable/README.html) just requires you to point it to the appropriate configuration file: ```sh-$ ln -s stack-8.6.yaml stack.yaml+$ ln -s stack-8.8.yaml stack.yaml $ stack setup $ stack install ```  Note that the version of [`llvm-hs`](https://hackage.haskell.org/package/llvm-hs)-used must match the installed version of LLVM, which is currently 8.0.+used must match the installed version of LLVM, which is currently 9.0.   ## libNVVM@@ -153,20 +159,23 @@ is also based on LLVM, and typically lags LLVM by several releases, you must install `accelerate-llvm` with a "compatible" version of LLVM, which will depend on the version of the CUDA toolkit you have installed. The following table shows-some combinations:+combinations which have been tested: -|               | LLVM-3.3 | LLVM-3.4 | LLVM-3.5 | LLVM-3.8 | LLVM-3.9 | LLVM-4.0 | LLVM-5.0 | LLVM-6.0 | LLVM-7.0 | LLVM-8.0 |-|:-------------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|-| **CUDA-7.0**  |     ⭕    |     ❌    |          |          |          |          |          |          |          |          |-| **CUDA-7.5**  |          |     ⭕    |     ⭕    |     ❌    |          |          |          |          |          |          |-| **CUDA-8.0**  |          |          |     ⭕    |     ⭕    |     ❌    |     ❌    |          |          |          |          |-| **CUDA-9.0**  |          |          |          |          |          |     ❌    |     ❌    |          |          |          |-| **CUDA-9.1**  |          |          |          |          |          |          |          |          |          |          |-| **CUDA-9.2**  |          |          |          |          |          |          |          |          |          |          |-| **CUDA-10.0** |          |          |          |          |          |          |          |          |          |          |-| **CUDA-10.1** |          |          |          |          |          |          |          |          |          |          |+|               | LLVM-3.3 | LLVM-3.4 | LLVM-3.5 | LLVM-3.8 | LLVM-3.9 | LLVM-4.0 | LLVM-5.0 | LLVM-6.0 | LLVM-7 | LLVM-8 | LLVM-9 |+| ------------- | :------: | :------: | :------: | :------: | :------: | :------: | :------: | :------: | :----: | :----: | :----: |+| **CUDA-7.0**  | ⭕       | ❌       |          |          |          |          |          |          |        |        |        |+| **CUDA-7.5**  |          | ⭕       | ⭕       | ❌       |          |          |          |          |        |        |        |+| **CUDA-8.0**  |          |          | ⭕       | ⭕       | ❌       | ❌       |          |          |        |        |        |+| **CUDA-9.0**  |          |          |          |          |          | ❌       | ❌       |          |        |        |        |+| **CUDA-9.1**  |          |          |          |          |          |          |          |          |        |        |        |+| **CUDA-9.2**  |          |          |          |          |          |          |          |          |        |        |        |+| **CUDA-10.0** |          |          |          |          |          |          |          |          |        |        |        |+| **CUDA-10.1** |          |          |          |          |          |          |          |          |        |        |        |  Where ⭕ = Works, and ❌ = Does not work.++The above table is incomplete! If you try a particular combination and find that+it does or does not work, please let us know!  Note that the above restrictions on CUDA and LLVM version exist _only_ if you want to use the NVVM component. Otherwise, you should be free to use any
accelerate-llvm-native.cabal view
@@ -1,7 +1,7 @@ name:                   accelerate-llvm-native-version:                1.2.0.1+version:                1.3.0.0 cabal-version:          >= 1.10-tested-with:            GHC >= 8.0+tested-with:            GHC >= 8.6 build-type:             Simple  synopsis:               Accelerate backend for multicore CPUs@@ -26,7 +26,7 @@     .     Example using Homebrew on macOS:     .-    > brew install llvm-hs/llvm/llvm-8+    > brew install llvm-hs/llvm/llvm-9     .     /Debian & Ubuntu/     .@@ -35,40 +35,24 @@     instructions for adding the correct package database for your OS version,     and then:     .-    > apt-get install llvm-8-dev+    > apt-get install llvm-9-dev     .     /Building from source/     .     If your OS does not have an appropriate LLVM distribution available, you can     also build from source. Detailed build instructions are available on-    <http://releases.llvm.org/8.0.0/docs/CMake.html LLVM.org>. Make sure to+    <http://releases.llvm.org/9.0.0/docs/CMake.html LLVM.org>. Make sure to     include the cmake build options     @-DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON@ so that the @libLLVM@     shared library will be built.     .-    [/Installing accelerate-llvm/]-    .-    To use @accelerate-llvm@ it is important that the @llvm-hs@ package is-    installed against the @libLLVM@ shared library, rather than statically-    linked, so that we can use LLVM from GHCi and Template Haskell. This is the-    default configuration, but you can also enforce this explicitly by adding-    the following to your @stack.yaml@ file:-    .-    > flags:-    >   llvm-hs:-    >     shared-llvm: true-    .-    Or by specifying the @shared-llvm@ flag to cabal:-    .-    > cabal install llvm-hs -fshared-llvm-    .  license:                BSD3 license-file:           LICENSE author:                 Trevor L. McDonell-maintainer:             Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+maintainer:             Trevor L. McDonell <trevor.mcdonell@gmail.com> bug-reports:            https://github.com/AccelerateHS/accelerate/issues-category:               Compilers/Interpreters, Concurrency, Data, Parallelism+category:               Accelerate, Compilers/Interpreters, Concurrency, Data, Parallelism  extra-source-files:     CHANGELOG.md@@ -83,7 +67,6 @@     Data.Array.Accelerate.LLVM.Native     Data.Array.Accelerate.LLVM.Native.Plugin     Data.Array.Accelerate.LLVM.Native.Foreign-    Data.Array.Accelerate.LLVM.Native.Distribution.Simple    other-modules:     Data.Array.Accelerate.LLVM.Native.Array.Data@@ -100,6 +83,8 @@     Data.Array.Accelerate.LLVM.Native.CodeGen.Map     Data.Array.Accelerate.LLVM.Native.CodeGen.Permute     Data.Array.Accelerate.LLVM.Native.CodeGen.Scan+    Data.Array.Accelerate.LLVM.Native.CodeGen.Stencil+    Data.Array.Accelerate.LLVM.Native.CodeGen.Transform      Data.Array.Accelerate.LLVM.Native.Compile     Data.Array.Accelerate.LLVM.Native.Compile.Cache@@ -113,40 +98,37 @@      Data.Array.Accelerate.LLVM.Native.Execute     Data.Array.Accelerate.LLVM.Native.Execute.Async+    Data.Array.Accelerate.LLVM.Native.Execute.Divide     Data.Array.Accelerate.LLVM.Native.Execute.Environment-    Data.Array.Accelerate.LLVM.Native.Execute.LBS     Data.Array.Accelerate.LLVM.Native.Execute.Marshal+    Data.Array.Accelerate.LLVM.Native.Execute.Scheduler      Data.Array.Accelerate.LLVM.Native.Plugin.Annotation     Data.Array.Accelerate.LLVM.Native.Plugin.BuildInfo -    Data.Array.Accelerate.LLVM.Native.Distribution.Simple.Build-    Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC-    Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC.Internal-     Paths_accelerate_llvm_native    build-depends:-          base                          >= 4.7 && < 4.13-        , accelerate                    == 1.2.*-        , accelerate-llvm               == 1.2.*+          base                          >= 4.10 && < 5+        , accelerate                    == 1.3.*+        , accelerate-llvm               == 1.3.*         , bytestring                    >= 0.10.4-        , Cabal                         >= 2.0         , cereal                        >= 0.4         , containers                    >= 0.5 && < 0.7+        , deepseq                       >= 1.4         , directory                     >= 1.0         , dlist                         >= 0.6         , filepath                      >= 1.0         , ghc         , hashable                      >= 1.0         , libffi                        >= 0.1-        , llvm-hs                       >= 4.1 && < 8.1-        , llvm-hs-pure                  >= 4.1 && < 8.1+        , llvm-hs                       >= 4.1 && < 9.1+        , llvm-hs-pure                  >= 4.1 && < 9.1         , lockfree-queue                >= 0.2         , mtl                           >= 2.2.1         , template-haskell-        , time                          >= 1.4         , unique+        , vector                        >= 0.11    hs-source-dirs:         src@@ -172,11 +154,8 @@       Data.Array.Accelerate.LLVM.Native.Link.MachO      build-depends:-          bytestring                    >= 0.10-        , cereal                        >= 0.4-        , ghc-prim+          ghc-prim         , unix                          >= 2.7-        , vector                        >= 0.11      build-tools:           c2hs                          >= 0.25@@ -186,11 +165,8 @@       Data.Array.Accelerate.LLVM.Native.Link.ELF      build-depends:-          bytestring                    >= 0.10-        , cereal                        >= 0.4-        , ghc-prim+          ghc-prim         , unix                          >= 2.7-        , vector                        >= 0.11      build-tools:           c2hs                          >= 0.25@@ -199,8 +175,7 @@     other-modules:       Data.Array.Accelerate.LLVM.Native.Link.COFF -    build-depends:-          bytestring                    >= 0.10+    -- build-depends:   test-suite nofib-llvm-native@@ -209,7 +184,7 @@   main-is:              Main.hs    build-depends:-          base                          >= 4.7+          base                          >= 4.10         , accelerate         , accelerate-llvm-native @@ -223,6 +198,7 @@         -rtsopts         -with-rtsopts=-A128M         -with-rtsopts=-n4M+        -with-rtsopts=-N   source-repository head@@ -231,7 +207,7 @@  source-repository this   type:                 git-  tag:                  v1.2.0.1+  tag:                  v1.3.0.0   location:             https://github.com/AccelerateHS/accelerate-llvm.git  -- vim: nospell
src/Data/Array/Accelerate/LLVM/Native.hs view
@@ -1,16 +1,19 @@ {-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE CPP                  #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE ScopedTypeVariables  #-} {-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeApplications     #-} {-# LANGUAGE TypeFamilies         #-} {-# LANGUAGE TypeSynonymInstances #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -49,34 +52,32 @@   runQAsync, runQAsyncWith,    -- * Execution targets-  Native, Strategy,-  createTarget, balancedParIO, unbalancedParIO,+  Native,+  createTarget,  ) where --- accelerate-import Data.Array.Accelerate.Array.Sugar                            ( Arrays )-import Data.Array.Accelerate.AST                                    ( PreOpenAfun(..) )-import Data.Array.Accelerate.Async+import Data.Array.Accelerate.AST                                    ( PreOpenAfun(..), arraysR, liftALeftHandSide )+import Data.Array.Accelerate.AST.LeftHandSide+import Data.Array.Accelerate.Async                                  ( Async, async, wait, poll, cancel )+import Data.Array.Accelerate.Representation.Array                   ( liftArraysR ) import Data.Array.Accelerate.Smart                                  ( Acc )+import Data.Array.Accelerate.Sugar.Array                            ( Arrays, toArr, fromArr, ArraysR ) import Data.Array.Accelerate.Trafo+import Data.Array.Accelerate.Trafo.Sharing                          ( Afunction(..), AfunctionRepr(..), afunctionRepr )+import qualified Data.Array.Accelerate.Sugar.Array                  as Sugar -import Data.Array.Accelerate.LLVM.Execute.Async                     ( AsyncR(..) )-import Data.Array.Accelerate.LLVM.Execute.Environment               ( AvalR(..) ) import Data.Array.Accelerate.LLVM.Native.Array.Data                 ( useRemoteAsync ) import Data.Array.Accelerate.LLVM.Native.Compile                    ( CompiledOpenAfun, compileAcc, compileAfun ) import Data.Array.Accelerate.LLVM.Native.Embed                      ( embedOpenAcc ) import Data.Array.Accelerate.LLVM.Native.Execute                    ( executeAcc, executeOpenAcc )-import Data.Array.Accelerate.LLVM.Native.Execute.Environment        ( Aval )+import Data.Array.Accelerate.LLVM.Native.Execute.Async              ( Par, evalPar, getArrays )+import Data.Array.Accelerate.LLVM.Native.Execute.Environment        ( Val, ValR(..), push ) import Data.Array.Accelerate.LLVM.Native.Link                       ( ExecOpenAfun, linkAcc, linkAfun ) import Data.Array.Accelerate.LLVM.Native.State import Data.Array.Accelerate.LLVM.Native.Target-import Data.Array.Accelerate.LLVM.State                             ( LLVM ) import Data.Array.Accelerate.LLVM.Native.Debug                      as Debug-import qualified Data.Array.Accelerate.LLVM.Native.Execute.Async    as E --- standard library-import Data.Typeable import Control.Monad.Trans import System.IO.Unsafe import Text.Printf@@ -97,8 +98,7 @@ -- | As 'run', but execute using the specified target (thread gang). -- runWith :: Arrays a => Native -> Acc a -> a-runWith target a = unsafePerformIO (run' target a)-+runWith target a = unsafePerformIO (runWithIO target a)  -- | As 'run', but allow the computation to run asynchronously and return -- immediately without waiting for the result. The status of the computation can@@ -110,19 +110,19 @@ -- | As 'runAsync', but execute using the specified target (thread gang). -- runAsyncWith :: Arrays a => Native -> Acc a -> IO (Async a)-runAsyncWith target a = async (run' target a)+runAsyncWith target a = async (runWithIO target a) -run' :: Arrays a => Native -> Acc a -> IO a-run' target a = execute+runWithIO :: Arrays a => Native -> Acc a -> IO a+runWithIO target a = execute   where-    !acc        = convertAccWith (config target) a-    execute     = do+    !acc    = convertAcc a+    execute = do       dumpGraph acc       evalNative target $ do         build <- phase "compile" elapsedS (compileAcc acc) >>= dumpStats         exec  <- phase "link"    elapsedS (linkAcc build)-        res   <- phase "execute" elapsedP (executeAcc exec)-        return res+        res   <- phase "execute" elapsedP (evalPar (executeAcc exec >>= getArrays (arraysR exec)))+        return $ toArr res   -- | This is 'runN', specialised to an array program of one argument.@@ -182,27 +182,32 @@  -- | As 'runN', but execute using the specified target (thread gang). ---runNWith :: Afunction f => Native -> f -> AfunctionR f-runNWith target f = exec+runNWith :: forall f. Afunction f => Native -> f -> AfunctionR f+runNWith target f = go (afunctionRepr @f) afun (return Empty)   where-    !acc  = convertAfunWith (config target) f+    !acc  = convertAfun f     !afun = unsafePerformIO $ do               dumpGraph acc               evalNative target $ do                 build <- phase "compile" elapsedS (compileAfun acc) >>= dumpStats                 link  <- phase "link"    elapsedS (linkAfun build)                 return link-    !exec = go afun (return Aempty) -    go :: ExecOpenAfun Native aenv t -> LLVM Native (Aval aenv) -> t-    go (Alam l) k = \arrs ->-      let k' = do aenv       <- k-                  AsyncR _ a <- E.async (useRemoteAsync arrs)-                  return (aenv `Apush` a)-      in go l k'-    go (Abody b) k = unsafePerformIO . phase "execute" elapsedP . evalNative target $ do-      aenv   <- k-      E.get =<< E.async (executeOpenAcc b aenv)+    go :: AfunctionRepr t (AfunctionR t) (ArraysFunctionR t)+       -> ExecOpenAfun Native aenv (ArraysFunctionR t)+       -> Par Native (Val aenv)+       -> AfunctionR t+    go (AfunctionReprLam repr) (Alam lhs l) k = \(arrs :: a) ->+      let k' = do aenv  <- k+                  a     <- useRemoteAsync (Sugar.arraysR @a) $ fromArr arrs+                  return (aenv `push` (lhs, a))+      in go repr l k'+    go AfunctionReprBody (Abody b) k = unsafePerformIO . phase "execute" elapsedP . evalNative target . evalPar $ do+      aenv <- k+      res  <- executeOpenAcc b aenv+      arrs <- getArrays (arraysR b) res+      return $ toArr arrs+    go _ _ _ = error "The moon is hanging upside down"   -- | As 'run1', but execute asynchronously.@@ -218,41 +223,44 @@  -- | As 'runN', but execute asynchronously. ---runNAsync :: (Afunction f, RunAsync r, AfunctionR f ~ RunAsyncR r) => f -> r+runNAsync :: (Afunction f, RunAsync r, ArraysFunctionR f ~ RunAsyncR r) => f -> r runNAsync = runNAsyncWith defaultTarget  -- | As 'runNWith', but execute asynchronously. ---runNAsyncWith :: (Afunction f, RunAsync r, AfunctionR f ~ RunAsyncR r) => Native -> f -> r-runNAsyncWith target f = runAsync' target afun (return Aempty)+runNAsyncWith :: (Afunction f, RunAsync r, ArraysFunctionR f ~ RunAsyncR r) => Native -> f -> r+runNAsyncWith target f = exec   where-    !acc  = convertAfunWith (config target) f+    !acc  = convertAfun f     !afun = unsafePerformIO $ do               dumpGraph acc               evalNative target $ do                 build <- phase "compile" elapsedS (compileAfun acc) >>= dumpStats                 link  <- phase "link"    elapsedS (linkAfun build)                 return link+    !exec = runAsync' target afun (return Empty)  class RunAsync f where   type RunAsyncR f-  runAsync' :: Native -> ExecOpenAfun Native aenv (RunAsyncR f) -> LLVM Native (Aval aenv) -> f+  runAsync' :: Native -> ExecOpenAfun Native aenv (RunAsyncR f) -> Par Native (Val aenv) -> f -instance RunAsync b => RunAsync (a -> b) where-  type RunAsyncR (a -> b) = a -> RunAsyncR b+instance (Arrays a, RunAsync b) => RunAsync (a -> b) where+  type RunAsyncR (a -> b) = ArraysR a -> RunAsyncR b   runAsync' _      Abody{}  _ _    = error "runAsync: function oversaturated"-  runAsync' target (Alam l) k arrs =-    let k' = do aenv       <- k-                AsyncR _ a <- E.async (useRemoteAsync arrs)-                return (aenv `Apush` a)+  runAsync' target (Alam lhs l) k arrs =+    let k' = do aenv  <- k+                a     <- useRemoteAsync (Sugar.arraysR @a) $ fromArr arrs+                return (aenv `push` (lhs, a))     in runAsync' target l k' -instance RunAsync (IO (Async b)) where-  type RunAsyncR  (IO (Async b)) = b+instance Arrays b => RunAsync (IO (Async b)) where+  type RunAsyncR  (IO (Async b)) = ArraysR b   runAsync' _      Alam{}    _ = error "runAsync: function not fully applied"-  runAsync' target (Abody b) k = async . phase "execute" elapsedP . evalNative target $ do-    aenv   <- k-    E.get =<< E.async (executeOpenAcc b aenv)+  runAsync' target (Abody b) k = async . phase "execute" elapsedP . evalNative target . evalPar $ do+    aenv  <- k+    ans   <- executeOpenAcc b aenv+    arrs  <- getArrays (arraysR b) ans+    return $ toArr arrs   -- | Stream a lazily read list of input arrays through the given program,@@ -299,38 +307,17 @@ -- Note that at the splice point the usage of @f@ must monomorphic; i.e. the -- types @a@, @b@ and @c@ must be at some known concrete type. ----- In order to link the final program together, the included GHC plugin must be--- used when compiling and linking the program. Add the following option to the--- .cabal file of your project:------ > ghc-options: -fplugin=Data.Array.Accelerate.LLVM.Native.Plugin------ Similarly, the plugin must also run when loading modules in @ghci@.------ Additionally, when building a _library_ with Cabal which utilises 'runQ', you--- will need to use the following custom build @Setup.hs@ to ensure that the--- library is linked together properly:------ > import Data.Array.Accelerate.LLVM.Native.Distribution.Simple--- > main = defaultMain------ And in the .cabal file:------ > build-type: Custom--- > custom-setup--- >   setup-depends:--- >       base--- >     , Cabal--- >     , accelerate-llvm-native------ The custom @Setup.hs@ is only required when building a library with Cabal.--- Building executables with cabal requires only the GHC plugin.--- -- See the <https://github.com/tmcdonell/lulesh-accelerate lulesh-accelerate> -- project for an example. -- -- [/Note:/] --+-- It is recommended to use GHC-8.6 or later. Earlier GHC versions can+-- successfully build executables utilising 'runQ', but fail to correctly link+-- libraries containing this function.+--+-- [/Note:/]+-- -- Due to <https://ghc.haskell.org/trac/ghc/ticket/13587 GHC#13587>, this -- currently must be as an /untyped/ splice. --@@ -382,59 +369,58 @@   TH.lamE [TH.varP target] (runQ' [| async |] (TH.varE target) f)  -runQ' :: Afunction f => TH.ExpQ -> TH.ExpQ -> f -> TH.ExpQ+runQ' :: forall f. Afunction f => TH.ExpQ -> TH.ExpQ -> f -> TH.ExpQ runQ' using target f = do-  -- Reification of the program for segmented folds depends on whether we are-  -- executing in parallel or sequentially, where the parallel case requires-  -- some extra work to convert the segments descriptor into a segment offset-  -- array. Also do this conversion, so that the program can be run both in-  -- parallel as well as sequentially (albeit with some additional work that-  -- could have been avoided).-  ---  -- TLM: We could also just reify the program twice and select at runtime which-  --      version to execute.-  ---  afun  <- let acc = convertAfunWith (phases { convertOffsetOfSegment = True }) f-           in  TH.runIO $ do+#if MIN_VERSION_template_haskell(2,13,0)+  -- The plugin ensures that objects are loaded correctly into GHCi+  TH.addCorePlugin "Data.Array.Accelerate.LLVM.Native.Plugin"+#endif++  afun  <- let acc = convertAfun f+            in TH.runIO $ do                  dumpGraph acc-                 evalNative (defaultTarget { segmentOffset = True }) $-                   phase "compile" elapsedS (compileAfun acc) >>= dumpStats+                 evalNative defaultTarget $+                  phase "compile" elapsedS (compileAfun acc) >>= dumpStats -  -- generate a lambda function with the correct number of arguments and apply-  -- directly to the body expression.+  -- generate a lambda function with the correct number of arguments and+  -- apply directly to the body expression.+  --+  -- XXX: remove use of 'getArrays', 'toArr', and 'fromArr' in the embedded+  -- code; we should be able to generate all bindings directly and assemble+  -- the pieces directly.+  --   let-      go :: Typeable aenv => CompiledOpenAfun Native aenv t -> [TH.PatQ] -> [TH.ExpQ] -> [TH.StmtQ] -> TH.ExpQ-      go (Alam lam) xs as stmts = do+      go :: CompiledOpenAfun Native aenv t -> [TH.PatQ] -> [TH.ExpQ] -> [TH.StmtQ] -> TH.ExpQ+      go (Alam lhs l) xs as stmts = do         x <- TH.newName "x" -- lambda bound variable         a <- TH.newName "a" -- local array name-        s <- TH.bindS (TH.conP 'AsyncR [TH.wildP, TH.varP a]) [| E.async (useRemoteAsync $(TH.varE x)) |]-        go lam (TH.varP x : xs) (TH.varE a : as) (return s : stmts)+        s <- TH.bindS (TH.varP a) [| useRemoteAsync $(TH.unTypeQ $ liftArraysR (lhsToTupR lhs)) (fromArr $(TH.varE x)) |]+        go l (TH.varP x : xs) ([| ($(TH.unTypeQ $ liftALeftHandSide lhs), $(TH.varE a)) |] : as) (return s : stmts) -      go (Abody body) xs as stmts =-        let aenv = foldr (\a gamma -> [| $gamma `Apush` $a |] ) [| Aempty |] as-            eval = TH.noBindS [| E.get =<< E.async (executeOpenAcc $(TH.unTypeQ (embedOpenAcc (defaultTarget { segmentOffset = True }) body)) $aenv) |]-        in-        TH.lamE (reverse xs) [| $using . phase "execute" elapsedP . evalNative ($target { segmentOffset = True }) $-                                  $(TH.doE (reverse (eval : stmts))) |]+      go (Abody b) xs as stmts = do+        r <- TH.newName "r" -- result+        s <- TH.newName "s"+        let+            aenv  = foldr (\a gamma -> [| $gamma `push` $a |]) [| Empty |] as+            body  = embedOpenAcc defaultTarget b+        --+        TH.lamE (reverse xs)+                [| $using . phase "execute" elapsedP . evalNative $target . evalPar $+                      $(TH.doE ( reverse stmts +++                               [ TH.bindS (TH.varP r) [| executeOpenAcc $(TH.unTypeQ body) $aenv |]+                               , TH.bindS (TH.varP s) [| getArrays $(TH.unTypeQ (liftArraysR (arraysR b))) $(TH.varE r) |]+                               , TH.noBindS [| return $ toArr $(TH.varE s) |]+                               ]))+                 |]   --   go afun [] [] []  --- How the Accelerate program should be evaluated.------ TODO: make sharing/fusion runtime configurable via debug flags or otherwise.----config :: Native -> Phase-config target = phases-  { convertOffsetOfSegment = segmentOffset target-  }-- -- Debugging -- =========  dumpStats :: MonadIO m => a -> m a-dumpStats x = dumpSimplStats >> return x+dumpStats x = liftIO dumpSimplStats >> return x  phase :: MonadIO m => String -> (Double -> Double -> String) -> m a -> m a phase n fmt go = timed dump_phases (\wall cpu -> printf "phase %s: %s" n (fmt wall cpu)) go
src/Data/Array/Accelerate/LLVM/Native/Array/Data.hs view
@@ -1,13 +1,14 @@+{-# LANGUAGE BangPatterns        #-} {-# LANGUAGE GADTs               #-}+{-# LANGUAGE MagicHash           #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Array.Data--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,89 +16,58 @@ module Data.Array.Accelerate.LLVM.Native.Array.Data (    module Data.Array.Accelerate.LLVM.Array.Data,-   cloneArray,  ) where --- accelerate-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Array.Unique+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Elt+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type  import Data.Array.Accelerate.LLVM.State import Data.Array.Accelerate.LLVM.Array.Data+import Data.Array.Accelerate.LLVM.Native.Execute.Async              ()  -- Async Native import Data.Array.Accelerate.LLVM.Native.Target-import Data.Array.Accelerate.LLVM.Native.Execute.Async () --- standard library import Control.Monad.Trans-import Data.Word-import Foreign.C import Foreign.Ptr-import Foreign.Storable   -- | Data instance for arrays in the native backend. We assume a shared-memory -- machine, and just manipulate the underlying Haskell array directly. ---instance Remote Native+instance Remote Native where+  {-# INLINE allocateRemote #-}+  allocateRemote repr = liftIO . allocateArray repr   -- | Copy an array into a newly allocated array. This uses 'memcpy'. ---cloneArray :: (Shape sh, Elt e) => Array sh e -> LLVM Native (Array sh e)-cloneArray arr@(Array _ src) = liftIO $ do-  out@(Array _ dst)    <- allocateArray sh-  copyR arrayElt src dst+cloneArray :: ArrayR (Array sh e) -> Array sh e -> LLVM Native (Array sh e)+cloneArray repr (Array sh src) = liftIO $ do+  out@(Array _ dst) <- allocateArray repr sh+  copyR (arrayRtype repr) src dst   return out   where-    sh                  = shape arr-    n                   = size sh+    n = size (arrayRshape repr) sh -    copyR :: ArrayEltR e -> ArrayData e -> ArrayData e -> IO ()-    copyR ArrayEltRunit             _   _   = return ()-    copyR (ArrayEltRpair aeR1 aeR2) ad1 ad2 = copyR aeR1 (fstArrayData ad1) (fstArrayData ad2) >>-                                              copyR aeR2 (sndArrayData ad1) (sndArrayData ad2)-    ---    copyR (ArrayEltRvec2 aeR)  (AD_V2 ad1)  (AD_V2 ad2)   = copyR aeR ad1 ad2-    copyR (ArrayEltRvec3 aeR)  (AD_V3 ad1)  (AD_V3 ad3)   = copyR aeR ad1 ad3-    copyR (ArrayEltRvec4 aeR)  (AD_V4 ad1)  (AD_V4 ad4)   = copyR aeR ad1 ad4-    copyR (ArrayEltRvec8 aeR)  (AD_V8 ad1)  (AD_V8 ad8)   = copyR aeR ad1 ad8-    copyR (ArrayEltRvec16 aeR) (AD_V16 ad1) (AD_V16 ad16) = copyR aeR ad1 ad16-    ---    copyR ArrayEltRint              ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRint8             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRint16            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRint32            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRint64            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRword             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRword8            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRword16           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRword32           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRword64           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRhalf             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRfloat            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRdouble           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRbool             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRchar             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcshort           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcushort          ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcint             ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcuint            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRclong            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRculong           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcllong           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcullong          ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcfloat           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcdouble          ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcchar            ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcschar           ad1 ad2 = copyPrim ad1 ad2-    copyR ArrayEltRcuchar           ad1 ad2 = copyPrim ad1 ad2+    copyR :: TypeR e -> ArrayData e -> ArrayData e -> IO ()+    copyR TupRunit          !_          !_          = return ()+    copyR (TupRsingle t)    !ad1        !ad2        = copyPrim t ad1 ad2+    copyR (TupRpair !t !t') (ad1, ad1') (ad2, ad2') = do+      copyR t  ad1  ad2+      copyR t' ad1' ad2' -    copyPrim :: forall e a. (ArrayElt e, ArrayPtrs e ~ Ptr a, Storable a) => ArrayData e -> ArrayData e -> IO ()-    copyPrim a1 a2 = do-      let p1 = ptrsOfArrayData a1-          p2 = ptrsOfArrayData a2-      memcpy (castPtr p2) (castPtr p1) (n * sizeOf (undefined :: a))+    copyPrim :: ScalarType e -> ArrayData e -> ArrayData e -> IO ()+    copyPrim !tp !a1 !a2+      | ScalarArrayDict{} <- scalarArrayDict tp = do+      let p1 = unsafeUniqueArrayPtr a1+          p2 = unsafeUniqueArrayPtr a2+      memcpy (castPtr p2) (castPtr p1) (n * bytesElt (TupRsingle tp))   -- Standard C functions
src/Data/Array/Accelerate/LLVM/Native/CodeGen.hs view
@@ -1,11 +1,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -26,21 +25,20 @@ import Data.Array.Accelerate.LLVM.Native.CodeGen.Map import Data.Array.Accelerate.LLVM.Native.CodeGen.Permute import Data.Array.Accelerate.LLVM.Native.CodeGen.Scan+import Data.Array.Accelerate.LLVM.Native.CodeGen.Stencil+import Data.Array.Accelerate.LLVM.Native.CodeGen.Transform import Data.Array.Accelerate.LLVM.Native.Target   instance Skeleton Native where-  map _         = mkMap-  generate _    = mkGenerate-  fold _        = mkFold-  fold1 _       = mkFold1-  foldSeg _     = mkFoldSeg-  fold1Seg _    = mkFold1Seg-  scanl _       = mkScanl-  scanl1 _      = mkScanl1-  scanl' _      = mkScanl'-  scanr _       = mkScanr-  scanr1 _      = mkScanr1-  scanr' _      = mkScanr'-  permute _     = mkPermute+  map         = mkMap+  generate    = mkGenerate+  transform   = mkTransform+  fold        = mkFold+  foldSeg     = mkFoldSeg+  scan        = mkScan+  scan'       = mkScan'+  permute     = mkPermute+  stencil1    = mkStencil1+  stencil2    = mkStencil2 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Base.hs view
@@ -1,13 +1,14 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Base--- Copyright   : [2015..2017] Trevor L. McDonell+-- Copyright   : [2015..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,20 +16,23 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Base   where -import Data.Array.Accelerate.Type import Data.Array.Accelerate.LLVM.CodeGen.Base-import Data.Array.Accelerate.LLVM.CodeGen.Downcast import Data.Array.Accelerate.LLVM.CodeGen.IR import Data.Array.Accelerate.LLVM.CodeGen.Module import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar import Data.Array.Accelerate.LLVM.Compile.Cache import Data.Array.Accelerate.LLVM.Native.Target                     ( Native )+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type +import LLVM.AST.Type.Downcast import LLVM.AST.Type.Name import qualified LLVM.AST.Global                                    as LLVM import qualified LLVM.AST.Type                                      as LLVM +import Control.Monad import Data.Monoid import Data.String import Text.Printf@@ -38,23 +42,21 @@ -- | Generate function parameters that will specify the first and last (linear) -- index of the array this thread should evaluate. ---gangParam :: (IR Int, IR Int, [LLVM.Parameter])-gangParam =-  let t         = scalarType-      start     = "ix.start"-      end       = "ix.end"+gangParam :: ShapeR sh -> (Operands sh, Operands sh, [LLVM.Parameter])+gangParam shr =+  let start = "ix.start"+      end   = "ix.end"+      tp    = shapeType shr   in-  (local t start, local t end, [ scalarParameter t start, scalarParameter t end ] )+  (local tp start, local tp end, parameter tp start ++ parameter tp end)  --- | The thread ID of a gang worker+-- | The worker ID of the calling thread ---gangId :: (IR Int, [LLVM.Parameter])+gangId :: (Operands Int, [LLVM.Parameter]) gangId =-  let t         = scalarType-      tid       = "ix.tid"-  in-  (local t tid, [ scalarParameter t tid ] )+  let tid = "ix.tid"+  in (local (TupRsingle scalarTypeInt) tid, [ scalarParameter scalarType tid ] )   -- Global function definitions@@ -69,7 +71,7 @@  -- | Create a single kernel program ---makeOpenAcc :: UID -> Label -> [LLVM.Parameter] -> CodeGen () -> CodeGen (IROpenAcc Native aenv a)+makeOpenAcc :: UID -> Label -> [LLVM.Parameter] -> CodeGen Native () -> CodeGen Native (IROpenAcc Native aenv a) makeOpenAcc uid name param kernel = do   body  <- makeKernel (name <> fromString (printf "_%s" (show uid))) param kernel   return $ IROpenAcc [body]@@ -77,7 +79,7 @@ -- | Create a complete kernel function by running the code generation process -- specified in the final parameter. ---makeKernel :: Label -> [LLVM.Parameter] -> CodeGen () -> CodeGen (Kernel Native aenv a)+makeKernel :: Label -> [LLVM.Parameter] -> CodeGen Native () -> CodeGen Native (Kernel Native aenv a) makeKernel name param kernel = do   _    <- kernel   code <- createBlocks
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Fold.hs view
@@ -2,13 +2,14 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Fold--- Copyright   : [2014..2017] Trevor L. McDonell+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,17 +17,17 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Fold   where --- accelerate-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Type -import Data.Array.Accelerate.LLVM.Analysis.Match import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic                as A import Data.Array.Accelerate.LLVM.CodeGen.Array import Data.Array.Accelerate.LLVM.CodeGen.Base import Data.Array.Accelerate.LLVM.CodeGen.Constant import Data.Array.Accelerate.LLVM.CodeGen.Environment+import Data.Array.Accelerate.LLVM.CodeGen.Exp import Data.Array.Accelerate.LLVM.CodeGen.IR import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar@@ -41,45 +42,28 @@ import Prelude                                                      as P hiding ( length )  --- Reduce a (possibly empty) array along the innermost dimension. The reduction+-- Reduce an array along the innermost dimension. The reduction -- function must be associative to allow for an efficient parallel--- implementation. The initial element does not need to be a neutral element of--- the operator.+-- implementation. When an initial value is given, the input can be+-- empty. The initial element does not need to be a neutral element of+-- the operator. When no initial value is given, the array must be+-- non-empty -- mkFold-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh :. Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkFold uid aenv f z acc-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = (+++) <$> mkFoldAll  uid aenv f (Just z) acc-          <*> mkFoldFill uid aenv z--  | otherwise-  = (+++) <$> mkFoldDim  uid aenv f (Just z) acc-          <*> mkFoldFill uid aenv z----- Reduce a non-empty array along the innermost dimension. The reduction--- function must be associative to allow for efficient parallel implementation.----mkFold1-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRDelayed Native aenv (Array (sh :. Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkFold1 uid aenv f acc-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = mkFoldAll uid aenv f Nothing acc--  | otherwise-  = mkFoldDim uid aenv f Nothing acc+    :: UID+    -> Gamma             aenv+    -> ArrayR (Array sh e)+    -> IRFun2       Native aenv (e -> e -> e)+    -> Maybe (IRExp Native aenv e)+    -> MIRDelayed   Native aenv (Array (sh, Int) e)+    -> CodeGen      Native      (IROpenAcc Native aenv (Array sh e))+mkFold uid aenv aR f z arr =+  (+++) <$> case aR of+              ArrayR ShapeRz eR -> mkFoldAll uid aenv eR f z arr+              _                 -> mkFoldDim uid aenv aR f z arr+        <*> case z of+              Just z' -> mkFoldFill uid aenv aR z'+              Nothing -> return (IROpenAcc [])   -- Reduce a multidimensional (>1) array along the innermost dimension.@@ -88,33 +72,33 @@ -- of an innermost-dimension index) is computed by a single thread. -- mkFoldDim-  :: forall aenv sh e. (Shape sh, Elt e)-  =>          UID-  ->          Gamma            aenv-  ->          IRFun2    Native aenv (e -> e -> e)-  -> Maybe   (IRExp     Native aenv e)-  ->          IRDelayed Native aenv (Array (sh :. Int) e)-  -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkFoldDim uid aenv combine mseed IRDelayed{..} =+  :: UID+  -> Gamma aenv+  -> ArrayR (Array sh e)+  -> IRFun2     Native aenv (e -> e -> e)+  -> MIRExp     Native aenv e+  -> MIRDelayed Native aenv (Array (sh, Int) e)+  -> CodeGen    Native      (IROpenAcc Native aenv (Array sh e))+mkFoldDim uid aenv aR@(ArrayR shR eR) combine mseed mdelayed =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array sh e))-      paramEnv                  = envParam aenv-      ---      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)-      stride                    = local           scalarType ("ix.stride" :: Name Int)+      (start, end, paramGang) = gangParam shR+      (arrOut, paramOut)      = mutableArray aR "out"+      (arrIn,  paramIn)       = delayedArray    "in"  mdelayed+      paramEnv                = envParam aenv+      zero                    = liftInt 0   in-  makeOpenAcc uid "fold" (paramGang ++ paramStride : paramOut ++ paramEnv) $ do+  makeOpenAcc uid "fold" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do -    imapFromTo start end $ \seg -> do-      from <- mul numType seg  stride-      to   <- add numType from stride-      ---      r    <- case mseed of-                Just seed -> do z <- seed-                                reduceFromTo  from to (app2 combine) z (app1 delayedLinearIndex)-                Nothing   ->    reduce1FromTo from to (app2 combine)   (app1 delayedLinearIndex)-      writeArray arrOut seg r+    sz <- indexHead <$> delayedExtent arrIn++    imapNestFromTo shR start end (irArrayShape arrOut) $ \ix i -> do+      r <- case mseed of+             Just seed -> do z <- seed+                             reduceFromTo  eR zero sz (app2 combine) z (app1 (delayedIndex arrIn) . indexCons ix)+             Nothing   ->    reduce1FromTo eR zero sz (app2 combine)   (app1 (delayedIndex arrIn) . indexCons ix)++      writeArray TypeInt arrOut i r+     return_  @@ -142,43 +126,44 @@ -- is an exclusive reduction, the seed element is included at this point. -- mkFoldAll-    :: forall aenv e. Elt e-    =>          UID-    ->          Gamma            aenv                           -- ^ array environment-    ->          IRFun2    Native aenv (e -> e -> e)             -- ^ combination function-    -> Maybe   (IRExp     Native aenv e)                        -- ^ seed element, if this is an exclusive reduction-    ->          IRDelayed Native aenv (Vector e)                -- ^ input data-    -> CodeGen (IROpenAcc Native aenv (Scalar e))-mkFoldAll uid aenv combine mseed arr =-  foldr1 (+++) <$> sequence [ mkFoldAllS  uid aenv combine mseed arr-                            , mkFoldAllP1 uid aenv combine       arr-                            , mkFoldAllP2 uid aenv combine mseed+    :: UID+    -> Gamma aenv                                   -- ^ array environment+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)         -- ^ combination function+    -> MIRExp     Native aenv e                     -- ^ seed element, if this is an exclusive reduction+    -> MIRDelayed Native aenv (Vector e)            -- ^ input data+    -> CodeGen    Native      (IROpenAcc Native aenv (Scalar e))+mkFoldAll uid aenv eR combine mseed mdelayed =+  foldr1 (+++) <$> sequence [ mkFoldAllS  uid aenv eR combine mseed mdelayed+                            , mkFoldAllP1 uid aenv eR combine       mdelayed+                            , mkFoldAllP2 uid aenv eR combine mseed                             ]   -- Sequential reduction of an entire array to a single element -- mkFoldAllS-    :: forall aenv e. Elt e-    =>          UID-    ->          Gamma            aenv                           -- ^ array environment-    ->          IRFun2    Native aenv (e -> e -> e)             -- ^ combination function-    -> Maybe   (IRExp     Native aenv e)                        -- ^ seed element, if this is an exclusive reduction-    ->          IRDelayed Native aenv (Vector e)                -- ^ input data-    -> CodeGen (IROpenAcc Native aenv (Scalar e))-mkFoldAllS uid aenv combine mseed IRDelayed{..} =+    :: UID+    -> Gamma aenv                                   -- ^ array environment+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)         -- ^ combination function+    -> MIRExp     Native aenv e                     -- ^ seed element, if this is an exclusive reduction+    -> MIRDelayed Native aenv (Vector e)            -- ^ input data+    -> CodeGen    Native      (IROpenAcc Native aenv (Scalar e))+mkFoldAllS uid aenv eR combine mseed mdelayed  =   let-      (start, end, paramGang)   = gangParam-      paramEnv                  = envParam aenv-      (arrOut,  paramOut)       = mutableArray ("out" :: Name (Scalar e))-      zero                      = lift 0 :: IR Int+      (start, end, paramGang) = gangParam    dim1+      (arrOut, paramOut)      = mutableArray (ArrayR dim0 eR) "out"+      (arrIn,  paramIn)       = delayedArray                  "in" mdelayed+      paramEnv                = envParam aenv+      zero                    = liftInt 0   in-  makeOpenAcc uid "foldAllS" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "foldAllS" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do     r <- case mseed of            Just seed -> do z <- seed-                           reduceFromTo  start end (app2 combine) z (app1 delayedLinearIndex)-           Nothing   ->    reduce1FromTo start end (app2 combine)   (app1 delayedLinearIndex)-    writeArray arrOut zero r+                           reduceFromTo  eR (indexHead start) (indexHead end) (app2 combine) z (app1 (delayedLinearIndex arrIn))+           Nothing   ->    reduce1FromTo eR (indexHead start) (indexHead end) (app2 combine)   (app1 (delayedLinearIndex arrIn))+    writeArray TypeInt arrOut zero r     return_  -- Parallel reduction of an entire array to a single element, step 1.@@ -187,36 +172,30 @@ -- any fused functions on the way. -- mkFoldAllP1-    :: forall aenv e. Elt e-    =>          UID-    ->          Gamma            aenv                           -- ^ array environment-    ->          IRFun2    Native aenv (e -> e -> e)             -- ^ combination function-    ->          IRDelayed Native aenv (Vector e)                -- ^ input data-    -> CodeGen (IROpenAcc Native aenv (Scalar e))-mkFoldAllP1 uid aenv combine IRDelayed{..} =+    :: UID+    -> Gamma             aenv                       -- ^ array environment+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)         -- ^ combination function+    -> MIRDelayed Native aenv (Vector e)            -- ^ input data+    -> CodeGen    Native      (IROpenAcc Native aenv (Scalar e))+mkFoldAllP1 uid aenv eR combine mdelayed =   let-      (start, end, paramGang)   = gangParam-      paramEnv                  = envParam aenv-      (arrTmp,  paramTmp)       = mutableArray ("tmp" :: Name (Vector e))-      length                    = local           scalarType ("ix.length" :: Name Int)-      stride                    = local           scalarType ("ix.stride" :: Name Int)-      paramLength               = scalarParameter scalarType ("ix.length" :: Name Int)-      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)+      (start, end, paramGang) = gangParam    dim1+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      (arrIn,  paramIn)       = delayedArray                  "in" mdelayed+      piece                   = local     (TupRsingle scalarTypeInt) "ix.piece"+      paramPiece              = parameter (TupRsingle scalarTypeInt) "ix.piece"+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "foldAllP1" (paramGang ++ paramLength : paramStride : paramTmp ++ paramEnv) $ do+  makeOpenAcc uid "foldAllP1" (paramGang ++ paramPiece ++ paramTmp ++ paramIn ++ paramEnv) $ do      -- A thread reduces a sequential (non-empty) stripe of the input and stores-    -- that value into a temporary array at a specific index. The size of the-    -- stripe is fixed, but work stealing occurs between stripe indices. This-    -- method thus supports non-commutative operators because the order of-    -- operations remains left-to-right.+    -- that value into a temporary array at a specific index. This method thus+    -- supports non-commutative operators because the order of operations+    -- remains left-to-right.     ---    imapFromTo start end $ \i -> do-      inf <- A.mul numType    i   stride-      a   <- A.add numType    inf stride-      sup <- A.min singleType a   length-      r   <- reduce1FromTo inf sup (app2 combine) (app1 delayedLinearIndex)-      writeArray arrTmp i r+    r <- reduce1FromTo eR (indexHead start) (indexHead end) (app2 combine) (app1 (delayedLinearIndex arrIn))+    writeArray TypeInt arrTmp piece r      return_ @@ -230,26 +209,26 @@ -- large, continuing reducing it in parallel. -- mkFoldAllP2-    :: forall aenv e. Elt e-    =>          UID-    ->          Gamma            aenv                           -- ^ array environment-    ->          IRFun2    Native aenv (e -> e -> e)             -- ^ combination function-    -> Maybe   (IRExp     Native aenv e)                        -- ^ seed element, if this is an exclusive reduction-    -> CodeGen (IROpenAcc Native aenv (Scalar e))-mkFoldAllP2 uid aenv combine mseed =+    :: UID+    -> Gamma          aenv                          -- ^ array environment+    -> TypeR e+    -> IRFun2  Native aenv (e -> e -> e)            -- ^ combination function+    -> MIRExp  Native aenv e                        -- ^ seed element, if this is an exclusive reduction+    -> CodeGen Native      (IROpenAcc Native aenv (Scalar e))+mkFoldAllP2 uid aenv eR combine mseed =   let-      (start, end, paramGang)   = gangParam-      paramEnv                  = envParam aenv-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Scalar e))-      zero                      = lift 0 :: IR Int+      (start, end, paramGang) = gangParam    dim1+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      (arrOut, paramOut)      = mutableArray (ArrayR dim0 eR) "out"+      paramEnv                = envParam aenv+      zero                    = liftInt 0   in   makeOpenAcc uid "foldAllP2" (paramGang ++ paramTmp ++ paramOut ++ paramEnv) $ do     r <- case mseed of            Just seed -> do z <- seed-                           reduceFromTo  start end (app2 combine) z (readArray arrTmp)-           Nothing   ->    reduce1FromTo start end (app2 combine)   (readArray arrTmp)-    writeArray arrOut zero r+                           reduceFromTo  eR (indexHead start) (indexHead end) (app2 combine) z (readArray TypeInt arrTmp)+           Nothing   ->    reduce1FromTo eR (indexHead start) (indexHead end) (app2 combine)   (readArray TypeInt arrTmp)+    writeArray TypeInt arrOut zero r     return_  @@ -257,13 +236,13 @@ -- dimensions with the initial element -- mkFoldFill-    :: (Shape sh, Elt e)-    => UID+    :: UID     -> Gamma aenv-    -> IRExp Native aenv e-    -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkFoldFill uid aenv seed =-  mkGenerate uid aenv (IRFun1 (const seed))+    -> ArrayR (Array sh e)+    -> IRExp   Native aenv e+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh e))+mkFoldFill uid aenv aR seed =+  mkGenerate uid aenv aR (IRFun1 (const seed))  -- Reduction loops -- ---------------@@ -271,15 +250,15 @@ -- Reduction of a (possibly empty) index space. -- reduceFromTo-    :: Elt a-    => IR Int                                   -- ^ starting index-    -> IR Int                                   -- ^ final index (exclusive)-    -> (IR a -> IR a -> CodeGen (IR a))         -- ^ combination function-    -> IR a                                     -- ^ initial value-    -> (IR Int -> CodeGen (IR a))               -- ^ function to retrieve element at index-    -> CodeGen (IR a)-reduceFromTo m n f z get =-  iterFromTo m n z $ \i acc -> do+    :: TypeR e+    -> Operands Int                                              -- ^ starting index+    -> Operands Int                                              -- ^ final index (exclusive)+    -> (Operands e -> Operands e -> CodeGen Native (Operands e)) -- ^ combination function+    -> Operands e                                                -- ^ initial value+    -> (Operands Int -> CodeGen Native (Operands e))             -- ^ function to retrieve element at index+    -> CodeGen Native (Operands e)+reduceFromTo eR m n f z get =+  iterFromTo eR m n z $ \i acc -> do     x <- get i     y <- f acc x     return y@@ -288,14 +267,14 @@ -- contain at least one element. -- reduce1FromTo-    :: Elt a-    => IR Int                                   -- ^ starting index-    -> IR Int                                   -- ^ final index-    -> (IR a -> IR a -> CodeGen (IR a))         -- ^ combination function-    -> (IR Int -> CodeGen (IR a))               -- ^ function to retrieve element at index-    -> CodeGen (IR a)-reduce1FromTo m n f get = do+    :: TypeR e+    -> Operands Int                                              -- ^ starting index+    -> Operands Int                                              -- ^ final index+    -> (Operands e -> Operands e -> CodeGen Native (Operands e)) -- ^ combination function+    -> (Operands Int -> CodeGen Native (Operands e))             -- ^ function to retrieve element at index+    -> CodeGen Native (Operands e)+reduce1FromTo eR m n f get = do   z  <- get m   m1 <- add numType m (ir numType (num numType 1))-  reduceFromTo m1 n f z get+  reduceFromTo eR m1 n f z get 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/FoldSeg.hs view
@@ -1,14 +1,15 @@ {-# LANGUAGE GADTs               #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.FoldSeg--- Copyright   : [2014..2017] Trevor L. McDonell+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,17 +17,14 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.FoldSeg   where --- accelerate-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Representation.Array import Data.Array.Accelerate.Type  import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic                as A import Data.Array.Accelerate.LLVM.CodeGen.Array import Data.Array.Accelerate.LLVM.CodeGen.Base import Data.Array.Accelerate.LLVM.CodeGen.Environment-import Data.Array.Accelerate.LLVM.CodeGen.IR-import Data.Array.Accelerate.LLVM.CodeGen.Exp                       ( indexHead )-import Data.Array.Accelerate.LLVM.CodeGen.Loop+import Data.Array.Accelerate.LLVM.CodeGen.Exp import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar import Data.Array.Accelerate.LLVM.Compile.Cache@@ -36,86 +34,54 @@ import Data.Array.Accelerate.LLVM.Native.CodeGen.Loop import Data.Array.Accelerate.LLVM.Native.Target                     ( Native ) -import Control.Applicative import Control.Monad import Prelude                                                      as P ---- Segmented reduction along the innermost dimension of an array. Performs one--- reduction per segment of the source array.----mkFoldSeg-    :: forall aenv sh i e. (Shape sh, IsIntegral i, Elt i, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh :. Int) e)-    -> IRDelayed Native aenv (Segments i)-    -> CodeGen (IROpenAcc Native aenv (Array (sh :. Int) e))-mkFoldSeg uid aenv combine seed arr seg =-  (+++) <$> mkFoldSegS uid aenv combine (Just seed) arr seg-        <*> mkFoldSegP uid aenv combine (Just seed) arr seg----- Segmented reduction along the innermost dimension of an array, where /all/--- segments are non-empty.----mkFold1Seg-    :: forall aenv sh i e. (Shape sh, IsIntegral i, Elt i, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRDelayed Native aenv (Array (sh :. Int) e)-    -> IRDelayed Native aenv (Segments i)-    -> CodeGen (IROpenAcc Native aenv (Array (sh :. Int) e))-mkFold1Seg uid aenv combine arr seg =-  (+++) <$> mkFoldSegS uid aenv combine Nothing arr seg-        <*> mkFoldSegP uid aenv combine Nothing arr seg--+{-- -- Segmented reduction where a single processor reduces the entire array. The -- segments array contains the length of each segment. -- mkFoldSegS     :: forall aenv sh i e. (Shape sh, IsIntegral i, Elt i, Elt e)-    =>          UID-    ->          Gamma            aenv-    ->          IRFun2    Native aenv (e -> e -> e)-    -> Maybe   (IRExp     Native aenv e)-    ->          IRDelayed Native aenv (Array (sh :. Int) e)-    ->          IRDelayed Native aenv (Segments i)-    -> CodeGen (IROpenAcc Native aenv (Array (sh :. Int) e))-mkFoldSegS uid aenv combine mseed arr seg =+    => UID+    -> Gamma             aenv+    -> IRFun2     Native aenv (e -> e -> e)+    -> MIRExp     Native aenv e+    -> MIRDelayed Native aenv (Array (sh :. Int) e)+    -> MIRDelayed Native aenv (Segments i)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array (sh :. Int) e))+mkFoldSegS uid aenv combine mseed marr mseg =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array (sh :. Int) e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam @DIM1+      (arrOut, paramOut)      = mutableArray @(sh:.Int) "out"+      (arrIn,  paramIn)       = delayedArray @(sh:.Int) "in"  marr+      (arrSeg, paramSeg)      = delayedArray @DIM1      "seg" mseg+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "foldSegS" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "foldSegS" (paramGang ++ paramOut ++ paramIn ++ paramSeg ++ paramEnv) $ do      -- Number of segments, useful only if reducing DIM2 and higher-    ss <- indexHead <$> delayedExtent seg+    ss <- indexHead <$> delayedExtent arrSeg -    let test si = A.lt singleType (A.fst si) end-        initial = A.pair start (lift 0)+    let test si = A.lt singleType (A.fst si) (indexHead end)+        initial = A.pair (indexHead start) (lift 0) -        body :: IR (Int,Int) -> CodeGen (IR (Int,Int))+        body :: IR (Int,Int) -> CodeGen Native (IR (Int,Int))         body (A.unpair -> (s,inf)) = do           -- We can avoid an extra division if this is a DIM1 array. Higher           -- dimensional reductions need to wrap around the segment array at           -- each new lower-dimensional index.-          s'  <- case rank (undefined::sh) of+          s'  <- case rank @sh of                    0 -> return s                    _ -> A.rem integralType s ss -          len <- A.fromIntegral integralType numType =<< app1 (delayedLinearIndex seg) s'+          len <- A.fromIntegral integralType numType =<< app1 (delayedLinearIndex arrSeg) s'           sup <- A.add numType inf len            r   <- case mseed of                    Just seed -> do z <- seed-                                   reduceFromTo  inf sup (app2 combine) z (app1 (delayedLinearIndex arr))-                   Nothing   ->    reduce1FromTo inf sup (app2 combine)   (app1 (delayedLinearIndex arr))+                                   reduceFromTo  inf sup (app2 combine) z (app1 (delayedLinearIndex arrIn))+                   Nothing   ->    reduce1FromTo inf sup (app2 combine)   (app1 (delayedLinearIndex arrIn))           writeArray arrOut s r            t <- A.add numType s (lift 1)@@ -123,59 +89,56 @@      void $ while test body initial     return_+--}  +-- Segmented reduction along the innermost dimension of an array. Performs one+-- reduction per segment of the source array. When no seed is given, assumes+-- that /all/ segments are non-empty.+-- -- This implementation assumes that the segments array represents the offset -- indices to the source array, rather than the lengths of each segment. The -- segment-offset approach is required for parallel implementations. ---mkFoldSegP-    :: forall aenv sh i e. (Shape sh, IsIntegral i, Elt i, Elt e)-    =>          UID-    ->          Gamma            aenv-    ->          IRFun2    Native aenv (e -> e -> e)-    -> Maybe   (IRExp     Native aenv e)-    ->          IRDelayed Native aenv (Array (sh :. Int) e)-    ->          IRDelayed Native aenv (Segments i)-    -> CodeGen (IROpenAcc Native aenv (Array (sh :. Int) e))-mkFoldSegP uid aenv combine mseed arr seg =+mkFoldSeg+    :: UID+    -> Gamma             aenv+    -> ArrayR (Array (sh, Int) e)+    -> IntegralType i+    -> IRFun2     Native aenv (e -> e -> e)+    -> MIRExp     Native aenv e+    -> MIRDelayed Native aenv (Array (sh, Int) e)+    -> MIRDelayed Native aenv (Segments i)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array (sh, Int) e))+mkFoldSeg uid aenv aR@(ArrayR shR eR) int combine mseed marr mseg =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array (sh :. Int) e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam shR+      (arrOut, paramOut)      = mutableArray aR "out"+      (arrIn,  paramIn)       = delayedArray    "in"  marr+      (arrSeg, paramSeg)      = delayedArray    "seg" mseg+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "foldSegP" (paramGang ++ paramOut ++ paramEnv) $ do--    -- Number of segments and size of the innermost dimension. These are-    -- required if we are reducing a DIM2 or higher array, to properly compute-    -- the start and end indices of the portion of the array to reduce. Note-    -- that this is a segment-offset array computed by 'scanl (+) 0' of the-    -- segment length array, so its size has increased by one.-    sz <- indexHead <$> delayedExtent arr-    ss <- do n <- indexHead <$> delayedExtent seg-             A.sub numType n (lift 1)--    imapFromTo start end $ \s -> do+  makeOpenAcc uid "foldSegP" (paramGang ++ paramOut ++ paramIn ++ paramSeg ++ paramEnv) $ do -      i   <- case rank (undefined::sh) of-               0 -> return s-               _ -> A.rem integralType s ss-      j   <- A.add numType i (lift 1)-      u   <- A.fromIntegral integralType numType =<< app1 (delayedLinearIndex seg) i-      v   <- A.fromIntegral integralType numType =<< app1 (delayedLinearIndex seg) j+    imapNestFromTo shR start end (irArrayShape arrOut) $ \ix ii -> do -      (inf,sup) <- A.unpair <$> case rank (undefined::sh) of-                     0 -> return (A.pair u v)-                     _ -> do q <- A.quot integralType s ss-                             a <- A.mul numType q sz-                             A.pair <$> A.add numType u a <*> A.add numType v a+      -- Determine the start and end indices of the innermost portion of+      -- the array to reduce. This is a segment-offset array computed by+      -- 'scanl (+) 0' of the segment length array.+      --+      let iz = indexTail ix+          i  = indexHead ix+      --+      j <- A.add numType i (liftInt 1)+      u <- A.fromIntegral int numType =<< app1 (delayedLinearIndex arrSeg) i+      v <- A.fromIntegral int numType =<< app1 (delayedLinearIndex arrSeg) j -      r   <- case mseed of-               Just seed -> do z <- seed-                               reduceFromTo  inf sup (app2 combine) z (app1 (delayedLinearIndex arr))-               Nothing   ->    reduce1FromTo inf sup (app2 combine)   (app1 (delayedLinearIndex arr))+      r <- case mseed of+             Just seed -> do z <- seed+                             reduceFromTo  eR u v (app2 combine) z (app1 (delayedIndex arrIn) . indexCons iz)+             Nothing   ->    reduce1FromTo eR u v (app2 combine)   (app1 (delayedIndex arrIn) . indexCons iz) -      writeArray arrOut s r+      writeArray TypeInt arrOut ii r      return_ 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Generate.hs view
@@ -1,12 +1,12 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Generate--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -14,13 +14,12 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Generate   where --- accelerate-import Data.Array.Accelerate.Array.Sugar                        ( Array, Shape, Elt )+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Type  import Data.Array.Accelerate.LLVM.CodeGen.Array import Data.Array.Accelerate.LLVM.CodeGen.Base import Data.Array.Accelerate.LLVM.CodeGen.Environment-import Data.Array.Accelerate.LLVM.CodeGen.Exp import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar import Data.Array.Accelerate.LLVM.Compile.Cache@@ -34,23 +33,23 @@ -- processes multiple adjacent elements. -- mkGenerate-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID+    :: UID     -> Gamma aenv-    -> IRFun1 Native aenv (sh -> e)-    -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkGenerate uid aenv apply =+    -> ArrayR (Array sh e)+    -> IRFun1  Native aenv (sh -> e)+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh e))+mkGenerate uid aenv repr apply =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array sh e))+      (start, end, paramGang)   = gangParam (arrayRshape repr)+      (arrOut, paramOut)        = mutableArray repr "out"       paramEnv                  = envParam aenv+      shOut                     = irArrayShape arrOut   in   makeOpenAcc uid "generate" (paramGang ++ paramOut ++ paramEnv) $ do -    imapFromTo start end $ \i -> do-      ix <- indexOfInt (irArrayShape arrOut) i  -- convert to multidimensional index-      r  <- app1 apply ix                       -- apply generator function-      writeArray arrOut i r                     -- store result+    imapNestFromTo (arrayRshape repr) start end shOut $ \ix i -> do+      r <- app1 apply ix                        -- apply generator function+      writeArray TypeInt arrOut i r             -- store result      return_ 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Loop.hs view
@@ -1,9 +1,13 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.LLVM.CodeGen.Native.Loop--- Copyright   : [2014..2017] Trevor L. McDonell+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -12,35 +16,145 @@   where  -- accelerate-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Representation.Shape  import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic+import Data.Array.Accelerate.LLVM.CodeGen.Exp import Data.Array.Accelerate.LLVM.CodeGen.IR import Data.Array.Accelerate.LLVM.CodeGen.Monad-import qualified Data.Array.Accelerate.LLVM.CodeGen.Loop        as Loop+import qualified Data.Array.Accelerate.LLVM.CodeGen.Loop            as Loop +import Data.Array.Accelerate.LLVM.Native.Target                     ( Native ) + -- | A standard 'for' loop, that steps from the start to end index executing the -- given function at each index. -- imapFromTo-    :: IR Int                                   -- ^ starting index (inclusive)-    -> IR Int                                   -- ^ final index (exclusive)-    -> (IR Int -> CodeGen ())                   -- ^ apply at each index-    -> CodeGen ()+    :: Operands Int                                   -- ^ starting index (inclusive)+    -> Operands Int                                   -- ^ final index (exclusive)+    -> (Operands Int -> CodeGen Native ())            -- ^ apply at each index+    -> CodeGen Native () imapFromTo start end body =-  Loop.imapFromStepTo start (lift 1) end body+  Loop.imapFromStepTo start (liftInt 1) end body ++-- | Generate a series of nested 'for' loops which iterate between the start and+-- end indices of a given hyper-rectangle. LLVM is very good at vectorising+-- these kinds of nested loops, but not so good at vectorising the flattened+-- representation utilising to/from index.+--+imapNestFromTo+    :: ShapeR sh+    -> Operands sh                                          -- ^ initial index (inclusive)+    -> Operands sh                                          -- ^ final index (exclusive)+    -> Operands sh                                          -- ^ total array extent+    -> (Operands sh -> Operands Int -> CodeGen Native ())   -- ^ apply at each index+    -> CodeGen Native ()+imapNestFromTo shr start end extent body =+  go shr start end body'+  where+    body' ix = body ix =<< intOfIndex shr extent ix++    go :: ShapeR t -> Operands t -> Operands t -> (Operands t -> CodeGen Native ()) -> CodeGen Native ()+    go ShapeRz OP_Unit OP_Unit k+      = k OP_Unit++    go (ShapeRsnoc shr') (OP_Pair ssh ssz) (OP_Pair esh esz) k+      = go shr' ssh esh+      $ \sz      -> imapFromTo ssz esz+      $ \i       -> k (OP_Pair sz i)+++{--+-- TLM: this version (seems to) compute the corresponding linear index as it+--      goes. We need to compare it against the above implementation to see if+--      there are any advantages.+--+imapNestFromTo'+    :: forall sh. Shape sh+    => Operands sh+    -> Operands sh+    -> Operands sh+    -> (Operands sh -> Operands Int -> CodeGen Native ())+    -> CodeGen Native ()+imapNestFromTo' start end extent body = do+  startl <- intOfIndex extent start+  void $ go (eltType @sh) start end extent (int 1) startl body'+  where+    body' :: Operands (EltRepr sh) -> Operands Int -> CodeGen Native (Operands Int)+    body' ix l = body ix l >> add numType (int 1) l++    go :: TupleType t+       -> Operands t+       -> Operands t+       -> Operands t+       -> Operands Int+       -> Operands Int+       -> (Operands t -> Operands Int -> CodeGen Native (Operands Int))+       -> CodeGen Native (Operands Int)+    go TypeRunit OP_Unit OP_Unit OP_Unit _delta l k+      = k OP_Unit l++    go (TypeRpair tsh tsz) (OP_Pair ssh ssz) (OP_Pair esh esz) (OP_Pair exh exz) delta l k+      | TypeRscalar t <- tsz+      , Just Refl     <- matchScalarType t (scalarType :: ScalarType Int)+      = do+          delta' <- mul numType delta exz+          go tsh ssh esh exh delta' l $ \sz ll -> do+            Loop.iterFromStepTo ssz (int 1) esz ll $ \i l' ->+              k (OP_Pair sz i) l'+            add numType ll delta'++    go _ _ _ _ _ _ _+      = $internalError "imapNestFromTo'" "expected shape with Int components"+--}++{--+-- | Generate a series of nested 'for' loops which iterate between the start and+-- end indices of a given hyper-rectangle. LLVM is very good at vectorising+-- these kinds of nested loops, but not so good at vectorising the flattened+-- representation utilising to/from index.+--+imapNestFromStepTo+    :: forall sh. Shape sh+    => Operands sh                                    -- ^ initial index (inclusive)+    -> Operands sh                                    -- ^ steps+    -> Operands sh                                    -- ^ final index (exclusive)+    -> Operands sh                                    -- ^ total array extent+    -> (Operands sh -> Operands Int -> CodeGen Native ())   -- ^ apply at each index+    -> CodeGen Native ()+imapNestFromStepTo start steps end extent body =+  go (eltType @sh) start steps end (body' . IR)+  where+    body' ix = body ix =<< intOfIndex extent ix++    go :: TupleType t -> Operands t -> Operands t -> Operands t -> (Operands t -> CodeGen Native ()) -> CodeGen Native ()+    go TypeRunit OP_Unit OP_Unit OP_Unit k+      = k OP_Unit++    go (TypeRpair tsh tsz) (OP_Pair ssh ssz) (OP_Pair sts stz) (OP_Pair esh esz) k+      | TypeRscalar t <- tsz+      , Just Refl     <- matchScalarType t (scalarType :: ScalarType Int)+      = go tsh ssh sts esh+      $ \sz      -> Loop.imapFromStepTo ssz stz esz+      $ \i       -> k (OP_Pair sz i)++    go _ _ _ _ _+      = $internalError "imapNestFromTo" "expected shape with Int components"+--}+ -- | Iterate with an accumulator between the start and end index, executing the -- given function at each. -- iterFromTo-    :: Elt a-    => IR Int                                   -- ^ starting index (inclusive)-    -> IR Int                                   -- ^ final index (exclusive)-    -> IR a                                     -- ^ initial value-    -> (IR Int -> IR a -> CodeGen (IR a))       -- ^ apply at each index-    -> CodeGen (IR a)-iterFromTo start end seed body =-  Loop.iterFromStepTo start (lift 1) end seed body+    :: TypeR a+    -> Operands Int                                       -- ^ starting index (inclusive)+    -> Operands Int                                       -- ^ final index (exclusive)+    -> Operands a                                         -- ^ initial value+    -> (Operands Int -> Operands a -> CodeGen Native (Operands a))    -- ^ apply at each index+    -> CodeGen Native (Operands a)+iterFromTo tp start end seed body =+  Loop.iterFromStepTo tp start (liftInt 1) end seed body 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Map.hs view
@@ -2,13 +2,13 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Map--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,12 +16,15 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Map   where --- accelerate-import Data.Array.Accelerate.Array.Sugar                        ( Array, Elt )+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type  import Data.Array.Accelerate.LLVM.CodeGen.Array import Data.Array.Accelerate.LLVM.CodeGen.Base import Data.Array.Accelerate.LLVM.CodeGen.Environment+import Data.Array.Accelerate.LLVM.CodeGen.Exp import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar import Data.Array.Accelerate.LLVM.Compile.Cache@@ -70,27 +73,30 @@ -- declare float @apply(float) -- - -- Apply the given unary function to each element of an array. ---mkMap :: forall aenv sh a b. Elt b-      => UID-      -> Gamma            aenv-      -> IRFun1    Native aenv (a -> b)-      -> IRDelayed Native aenv (Array sh a)-      -> CodeGen (IROpenAcc Native aenv (Array sh b))-mkMap uid aenv apply IRDelayed{..} =+-- The map operation can always treat an array of any dimension in its flat+-- underlying representation, which simplifies code generation.+--+mkMap :: UID+      -> Gamma aenv+      -> ArrayR (Array sh a)+      -> TypeR b+      -> IRFun1  Native aenv (a -> b)+      -> CodeGen Native      (IROpenAcc Native aenv (Array sh b))+mkMap uid aenv (ArrayR shR aR) bR apply =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array sh b))+      (start, end, paramGang)   = gangParam dim1+      (arrIn,  paramIn)         = mutableArray (ArrayR shR aR) "in"+      (arrOut, paramOut)        = mutableArray (ArrayR shR bR) "out"       paramEnv                  = envParam aenv   in-  makeOpenAcc uid "map" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "map" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do -    imapFromTo start end $ \i -> do-      xs <- app1 delayedLinearIndex i+    imapFromTo (indexHead start) (indexHead end) $ \i -> do+      xs <- readArray TypeInt arrIn i       ys <- app1 apply xs-      writeArray arrOut i ys+      writeArray TypeInt arrOut i ys      return_ 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Permute.hs view
@@ -1,14 +1,15 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Permute--- Copyright   : [2016..2017] Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,10 +17,11 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Permute   where --- accelerate-import Data.Array.Accelerate.Array.Sugar                            ( Array, Vector, Shape, Elt, eltType )+import Data.Array.Accelerate.AST                                    ( PrimMaybe ) import Data.Array.Accelerate.Error-import qualified Data.Array.Accelerate.Array.Sugar                  as S+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type  import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic                as A import Data.Array.Accelerate.LLVM.CodeGen.Array@@ -47,7 +49,6 @@  import Control.Applicative import Control.Monad                                                ( void )-import Data.Typeable import Prelude  @@ -60,16 +61,18 @@ -- that are mapped to the magic index 'ignore' are dropped. -- mkPermute-    :: (Shape sh, Shape sh', Elt e)+    :: HasCallStack     => UID-    -> Gamma aenv+    -> Gamma               aenv+    -> ArrayR (Array sh e)+    -> ShapeR sh'     -> IRPermuteFun Native aenv (e -> e -> e)-    -> IRFun1       Native aenv (sh -> sh')-    -> IRDelayed    Native aenv (Array sh e)-    -> CodeGen (IROpenAcc Native aenv (Array sh' e))-mkPermute uid aenv combine project arr =-  (+++) <$> mkPermuteS uid aenv combine project arr-        <*> mkPermuteP uid aenv combine project arr+    -> IRFun1       Native aenv (sh -> PrimMaybe sh')+    -> MIRDelayed   Native aenv (Array sh e)+    -> CodeGen      Native      (IROpenAcc Native aenv (Array sh' e))+mkPermute uid aenv repr shr combine project arr =+  (+++) <$> mkPermuteS uid aenv repr shr combine project arr+        <*> mkPermuteP uid aenv repr shr combine project arr   -- Forward permutation which does not require locking the output array. This@@ -81,37 +84,39 @@ -- co-domain). -- mkPermuteS-    :: forall aenv sh sh' e. (Shape sh, Shape sh', Elt e)-    => UID-    -> Gamma aenv+    :: UID+    -> Gamma               aenv+    -> ArrayR (Array sh e)+    -> ShapeR sh'     -> IRPermuteFun Native aenv (e -> e -> e)-    -> IRFun1       Native aenv (sh -> sh')-    -> IRDelayed    Native aenv (Array sh e)-    -> CodeGen (IROpenAcc Native aenv (Array sh' e))-mkPermuteS uid aenv IRPermuteFun{..} project IRDelayed{..} =+    -> IRFun1       Native aenv (sh -> PrimMaybe sh')+    -> MIRDelayed   Native aenv (Array sh e)+    -> CodeGen      Native      (IROpenAcc Native aenv (Array sh' e))+mkPermuteS uid aenv repr shr IRPermuteFun{..} project marr =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array sh' e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    (arrayRshape repr)+      (arrOut, paramOut)      = mutableArray (reprOut repr shr) "out"+      (arrIn,  paramIn)       = delayedArray "in" marr+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "permuteS" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "permuteS" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do -    sh <- delayedExtent+    sh <- delayedExtent arrIn -    imapFromTo start end $ \i -> do+    imapNestFromTo (arrayRshape repr) start end sh $ \ix _ -> do -      ix  <- indexOfInt sh i       ix' <- app1 project ix -      unless (ignore ix') $ do-        j <- intOfIndex (irArrayShape arrOut) ix'+      when (isJust ix') $ do+        i <- fromJust ix'+        j <- intOfIndex shr (irArrayShape arrOut) i          -- project element onto the destination array and update-        x <- app1 delayedLinearIndex i-        y <- readArray arrOut j+        x <- app1 (delayedIndex arrIn) ix+        y <- readArray TypeInt arrOut j         r <- app2 combine x y -        writeArray arrOut j r+        writeArray TypeInt arrOut j r      return_ @@ -127,71 +132,79 @@ -- a queue or some such. -- mkPermuteP-    :: forall aenv sh sh' e. (Shape sh, Shape sh', Elt e)+    :: HasCallStack     => UID-    -> Gamma aenv+    -> Gamma               aenv+    -> ArrayR (Array sh e)+    -> ShapeR sh'     -> IRPermuteFun Native aenv (e -> e -> e)-    -> IRFun1       Native aenv (sh -> sh')-    -> IRDelayed    Native aenv (Array sh e)-    -> CodeGen (IROpenAcc Native aenv (Array sh' e))-mkPermuteP uid aenv IRPermuteFun{..} project arr =+    -> IRFun1       Native aenv (sh -> PrimMaybe sh')+    -> MIRDelayed   Native aenv (Array sh e)+    -> CodeGen      Native      (IROpenAcc Native aenv (Array sh' e))+mkPermuteP uid aenv repr shr IRPermuteFun{..} project arr =   case atomicRMW of-    Nothing       -> mkPermuteP_mutex uid aenv combine project arr-    Just (rmw, f) -> mkPermuteP_rmw   uid aenv rmw f   project arr+    Nothing       -> mkPermuteP_mutex uid aenv repr shr combine project arr+    Just (rmw, f) -> mkPermuteP_rmw   uid aenv repr shr rmw f   project arr   -- Parallel forward permutation function which uses atomic instructions to -- implement lock-free array updates. -- mkPermuteP_rmw-    :: forall aenv sh sh' e. (Shape sh, Shape sh', Elt e)+    :: HasCallStack     => UID     -> Gamma aenv+    -> ArrayR (Array sh e)+    -> ShapeR sh'     -> RMWOperation-    -> IRFun1    Native aenv (e -> e)-    -> IRFun1    Native aenv (sh -> sh')-    -> IRDelayed Native aenv (Array sh e)-    -> CodeGen (IROpenAcc Native aenv (Array sh' e))-mkPermuteP_rmw uid aenv rmw update project IRDelayed{..} =+    -> IRFun1     Native aenv (e -> e)+    -> IRFun1     Native aenv (sh -> PrimMaybe sh')+    -> MIRDelayed Native aenv (Array sh e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array sh' e))+mkPermuteP_rmw uid aenv repr shr rmw update project marr =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array sh' e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    (arrayRshape repr)+      (arrOut, paramOut)      = mutableArray (reprOut repr shr) "out"+      (arrIn,  paramIn)       = delayedArray "in" marr+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "permuteP_rmw" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "permuteP_rmw" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do -    sh <- delayedExtent+    sh <- delayedExtent arrIn -    imapFromTo start end $ \i -> do+    imapNestFromTo (arrayRshape repr) start end sh $ \ix _ -> do -      ix  <- indexOfInt sh i       ix' <- app1 project ix -      unless (ignore ix') $ do-        j <- intOfIndex (irArrayShape arrOut) ix'-        x <- app1 delayedLinearIndex i+      when (isJust ix') $ do+        i <- fromJust ix'+        j <- intOfIndex shr (irArrayShape arrOut) i+        x <- app1 (delayedIndex arrIn) ix         r <- app1 update x          case rmw of           Exchange-            -> writeArray arrOut j r+            -> writeArray TypeInt arrOut j r           ---          _ | TypeRscalar (SingleScalarType s)  <- eltType (undefined::e)-            , Just adata                        <- gcast (irArrayData arrOut)-            , Just r'                           <- gcast r+          _ | TupRsingle (SingleScalarType s)   <- arrayRtype repr+            , adata                             <- irArrayData arrOut             -> do                   addr <- instr' $ GetElementPtr (asPtr defaultAddrSpace (op s adata)) [op integralType j]                   --                   case s of-                    NumSingleType (IntegralNumType t) -> void . instr' $ AtomicRMW t NonVolatile rmw addr (op t r') (CrossThread, AcquireRelease)-                    NumSingleType t | RMW.Add <- rmw  -> atomicCAS_rmw s (A.add t r') addr-                    NumSingleType t | RMW.Sub <- rmw  -> atomicCAS_rmw s (A.sub t r') addr-                    _ -> case rmw of-                           RMW.Min                    -> atomicCAS_cmp s A.lt addr (op s r')-                           RMW.Max                    -> atomicCAS_cmp s A.gt addr (op s r')-                           _                          -> $internalError "mkPermute_rmw" "unexpected transition"+#if MIN_VERSION_llvm_hs(10,0,0)+                    NumSingleType t             -> void . instr' $ AtomicRMW t NonVolatile rmw addr (op t r) (CrossThread, AcquireRelease)+#else+                    NumSingleType t+                      | IntegralNumType{} <- t  -> void . instr' $ AtomicRMW t NonVolatile rmw addr (op t r) (CrossThread, AcquireRelease)+                      | RMW.Add <- rmw          -> atomicCAS_rmw s (A.add t r) addr+                      | RMW.Sub <- rmw          -> atomicCAS_rmw s (A.sub t r) addr+#endif+                    _ | RMW.Min <- rmw          -> atomicCAS_cmp s A.lt addr (op s r)+                      | RMW.Max <- rmw          -> atomicCAS_cmp s A.gt addr (op s r)+                    _                           -> internalError "unexpected transition"           ---          _ -> $internalError "mkPermute_rmw" "unexpected transition"+          _ -> internalError "unexpected transition"      return_ @@ -200,38 +213,40 @@ -- a mutex before updating the value at that location. -- mkPermuteP_mutex-    :: forall aenv sh sh' e. (Shape sh, Shape sh', Elt e)-    => UID-    -> Gamma aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRFun1    Native aenv (sh -> sh')-    -> IRDelayed Native aenv (Array sh e)-    -> CodeGen (IROpenAcc Native aenv (Array sh' e))-mkPermuteP_mutex uid aenv combine project IRDelayed{..} =+    :: UID+    -> Gamma             aenv+    -> ArrayR (Array sh e)+    -> ShapeR sh'+    -> IRFun2     Native aenv (e -> e -> e)+    -> IRFun1     Native aenv (sh -> PrimMaybe sh')+    -> MIRDelayed Native aenv (Array sh e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array sh' e))+mkPermuteP_mutex uid aenv repr shr combine project marr =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out"  :: Name (Array sh' e))-      (arrLock, paramLock)      = mutableArray ("lock" :: Name (Vector Word8))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    (arrayRshape repr)+      (arrOut,  paramOut)     = mutableArray (reprOut repr shr)  "out"+      (arrLock, paramLock)    = mutableArray reprLock "lock"+      (arrIn,   paramIn)      = delayedArray "in" marr+      paramEnv                = envParam aenv   in-  makeOpenAcc uid "permuteP_mutex" (paramGang ++ paramOut ++ paramLock ++ paramEnv) $ do+  makeOpenAcc uid "permuteP_mutex" (paramGang ++ paramOut ++ paramLock ++ paramIn ++ paramEnv) $ do -    sh <- delayedExtent+    sh <- delayedExtent arrIn -    imapFromTo start end $ \i -> do+    imapNestFromTo (arrayRshape repr) start end sh $ \ix _ -> do -      ix  <- indexOfInt sh i       ix' <- app1 project ix        -- project element onto the destination array and (atomically) update-      unless (ignore ix') $ do-        j <- intOfIndex (irArrayShape arrOut) ix'-        x <- app1 delayedLinearIndex i+      when (isJust ix') $ do+        i <- fromJust ix'+        j <- intOfIndex shr (irArrayShape arrOut) i+        x <- app1 (delayedIndex arrIn) ix          atomically arrLock j $ do-          y <- readArray arrOut j+          y <- readArray TypeInt arrOut j           r <- app2 combine x y-          writeArray arrOut j r+          writeArray TypeInt arrOut j r      return_ @@ -249,14 +264,14 @@ -- atomically     :: IRArray (Vector Word8)-    -> IR Int-    -> CodeGen a-    -> CodeGen a+    -> Operands Int+    -> CodeGen Native a+    -> CodeGen Native a atomically barriers i action = do   let       lock      = integral integralType 1       unlock    = integral integralType 0-      unlocked  = lift 0+      unlocked  = ir TypeWord8 unlock   --   spin <- newBlock "spinlock.entry"   crit <- newBlock "spinlock.critical-section"@@ -269,7 +284,7 @@   -- was unlocked we just acquired it, otherwise the state remains unchanged and   -- we spin until it becomes available.   setBlock spin-  old  <- instr $ AtomicRMW integralType NonVolatile Exchange addr lock   (CrossThread, Acquire)+  old  <- instr $ AtomicRMW numType NonVolatile Exchange addr lock   (CrossThread, Acquire)   ok   <- A.eq singleType old unlocked   _    <- cbr ok crit spin @@ -279,7 +294,7 @@   -- rules.   setBlock crit   r    <- action-  _    <- instr $ AtomicRMW integralType NonVolatile Exchange addr unlock (CrossThread, Release)+  _    <- instr $ AtomicRMW numType NonVolatile Exchange addr unlock (CrossThread, Release)   _    <- br exit    setBlock exit@@ -289,18 +304,9 @@ -- Helper functions -- ---------------- --- Test whether the given index is the magic value 'ignore'. This operates--- strictly rather than performing short-circuit (&&).----ignore :: forall ix. Shape ix => IR ix -> CodeGen (IR Bool)-ignore (IR ix) = go (S.eltType (undefined::ix)) (S.fromElt (S.ignore::ix)) ix-  where-    go :: TupleType t -> t -> Operands t -> CodeGen (IR Bool)-    go TypeRunit           ()          OP_Unit        = return (lift True)-    go (TypeRpair tsh tsz) (ish, isz) (OP_Pair sh sz) = do x <- go tsh ish sh-                                                           y <- go tsz isz sz-                                                           land' x y-    go (TypeRscalar s)     ig         sz              = case s of-                                                          SingleScalarType t -> A.eq t (ir t (single t ig)) (ir t (op' t sz))-                                                          VectorScalarType{} -> $internalError "ignore" "unexpected shape type"+reprOut :: ArrayR (Array sh e) -> ShapeR sh' -> ArrayR (Array sh' e)+reprOut (ArrayR _ tp) shr = ArrayR shr tp++reprLock :: ArrayR (Array ((), Int) Word8)+reprLock = ArrayR (ShapeRsnoc ShapeRz) $ TupRsingle scalarTypeWord8 
src/Data/Array/Accelerate/LLVM/Native/CodeGen/Scan.hs view
@@ -3,14 +3,15 @@ {-# LANGUAGE RebindableSyntax    #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-} {-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Scan--- Copyright   : [2014..2017] Trevor L. McDonell+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -18,18 +19,17 @@ module Data.Array.Accelerate.LLVM.Native.CodeGen.Scan   where --- accelerate-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.AST                                    ( Direction(..) )+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type import Data.Array.Accelerate.Type -import Data.Array.Accelerate.LLVM.Analysis.Match import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic                as A import Data.Array.Accelerate.LLVM.CodeGen.Array import Data.Array.Accelerate.LLVM.CodeGen.Base import Data.Array.Accelerate.LLVM.CodeGen.Environment import Data.Array.Accelerate.LLVM.CodeGen.Exp-import Data.Array.Accelerate.LLVM.CodeGen.IR                        ( IR ) import Data.Array.Accelerate.LLVM.CodeGen.Loop import Data.Array.Accelerate.LLVM.CodeGen.Monad import Data.Array.Accelerate.LLVM.CodeGen.Sugar@@ -47,59 +47,34 @@ import Prelude                                                      as P  -data Direction = L | R---- 'Data.List.scanl' style left-to-right exclusive scan, but with the--- restriction that the combination function must be associative to enable--- efficient parallel implementation.+-- 'Data.List.scanl' or 'Data.List.scanl1' style exclusive scan,+-- but with the restriction that the combination function must be associative+-- to enable efficient parallel implementation. -- -- > scanl (+) 10 (use $ fromList (Z :. 10) [0..]) -- > -- > ==> Array (Z :. 11) [10,10,11,13,16,20,25,31,38,46,55] ---mkScanl-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e))-mkScanl uid aenv combine seed arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = foldr1 (+++) <$> sequence [ mkScanS L uid aenv combine (Just seed) arr-                              , mkScanP L uid aenv combine (Just seed) arr-                              , mkScanFill uid aenv seed-                              ]-  ---  | otherwise-  = (+++) <$> mkScanS L uid aenv combine (Just seed) arr-          <*> mkScanFill uid aenv seed----- 'Data.List.scanl1' style left-to-right inclusive scan, but with the--- restriction that the combination function must be associative to enable--- efficient parallel implementation. The array must not be empty.------ > scanl1 (+) (use $ fromList (Z :. 10) [0..])--- >--- > ==> Array (Z :. 10) [0,1,3,6,10,15,21,28,36,45]----mkScanl1-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e))-mkScanl1 uid aenv combine arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = (+++) <$> mkScanS L uid aenv combine Nothing arr-          <*> mkScanP L uid aenv combine Nothing arr-  ---  | otherwise-  = mkScanS L uid aenv combine Nothing arr-+mkScan+    :: UID+    -> Gamma             aenv+    -> ArrayR                   (Array (sh, Int) e)+    -> Direction+    -> IRFun2       Native aenv (e -> e -> e)+    -> Maybe (IRExp Native aenv e)+    -> MIRDelayed   Native aenv (Array (sh, Int) e)+    -> CodeGen      Native      (IROpenAcc Native aenv (Array (sh, Int) e))+mkScan uid aenv aR dir combine seed arr+  = foldr1 (+++) <$> sequence (codeScanS ++ codeScanP ++ codeScanFill)+  where+    codeScanS = [ mkScanS dir uid aenv aR combine seed arr ]+    codeScanP = case aR of+      ArrayR (ShapeRsnoc ShapeRz) eR -> [ mkScanP dir uid aenv eR combine seed arr ]+      _                              -> []+    -- Input can be empty iff a seed is given. We then need to compile a fill kernel+    codeScanFill = case seed of+      Just s  -> [ mkScanFill uid aenv aR s ]+      Nothing -> []  -- Variant of 'scanl' where the final result is returned in a separate array. --@@ -109,126 +84,46 @@ --       , Array Z [55] --       ) ---mkScanl'-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e, Array sh e))-mkScanl' uid aenv combine seed arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = foldr1 (+++) <$> sequence [ mkScan'S L uid aenv combine seed arr-                              , mkScan'P L uid aenv combine seed arr-                              , mkScan'Fill uid aenv seed-                              ]-  ---  | otherwise-  = (+++) <$> mkScan'S L uid aenv combine seed arr-          <*> mkScan'Fill uid aenv seed----- 'Data.List.scanr' style right-to-left exclusive scan, but with the--- restriction that the combination function must be associative to enable--- efficient parallel implementation.------ > scanr (+) 10 (use $ fromList (Z :. 10) [0..])--- >--- > ==> Array (Z :. 11) [55,55,54,52,49,45,40,34,27,19,10]----mkScanr-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e))-mkScanr uid aenv combine seed arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = foldr1 (+++) <$> sequence [ mkScanS R uid aenv combine (Just seed) arr-                              , mkScanP R uid aenv combine (Just seed) arr-                              , mkScanFill uid aenv seed-                              ]-  ---  | otherwise-  = (+++) <$> mkScanS R uid aenv combine (Just seed) arr-          <*> mkScanFill uid aenv seed----- 'Data.List.scanr1' style right-to-left inclusive scan, but with the--- restriction that the combination function must be associative to enable--- efficient parallel implementation. The array must not be empty.------ > scanr (+) 10 (use $ fromList (Z :. 10) [0..])--- >--- > ==> Array (Z :. 10) [45,45,44,42,39,35,30,24,17,9]----mkScanr1-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e))-mkScanr1 uid aenv combine arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = (+++) <$> mkScanS R uid aenv combine Nothing arr-          <*> mkScanP R uid aenv combine Nothing arr-  ---  | otherwise-  = mkScanS R uid aenv combine Nothing arr----- Variant of 'scanr' where the final result is returned in a separate array.------ > scanr' (+) 10 (use $ fromList (Z :. 10) [0..])--- >--- > ==> ( Array (Z :. 10) [55,54,52,49,45,40,34,27,19,10]---       , Array Z [55]---       )----mkScanr'-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma            aenv-    -> IRFun2    Native aenv (e -> e -> e)-    -> IRExp     Native aenv e-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e, Array sh e))-mkScanr' uid aenv combine seed arr-  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)-  = foldr1 (+++) <$> sequence [ mkScan'S R uid aenv combine seed arr-                              , mkScan'P R uid aenv combine seed arr-                              , mkScan'Fill uid aenv seed+mkScan'+    :: UID+    -> Gamma             aenv+    -> ArrayR                 (Array (sh, Int) e)+    -> Direction+    -> IRFun2     Native aenv (e -> e -> e)+    -> IRExp      Native aenv e+    -> MIRDelayed Native aenv (Array (sh, Int) e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array (sh, Int) e, Array sh e))+mkScan' uid aenv aR dir combine seed arr+  | ArrayR (ShapeRsnoc ShapeRz) eR <- aR+  = foldr1 (+++) <$> sequence [ mkScan'S dir uid aenv aR combine seed arr+                              , mkScan'P dir uid aenv eR combine seed arr+                              , mkScan'Fill uid aenv aR seed                               ]   --   | otherwise-  = (+++) <$> mkScan'S R uid aenv combine seed arr-          <*> mkScan'Fill uid aenv seed-+  = (+++) <$> mkScan'S dir uid aenv aR combine seed arr+          <*> mkScan'Fill uid aenv aR seed  -- If the innermost dimension of an exclusive scan is empty, then we just fill -- the result with the seed element. -- mkScanFill-    :: (Shape sh, Elt e)-    => UID-    -> Gamma aenv-    -> IRExp Native aenv e-    -> CodeGen (IROpenAcc Native aenv (Array sh e))-mkScanFill uid aenv seed =-  mkGenerate uid aenv (IRFun1 (const seed))+    :: UID+    -> Gamma          aenv+    -> ArrayR (Array sh e)+    -> IRExp   Native aenv e+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh e))+mkScanFill uid aenv aR seed =+  mkGenerate uid aenv aR (IRFun1 (const seed))  mkScan'Fill-    :: forall aenv sh e. (Shape sh, Elt e)-    => UID-    -> Gamma aenv-    -> IRExp Native aenv e-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e, Array sh e))-mkScan'Fill uid aenv seed =-  Safe.coerce <$> (mkScanFill uid aenv seed :: CodeGen (IROpenAcc Native aenv (Array sh e)))+    :: UID+    -> Gamma          aenv+    -> ArrayR (Array (sh, Int) e)+    -> IRExp   Native aenv e+    -> CodeGen Native     (IROpenAcc Native aenv (Array (sh, Int) e, Array sh e))+mkScan'Fill uid aenv aR seed =+  Safe.coerce <$> mkScanFill uid aenv (reduceRank aR) seed   -- A single thread sequentially scans along an entire innermost dimension. For@@ -239,162 +134,159 @@ -- where threads are scheduled over the outer dimensions (segments). -- mkScanS-    :: forall aenv sh e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> Maybe (IRExp Native aenv e)-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e))-mkScanS dir uid aenv combine mseed IRDelayed{..} =+    -> Gamma             aenv+    -> ArrayR (Array (sh, Int) e)+    -> IRFun2     Native aenv (e -> e -> e)+    -> MIRExp     Native aenv e+    -> MIRDelayed Native aenv (Array (sh, Int) e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array (sh, Int) e))+mkScanS dir uid aenv aR combine mseed marr =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array (sh:.Int) e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam shR+      (arrOut, paramOut)      = mutableArray aR "out"+      (arrIn,  paramIn)       = delayedArray    "in"  marr+      paramEnv                = envParam aenv+      ShapeRsnoc shR          = arrayRshape aR       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)   in-  makeOpenAcc uid "scanS" (paramGang ++ paramOut ++ paramEnv) $ do+  makeOpenAcc uid "scanS" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do -    sz    <- indexHead <$> delayedExtent-    szp1  <- A.add numType sz (lift 1)-    szm1  <- A.sub numType sz (lift 1)+    -- The dimensions of the input and output arrays are (almost) the same+    -- but LLVM can't know that so make it explicit so that we reuse loop+    -- variables and index calculations+    shIn <- delayedExtent arrIn+    let sz    = indexHead shIn+        shOut = case mseed of+                  Nothing -> shIn+                  Just{}  -> indexCons (indexTail shIn) (indexHead (irArrayShape arrOut)) -    -- loop over each lower-dimensional index (segment)-    imapFromTo start end $ \seg -> do+    -- Loop over the outer dimensions+    imapNestFromTo shR start end (indexTail shIn) $ \ix _ -> do        -- index i* is the index that we will read data from. Recall that the       -- supremum index is exclusive       i0 <- case dir of-              L -> A.mul numType sz seg-              R -> do x <- A.mul numType sz seg-                      y <- A.add numType szm1 x-                      return y+              LeftToRight -> return (liftInt 0)+              RightToLeft -> A.sub numType sz (liftInt 1)        -- index j* is the index that we write to. Recall that for exclusive scans       -- the output array inner dimension is one larger than the input.       j0 <- case mseed of               Nothing -> return i0        -- merge 'i' and 'j' indices whenever we can               Just{}  -> case dir of-                           L -> A.mul numType szp1 seg-                           R -> do x <- A.mul numType szp1 seg-                                   y <- A.add numType x sz-                                   return y+                           LeftToRight -> return i0+                           RightToLeft -> return sz        -- Evaluate or read the initial element. Update the read-from index       -- appropriately.       (v0,i1) <- case mseed of-                   Just seed -> (,) <$> seed                       <*> pure i0-                   Nothing   -> (,) <$> app1 delayedLinearIndex i0 <*> next i0+                   Just seed -> (,) <$> seed                                        <*> pure i0+                   Nothing   -> (,) <$> app1 (delayedIndex arrIn) (indexCons ix i0) <*> next i0 -      -- Write first element, then continue looping through the rest-      writeArray arrOut j0 v0+      -- Write first element, then continue looping through the rest of+      -- this innermost dimension+      k0 <- intOfIndex (arrayRshape aR) shOut (indexCons ix j0)       j1 <- next j0--      iz <- case dir of-              L -> A.add numType i0 sz-              R -> A.sub numType i0 sz--      let cont i = case dir of-                     L -> A.lt singleType i iz-                     R -> A.gt singleType i iz+      writeArray TypeInt arrOut k0 v0 -      void $ while (cont . A.fst3)-                   (\(A.untrip -> (i,j,v)) -> do-                       u  <- app1 delayedLinearIndex i-                       v' <- case dir of-                               L -> app2 combine v u-                               R -> app2 combine u v-                       writeArray arrOut j v'-                       A.trip <$> next i <*> next j <*> pure v')+      void $ while (TupRunit `TupRpair` TupRsingle scalarTypeInt `TupRpair` TupRsingle scalarTypeInt `TupRpair` arrayRtype aR)+                   (\(A.untrip -> (i,_,_)) -> do+                       case dir of+                         LeftToRight -> A.lt  singleType i sz+                         RightToLeft -> A.gte singleType i (liftInt 0))+                   (\(A.untrip -> (i,j,u)) -> do+                       v <- app1 (delayedIndex arrIn) (indexCons ix i)+                       w <- case dir of+                              LeftToRight -> app2 combine u v+                              RightToLeft -> app2 combine v u+                       k <- intOfIndex (arrayRshape aR) shOut (indexCons ix j)+                       writeArray TypeInt arrOut k w+                       A.trip <$> next i <*> next j <*> pure w)                    (A.trip i1 j1 v0)      return_   mkScan'S-    :: forall aenv sh e. (Shape sh, Elt e)-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> IRExp Native aenv e-    -> IRDelayed Native aenv (Array (sh:.Int) e)-    -> CodeGen (IROpenAcc Native aenv (Array (sh:.Int) e, Array sh e))-mkScan'S dir uid aenv combine seed IRDelayed{..} =+    -> Gamma             aenv+    -> ArrayR (Array (sh, Int) e)+    -> IRFun2     Native aenv (e -> e -> e)+    -> IRExp      Native aenv e+    -> MIRDelayed Native aenv (Array (sh, Int) e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Array (sh, Int) e, Array sh e))+mkScan'S dir uid aenv aR combine seed marr =   let-      (start, end, paramGang)   = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Array (sh:.Int) e))-      (arrSum, paramSum)        = mutableArray ("sum" :: Name (Array sh e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    shR+      (arrOut, paramOut)      = mutableArray aR              "out"+      (arrSum, paramSum)      = mutableArray (reduceRank aR) "sum"+      (arrIn,  paramIn)       = delayedArray "in" marr+      paramEnv                = envParam aenv+      ShapeRsnoc shR          = arrayRshape aR       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)   in-  makeOpenAcc uid "scanS" (paramGang ++ paramOut ++ paramSum ++ paramEnv) $ do+  makeOpenAcc uid "scanS" (paramGang ++ paramOut ++ paramSum ++ paramIn ++ paramEnv) $ do -    sz    <- indexHead <$> delayedExtent-    szm1  <- A.sub numType sz (lift 1)+    shIn  <- delayedExtent arrIn+    let sz    = indexHead shIn+        shOut = shIn -    -- iterate over each lower-dimensional index (segment)-    imapFromTo start end $ \seg -> do+    imapNestFromTo shR start end (indexTail shIn) $ \ix ii -> do        -- index to read data from       i0 <- case dir of-              L -> A.mul numType seg sz-              R -> do x <- A.mul numType sz seg-                      y <- A.add numType x szm1-                      return y+              LeftToRight -> return (liftInt 0)+              RightToLeft -> A.sub numType sz (liftInt 1)        -- initial element       v0 <- seed -      iz <- case dir of-              L -> A.add numType i0 sz-              R -> A.sub numType i0 sz--      let cont i  = case dir of-                      L -> A.lt singleType i iz-                      R -> A.gt singleType i iz-       -- Loop through the input. Only at the top of the loop to we write the       -- carry-in value (i.e. value from the last loop iteration) to the output       -- array. This ensures correct behaviour if the input array was empty.-      r  <- while (cont . A.fst)-                  (\(A.unpair -> (i,v)) -> do-                      writeArray arrOut i v+      r  <- while (TupRsingle scalarTypeInt `TupRpair` arrayRtype aR)+                  (\(A.unpair -> (i,_)) -> do+                      case dir of+                        LeftToRight -> A.lt  singleType i sz+                        RightToLeft -> A.gte singleType i (liftInt 0))+                  (\(A.unpair -> (i,u)) -> do+                      k <- intOfIndex (arrayRshape aR) shOut (indexCons ix i)+                      writeArray TypeInt arrOut k u -                      u  <- app1 delayedLinearIndex i-                      v' <- case dir of-                              L -> app2 combine v u-                              R -> app2 combine u v-                      i' <- next i-                      return $ A.pair i' v')+                      v <- app1 (delayedIndex arrIn) (indexCons ix i)+                      w <- case dir of+                             LeftToRight -> app2 combine u v+                             RightToLeft -> app2 combine v u+                      A.pair <$> next i <*> pure w)                   (A.pair i0 v0) -      -- write final reduction result-      writeArray arrSum seg (A.snd r)+      writeArray TypeInt arrSum ii (A.snd r)      return_   mkScanP-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> Maybe (IRExp Native aenv e)-    -> IRDelayed Native aenv (Vector e)-    -> CodeGen (IROpenAcc Native aenv (Vector e))-mkScanP dir uid aenv combine mseed arr =-  foldr1 (+++) <$> sequence [ mkScanP1 dir uid aenv combine mseed arr-                            , mkScanP2 dir uid aenv combine-                            , mkScanP3 dir uid aenv combine mseed+    -> Gamma             aenv+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)+    -> MIRExp     Native aenv e+    -> MIRDelayed Native aenv (Vector e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Vector e))+mkScanP dir uid aenv eR combine mseed marr =+  foldr1 (+++) <$> sequence [ mkScanP1 dir uid aenv eR combine mseed marr+                            , mkScanP2 dir uid aenv eR combine+                            , mkScanP3 dir uid aenv eR combine mseed                             ]  -- Parallel scan, step 1.@@ -404,36 +296,35 @@ -- result of this chunk is written to a separate array. -- mkScanP1-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> Maybe (IRExp Native aenv e)-    -> IRDelayed Native aenv (Vector e)-    -> CodeGen (IROpenAcc Native aenv (Vector e))-mkScanP1 dir uid aenv combine mseed IRDelayed{..} =+    -> Gamma             aenv+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)+    -> MIRExp     Native aenv e+    -> MIRDelayed Native aenv (Vector e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Vector e))+mkScanP1 dir uid aenv eR combine mseed marr =   let-      (chunk, _, paramGang)     = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Vector e))-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrOut, paramOut)      = mutableArray (ArrayR dim1 eR) "out"+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      (arrIn,  paramIn)       = delayedArray "in" marr+      paramEnv                = envParam aenv       ---      steps                     = local           scalarType ("ix.steps"  :: Name Int)-      paramSteps                = scalarParameter scalarType ("ix.steps"  :: Name Int)-      stride                    = local           scalarType ("ix.stride" :: Name Int)-      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)+      steps                   = local     (TupRsingle scalarTypeInt) "ix.steps"+      paramSteps              = parameter (TupRsingle scalarTypeInt) "ix.steps"+      piece                   = local     (TupRsingle scalarTypeInt) "ix.piece"+      paramPiece              = parameter (TupRsingle scalarTypeInt) "ix.piece"       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)-      firstChunk                = case dir of-                                    L -> lift 0-                                    R -> steps+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)+      firstPiece              = case dir of+                                  LeftToRight -> liftInt 0+                                  RightToLeft -> steps   in-  makeOpenAcc uid "scanP1" (paramGang ++ paramStride : paramSteps : paramOut ++ paramTmp ++ paramEnv) $ do--    len <- indexHead <$> delayedExtent+  makeOpenAcc uid "scanP1" (paramGang ++ paramPiece ++ paramSteps ++ paramOut ++ paramTmp ++ paramIn ++ paramEnv) $ do      -- A thread scans a non-empty stripe of the input, storing the final     -- reduction result into a separate array.@@ -441,59 +332,57 @@     -- For exclusive scans the first chunk must incorporate the initial element     -- into the input and output, while all other chunks increment their output     -- index by one.-    inf <- A.mul numType    chunk stride-    a   <- A.add numType    inf   stride-    sup <- A.min singleType a     len-+    --     -- index i* is the index that we read data from. Recall that the supremum     -- index is exclusive     i0  <- case dir of-             L -> return inf-             R -> next sup+             LeftToRight -> return (indexHead start)+             RightToLeft -> next (indexHead end)      -- index j* is the index that we write to. Recall that for exclusive scan-    -- the output array is one larger than the input; the first chunk uses+    -- the output array is one larger than the input; the first piece uses     -- this spot to write the initial element, all other chunks shift by one.     j0  <- case mseed of              Nothing -> return i0              Just _  -> case dir of-                          L -> if A.eq singleType chunk firstChunk-                                 then return i0-                                 else next i0-                          R -> if A.eq singleType chunk firstChunk-                                 then return sup-                                 else return i0+                          LeftToRight -> if (TupRsingle scalarTypeInt, A.eq singleType piece firstPiece)+                                         then return i0+                                         else next i0+                          RightToLeft -> if (TupRsingle scalarTypeInt, A.eq singleType piece firstPiece)+                                         then return (indexHead end)+                                         else return i0 -    -- Evaluate/read the initial element for this chunk. Update the read-from+    -- Evaluate/read the initial element for this piece. Update the read-from     -- index appropriately     (v0,i1) <- A.unpair <$> case mseed of-                 Just seed -> if A.eq singleType chunk firstChunk-                                then A.pair <$> seed                       <*> pure i0-                                else A.pair <$> app1 delayedLinearIndex i0 <*> next i0-                 Nothing   ->        A.pair <$> app1 delayedLinearIndex i0 <*> next i0+                 Just seed -> if (eR `TupRpair` TupRsingle scalarTypeInt, A.eq singleType piece firstPiece)+                                then A.pair <$> seed                               <*> pure i0+                                else A.pair <$> app1 (delayedLinearIndex arrIn) i0 <*> next i0+                 Nothing   ->        A.pair <$> app1 (delayedLinearIndex arrIn) i0 <*> next i0      -- Write first element-    writeArray arrOut j0 v0+    writeArray TypeInt arrOut j0 v0     j1  <- next j0      -- Continue looping through the rest of the input     let cont i =            case dir of-             L -> A.lt  singleType i sup-             R -> A.gte singleType i inf+             LeftToRight -> A.lt  singleType i (indexHead end)+             RightToLeft -> A.gte singleType i (indexHead start) -    r   <- while (cont . A.fst3)+    r   <- while (TupRunit `TupRpair` TupRsingle scalarTypeInt `TupRpair` TupRsingle scalarTypeInt `TupRpair` eR)+                 (cont . A.fst3)                  (\(A.untrip -> (i,j,v)) -> do-                     u  <- app1 delayedLinearIndex i+                     u  <- app1 (delayedLinearIndex arrIn) i                      v' <- case dir of-                             L -> app2 combine v u-                             R -> app2 combine u v-                     writeArray arrOut j v'+                             LeftToRight -> app2 combine v u+                             RightToLeft -> app2 combine u v+                     writeArray TypeInt arrOut j v'                      A.trip <$> next i <*> next j <*> pure v')                  (A.trip i1 j1 v0) -    -- Final reduction result of this chunk-    writeArray arrTmp chunk (A.thd3 r)+    -- Final reduction result of this piece+    writeArray TypeInt arrTmp piece (A.thd3 r)      return_ @@ -505,43 +394,44 @@ -- results in the final step. -- mkScanP2-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> CodeGen (IROpenAcc Native aenv (Vector e))-mkScanP2 dir uid aenv combine =+    -> Gamma          aenv+    -> TypeR e+    -> IRFun2  Native aenv (e -> e -> e)+    -> CodeGen Native      (IROpenAcc Native aenv (Vector e))+mkScanP2 dir uid aenv eR combine =   let-      (start, end, paramGang)   = gangParam-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      paramEnv                = envParam aenv       ---      cont i                    = case dir of-                                    L -> A.lt  singleType i end-                                    R -> A.gte singleType i start+      cont i                  = case dir of+                                  LeftToRight -> A.lt  singleType i (indexHead end)+                                  RightToLeft -> A.gte singleType i (indexHead start) -      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)   in   makeOpenAcc uid "scanP2" (paramGang ++ paramTmp ++ paramEnv) $ do      i0 <- case dir of-            L -> return start-            R -> next end+            LeftToRight -> return (indexHead start)+            RightToLeft -> next (indexHead end) -    v0 <- readArray arrTmp i0+    v0 <- readArray TypeInt arrTmp i0     i1 <- next i0 -    void $ while (cont . A.fst)+    void $ while (TupRsingle scalarTypeInt `TupRpair` eR)+                 (cont . A.fst)                  (\(A.unpair -> (i,v)) -> do-                    u  <- readArray arrTmp i+                    u  <- readArray TypeInt arrTmp i                     i' <- next i                     v' <- case dir of-                            L -> app2 combine v u-                            R -> app2 combine u v-                    writeArray arrTmp i v'+                            LeftToRight -> app2 combine v u+                            RightToLeft -> app2 combine u v+                    writeArray TypeInt arrTmp i v'                     return $ A.pair i' v')                  (A.pair i1 v0) @@ -553,165 +443,158 @@ -- Threads combine every element of the partial block results with the carry-in -- value computed from step 2. ----- Note that we launch (chunks-1) threads, because the first chunk does not need--- extra processing (has no carry-in value).+-- Note that first chunk does not need extra processing (has no carry-in value). -- mkScanP3-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID     -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> Maybe (IRExp Native aenv e)-    -> CodeGen (IROpenAcc Native aenv (Vector e))-mkScanP3 dir uid aenv combine mseed =+    -> TypeR e+    -> IRFun2  Native aenv (e -> e -> e)+    -> MIRExp  Native aenv e+    -> CodeGen Native      (IROpenAcc Native aenv (Vector e))+mkScanP3 dir uid aenv eR combine mseed =   let-      (chunk, _, paramGang)     = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Vector e))-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrOut, paramOut)      = mutableArray (ArrayR dim1 eR) "out"+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      paramEnv                = envParam aenv       ---      stride                    = local           scalarType ("ix.stride" :: Name Int)-      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)+      steps                   = local     (TupRsingle scalarTypeInt) "ix.steps"+      paramSteps              = parameter (TupRsingle scalarTypeInt) "ix.steps"+      piece                   = local     (TupRsingle scalarTypeInt) "ix.piece"+      paramPiece              = parameter (TupRsingle scalarTypeInt) "ix.piece"       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)-      prev i                    = case dir of-                                    L -> A.sub numType i (lift 1)-                                    R -> A.add numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)+      prev i                  = case dir of+                                  LeftToRight -> A.sub numType i (liftInt 1)+                                  RightToLeft -> A.add numType i (liftInt 1)+      firstPiece              = case dir of+                                  LeftToRight -> liftInt 0+                                  RightToLeft -> steps   in-  makeOpenAcc uid "scanP3" (paramGang ++ paramStride : paramOut ++ paramTmp ++ paramEnv) $ do--    -- Determine which chunk will be carrying in values for. Compute appropriate-    -- start and end indices.-    a     <- case dir of-               L -> next chunk-               R -> pure chunk+  makeOpenAcc uid "scanP3" (paramGang ++ paramPiece ++ paramSteps ++ paramOut ++ paramTmp ++ paramEnv) $ do -    b     <- A.mul numType    a stride-    c     <- A.add numType    b stride-    d     <- A.min singleType c (indexHead (irArrayShape arrOut))+    -- TODO: Don't schedule the "first" piece. In the scheduler this corresponds+    -- to the split range with the smallest/largest linear index for left/right+    -- scans respectively. For right scans this is not necessarily the last piece(?).+    --+    A.when (neq singleType piece firstPiece) $ do -    (inf,sup) <- case (dir,mseed) of-                   (L,Just _) -> (,) <$> next b <*> next d-                   _          -> (,) <$> pure b <*> pure d+      -- Compute start and end indices, leaving space for the initial element+      (inf,sup) <- case (dir, mseed) of+                     (LeftToRight, Just{}) -> (,) <$> next (indexHead start) <*> next (indexHead end)+                     _                     -> (,) <$> pure (indexHead start) <*> pure (indexHead end) -    -- Carry in value from the previous chunk-    e     <- case dir of-               L -> pure chunk-               R -> prev chunk-    carry <- readArray arrTmp e+      -- Read in the carry in value for this piece+      c <- readArray TypeInt arrTmp =<< prev piece -    imapFromTo inf sup $ \i -> do-      x <- readArray arrOut i-      y <- case dir of-             L -> app2 combine carry x-             R -> app2 combine x carry-      writeArray arrOut i y+      imapFromTo inf sup $ \i -> do+        x <- readArray TypeInt arrOut i+        y <- case dir of+               LeftToRight -> app2 combine c x+               RightToLeft -> app2 combine x c+        writeArray TypeInt arrOut i y      return_   mkScan'P-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> IRExp Native aenv e-    -> IRDelayed Native aenv (Vector e)-    -> CodeGen (IROpenAcc Native aenv (Vector e, Scalar e))-mkScan'P dir uid aenv combine seed arr =-  foldr1 (+++) <$> sequence [ mkScan'P1 dir uid aenv combine seed arr-                            , mkScan'P2 dir uid aenv combine-                            , mkScan'P3 dir uid aenv combine+    -> Gamma             aenv+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)+    -> IRExp      Native aenv e+    -> MIRDelayed Native aenv (Vector e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Vector e, Scalar e))+mkScan'P dir uid aenv eR combine seed arr =+  foldr1 (+++) <$> sequence [ mkScan'P1 dir uid aenv eR combine seed arr+                            , mkScan'P2 dir uid aenv eR combine+                            , mkScan'P3 dir uid aenv eR combine                             ]  -- Parallel scan', step 1 -- -- Threads scan a stripe of the input into a temporary array. Similar to--- exclusive scan, but since the size of the output array is the same as the--- input, input and output indices are shifted by one.+-- exclusive scan, the output indices are shifted by one relative to the input+-- indices to make space for the initial element. -- mkScan'P1-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> IRExp Native aenv e-    -> IRDelayed Native aenv (Vector e)-    -> CodeGen (IROpenAcc Native aenv (Vector e, Scalar e))-mkScan'P1 dir uid aenv combine seed IRDelayed{..} =+    -> Gamma             aenv+    -> TypeR e+    -> IRFun2     Native aenv (e -> e -> e)+    -> IRExp      Native aenv e+    -> MIRDelayed Native aenv (Vector e)+    -> CodeGen    Native      (IROpenAcc Native aenv (Vector e, Scalar e))+mkScan'P1 dir uid aenv eR combine seed marr =   let-      (chunk, _, paramGang)     = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Vector e))-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrOut, paramOut)      = mutableArray (ArrayR dim1 eR) "out"+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      (arrIn,  paramIn)       = delayedArray "in" marr+      paramEnv                = envParam aenv       ---      steps                     = local           scalarType ("ix.steps"  :: Name Int)-      paramSteps                = scalarParameter scalarType ("ix.steps"  :: Name Int)-      stride                    = local           scalarType ("ix.stride" :: Name Int)-      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)+      steps                   = local     (TupRsingle scalarTypeInt) "ix.steps"+      paramSteps              = parameter (TupRsingle scalarTypeInt) "ix.steps"+      piece                   = local     (TupRsingle scalarTypeInt) "ix.piece"+      paramPiece              = parameter (TupRsingle scalarTypeInt) "ix.piece"       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1) -      firstChunk                = case dir of-                                    L -> lift 0-                                    R -> steps+      firstPiece              = case dir of+                                  LeftToRight -> liftInt 0+                                  RightToLeft -> steps   in-  makeOpenAcc uid "scanP1" (paramGang ++ paramStride : paramSteps : paramOut ++ paramTmp ++ paramEnv) $ do--    -- Compute the start and end indices for this non-empty chunk of the input.-    ---    len <- indexHead <$> delayedExtent-    inf <- A.mul numType    chunk stride-    a   <- A.add numType    inf   stride-    sup <- A.min singleType a     len+  makeOpenAcc uid "scanP1" (paramGang ++ paramPiece ++ paramSteps ++ paramOut ++ paramTmp ++ paramIn ++ paramEnv) $ do      -- index i* is the index that we pull data from.     i0 <- case dir of-            L -> return inf-            R -> next sup+            LeftToRight -> return (indexHead start)+            RightToLeft -> next (indexHead end) -    -- index j* is the index that we write results to. The first chunk needs to+    -- index j* is the index that we write results to. The first piece needs to     -- include the initial element, and all other chunks shift their results     -- across by one to make space.-    j0      <- if A.eq singleType chunk firstChunk+    j0      <- if (TupRsingle scalarTypeInt, A.eq singleType piece firstPiece)                  then pure i0                  else next i0      -- Evaluate/read the initial element. Update the read-from index     -- appropriately.-    (v0,i1) <- A.unpair <$> if A.eq singleType chunk firstChunk-                              then A.pair <$> seed                       <*> pure i0-                              else A.pair <$> app1 delayedLinearIndex i0 <*> pure j0+    (v0,i1) <- A.unpair <$> if (eR `TupRpair` TupRsingle scalarTypeInt, A.eq singleType piece firstPiece)+                              then A.pair <$> seed                               <*> pure i0+                              else A.pair <$> app1 (delayedLinearIndex arrIn) i0 <*> pure j0      -- Write the first element-    writeArray arrOut j0 v0+    writeArray TypeInt arrOut j0 v0     j1 <- next j0      -- Continue looping through the rest of the input     let cont i =            case dir of-             L -> A.lt  singleType i sup-             R -> A.gte singleType i inf+             LeftToRight -> A.lt  singleType i (indexHead end)+             RightToLeft -> A.gte singleType i (indexHead start) -    r  <- while (cont . A.fst3)+    r  <- while (TupRunit `TupRpair` TupRsingle scalarTypeInt `TupRpair` TupRsingle scalarTypeInt `TupRpair` eR)+                (cont . A.fst3)                 (\(A.untrip-> (i,j,v)) -> do-                    u  <- app1 delayedLinearIndex i+                    u  <- app1 (delayedLinearIndex arrIn) i                     v' <- case dir of-                            L -> app2 combine v u-                            R -> app2 combine u v-                    writeArray arrOut j v'+                            LeftToRight -> app2 combine v u+                            RightToLeft -> app2 combine u v+                    writeArray TypeInt arrOut j v'                     A.trip <$> next i <*> next j <*> pure v')                 (A.trip i1 j1 v0) -    -- Write the final reduction result of this chunk-    writeArray arrTmp chunk (A.thd3 r)+    -- Write the final reduction result of this piece+    writeArray TypeInt arrTmp piece (A.thd3 r)      return_ @@ -722,48 +605,49 @@ -- array (rather than discard it). -- mkScan'P2-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> CodeGen (IROpenAcc Native aenv (Vector e, Scalar e))-mkScan'P2 dir uid aenv combine =+    -> Gamma          aenv+    -> TypeR e+    -> IRFun2  Native aenv (e -> e -> e)+    -> CodeGen Native      (IROpenAcc Native aenv (Vector e, Scalar e))+mkScan'P2 dir uid aenv eR combine =   let-      (start, end, paramGang)   = gangParam-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      (arrSum, paramSum)        = mutableArray ("sum" :: Name (Scalar e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      (arrSum, paramSum)      = mutableArray (ArrayR dim0 eR) "sum"+      paramEnv                = envParam aenv       ---      cont i                    = case dir of-                                    L -> A.lt  singleType i end-                                    R -> A.gte singleType i start+      cont i                  = case dir of+                                  LeftToRight -> A.lt  singleType i (indexHead end)+                                  RightToLeft -> A.gte singleType i (indexHead start) -      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)   in   makeOpenAcc uid "scanP2" (paramGang ++ paramSum ++ paramTmp ++ paramEnv) $ do      i0 <- case dir of-            L -> return start-            R -> next end+            LeftToRight -> return (indexHead start)+            RightToLeft -> next (indexHead end) -    v0 <- readArray arrTmp i0+    v0 <- readArray TypeInt arrTmp i0     i1 <- next i0 -    r  <- while (cont . A.fst)+    r  <- while (TupRpair (TupRsingle scalarTypeInt) eR)+                (cont . A.fst)                 (\(A.unpair -> (i,v)) -> do-                   u  <- readArray arrTmp i+                   u  <- readArray TypeInt arrTmp i                    i' <- next i                    v' <- case dir of-                           L -> app2 combine v u-                           R -> app2 combine u v-                   writeArray arrTmp i v'+                           LeftToRight -> app2 combine v u+                           RightToLeft -> app2 combine u v+                   writeArray TypeInt arrTmp i v'                    return $ A.pair i' v')                 (A.pair i1 v0) -    writeArray arrSum (lift 0 :: IR Int) (A.snd r)+    writeArray TypeInt arrSum (liftInt 0) (A.snd r)      return_ @@ -773,61 +657,58 @@ -- Similar to mkScanP3, except that indices are shifted by one since the output -- array is the same size as the input (despite being an exclusive scan). ----- Launch (chunks-1) threads, because the first chunk does not need extra--- processing.+-- Note that the first chunk does not need to do any extra processing (has no+-- carry-in value). -- mkScan'P3-    :: forall aenv e. Elt e-    => Direction+    :: Direction     -> UID-    -> Gamma aenv-    -> IRFun2 Native aenv (e -> e -> e)-    -> CodeGen (IROpenAcc Native aenv (Vector e, Scalar e))-mkScan'P3 dir uid aenv combine =+    -> Gamma          aenv+    -> TypeR e+    -> IRFun2  Native aenv (e -> e -> e)+    -> CodeGen Native      (IROpenAcc Native aenv (Vector e, Scalar e))+mkScan'P3 dir uid aenv eR combine =   let-      (chunk, _, paramGang)     = gangParam-      (arrOut, paramOut)        = mutableArray ("out" :: Name (Vector e))-      (arrTmp, paramTmp)        = mutableArray ("tmp" :: Name (Vector e))-      paramEnv                  = envParam aenv+      (start, end, paramGang) = gangParam    dim1+      (arrOut, paramOut)      = mutableArray (ArrayR dim1 eR) "out"+      (arrTmp, paramTmp)      = mutableArray (ArrayR dim1 eR) "tmp"+      paramEnv                = envParam aenv       ---      stride                    = local           scalarType ("ix.stride" :: Name Int)-      paramStride               = scalarParameter scalarType ("ix.stride" :: Name Int)+      steps                   = local     (TupRsingle scalarTypeInt) "ix.steps"+      paramSteps              = parameter (TupRsingle scalarTypeInt) "ix.steps"+      piece                   = local     (TupRsingle scalarTypeInt) "ix.piece"+      paramPiece              = parameter (TupRsingle scalarTypeInt) "ix.piece"       ---      next i                    = case dir of-                                    L -> A.add numType i (lift 1)-                                    R -> A.sub numType i (lift 1)-      prev i                    = case dir of-                                    L -> A.sub numType i (lift 1)-                                    R -> A.add numType i (lift 1)+      next i                  = case dir of+                                  LeftToRight -> A.add numType i (liftInt 1)+                                  RightToLeft -> A.sub numType i (liftInt 1)+      prev i                  = case dir of+                                  LeftToRight -> A.sub numType i (liftInt 1)+                                  RightToLeft -> A.add numType i (liftInt 1)+      firstPiece              = case dir of+                                  LeftToRight -> liftInt 0+                                  RightToLeft -> steps   in-  makeOpenAcc uid "scanP3" (paramGang ++ paramStride : paramOut ++ paramTmp ++ paramEnv) $ do--    -- Determine which chunk we will be carrying in the values of, and compute-    -- the appropriate start and end indices-    a     <- case dir of-               L -> next chunk-               R -> pure chunk--    b     <- A.mul numType a stride-    c     <- A.add numType b stride-    d     <- A.min singleType c (indexHead (irArrayShape arrOut))+  makeOpenAcc uid "scanP3" (paramGang ++ paramPiece ++ paramSteps ++ paramOut ++ paramTmp ++ paramEnv) $ do -    inf   <- next b-    sup   <- next d+    -- TODO: don't schedule the "first" piece.+    --+    A.when (neq singleType piece firstPiece) $ do -    -- Carry-value from the previous chunk-    e     <- case dir of-               L -> pure chunk-               R -> prev chunk+      -- Compute start and end indices, leaving space for the initial element+      inf <- next (indexHead start)+      sup <- next (indexHead end) -    carry <- readArray arrTmp e+      -- Read the carry-in value for this piece+      c   <- readArray TypeInt arrTmp =<< prev piece -    imapFromTo inf sup $ \i -> do-      x <- readArray arrOut i-      y <- case dir of-             L -> app2 combine carry x-             R -> app2 combine x carry-      writeArray arrOut i y+      -- Apply the carry-in value to all elements of the output+      imapFromTo inf sup $ \i -> do+        x <- readArray TypeInt arrOut i+        y <- case dir of+               LeftToRight -> app2 combine c x+               RightToLeft -> app2 combine x c+        writeArray TypeInt arrOut i y      return_ 
+ src/Data/Array/Accelerate/LLVM/Native/CodeGen/Stencil.hs view
@@ -0,0 +1,217 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeApplications    #-}+-- |+-- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Stencil+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.LLVM.Native.CodeGen.Stencil (++  mkStencil1,+  mkStencil2,++) where++import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Stencil+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.LLVM.CodeGen.Arithmetic+import Data.Array.Accelerate.LLVM.CodeGen.Array+import Data.Array.Accelerate.LLVM.CodeGen.Base+import Data.Array.Accelerate.LLVM.CodeGen.Environment+import Data.Array.Accelerate.LLVM.CodeGen.Exp+import Data.Array.Accelerate.LLVM.CodeGen.IR+import Data.Array.Accelerate.LLVM.CodeGen.Loop                      hiding ( imapFromStepTo )+import Data.Array.Accelerate.LLVM.CodeGen.Monad+import Data.Array.Accelerate.LLVM.CodeGen.Stencil+import Data.Array.Accelerate.LLVM.CodeGen.Sugar+import Data.Array.Accelerate.LLVM.Compile.Cache++import Data.Array.Accelerate.LLVM.Native.CodeGen.Base+import Data.Array.Accelerate.LLVM.Native.CodeGen.Loop+import Data.Array.Accelerate.LLVM.Native.Target                     ( Native )++import qualified LLVM.AST.Global                                    as LLVM++import Control.Monad+++-- The stencil function is similar to a map, but has access to surrounding+-- elements as specified by the stencil pattern.+--+-- This generates two functions:+--+--  * stencil_inside: does not apply boundary conditions, assumes all element+--                    accesses are valid+--+--  * stencil_border: applies boundary condition check to each array access+--+mkStencil1+    :: UID+    -> Gamma              aenv+    -> StencilR sh a stencil+    -> TypeR b+    -> IRFun1      Native aenv (stencil -> b)+    -> IRBoundary  Native aenv (Array sh a)+    -> MIRDelayed  Native aenv (Array sh a)+    -> CodeGen     Native      (IROpenAcc Native aenv (Array sh b))+mkStencil1 uid aenv sr tp f bnd marr =+  let (arrIn, paramIn) = delayedArray "in" marr+      repr = ArrayR (stencilShapeR sr) tp+   in (+++) <$> mkInside uid aenv repr (IRFun1 $ app1 f <=< stencilAccess sr Nothing    arrIn) paramIn+            <*> mkBorder uid aenv repr (IRFun1 $ app1 f <=< stencilAccess sr (Just bnd) arrIn) paramIn++mkStencil2+    :: UID+    -> Gamma              aenv+    -> StencilR sh a stencil1+    -> StencilR sh b stencil2+    -> TypeR c+    -> IRFun2      Native aenv (stencil1 -> stencil2 -> c)+    -> IRBoundary  Native aenv (Array sh a)+    -> MIRDelayed  Native aenv (Array sh a)+    -> IRBoundary  Native aenv (Array sh b)+    -> MIRDelayed  Native aenv (Array sh b)+    -> CodeGen     Native      (IROpenAcc Native aenv (Array sh c))+mkStencil2 uid aenv sr1 sr2 tp f bnd1 marr1 bnd2 marr2 =+  let+      (arrIn1, paramIn1)  = delayedArray "in1" marr1+      (arrIn2, paramIn2)  = delayedArray "in2" marr2++      repr = ArrayR (stencilShapeR sr1) tp++      inside  = IRFun1 $ \ix -> do+        stencil1 <- stencilAccess sr1 Nothing arrIn1 ix+        stencil2 <- stencilAccess sr2 Nothing arrIn2 ix+        app2 f stencil1 stencil2+      --+      border  = IRFun1 $ \ix -> do+        stencil1 <- stencilAccess sr1 (Just bnd1) arrIn1 ix+        stencil2 <- stencilAccess sr2 (Just bnd2) arrIn2 ix+        app2 f stencil1 stencil2+  in+  (+++) <$> mkInside uid aenv repr inside (paramIn1 ++ paramIn2)+        <*> mkBorder uid aenv repr border (paramIn1 ++ paramIn2)+++mkInside+    :: UID+    -> Gamma aenv+    -> ArrayR (Array sh e)+    -> IRFun1  Native aenv (sh -> e)+    -> [LLVM.Parameter]+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh e))+mkInside uid aenv repr apply paramIn =+  let+      (start, end, paramGang)   = gangParam    (arrayRshape repr)+      (arrOut, paramOut)        = mutableArray repr "out"+      paramEnv                  = envParam aenv+      shOut                     = irArrayShape arrOut+  in+  makeOpenAcc uid "stencil_inside" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do++    imapNestFromToTile (arrayRshape repr) 4 start end shOut $ \ix i -> do+      r <- app1 apply ix                        -- apply generator function+      writeArray TypeInt arrOut i r                     -- store result++    return_++mkBorder+    :: UID+    -> Gamma aenv+    -> ArrayR (Array sh e)+    -> IRFun1  Native aenv (sh -> e)+    -> [LLVM.Parameter]+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh e))+mkBorder uid aenv repr apply paramIn =+  let+      (start, end, paramGang)   = gangParam    (arrayRshape repr)+      (arrOut, paramOut)        = mutableArray repr "out"+      paramEnv                  = envParam aenv+      shOut                     = irArrayShape arrOut+  in+  makeOpenAcc uid "stencil_border" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do++    imapNestFromTo (arrayRshape repr) start end shOut $ \ix i -> do+      r <- app1 apply ix                        -- apply generator function+      writeArray TypeInt arrOut i r             -- store result++    return_+++imapNestFromToTile+    :: ShapeR sh+    -> Int                                                  -- ^ unroll amount (tile height)+    -> Operands sh                                          -- ^ initial index (inclusive)+    -> Operands sh                                          -- ^ final index (exclusive)+    -> Operands sh                                          -- ^ total array extent+    -> (Operands sh -> Operands Int -> CodeGen Native ())   -- ^ apply at each index+    -> CodeGen Native ()+imapNestFromToTile shr unroll start end extent body =+  go shr start end body'+  where+    body' ix = body ix =<< intOfIndex shr extent ix++    go :: ShapeR t+       -> Operands t+       -> Operands t+       -> (Operands t -> CodeGen Native ())+       -> CodeGen Native ()+    go ShapeRz OP_Unit OP_Unit k+      = k OP_Unit++    -- To correctly generate the unrolled loop nest we need to explicitly match+    -- on the last two dimensions.+    --+    go (ShapeRsnoc (ShapeRsnoc ShapeRz)) (OP_Pair (OP_Pair OP_Unit sy) sx) (OP_Pair (OP_Pair OP_Unit ey) ex) k+      = do+          -- Tile the stencil operator in the xy-plane by unrolling in the+          -- y-dimension and vectorising in the x-dimension.+          --+          sy' <- imapFromStepTo sy (liftInt unroll) ey $ \iy ->+                  imapFromTo    sx                  ex $ \ix ->+                    forM_ [0 .. unroll-1] $ \n -> do+                    iy' <- add numType iy (liftInt n)+                    k (OP_Pair (OP_Pair OP_Unit iy') ix)++          -- Take care of any remaining loop iterations in the y-dimension+          --+          _       <- imapFromTo  sy' ey $ \iy ->+                      imapFromTo sx  ex $ \ix ->+                        k (OP_Pair (OP_Pair OP_Unit iy) ix)+          return ()++    -- The 1- and 3+-dimensional cases can recurse normally+    --+    go (ShapeRsnoc shr') (OP_Pair ssh ssz) (OP_Pair esh esz) k+      = go shr' ssh esh+      $ \sz      -> imapFromTo ssz esz+      $ \i       -> k (OP_Pair sz i)++imapFromStepTo+    :: Operands Int+    -> Operands Int+    -> Operands Int+    -> (Operands Int -> CodeGen Native ())+    -> CodeGen Native (Operands Int)+imapFromStepTo start step end body =+  let+      incr i = add numType i step+      test i = do i' <- incr i+                  lt singleType i' end+  in+  while (TupRsingle scalarTypeInt) test+        (\i -> body i >> incr i)+        start+
+ src/Data/Array/Accelerate/LLVM/Native/CodeGen/Transform.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+-- |+-- Module      : Data.Array.Accelerate.LLVM.Native.CodeGen.Transform+-- Copyright   : [2014..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.LLVM.Native.CodeGen.Transform+  where++-- accelerate+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.LLVM.CodeGen.Array+import Data.Array.Accelerate.LLVM.CodeGen.Base+import Data.Array.Accelerate.LLVM.CodeGen.Environment+import Data.Array.Accelerate.LLVM.CodeGen.Exp+import Data.Array.Accelerate.LLVM.CodeGen.Monad+import Data.Array.Accelerate.LLVM.CodeGen.Sugar+import Data.Array.Accelerate.LLVM.Compile.Cache++import Data.Array.Accelerate.LLVM.Native.Target                     ( Native )+import Data.Array.Accelerate.LLVM.Native.CodeGen.Base+import Data.Array.Accelerate.LLVM.Native.CodeGen.Loop+++-- Hybrid map/backpermute operation+--+mkTransform+    :: UID+    -> Gamma aenv+    -> ArrayR (Array sh  a)+    -> ArrayR (Array sh' b)+    -> IRFun1  Native aenv (sh' -> sh)+    -> IRFun1  Native aenv (a -> b)+    -> CodeGen Native      (IROpenAcc Native aenv (Array sh' b))+mkTransform uid aenv reprIn reprOut p f =+  let+      (start, end, paramGang)   = gangParam (arrayRshape reprOut)+      (arrIn,  paramIn)         = mutableArray reprIn  "in"+      (arrOut, paramOut)        = mutableArray reprOut "out"+      paramEnv                  = envParam aenv+      shIn                      = irArrayShape arrIn+      shOut                     = irArrayShape arrOut+  in+  makeOpenAcc uid "transform" (paramGang ++ paramOut ++ paramIn ++ paramEnv) $ do++    imapNestFromTo (arrayRshape reprOut) start end shOut $ \ix' i' -> do+      ix  <- app1 p ix'+      i   <- intOfIndex (arrayRshape reprIn) shIn ix+      a   <- readArray TypeInt arrIn i+      b   <- app1 f a+      writeArray TypeInt arrOut i' b++    return_+
src/Data/Array/Accelerate/LLVM/Native/Compile.hs view
@@ -3,11 +3,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Compile--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -19,14 +18,8 @@  ) where --- llvm-hs-import LLVM.AST                                                     hiding ( Module )-import LLVM.Module                                                  as LLVM hiding ( Module )-import LLVM.Context-import LLVM.Target---- accelerate-import Data.Array.Accelerate.Trafo                                  ( DelayedOpenAcc )+import Data.Array.Accelerate.AST                                    ( PreOpenAcc )+import Data.Array.Accelerate.Trafo.Delayed  import Data.Array.Accelerate.LLVM.CodeGen import Data.Array.Accelerate.LLVM.Compile@@ -41,7 +34,11 @@ import Data.Array.Accelerate.LLVM.Native.Target import qualified Data.Array.Accelerate.LLVM.Native.Debug            as Debug --- standard library+import LLVM.AST                                                     hiding ( Module )+import LLVM.Module                                                  as LLVM hiding ( Module )+import LLVM.Context+import LLVM.Target+ import Control.Monad.State import Data.ByteString                                              ( ByteString ) import Data.ByteString.Short                                        ( ShortByteString )@@ -67,15 +64,19 @@  -- | Compile an Accelerate expression to object code ---compile :: DelayedOpenAcc aenv a -> Gamma aenv -> LLVM Native (ObjectR Native)-compile acc aenv = do-  target            <- gets llvmTarget-  (uid, cacheFile)  <- cacheOfOpenAcc acc+compile :: PreOpenAcc DelayedOpenAcc aenv a -> Gamma aenv -> LLVM Native (ObjectR Native)+compile pacc aenv = do    -- Generate code for this Acc operation   ---  let Module ast md = llvmOfOpenAcc target uid acc aenv-      triple        = fromMaybe BS.empty (moduleTargetTriple ast)+  -- We require the metadata result, which will give us the names of the+  -- functions which will be contained in the object code, but the actual+  -- code generation step is executed lazily.+  --+  (uid, cacheFile)  <- cacheOfPreOpenAcc pacc+  Module ast md     <- llvmOfPreOpenAcc uid pacc aenv++  let triple        = fromMaybe BS.empty (moduleTargetTriple ast)       datalayout    = moduleDataLayout ast       nms           = [ f | Name f <- Map.keys md ] 
src/Data/Array/Accelerate/LLVM/Native/Compile/Cache.hs view
@@ -2,10 +2,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Compile.Cache--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Compile/Optimise.hs view
@@ -1,10 +1,9 @@ -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Compile.Optimise--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Debug.hs view
@@ -2,11 +2,10 @@ {-# LANGUAGE TypeOperators #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Debug--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
− src/Data/Array/Accelerate/LLVM/Native/Distribution/Simple.hs
@@ -1,65 +0,0 @@--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Distribution.Simple--- Copyright   : [2017] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.LLVM.Native.Distribution.Simple (--  defaultMain,-  simpleUserHooks,-  module Distribution.Simple,--) where--import Data.Array.Accelerate.LLVM.Native.Distribution.Simple.Build--import Distribution.PackageDescription                              ( PackageDescription )-import Distribution.Simple.Setup                                    ( BuildFlags )-import Distribution.Simple.LocalBuildInfo                           ( LocalBuildInfo )-import Distribution.Simple.PreProcess                               ( PPSuffixHandler, knownSuffixHandlers )-import Distribution.Simple                                          hiding ( defaultMain, simpleUserHooks )-import qualified Distribution.Simple                                as Cabal--import Data.List                                                    ( unionBy )----- | A simple implementation of @main@ for a Cabal setup script. This is the--- same as 'Distribution.Simple.defaultMain', with added support for building--- libraries utilising 'Data.Array.Accelerate.LLVM.Native.runQ'*.----defaultMain :: IO ()-defaultMain = Cabal.defaultMainWithHooks simpleUserHooks----- | Hooks that correspond to a plain instantiation of the \"simple\" build--- system.----simpleUserHooks :: UserHooks-simpleUserHooks =-  Cabal.simpleUserHooks-    { buildHook = accelerateBuildHook-    }--accelerateBuildHook-    :: PackageDescription-    -> LocalBuildInfo-    -> UserHooks-    -> BuildFlags-    -> IO ()-accelerateBuildHook pkg_descr localbuildinfo hooks flags =-  build pkg_descr localbuildinfo flags (allSuffixHandlers hooks)---- | Combine the preprocessors in the given hooks with the--- preprocessors built into cabal.-allSuffixHandlers :: UserHooks -> [PPSuffixHandler]-allSuffixHandlers hooks-    = overridesPP (hookedPreProcessors hooks) knownSuffixHandlers-    where-      overridesPP :: [PPSuffixHandler] -> [PPSuffixHandler] -> [PPSuffixHandler]-      overridesPP = unionBy (\x y -> fst x == fst y)-
− src/Data/Array/Accelerate/LLVM/Native/Distribution/Simple/Build.hs
@@ -1,467 +0,0 @@-{-# LANGUAGE CPP #-}--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Distribution.Simple.Build--- Copyright   : [2017] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ Copied from: https://github.com/haskell/cabal/blob/2.0/Cabal/Distribution/Simple/Build.hs-----module Data.Array.Accelerate.LLVM.Native.Distribution.Simple.Build (--  build,--) where--import qualified Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC as Acc--import qualified Distribution.Simple.Build as Cabal--import Distribution.Types.Dependency-import Distribution.Types.LocalBuildInfo-import Distribution.Types.TargetInfo-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ForeignLib-import Distribution.Types.MungedPackageId-import Distribution.Types.MungedPackageName-import Distribution.Types.UnqualComponentName-import Distribution.Types.ComponentLocalBuildInfo-import Distribution.Types.ExecutableScope--import Distribution.Package-import Distribution.Backpack-import Distribution.Backpack.DescribeUnitId-import qualified Distribution.Simple.GHC   as GHC-import qualified Distribution.Simple.GHCJS as GHCJS-import qualified Distribution.Simple.UHC   as UHC-import qualified Distribution.Simple.HaskellSuite as HaskellSuite-import qualified Distribution.Simple.PackageIndex as Index--import qualified Distribution.Simple.Program.HcPkg as HcPkg--import Distribution.Simple.Compiler hiding (Flag)-import Distribution.PackageDescription hiding (Flag)-import qualified Distribution.InstalledPackageInfo as IPI-import Distribution.InstalledPackageInfo (InstalledPackageInfo)--import Distribution.Simple.Setup-import Distribution.Simple.BuildTarget-import Distribution.Simple.BuildToolDepends-import Distribution.Simple.PreProcess-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Db-import Distribution.Simple.BuildPaths-import Distribution.Simple.Configure-import Distribution.Simple.Register-import Distribution.Simple.Test.LibV09-import Distribution.Simple.Utils--import Distribution.Text-#if MIN_VERSION_Cabal(2,4,0)-import Distribution.System (buildPlatform, Platform)-#else-import Distribution.System (buildPlatform)-#endif-import Distribution.Verbosity--import Distribution.Compat.Graph (IsNode(..))--import Control.Monad-import qualified Data.Set as Set-import System.FilePath ( (</>), (<.>) )-import System.Directory ( getCurrentDirectory )---build    :: PackageDescription  -- ^ Mostly information from the .cabal file-         -> LocalBuildInfo      -- ^ Configuration information-         -> BuildFlags          -- ^ Flags that the user passed to build-         -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling-         -> IO ()-build pkg_descr lbi flags suffixes = do-  targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)-  let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)-  info verbosity $ "Component build order: "-                ++ intercalate ", "-                    (map (showComponentName . componentLocalName . targetCLBI)-                        componentsToBuild)--  when (null targets) $-    -- Only bother with this message if we're building the whole package-    setupMessage verbosity "Building" (packageId pkg_descr)--  internalPackageDB <- createInternalPackageDB verbosity lbi distPref--  (\f -> foldM_ f (installedPkgs lbi) componentsToBuild) $ \index target -> do-    let comp = targetComponent target-        clbi = targetCLBI target-    Cabal.componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity-    let bi     = componentBuildInfo comp-        progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)-        lbi'   = lbi {-                   withPrograms  = progs',-                   withPackageDB = withPackageDB lbi ++ [internalPackageDB],-                   installedPkgs = index-                 }-    mb_ipi <- buildComponent verbosity (buildNumJobs flags) pkg_descr-                   lbi' suffixes comp clbi distPref-    return (maybe index (Index.insert `flip` index) mb_ipi)-  return ()- where-  distPref  = fromFlag (buildDistPref flags)-  verbosity = fromFlag (buildVerbosity flags)---buildComponent :: Verbosity-               -> Flag (Maybe Int)-               -> PackageDescription-               -> LocalBuildInfo-               -> [PPSuffixHandler]-               -> Component-               -> ComponentLocalBuildInfo-               -> FilePath-               -> IO (Maybe InstalledPackageInfo)-buildComponent verbosity numJobs pkg_descr lbi suffixes-               comp@(CLib lib) clbi distPref = do-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    extras <- preprocessExtras verbosity comp lbi-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    let libbi = libBuildInfo lib-        lib' = lib { libBuildInfo = addExtraCSources libbi extras }-    buildLib verbosity numJobs pkg_descr lbi lib' clbi--    let oneComponentRequested (OneComponentRequestedSpec _) = True-        oneComponentRequested _ = False-    -- Don't register inplace if we're only building a single component;-    -- it's not necessary because there won't be any subsequent builds-    -- that need to tag us-    if (not (oneComponentRequested (componentEnabledSpec lbi)))-      then do-        -- Register the library in-place, so exes can depend-        -- on internally defined libraries.-        pwd <- getCurrentDirectory-        let -- The in place registration uses the "-inplace" suffix, not an ABI hash-            installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr-                                    -- NB: Use a fake ABI hash to avoid-                                    -- needing to recompute it every build.-                                    (mkAbiHash "inplace") lib' lbi clbi--        debug verbosity $ "Registering inplace:\n" ++ (IPI.showInstalledPackageInfo installedPkgInfo)-        registerPackage verbosity (compiler lbi) (withPrograms lbi)-                        (withPackageDB lbi) installedPkgInfo-                        HcPkg.defaultRegisterOptions {-                          HcPkg.registerMultiInstance = True-                        }-        return (Just installedPkgInfo)-      else return Nothing--buildComponent verbosity numJobs pkg_descr lbi suffixes-               comp@(CFLib flib) clbi _distPref = do-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    buildFLib verbosity numJobs pkg_descr lbi flib clbi-    return Nothing--buildComponent verbosity numJobs pkg_descr lbi suffixes-               comp@(CExe exe) clbi _ = do-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    extras <- preprocessExtras verbosity comp lbi-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    let ebi = buildInfo exe-        exe' = exe { buildInfo = addExtraCSources ebi extras }-    buildExe verbosity numJobs pkg_descr lbi exe' clbi-    return Nothing---buildComponent verbosity numJobs pkg_descr lbi suffixes-               comp@(CTest test@TestSuite { testInterface = TestSuiteExeV10{} })-               clbi _distPref = do-    let exe = testSuiteExeV10AsExe test-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    extras <- preprocessExtras verbosity comp lbi-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    let ebi = buildInfo exe-        exe' = exe { buildInfo = addExtraCSources ebi extras }-    buildExe verbosity numJobs pkg_descr lbi exe' clbi-    return Nothing---buildComponent verbosity numJobs pkg_descr lbi0 suffixes-               comp@(CTest-                 test@TestSuite { testInterface = TestSuiteLibV09{} })-               clbi -- This ComponentLocalBuildInfo corresponds to a detailed-                    -- test suite and not a real component. It should not-                    -- be used, except to construct the CLBIs for the-                    -- library and stub executable that will actually be-                    -- built.-               distPref = do-    pwd <- getCurrentDirectory-    let (pkg, lib, libClbi, lbi, ipi, exe, exeClbi) =-          testSuiteLibV09AsLibAndExe pkg_descr test clbi lbi0 distPref pwd-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    extras <- preprocessExtras verbosity comp lbi-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    buildLib verbosity numJobs pkg lbi lib libClbi-    -- NB: need to enable multiple instances here, because on 7.10+-    -- the package name is the same as the library, and we still-    -- want the registration to go through.-    registerPackage verbosity (compiler lbi) (withPrograms lbi)-                    (withPackageDB lbi) ipi-                    HcPkg.defaultRegisterOptions {-                      HcPkg.registerMultiInstance = True-                    }-    let ebi = buildInfo exe-        exe' = exe { buildInfo = addExtraCSources ebi extras }-    buildExe verbosity numJobs pkg_descr lbi exe' exeClbi-    return Nothing -- Can't depend on test suite---buildComponent verbosity _ _ _ _-               (CTest TestSuite { testInterface = TestSuiteUnsupported tt })-               _ _ =-    die' verbosity $ "No support for building test suite type " ++ display tt---buildComponent verbosity numJobs pkg_descr lbi suffixes-               comp@(CBench bm@Benchmark { benchmarkInterface = BenchmarkExeV10 {} })-               clbi _ = do-    let (exe, exeClbi) = benchmarkExeV10asExe bm clbi-    preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes-    extras <- preprocessExtras verbosity comp lbi-    setupMessage' verbosity "Building" (packageId pkg_descr)-      (componentLocalName clbi) (maybeComponentInstantiatedWith clbi)-    let ebi = buildInfo exe-        exe' = exe { buildInfo = addExtraCSources ebi extras }-    buildExe verbosity numJobs pkg_descr lbi exe' exeClbi-    return Nothing---buildComponent verbosity _ _ _ _-               (CBench Benchmark { benchmarkInterface = BenchmarkUnsupported tt })-               _ _ =-    die' verbosity $ "No support for building benchmark type " ++ display tt------ | Add extra C sources generated by preprocessing to build--- information.-addExtraCSources :: BuildInfo -> [FilePath] -> BuildInfo-addExtraCSources bi extras = bi { cSources = new }-  where new = Set.toList $ old `Set.union` exs-        old = Set.fromList $ cSources bi-        exs = Set.fromList extras----- | Translate a exe-style 'TestSuite' component into an exe for building-testSuiteExeV10AsExe :: TestSuite -> Executable-testSuiteExeV10AsExe test@TestSuite { testInterface = TestSuiteExeV10 _ mainFile } =-    Executable {-      exeName    = testName test,-      modulePath = mainFile,-      exeScope   = ExecutablePublic,-      buildInfo  = testBuildInfo test-    }-testSuiteExeV10AsExe TestSuite{} = error "testSuiteExeV10AsExe: wrong kind"--#if MIN_VERSION_Cabal(2,4,0)-setBuildDepends :: [Dependency] -> PackageDescription -> PackageDescription-setBuildDepends deps pkg_descr@PackageDescription{ setupBuildInfo = Just buildInfo'}-  = pkg_descr { setupBuildInfo = Just (buildInfo' {setupDepends = deps})}-setBuildDepends deps pkg_descr@PackageDescription{ setupBuildInfo = Nothing}-  = pkg_descr-    { setupBuildInfo = Just (SetupBuildInfo {setupDepends = deps, defaultSetupDepends = True})-    }-exeExtension' :: Platform -> String-exeExtension' = exeExtension-#else-setBuildDepends :: [Dependency] -> PackageDescription -> PackageDescription-setBuildDepends deps pkg_descr = pkg_descr {buildDepends = deps}-exeExtension' :: a -> String-exeExtension' _ = exeExtension-#endif----- | Translate a lib-style 'TestSuite' component into a lib + exe for building-testSuiteLibV09AsLibAndExe :: PackageDescription-                           -> TestSuite-                           -> ComponentLocalBuildInfo-                           -> LocalBuildInfo-                           -> FilePath-                           -> FilePath-                           -> (PackageDescription,-                               Library, ComponentLocalBuildInfo,-                               LocalBuildInfo,-                               IPI.InstalledPackageInfo,-                               Executable, ComponentLocalBuildInfo)-testSuiteLibV09AsLibAndExe pkg_descr-                     test@TestSuite { testInterface = TestSuiteLibV09 _ m }-                     clbi lbi distPref pwd =-    (pkg, lib, libClbi, lbi, ipi, exe, exeClbi)-  where-    bi  = testBuildInfo test-    lib = Library {-            libName = Nothing,-            exposedModules = [ m ],-            reexportedModules = [],-            signatures = [],-            libExposed     = True,-            libBuildInfo   = bi-          }-    -- This is, like, the one place where we use a CTestName for a library.-    -- Should NOT use library name, since that could conflict!-    PackageIdentifier pkg_name pkg_ver = package pkg_descr-    compat_name = computeCompatPackageName pkg_name (Just (testName test))-    compat_key = computeCompatPackageKey (compiler lbi) compat_name pkg_ver (componentUnitId clbi)-    libClbi = LibComponentLocalBuildInfo-                { componentPackageDeps = componentPackageDeps clbi-                , componentInternalDeps = componentInternalDeps clbi-                , componentIsIndefinite_ = False-                , componentExeDeps = componentExeDeps clbi-                , componentLocalName = CSubLibName (testName test)-                , componentIsPublic = False-                , componentIncludes = componentIncludes clbi-                , componentUnitId = componentUnitId clbi-                , componentComponentId = componentComponentId clbi-                , componentInstantiatedWith = []-                , componentCompatPackageName = compat_name-                , componentCompatPackageKey = compat_key-                , componentExposedModules = [IPI.ExposedModule m Nothing]-                }-    pkg = setBuildDepends (targetBuildDepends $ testBuildInfo test) $ pkg_descr {-            package      = (package pkg_descr) { pkgName = mkPackageName $ unMungedPackageName compat_name }-          , executables  = []-          , testSuites   = []-          , subLibraries = [lib]-          }-    ipi    = inplaceInstalledPackageInfo pwd distPref pkg (mkAbiHash "") lib lbi libClbi-    testDir = buildDir lbi </> stubName test-          </> stubName test ++ "-tmp"-    testLibDep = thisPackageVersion $ package pkg-    exe = Executable {-            exeName    = mkUnqualComponentName $ stubName test,-            modulePath = stubFilePath test,-            exeScope   = ExecutablePublic,-            buildInfo  = (testBuildInfo test) {-                           hsSourceDirs       = [ testDir ],-                           targetBuildDepends = testLibDep-                             : (targetBuildDepends $ testBuildInfo test)-                         }-          }-    -- | The stub executable needs a new 'ComponentLocalBuildInfo'-    -- that exposes the relevant test suite library.-    deps = (IPI.installedUnitId ipi, mungedId ipi)-         : (filter (\(_, x) -> let name = unMungedPackageName $ mungedName x-                               in name == "Cabal" || name == "base")-                   (componentPackageDeps clbi))-    exeClbi = ExeComponentLocalBuildInfo {-                -- TODO: this is a hack, but as long as this is unique-                -- (doesn't clobber something) we won't run into trouble-                componentUnitId = mkUnitId (stubName test),-                componentComponentId = mkComponentId (stubName test),-                componentInternalDeps = [componentUnitId clbi],-                componentExeDeps = [],-                componentLocalName = CExeName $ mkUnqualComponentName $ stubName test,-                componentPackageDeps = deps,-                -- Assert DefUnitId invariant!-                -- Executable can't be indefinite, so dependencies must-                -- be definite packages.-                componentIncludes = zip (map (DefiniteUnitId . unsafeMkDefUnitId . fst) deps)-                                        (repeat defaultRenaming)-              }-testSuiteLibV09AsLibAndExe _ TestSuite{} _ _ _ _ = error "testSuiteLibV09AsLibAndExe: wrong kind"----- | Translate a exe-style 'Benchmark' component into an exe for building-benchmarkExeV10asExe :: Benchmark -> ComponentLocalBuildInfo-                     -> (Executable, ComponentLocalBuildInfo)-benchmarkExeV10asExe bm@Benchmark { benchmarkInterface = BenchmarkExeV10 _ f }-                     clbi =-    (exe, exeClbi)-  where-    exe = Executable {-            exeName    = benchmarkName bm,-            modulePath = f,-            exeScope   = ExecutablePublic,-            buildInfo  = benchmarkBuildInfo bm-          }-    exeClbi = ExeComponentLocalBuildInfo {-                componentUnitId = componentUnitId clbi,-                componentComponentId = componentComponentId clbi,-                componentLocalName = CExeName (benchmarkName bm),-                componentInternalDeps = componentInternalDeps clbi,-                componentExeDeps = componentExeDeps clbi,-                componentPackageDeps = componentPackageDeps clbi,-                componentIncludes = componentIncludes clbi-              }-benchmarkExeV10asExe Benchmark{} _ = error "benchmarkExeV10asExe: wrong kind"----- | Initialize a new package db file for libraries defined--- internally to the package.-createInternalPackageDB :: Verbosity -> LocalBuildInfo -> FilePath-                        -> IO PackageDB-createInternalPackageDB verbosity lbi distPref = do-    existsAlready <- doesPackageDBExist dbPath-    when existsAlready $ deletePackageDB dbPath-    createPackageDB verbosity (compiler lbi) (withPrograms lbi) False dbPath-    return (SpecificPackageDB dbPath)-  where-    dbPath = internalPackageDBPath lbi distPref--addInternalBuildTools :: PackageDescription -> LocalBuildInfo -> BuildInfo-                      -> ProgramDb -> ProgramDb-addInternalBuildTools pkg lbi bi progs =-    foldr updateProgram progs internalBuildTools-  where-    internalBuildTools =-      [ simpleConfiguredProgram toolName' (FoundOnSystem toolLocation)-      | toolName <- getAllInternalToolDependencies pkg bi-      , let toolName' = unUnqualComponentName toolName-      , let toolLocation = buildDir lbi </> toolName' </> toolName' <.> exeExtension' buildPlatform ]----- TODO: build separate libs in separate dirs so that we can build--- multiple libs, e.g. for 'LibTest' library-style test suites-buildLib :: Verbosity -> Flag (Maybe Int)-                      -> PackageDescription -> LocalBuildInfo-                      -> Library            -> ComponentLocalBuildInfo -> IO ()-buildLib verbosity numJobs pkg_descr lbi lib clbi =-  case compilerFlavor (compiler lbi) of-    GHC   -> Acc.buildLib   verbosity numJobs pkg_descr lbi lib clbi    -- XXX only change here-    GHCJS -> GHCJS.buildLib verbosity numJobs pkg_descr lbi lib clbi-    UHC   -> UHC.buildLib   verbosity         pkg_descr lbi lib clbi-    HaskellSuite {} -> HaskellSuite.buildLib verbosity pkg_descr lbi lib clbi-    _    -> die' verbosity "Building is not supported with this compiler."---- | Build a foreign library------ NOTE: We assume that we already checked that we can actually build the--- foreign library in configure.-buildFLib :: Verbosity -> Flag (Maybe Int)-                       -> PackageDescription -> LocalBuildInfo-                       -> ForeignLib         -> ComponentLocalBuildInfo -> IO ()-buildFLib verbosity numJobs pkg_descr lbi flib clbi =-    case compilerFlavor (compiler lbi) of-      GHC -> GHC.buildFLib verbosity numJobs pkg_descr lbi flib clbi-      _   -> die' verbosity "Building is not supported with this compiler."--buildExe :: Verbosity -> Flag (Maybe Int)-                      -> PackageDescription -> LocalBuildInfo-                      -> Executable         -> ComponentLocalBuildInfo -> IO ()-buildExe verbosity numJobs pkg_descr lbi exe clbi =-  case compilerFlavor (compiler lbi) of-    GHC   -> GHC.buildExe   verbosity numJobs pkg_descr lbi exe clbi-    GHCJS -> GHCJS.buildExe verbosity numJobs pkg_descr lbi exe clbi-    UHC   -> UHC.buildExe   verbosity         pkg_descr lbi exe clbi-    _     -> die' verbosity "Building is not supported with this compiler."--
− src/Data/Array/Accelerate/LLVM/Native/Distribution/Simple/GHC.hs
@@ -1,458 +0,0 @@-{-# LANGUAGE CPP #-}--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC--- Copyright   : [2017] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ Copied from: https://github.com/haskell/cabal/blob/2.0/Cabal/Distribution/Simple/GHC.hs-----module Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC (--  buildLib,-  replLib,--) where--import qualified Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC.Internal as Internal-import qualified Data.Array.Accelerate.LLVM.Native.Plugin.BuildInfo                 as Internal--import qualified Distribution.Simple.GHC as Cabal-import Distribution.PackageDescription as PD-import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ComponentLocalBuildInfo-import qualified Distribution.Simple.Hpc as Hpc-import Distribution.Simple.BuildPaths-import Distribution.Simple.Utils-import qualified Distribution.ModuleName as ModuleName-import Distribution.Simple.Program-import qualified Distribution.Simple.Program.Ar    as Ar-import Distribution.Simple.Program.GHC-import Distribution.Simple.Setup-import qualified Distribution.Simple.Setup as Cabal-import Distribution.Simple.Compiler hiding (Flag)-import Distribution.Version-import Distribution.System-import Distribution.Verbosity-import Distribution.Text-import Distribution.Types.UnitId(UnitId)-import Distribution.Utils.NubList-import Language.Haskell.Extension--import Control.Monad (when, unless)-import Data.List (nub)-import Data.Maybe (catMaybes)-import System.FilePath ( (</>), replaceExtension, isRelative )-import qualified Data.Map as Map----- <https://github.com/haskell/cabal/blob/2.0/Cabal/Distribution/Simple/GHC.hs#L505>----buildLib, replLib :: Verbosity          -> Cabal.Flag (Maybe Int)-                  -> PackageDescription -> LocalBuildInfo-                  -> Library            -> ComponentLocalBuildInfo -> IO ()-buildLib = buildOrReplLib False-replLib  = buildOrReplLib True---#if MIN_VERSION_Cabal(2,4,0)-nubList :: a -> a-nubList = id--overNubListR' :: a -> a-overNubListR' = id--mkSharedLibName' :: Platform -> CompilerId -> UnitId -> String -mkSharedLibName' = mkSharedLibName-#else-nubList :: (Ord a) => [a] -> NubListR a-nubList = toNubListR--overNubListR' :: (Ord a) => ([a] -> [a]) -> NubListR a -> NubListR a-overNubListR' = overNubListR--mkSharedLibName' :: Platform -> CompilerId -> UnitId -> String -mkSharedLibName' _ compiler_uid path = mkSharedLibName compiler_uid path-#endif--buildOrReplLib :: Bool -> Verbosity  -> Cabal.Flag (Maybe Int)-               -> PackageDescription -> LocalBuildInfo-               -> Library            -> ComponentLocalBuildInfo -> IO ()-buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do-  let uid = componentUnitId clbi-      libTargetDir = componentBuildDir lbi clbi-      whenVanillaLib forceVanilla =-        when (forceVanilla || withVanillaLib lbi)-      whenProfLib = when (withProfLib lbi)-      whenSharedLib forceShared =-        when (forceShared || withSharedLib lbi)-      whenGHCiLib = when (withGHCiLib lbi && withVanillaLib lbi)-      ifReplLib = when forRepl-      comp = compiler lbi-      ghcVersion = compilerVersion comp-      implInfo  = Cabal.getImplInfo comp-      platform@(Platform _hostArch hostOS) = hostPlatform lbi-      has_code = not (componentIsIndefinite clbi)--  (ghcProg, _) <- requireProgram verbosity ghcProgram (withPrograms lbi)-  let runGhcProg = runGHC verbosity ghcProg comp platform--  libBi <- hackThreadedFlag verbosity-             comp (withProfLib lbi) (libBuildInfo lib)--  let isGhcDynamic        = Cabal.isDynamic comp-      dynamicTooSupported = supportsDynamicToo comp-      doingTH = EnableExtension TemplateHaskell `elem` allExtensions libBi-      forceVanillaLib = doingTH && not isGhcDynamic-      forceSharedLib  = doingTH &&     isGhcDynamic-      -- TH always needs default libs, even when building for profiling--  -- Determine if program coverage should be enabled and if so, what-  -- '-hpcdir' should be.-  let isCoverageEnabled = libCoverage lbi-      -- TODO: Historically HPC files have been put into a directory which-      -- has the package name.  I'm going to avoid changing this for-      -- now, but it would probably be better for this to be the-      -- component ID instead...-      pkg_name = display (PD.package pkg_descr)-      distPref = fromFlag $ configDistPref $ configFlags lbi-      hpcdir way-        | forRepl = mempty  -- HPC is not supported in ghci-        | isCoverageEnabled = toFlag $ Hpc.mixDir distPref way pkg_name-        | otherwise = mempty--  createDirectoryIfMissingVerbose verbosity True libTargetDir-  -- TODO: do we need to put hs-boot files into place for mutually recursive-  -- modules?-  let cObjs       = map (`replaceExtension` objExtension) (cSources libBi)-      baseOpts    = Cabal.componentGhcOptions verbosity lbi libBi clbi libTargetDir-      vanillaOpts = baseOpts `mappend` mempty {-                      ghcOptMode         = toFlag GhcModeMake,-                      ghcOptNumJobs      = numJobs,-                      ghcOptInputModules = toNubListR $ allLibModules lib clbi,-                      ghcOptHPCDir       = hpcdir Hpc.Vanilla-                    }--      profOpts    = vanillaOpts `mappend` mempty {-                      ghcOptProfilingMode = toFlag True,-                      ghcOptProfilingAuto = Internal.profDetailLevelFlag True-                                              (withProfLibDetail lbi),-                      ghcOptHiSuffix      = toFlag "p_hi",-                      ghcOptObjSuffix     = toFlag "p_o",-                      ghcOptExtra         = nubList $ hcProfOptions GHC libBi,-                      ghcOptHPCDir        = hpcdir Hpc.Prof-                    }--      sharedOpts  = vanillaOpts `mappend` mempty {-                      ghcOptDynLinkMode = toFlag GhcDynamicOnly,-                      ghcOptFPic        = toFlag True,-                      ghcOptHiSuffix    = toFlag "dyn_hi",-                      ghcOptObjSuffix   = toFlag "dyn_o",-                      ghcOptExtra       = nubList $ hcSharedOptions GHC libBi,-                      ghcOptHPCDir      = hpcdir Hpc.Dyn-                    }-      linkerOpts = mempty {-                      ghcOptLinkOptions       = nubList $ PD.ldOptions libBi,-                      ghcOptLinkLibs          = nubList $ extraLibs libBi,-                      ghcOptLinkLibPath       = toNubListR $ extraLibDirs libBi,-                      ghcOptLinkFrameworks    = toNubListR $-                                                PD.frameworks libBi,-                      ghcOptLinkFrameworkDirs = toNubListR $-                                                PD.extraFrameworkDirs libBi,-                      ghcOptInputFiles     = toNubListR-                                             [libTargetDir </> x | x <- cObjs]-                   }-      replOpts    = vanillaOpts {-                      ghcOptExtra        = overNubListR' Internal.filterGhciFlags $-                                           ghcOptExtra vanillaOpts,-                      ghcOptNumJobs      = mempty-                    }-                    `mappend` linkerOpts-                    `mappend` mempty {-                      ghcOptMode         = toFlag GhcModeInteractive,-                      ghcOptOptimisation = toFlag GhcNoOptimisation-                    }--      vanillaSharedOpts = vanillaOpts `mappend` mempty {-                      ghcOptDynLinkMode  = toFlag GhcStaticAndDynamic,-                      ghcOptDynHiSuffix  = toFlag "dyn_hi",-                      ghcOptDynObjSuffix = toFlag "dyn_o",-                      ghcOptHPCDir       = hpcdir Hpc.Dyn-                    }--  unless (forRepl || null (allLibModules lib clbi)) $-    do let vanilla = whenVanillaLib forceVanillaLib (runGhcProg vanillaOpts)-           shared  = whenSharedLib  forceSharedLib  (runGhcProg sharedOpts)-           useDynToo = dynamicTooSupported &&-                       (forceVanillaLib || withVanillaLib lbi) &&-                       (forceSharedLib  || withSharedLib  lbi) &&-                       null (hcSharedOptions GHC libBi)-       if not has_code-        then vanilla-        else-         if useDynToo-          then do-              runGhcProg vanillaSharedOpts-              case (hpcdir Hpc.Dyn, hpcdir Hpc.Vanilla) of-                (Cabal.Flag dynDir, Cabal.Flag vanillaDir) ->-                    -- When the vanilla and shared library builds are done-                    -- in one pass, only one set of HPC module interfaces-                    -- are generated. This set should suffice for both-                    -- static and dynamically linked executables. We copy-                    -- the modules interfaces so they are available under-                    -- both ways.-                    copyDirectoryRecursive verbosity dynDir vanillaDir-                _ -> return ()-          else if isGhcDynamic-            then do shared;  vanilla-            else do vanilla; shared-       when has_code $ whenProfLib (runGhcProg profOpts)--  -- build any C sources-  unless (not has_code || null (cSources libBi)) $ do-    info verbosity "Building C Sources..."-    sequence_-      [ do let baseCcOpts    = Cabal.componentCcGhcOptions verbosity-                               lbi libBi clbi libTargetDir filename-               vanillaCcOpts = if isGhcDynamic-                               -- Dynamic GHC requires C sources to be built-                               -- with -fPIC for REPL to work. See #2207.-                               then baseCcOpts { ghcOptFPic = toFlag True }-                               else baseCcOpts-               profCcOpts    = vanillaCcOpts `mappend` mempty {-                                 ghcOptProfilingMode = toFlag True,-                                 ghcOptObjSuffix     = toFlag "p_o"-                               }-               sharedCcOpts  = vanillaCcOpts `mappend` mempty {-                                 ghcOptFPic        = toFlag True,-                                 ghcOptDynLinkMode = toFlag GhcDynamicOnly,-                                 ghcOptObjSuffix   = toFlag "dyn_o"-                               }-               odir          = fromFlag (ghcOptObjDir vanillaCcOpts)-           createDirectoryIfMissingVerbose verbosity True odir-           let runGhcProgIfNeeded ccOpts = do-                 needsRecomp <- checkNeedsRecompilation filename ccOpts-                 when needsRecomp $ runGhcProg ccOpts-           runGhcProgIfNeeded vanillaCcOpts-           unless forRepl $-             whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCcOpts)-           unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)-      | filename <- cSources libBi]--  -- TODO: problem here is we need the .c files built first, so we can load them-  -- with ghci, but .c files can depend on .h files generated by ghc by ffi-  -- exports.--  when has_code . ifReplLib $ do-    when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"-    ifReplLib (runGhcProg replOpts)--  -- link:-  when has_code . unless forRepl $ do-    info verbosity "Linking..."-    let cProfObjs   = map (`replaceExtension` ("p_" ++ objExtension))-                      (cSources libBi)-        cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))-                      (cSources libBi)-        compiler_id = compilerId (compiler lbi)-        vanillaLibFilePath = libTargetDir </> mkLibName uid-        profileLibFilePath = libTargetDir </> mkProfLibName uid-        sharedLibFilePath  = libTargetDir </> mkSharedLibName' buildPlatform compiler_id uid-        ghciLibFilePath    = libTargetDir </> Internal.mkGHCiLibName uid-        libInstallPath = libdir $ absoluteComponentInstallDirs pkg_descr lbi uid NoCopyDest-        sharedLibInstallPath = libInstallPath </> mkSharedLibName' buildPlatform compiler_id uid--    stubObjs <- catMaybes <$> sequenceA-      [ findFileWithExtension [objExtension] [libTargetDir]-          (ModuleName.toFilePath x ++"_stub")-      | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files-      , x <- allLibModules lib clbi ]-    stubProfObjs <- catMaybes <$> sequenceA-      [ findFileWithExtension ["p_" ++ objExtension] [libTargetDir]-          (ModuleName.toFilePath x ++"_stub")-      | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files-      , x <- allLibModules lib clbi ]-    stubSharedObjs <- catMaybes <$> sequenceA-      [ findFileWithExtension ["dyn_" ++ objExtension] [libTargetDir]-          (ModuleName.toFilePath x ++"_stub")-      | ghcVersion < mkVersion [7,2] -- ghc-7.2+ does not make _stub.o files-      , x <- allLibModules lib clbi ]--    hObjs     <- Internal.getHaskellObjects implInfo lib lbi clbi-                      libTargetDir objExtension True-    hProfObjs <--      if withProfLib lbi-              then Internal.getHaskellObjects implInfo lib lbi clbi-                      libTargetDir ("p_" ++ objExtension) True-              else return []-    hSharedObjs <--      if withSharedLib lbi-              then Internal.getHaskellObjects implInfo lib lbi clbi-                      libTargetDir ("dyn_" ++ objExtension) False-              else return []--    -- XXX: This is the only change; determine if there are any-    -- accelerate-generated object files which need to linked into the final-    -- libraries.-    accObjs   <- fmap (nub . concat . Map.elems)-               $ Internal.readBuildInfo-               $ Internal.mkBuildInfoFileName libTargetDir--    unless (null accObjs && null hObjs && null cObjs && null stubObjs) $ do-      rpaths <- getRPaths lbi clbi--      let staticObjectFiles =-                 hObjs-              ++ accObjs-              ++ map (libTargetDir </>) cObjs-              ++ stubObjs-          profObjectFiles =-                 hProfObjs-              ++ accObjs-              ++ map (libTargetDir </>) cProfObjs-              ++ stubProfObjs-          ghciObjFiles =-                 hObjs-              ++ accObjs-              ++ map (libTargetDir </>) cObjs-              ++ stubObjs-          dynamicObjectFiles =-                 hSharedObjs-              ++ accObjs-              ++ map (libTargetDir </>) cSharedObjs-              ++ stubSharedObjs-          -- After the relocation lib is created we invoke ghc -shared-          -- with the dependencies spelled out as -package arguments-          -- and ghc invokes the linker with the proper library paths-          ghcSharedLinkArgs =-              mempty {-                ghcOptShared             = toFlag True,-                ghcOptDynLinkMode        = toFlag GhcDynamicOnly,-                ghcOptInputFiles         = toNubListR dynamicObjectFiles,-                ghcOptOutputFile         = toFlag sharedLibFilePath,-                ghcOptExtra              = nubList $ hcSharedOptions GHC libBi,-                -- For dynamic libs, Mac OS/X needs to know the install location-                -- at build time. This only applies to GHC < 7.8 - see the-                -- discussion in #1660.-                ghcOptDylibName          = if hostOS == OSX-                                              && ghcVersion < mkVersion [7,8]-                                            then toFlag sharedLibInstallPath-                                            else mempty,-                ghcOptHideAllPackages    = toFlag True,-                ghcOptNoAutoLinkPackages = toFlag True,-                ghcOptPackageDBs         = withPackageDB lbi,-                ghcOptThisUnitId = case clbi of-                    LibComponentLocalBuildInfo { componentCompatPackageKey = pk }-                      -> toFlag pk-                    _ -> mempty,-                ghcOptThisComponentId = case clbi of-                    LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->-                        if null insts-                            then mempty-                            else toFlag (componentComponentId clbi)-                    _ -> mempty,-                ghcOptInstantiatedWith = case clbi of-                    LibComponentLocalBuildInfo { componentInstantiatedWith = insts }-                      -> insts-                    _ -> [],-                ghcOptPackages           = toNubListR $-                                           Internal.mkGhcOptPackages clbi ,-                ghcOptLinkLibs           = nubList $ extraLibs libBi,-                ghcOptLinkLibPath        = toNubListR $ extraLibDirs libBi,-                ghcOptLinkFrameworks     = toNubListR $ PD.frameworks libBi,-                ghcOptLinkFrameworkDirs  =-                  toNubListR $ PD.extraFrameworkDirs libBi,-                ghcOptRPaths             = rpaths-              }--      info verbosity (show (ghcOptPackages ghcSharedLinkArgs))--      whenVanillaLib False $-        Ar.createArLibArchive verbosity lbi vanillaLibFilePath staticObjectFiles--      whenProfLib $-        Ar.createArLibArchive verbosity lbi profileLibFilePath profObjectFiles--      whenGHCiLib $ do-        (ldProg, _) <- requireProgram verbosity ldProgram (withPrograms lbi)-        Internal.combineObjectFiles verbosity lbi ldProg-          ghciLibFilePath ghciObjFiles--      whenSharedLib False $-        runGhcProg ghcSharedLinkArgs----- | Returns True if the modification date of the given source file is newer than--- the object file we last compiled for it, or if no object file exists yet.-checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool-checkNeedsRecompilation filename opts = filename `moreRecentFile` oname-    where oname = getObjectFileName filename opts---- | Finds the object file name of the given source file-getObjectFileName :: FilePath -> GhcOptions -> FilePath-getObjectFileName filename opts = oname-    where odir  = fromFlag (ghcOptObjDir opts)-          oext  = fromFlagOrDefault "o" (ghcOptObjSuffix opts)-          oname = odir </> replaceExtension filename oext---- | Calculate the RPATHs for the component we are building.------ Calculates relative RPATHs when 'relocatable' is set.-getRPaths :: LocalBuildInfo-          -> ComponentLocalBuildInfo -- ^ Component we are building-          -> IO (NubListR FilePath)-getRPaths lbi clbi | supportRPaths hostOS = do-    libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi-    let hostPref = case hostOS of-                     OSX -> "@loader_path"-                     _   -> "$ORIGIN"-        relPath p = if isRelative p then hostPref </> p else p-        rpaths    = toNubListR (map relPath libraryPaths)-    return rpaths-  where-    (Platform _ hostOS) = hostPlatform lbi--    -- The list of RPath-supported operating systems below reflects the-    -- platforms on which Cabal's RPATH handling is tested. It does _NOT_-    -- reflect whether the OS supports RPATH.--    -- E.g. when this comment was written, the *BSD operating systems were-    -- untested with regards to Cabal RPATH handling, and were hence set to-    -- 'False', while those operating systems themselves do support RPATH.-    supportRPaths Linux       = True-    supportRPaths Windows     = False-    supportRPaths OSX         = True-    supportRPaths FreeBSD     = False-    supportRPaths OpenBSD     = False-    supportRPaths NetBSD      = False-    supportRPaths DragonFly   = False-    supportRPaths Solaris     = False-    supportRPaths AIX         = False-    supportRPaths HPUX        = False-    supportRPaths IRIX        = False-    supportRPaths HaLVM       = False-    supportRPaths IOS         = False-    supportRPaths Android     = False-    supportRPaths Ghcjs       = False-    supportRPaths Hurd        = False-    supportRPaths (OtherOS _) = False-    -- Do _not_ add a default case so that we get a warning here when a new OS-    -- is added.--getRPaths _ _ = return mempty---- | Filter the "-threaded" flag when profiling as it does not---   work with ghc-6.8 and older.-hackThreadedFlag :: Verbosity -> Compiler -> Bool -> BuildInfo -> IO BuildInfo-hackThreadedFlag _ _ _ = return---- -------------------------------------------------------------------------------- Utils--supportsDynamicToo :: Compiler -> Bool-supportsDynamicToo = Internal.ghcLookupProperty "Support dynamic-too"-
− src/Data/Array/Accelerate/LLVM/Native/Distribution/Simple/GHC/Internal.hs
@@ -1,126 +0,0 @@-{-# LANGUAGE CPP #-}--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC.Internal--- Copyright   : [2017] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ Copied from: https://github.com/haskell/cabal/blob/2.0/Cabal/Distribution/Simple/GHC/Internal.hs-----module Data.Array.Accelerate.LLVM.Native.Distribution.Simple.GHC.Internal (--  mkGHCiLibName,-  ghcLookupProperty,-  filterGhciFlags,-  getHaskellObjects,-  mkGhcOptPackages,-  profDetailLevelFlag,-  combineObjectFiles--) where--#if MIN_VERSION_Cabal(2,0,0)-import Distribution.Backpack-#endif-import Distribution.PackageDescription as PD hiding (Flag)-import Distribution.Simple.Compiler hiding (Flag)-import Distribution.Simple.LocalBuildInfo-import Distribution.Simple.Program (ConfiguredProgram)-import Distribution.Simple.Program.GHC-import qualified Distribution.Simple.Program.Ld as Ld-import Distribution.Simple.Setup-import Distribution.Simple-import Distribution.Verbosity (Verbosity)-import qualified Distribution.ModuleName as ModuleName--import qualified Data.Map as Map-import System.Directory ( getDirectoryContents )-import System.FilePath ( (</>), (<.>), takeExtension )----- | Strip out flags that are not supported in ghci-filterGhciFlags :: [String] -> [String]-filterGhciFlags = filter supported-  where-    supported ('-':'O':_) = False-    supported "-debug"    = False-    supported "-threaded" = False-    supported "-ticky"    = False-    supported "-eventlog" = False-    supported "-prof"     = False-    supported "-unreg"    = False-    supported _           = True--#if MIN_VERSION_Cabal(1,24,0)-mkGHCiLibName :: UnitId -> String-mkGHCiLibName lib = getHSLibraryName lib <.> "o"-#else-mkGHCiLibName :: LibraryName -> String-mkGHCiLibName (LibraryName lib) = lib <.> "o"-#endif--ghcLookupProperty :: String -> Compiler -> Bool-ghcLookupProperty prop comp =-  case Map.lookup prop (compilerProperties comp) of-    Just "YES" -> True-    _          -> False---- when using -split-objs, we need to search for object files in the--- Module_split directory for each module.-getHaskellObjects :: _GhcImplInfo -> Library -> LocalBuildInfo-                  -> ComponentLocalBuildInfo-                  -> FilePath -> String -> Bool -> IO [FilePath]-getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs-  | splitObjs lbi && allow_split_objs = do-        let splitSuffix = "_" ++ wanted_obj_ext ++ "_split"-            dirs = [ pref </> (ModuleName.toFilePath x ++ splitSuffix)-                   | x <- allLibModules lib clbi ]-        objss <- traverse getDirectoryContents dirs-        let objs = [ dir </> obj-                   | (objs',dir) <- zip objss dirs, obj <- objs',-                     let obj_ext = takeExtension obj,-                     '.':wanted_obj_ext == obj_ext ]-        return objs-  | otherwise  =-        return [ pref </> ModuleName.toFilePath x <.> wanted_obj_ext-               | x <- allLibModules lib clbi ]--#if MIN_VERSION_Cabal(2,0,0)-mkGhcOptPackages :: ComponentLocalBuildInfo-                 -> [(OpenUnitId, ModuleRenaming)]-mkGhcOptPackages = componentIncludes-#else-mkGhcOptPackages :: ComponentLocalBuildInfo-                 -> [(InstalledPackageId, PackageId, ModuleRenaming)]-mkGhcOptPackages clbi =-  map (\(i,p) -> (i,p,lookupRenaming p (componentPackageRenaming clbi)))-      (componentPackageDeps clbi)-#endif--profDetailLevelFlag :: Bool -> ProfDetailLevel -> Flag GhcProfAuto-profDetailLevelFlag forLib mpl =-    case mpl of-      ProfDetailNone                -> mempty-      ProfDetailDefault | forLib    -> toFlag GhcProfAutoExported-                        | otherwise -> toFlag GhcProfAutoToplevel-      ProfDetailExportedFunctions   -> toFlag GhcProfAutoExported-      ProfDetailToplevelFunctions   -> toFlag GhcProfAutoToplevel-      ProfDetailAllFunctions        -> toFlag GhcProfAutoAll-      ProfDetailOther _             -> mempty--#if !MIN_VERSION_Cabal(2,0,0)-allLibModules :: Library -> ComponentLocalBuildInfo -> [ModuleName.ModuleName]-allLibModules lib _ = libModules lib-#endif--combineObjectFiles :: Verbosity -> LocalBuildInfo -> ConfiguredProgram-                   -> FilePath -> [FilePath] -> IO ()-#if MIN_VERSION_Cabal(2,1,0)-combineObjectFiles = Ld.combineObjectFiles-#else-combineObjectFiles v _ = Ld.combineObjectFiles v-#endif
src/Data/Array/Accelerate/LLVM/Native/Embed.hs view
@@ -1,14 +1,15 @@ {-# LANGUAGE BangPatterns    #-}+{-# LANGUAGE CPP             #-} {-# LANGUAGE QuasiQuotes     #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns    #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Embed--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -39,14 +40,18 @@ import Control.Monad import Data.Hashable import Foreign.Ptr-import GHC.Ptr                                                      ( Ptr(..) ) import Language.Haskell.TH                                          ( Q, TExp ) import Numeric import System.IO.Unsafe import qualified Language.Haskell.TH                                as TH import qualified Language.Haskell.TH.Syntax                         as TH +#if __GLASGOW_HASKELL__ >= 806+import Data.Maybe+import qualified Data.Set                                           as Set+#endif + instance Embed Native where   embedForTarget = embed @@ -56,7 +61,7 @@ -- embed :: Native -> ObjectR Native -> Q (TExp (ExecutableR Native)) embed target (ObjectR uid nms !_) = do-  objFile <- TH.runIO (evalNative target (cacheOfUID uid))+  objFile <- getObjectFile   funtab  <- forM nms $ \fn -> return [|| ( $$(liftSBS (BS.take (BS.length fn - 65) fn)), $$(makeFFI fn objFile) ) ||]   --   [|| NativeR (unsafePerformIO $ newLifetime (FunctionTable $$(listE funtab))) ||]@@ -64,13 +69,6 @@     listE :: [Q (TExp a)] -> Q (TExp [a])     listE xs = TH.unsafeTExpCoerce (TH.listE (map TH.unTypeQ xs)) -    liftSBS :: ShortByteString -> Q (TExp ShortByteString)-    liftSBS bs =-      let bytes = BS.unpack bs-          len   = BS.length bs-      in-      [|| unsafePerformIO $ BS.createFromPtr $$( TH.unsafeTExpCoerce [| Ptr $(TH.litE (TH.StringPrimL bytes)) |]) len ||]-     makeFFI :: ShortByteString -> FilePath -> Q (TExp (FunPtr ()))     makeFFI (S8.unpack -> fn) objFile = do       i   <- TH.runIO newUnique@@ -79,4 +77,26 @@       ann <- TH.pragAnnD (TH.ValueAnnotation fn') [| (Object objFile) |]       TH.addTopDecls [dec, ann]       TH.unsafeTExpCoerce (TH.varE fn')++    -- Note: [Template Haskell and raw object files]+    --+    -- We can only addForeignFilePath once per object file, otherwise the+    -- linker will complain about duplicate symbols. To work around this,+    -- we use putQ/getQ to keep track of which object files have already+    -- been encountered during compilation _of the current module_. This+    -- means that we might still run into problems if runQ is invoked at+    -- multiple modules.+    --+    getObjectFile :: Q FilePath+    getObjectFile = do+      this <- TH.runIO (evalNative target (cacheOfUID uid))+#if __GLASGOW_HASKELL__ >= 806+      rest <- fromMaybe Set.empty <$> TH.getQ+      if Set.member this rest+         then return ()+         else do+           TH.addForeignFilePath TH.RawObject this+           TH.putQ (Set.insert this rest)+#endif+      return this 
src/Data/Array/Accelerate/LLVM/Native/Execute.hs view
@@ -1,516 +1,1017 @@-{-# LANGUAGE FlexibleContexts         #-}-{-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE GADTs                    #-}-{-# LANGUAGE OverloadedStrings        #-}-{-# LANGUAGE RecordWildCards          #-}-{-# LANGUAGE ScopedTypeVariables      #-}-{-# LANGUAGE TemplateHaskell          #-}-{-# LANGUAGE TypeOperators            #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Execute--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.LLVM.Native.Execute (--  executeAcc, executeAfun,-  executeOpenAcc--) where---- accelerate-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Error--import Data.Array.Accelerate.LLVM.Analysis.Match-import Data.Array.Accelerate.LLVM.Execute-import Data.Array.Accelerate.LLVM.State--import Data.Array.Accelerate.LLVM.Native.Array.Data-import Data.Array.Accelerate.LLVM.Native.Link-import Data.Array.Accelerate.LLVM.Native.Execute.Async-import Data.Array.Accelerate.LLVM.Native.Execute.Environment-import Data.Array.Accelerate.LLVM.Native.Execute.Marshal-import Data.Array.Accelerate.LLVM.Native.Target-import qualified Data.Array.Accelerate.LLVM.Native.Debug            as Debug---- Use work-stealing scheduler-import Data.Range                                                   ( Range(..) )-import Control.Parallel.Meta                                        ( Executable(..) )-import Data.Array.Accelerate.LLVM.Native.Execute.LBS---- library-import Control.Monad.State                                          ( gets )-import Control.Monad.Trans                                          ( liftIO )-import Data.ByteString.Short                                        ( ShortByteString )-import Data.List                                                    ( find )-import Data.Maybe                                                   ( fromMaybe )-import Data.Time.Clock                                              ( getCurrentTime, diffUTCTime )-import Data.Word                                                    ( Word8 )-import Text.Printf                                                  ( printf )-import Prelude                                                      hiding ( map, sum, scanl, scanr, init )-import qualified Data.ByteString.Short.Char8                        as S8--import Foreign.C-import Foreign.LibFFI-import Foreign.Ptr----- Array expression evaluation--- ------------------------------- Computations are evaluated by traversing the AST bottom up, and for each node--- distinguishing between three cases:------  1. If it is a Use node, we return a reference to the array data. Even though---     we execute with multiple cores, we assume a shared memory multiprocessor---     machine.------  2. If it is a non-skeleton node, such as a let binding or shape conversion,---     then execute directly by updating the environment or similar.------  3. If it is a skeleton node, then we need to execute the generated LLVM---     code.----instance Execute Native where-  map           = simpleOp-  generate      = simpleOp-  transform     = simpleOp-  backpermute   = simpleOp-  fold          = foldOp-  fold1         = fold1Op-  foldSeg       = foldSegOp-  fold1Seg      = foldSegOp-  scanl         = scanOp-  scanl1        = scan1Op-  scanl'        = scan'Op-  scanr         = scanOp-  scanr1        = scan1Op-  scanr'        = scan'Op-  permute       = permuteOp-  stencil1      = simpleOp-  stencil2      = stencil2Op-  aforeign      = aforeignOp----- Skeleton implementation--- --------------------------- Simple kernels just needs to know the shape of the output array.----simpleOp-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh-    -> LLVM Native (Array sh e)-simpleOp exe gamma aenv () sh = withExecutable exe $ \nativeExecutable -> do-  let fun = case functionTable nativeExecutable of-              f:_ -> f-              _   -> $internalError "simpleOp" "no functions found"-  ---  Native{..} <- gets llvmTarget-  liftIO $ do-    out <- allocateArray sh-    executeOp defaultLargePPT fillP fun gamma aenv (IE 0 (size sh)) out-    return out--simpleNamed-    :: (Shape sh, Elt e)-    => ShortByteString-    -> ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh-    -> LLVM Native (Array sh e)-simpleNamed name exe gamma aenv () sh = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  liftIO $ do-    out <- allocateArray sh-    executeOp defaultLargePPT fillP (nativeExecutable !# name) gamma aenv (IE 0 (size sh)) out-    return out----- Note: [Reductions]------ There are two flavours of reduction:------   1. If we are collapsing to a single value, then threads reduce strips of---      the input in parallel, and then a single thread reduces the partial---      reductions to a single value. Load balancing occurs over the input---      stripes.------   2. If this is a multidimensional reduction, then each inner dimension is---      handled by a single thread. Load balancing occurs over the outer---      dimension indices.------ The entry points to executing the reduction are 'foldOp' and 'fold1Op', for--- exclusive and inclusive reductions respectively. These functions handle--- whether the input array is empty. If the input and output arrays are--- non-empty, we then further dispatch (via 'foldCore') to 'foldAllOp' or--- 'foldDimOp' for single or multidimensional reductions, respectively.--- 'foldAllOp' in particular must execute specially whether the gang has--- multiple worker threads which can process the array in parallel.-----fold1Op-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> (sh :. Int)-    -> LLVM Native (Array sh e)-fold1Op kernel gamma aenv stream sh@(sx :. sz)-  = $boundsCheck "fold1" "empty array" (sz > 0)-  $ case size sh of-      0 -> liftIO $ allocateArray sx   -- empty, but possibly with non-zero dimensions-      _ -> foldCore kernel gamma aenv stream sh--foldOp-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> (sh :. Int)-    -> LLVM Native (Array sh e)-foldOp kernel gamma aenv stream sh@(sx :. _) =-  case size sh of-    0 -> simpleNamed "generate" kernel gamma aenv stream sx-    _ -> foldCore kernel gamma aenv stream sh--foldCore-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> (sh :. Int)-    -> LLVM Native (Array sh e)-foldCore kernel gamma aenv stream sh-  | Just Refl <- matchShapeType sh (undefined::DIM1)-  = foldAllOp kernel gamma aenv stream sh-  ---  | otherwise-  = foldDimOp kernel gamma aenv stream sh--foldAllOp-    :: forall aenv e. Elt e-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> DIM1-    -> LLVM Native (Scalar e)-foldAllOp exe gamma aenv () (Z :. sz) = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  let-      ncpu    = gangSize-      stride  = defaultLargePPT `min` ((sz + ncpu - 1) `quot` ncpu)-      steps   = (sz + stride - 1) `quot` stride-  ---  if ncpu == 1 || sz <= defaultLargePPT-    then liftIO $ do-      -- Sequential reduction-      out <- allocateArray Z-      executeOp 1 fillS (nativeExecutable !# "foldAllS") gamma aenv (IE 0 sz) out-      return out--    else liftIO $ do-      -- Parallel reduction-      out <- allocateArray Z-      tmp <- allocateArray (Z :. steps) :: IO (Vector e)-      executeOp 1 fillP (nativeExecutable !# "foldAllP1") gamma aenv (IE 0 steps) (sz, stride, tmp)-      executeOp 1 fillS (nativeExecutable !# "foldAllP2") gamma aenv (IE 0 steps) (tmp, out)-      return out--foldDimOp-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> (sh :. Int)-    -> LLVM Native (Array sh e)-foldDimOp exe gamma aenv () (sh :. sz) = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  let ppt = defaultSmallPPT `max` (defaultLargePPT `quot` (max 1 sz))-  liftIO $ do-    out <- allocateArray sh-    executeOp ppt fillP (nativeExecutable !# "fold") gamma aenv (IE 0 (size sh)) (sz, out)-    return out--foldSegOp-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> (sh :. Int)-    -> (Z  :. Int)-    -> LLVM Native (Array (sh :. Int) e)-foldSegOp exe gamma aenv () (sh :. _) (Z :. ss) = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  let-      kernel | segmentOffset  = "foldSegP"-             | otherwise      = "foldSegS"-      n      | segmentOffset  = ss - 1            -- segments array has been 'scanl (+) 0'`ed-             | otherwise      = ss-      ppt    | rank sh == 0   = defaultLargePPT   -- work-steal over the single dimension-             | otherwise      = n                 -- a thread computes all segments along an index-  ---  liftIO $ do-    out <- allocateArray (sh :. n)-    executeOp ppt fillP (nativeExecutable !# kernel) gamma aenv (IE 0 (size (sh :. n))) out-    return out---scanOp-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh :. Int-    -> LLVM Native (Array (sh:.Int) e)-scanOp kernel gamma aenv stream (sz :. n) =-  case n of-    0 -> simpleNamed "generate" kernel gamma aenv stream (sz :. 1)-    _ -> scanCore kernel gamma aenv stream sz n (n+1)--scan1Op-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh :. Int-    -> LLVM Native (Array (sh:.Int) e)-scan1Op kernel gamma aenv stream (sz :. n)-  = $boundsCheck "scan1" "empty array" (n > 0)-  $ scanCore kernel gamma aenv stream sz n n--scanCore-    :: forall aenv sh e. (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh-    -> Int-    -> Int-    -> LLVM Native (Array (sh:.Int) e)-scanCore exe gamma aenv () sz n m = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  let-      ncpu    = gangSize-      stride  = defaultLargePPT `min` ((n + ncpu - 1) `quot` ncpu)-      steps   = (n + stride - 1) `quot` stride-      steps'  = steps - 1-  ---  if ncpu == 1 || rank sz > 0 || n <= 2 * defaultLargePPT-    then liftIO $ do-      -- Either:-      ---      --  1. Sequential scan of an array of any rank-      ---      --  2. Parallel scan of multidimensional array: threads scan along the-      --     length of the innermost dimension. Threads are scheduled over the-      --     inner dimensions.-      ---      --  3. Small 1D array. Since parallel scan requires ~4n data transfer-      --     compared to ~2n in the sequential case, it is only worthwhile if-      --     the extra cores can offset the increased bandwidth requirements.-      ---      out <- allocateArray (sz :. m)-      executeOp 1 fillP (nativeExecutable !# "scanS") gamma aenv (IE 0 (size sz)) out-      return out--    else liftIO $ do-      -- parallel one-dimensional scan-      out <- allocateArray (sz :. m)-      tmp <- allocateArray (Z  :. steps) :: IO (Vector e)-      executeOp 1 fillP (nativeExecutable !# "scanP1") gamma aenv (IE 0 steps) (stride, steps', out, tmp)-      executeOp 1 fillS (nativeExecutable !# "scanP2") gamma aenv (IE 0 steps) tmp-      executeOp 1 fillP (nativeExecutable !# "scanP3") gamma aenv (IE 0 steps') (stride, out, tmp)-      return out---scan'Op-    :: forall aenv sh e. (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh :. Int-    -> LLVM Native (Array (sh:.Int) e, Array sh e)-scan'Op native gamma aenv stream sh@(sz :. n) =-  case n of-    0 -> do-      out <- liftIO $ allocateArray (sz :. 0)-      sum <- simpleNamed "generate" native gamma aenv stream sz-      return (out, sum)-    ---    _ -> scan'Core native gamma aenv stream sh--scan'Core-    :: forall aenv sh e. (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh :. Int-    -> LLVM Native (Array (sh:.Int) e, Array sh e)-scan'Core exe gamma aenv () sh@(sz :. n) = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  let-      ncpu    = gangSize-      stride  = defaultLargePPT `min` ((n + ncpu - 1) `quot` ncpu)-      steps   = (n + stride - 1) `quot` stride-      steps'  = steps - 1-  ---  if ncpu == 1 || rank sz > 0 || n <= 2 * defaultLargePPT-    then liftIO $ do-      out <- allocateArray sh-      sum <- allocateArray sz-      executeOp 1 fillP (nativeExecutable !# "scanS") gamma aenv (IE 0 (size sz)) (out,sum)-      return (out,sum)--    else liftIO $ do-      tmp <- allocateArray (Z :. steps) :: IO (Vector e)-      out <- allocateArray sh-      sum <- allocateArray sz-      executeOp 1 fillP (nativeExecutable !# "scanP1") gamma aenv (IE 0 steps)  (stride, steps', out, tmp)-      executeOp 1 fillS (nativeExecutable !# "scanP2") gamma aenv (IE 0 steps)  (sum, tmp)-      executeOp 1 fillP (nativeExecutable !# "scanP3") gamma aenv (IE 0 steps') (stride, out, tmp)-      return (out,sum)----- Forward permutation, specified by an indexing mapping into an array and a--- combination function to combine elements.----permuteOp-    :: (Shape sh, Shape sh', Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> Bool-    -> sh-    -> Array sh' e-    -> LLVM Native (Array sh' e)-permuteOp exe gamma aenv () inplace shIn dfs = withExecutable exe $ \nativeExecutable -> do-  Native{..} <- gets llvmTarget-  out        <- if inplace-                  then return dfs-                  else cloneArray dfs-  let-      ncpu    = gangSize-      n       = size shIn-      m       = size (shape out)-  ---  if ncpu == 1 || n <= defaultLargePPT-    then liftIO $ do-      -- sequential permutation-      executeOp 1 fillS (nativeExecutable !# "permuteS") gamma aenv (IE 0 n) out--    else liftIO $ do-      -- parallel permutation-      case lookupFunction "permuteP_rmw" nativeExecutable of-        Just f  -> executeOp defaultLargePPT fillP f gamma aenv (IE 0 n) out-        Nothing -> do-          barrier@(Array _ adb) <- allocateArray (Z :. m) :: IO (Vector Word8)-          memset (ptrsOfArrayData adb) 0 m-          executeOp defaultLargePPT fillP (nativeExecutable !# "permuteP_mutex") gamma aenv (IE 0 n) (out, barrier)--  return out---stencil2Op-    :: (Shape sh, Elt e)-    => ExecutableR Native-    -> Gamma aenv-    -> Aval aenv-    -> Stream-    -> sh-    -> sh-    -> LLVM Native (Array sh e)-stencil2Op kernel gamma aenv stream sh1 sh2 =-  simpleOp kernel gamma aenv stream (sh1 `intersect` sh2)---aforeignOp-    :: (Arrays as, Arrays bs)-    => String-    -> (Stream -> as -> LLVM Native bs)-    -> Stream-    -> as-    -> LLVM Native bs-aforeignOp name asm stream arr = do-  wallBegin <- liftIO $ getCurrentTime-  result    <- Debug.timed Debug.dump_exec (\wall cpu -> printf "exec: %s %s" name (Debug.elapsedP wall cpu)) (asm stream arr)-  wallEnd   <- liftIO $ getCurrentTime-  liftIO $ Debug.addProcessorTime Debug.Native (realToFrac (diffUTCTime wallEnd wallBegin))-  return result----- Skeleton execution--- --------------------(!#) :: FunctionTable -> ShortByteString -> Function-(!#) exe name-  = fromMaybe ($internalError "lookupFunction" ("function not found: " ++ S8.unpack name))-  $ lookupFunction name exe--lookupFunction :: ShortByteString -> FunctionTable -> Maybe Function-lookupFunction name nativeExecutable = do-  find (\(n,_) -> n == name) (functionTable nativeExecutable)---- Execute the given function distributed over the available threads.----executeOp-    :: Marshalable args-    => Int-    -> Executable-    -> Function-    -> Gamma aenv-    -> Aval aenv-    -> Range-    -> args-    -> IO ()-executeOp ppt exe (name, f) gamma aenv r args = do-  args' <- marshal (undefined::Native) () (args, (gamma, aenv))-  ---  runExecutable exe name ppt r $ \start end _tid -> do-   monitorProcTime             $-    callFFI f retVoid (argInt start : argInt end : args')----- Standard C functions--- ----------------------memset :: Ptr Word8 -> Word8 -> Int -> IO ()-memset p w s = c_memset p (fromIntegral w) (fromIntegral s) >> return ()--foreign import ccall unsafe "string.h memset" c_memset-    :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8)----- Debugging--- -----------monitorProcTime :: IO a -> IO a-monitorProcTime = Debug.withProcessor Debug.Native+{-# LANGUAGE BangPatterns             #-}+{-# LANGUAGE FlexibleContexts         #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GADTs                    #-}+{-# LANGUAGE LambdaCase               #-}+{-# LANGUAGE OverloadedStrings        #-}+{-# LANGUAGE RecordWildCards          #-}+{-# LANGUAGE ScopedTypeVariables      #-}+{-# LANGUAGE TemplateHaskell          #-}+{-# LANGUAGE TypeApplications         #-}+{-# LANGUAGE TypeOperators            #-}+{-# LANGUAGE ViewPatterns             #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.LLVM.Native.Execute+-- Copyright   : [2014..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.LLVM.Native.Execute (++  executeAcc,+  executeOpenAcc++) where++import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Array.Unique+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Lifetime+import Data.Array.Accelerate.Representation.Array+import Data.Array.Accelerate.Representation.Shape+import Data.Array.Accelerate.Representation.Type+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.LLVM.Execute+import Data.Array.Accelerate.LLVM.Execute.Async (FutureArraysR)+import Data.Array.Accelerate.LLVM.State++import Data.Array.Accelerate.LLVM.Native.Array.Data+import Data.Array.Accelerate.LLVM.Native.Execute.Async+import Data.Array.Accelerate.LLVM.Native.Execute.Divide+import Data.Array.Accelerate.LLVM.Native.Execute.Environment        ( Val )+import Data.Array.Accelerate.LLVM.Native.Execute.Marshal+import Data.Array.Accelerate.LLVM.Native.Execute.Scheduler+import Data.Array.Accelerate.LLVM.Native.Link+import Data.Array.Accelerate.LLVM.Native.Target+import qualified Data.Array.Accelerate.LLVM.Native.Debug            as Debug++import Control.Concurrent                                           ( myThreadId )+import Control.Monad.State                                          ( gets )+import Control.Monad.Trans                                          ( liftIO )+import Data.ByteString.Short                                        ( ShortByteString )+import Data.IORef                                                   ( newIORef, readIORef, writeIORef )+import Data.List                                                    ( find )+import Data.Maybe                                                   ( fromMaybe )+import Data.Sequence                                                ( Seq )+import Data.Foldable                                                ( asum )+import System.CPUTime                                               ( getCPUTime )+import Text.Printf                                                  ( printf )+import qualified Data.ByteString.Short.Char8                        as S8+import qualified Data.Sequence                                      as Seq+import qualified Data.DList                                         as DL+import Prelude                                                      hiding ( map, sum, scanl, scanr, init )++import Foreign.LibFFI+import Foreign.Ptr++{-# SPECIALISE INLINE executeAcc     :: ExecAcc     Native      a ->             Par Native (FutureArraysR Native a) #-}+{-# SPECIALISE INLINE executeOpenAcc :: ExecOpenAcc Native aenv a -> Val aenv -> Par Native (FutureArraysR Native a) #-}++-- Array expression evaluation+-- ---------------------------++-- Computations are evaluated by traversing the AST bottom up, and for each node+-- distinguishing between three cases:+--+--  1. If it is a Use node, we return a reference to the array data. Even though+--     we execute with multiple cores, we assume a shared memory multiprocessor+--     machine.+--+--  2. If it is a non-skeleton node, such as a let binding or shape conversion,+--     then execute directly by updating the environment or similar.+--+--  3. If it is a skeleton node, then we need to execute the generated LLVM+--     code.+--+instance Execute Native where+  {-# INLINE map         #-}+  {-# INLINE generate    #-}+  {-# INLINE transform   #-}+  {-# INLINE backpermute #-}+  {-# INLINE fold        #-}+  {-# INLINE foldSeg     #-}+  {-# INLINE scan        #-}+  {-# INLINE scan'       #-}+  {-# INLINE permute     #-}+  {-# INLINE stencil1    #-}+  {-# INLINE stencil2    #-}+  {-# INLINE aforeign    #-}+  map           = mapOp+  generate      = generateOp+  transform     = transformOp+  backpermute   = backpermuteOp+  fold True     = foldOp+  fold False    = fold1Op+  foldSeg i _   = foldSegOp i+  scan _ True   = scanOp+  scan _ False  = scan1Op+  scan' _       = scan'Op+  permute       = permuteOp+  stencil1      = stencil1Op+  stencil2      = stencil2Op+  aforeign      = aforeignOp+++-- Skeleton implementation+-- -----------------------++-- Simple kernels just needs to know the shape of the output array.+--+{-# INLINE simpleOp #-}+simpleOp+    :: HasCallStack+    => ShortByteString+    -> ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> sh+    -> Par Native (Future (Array sh e))+simpleOp name repr NativeR{..} gamma aenv sh = do+  let fun   = nativeExecutable !# name+      param = TupRsingle $ ParamRarray repr+  Native{..} <- gets llvmTarget+  future     <- new+  result     <- allocateRemote repr sh+  scheduleOp fun gamma aenv (arrayRshape repr) sh param result+    `andThen` do putIO workers future result+                 touchLifetime nativeExecutable   -- XXX: must not unload the object code early+  return future++-- Mapping over an array can ignore the dimensionality of the array and+-- treat it as its underlying linear representation.+--+{-# INLINE mapOp #-}+mapOp+    :: HasCallStack+    => Maybe (a :~: b)+    -> ArrayR (Array sh a)+    -> TypeR b+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Array sh a+    -> Par Native (Future (Array sh b))+mapOp inplace repr tp NativeR{..} gamma aenv input = do+  let fun   = nativeExecutable !# "map"+      sh    = shape input+      shr   = arrayRshape repr+      repr' = ArrayR shr tp+      param = TupRsingle (ParamRarray repr') `TupRpair` TupRsingle (ParamRarray repr)+  Native{..} <- gets llvmTarget+  future     <- new+  result     <- case inplace of+                  Just Refl -> return input+                  Nothing   -> allocateRemote repr' sh+  scheduleOp fun gamma aenv dim1 ((), size shr sh) param (result, input)+    `andThen` do putIO workers future result+                 touchLifetime nativeExecutable+  return future++{-# INLINE generateOp #-}+generateOp+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> sh+    -> Par Native (Future (Array sh e))+generateOp = simpleOp "generate"++{-# INLINE transformOp #-}+transformOp+    :: HasCallStack+    => ArrayR (Array sh  a)+    -> ArrayR (Array sh' b)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> sh'+    -> Array sh a+    -> Par Native (Future (Array sh' b))+transformOp repr repr' NativeR{..} gamma aenv sh' input = do+  let fun = nativeExecutable !# "transform"+  Native{..} <- gets llvmTarget+  future     <- new+  result     <- allocateRemote repr' sh'+  let param = TupRsingle (ParamRarray repr') `TupRpair` TupRsingle (ParamRarray repr)+  scheduleOp fun gamma aenv (arrayRshape repr') sh' param (result, input)+    `andThen` do putIO workers future result+                 touchLifetime nativeExecutable+  return future++{-# INLINE backpermuteOp #-}+backpermuteOp+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ShapeR sh'+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> sh'+    -> Array sh e+    -> Par Native (Future (Array sh' e))+backpermuteOp (ArrayR shr tp) shr' = transformOp (ArrayR shr tp) (ArrayR shr' tp)++-- Note: [Reductions]+--+-- There are two flavours of reduction:+--+--   1. If we are collapsing to a single value, then threads reduce strips of+--      the input in parallel, and then a single thread reduces the partial+--      reductions to a single value. Load balancing occurs over the input+--      stripes.+--+--   2. If this is a multidimensional reduction, then each inner dimension is+--      handled by a single thread. Load balancing occurs over the outer+--      dimension indices.+--+-- The entry points to executing the reduction are 'foldOp' and 'fold1Op', for+-- exclusive and inclusive reductions respectively. These functions handle+-- whether the input array is empty. If the input and output arrays are+-- non-empty, we then further dispatch (via 'foldCore') to 'foldAllOp' or+-- 'foldDimOp' for single or multidimensional reductions, respectively.+-- 'foldAllOp' in particular behaves differently whether we are evaluating the+-- array in parallel or sequentially.+--++{-# INLINE fold1Op #-}+fold1Op+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array sh e))+fold1Op repr exe gamma aenv arr@(delayedShape -> sh@(sx, sz))+  = boundsCheck "empty array" (sz > 0)+  $ case size (ShapeRsnoc $ arrayRshape repr) sh of+      0 -> newFull =<< allocateRemote repr sx    -- empty, but possibly with non-zero dimensions+      _ -> foldCore repr exe gamma aenv arr++{-# INLINE foldOp #-}+foldOp+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array sh e))+foldOp repr exe gamma aenv arr@(delayedShape -> sh@(sx, _)) =+  case size (ShapeRsnoc $ arrayRshape repr) sh of+    0 -> generateOp repr exe gamma aenv sx+    _ -> foldCore repr exe gamma aenv arr++{-# INLINE foldCore #-}+foldCore+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array sh e))+foldCore repr exe gamma aenv arr+  | ArrayR ShapeRz tp <- repr+  = foldAllOp tp exe gamma aenv arr+  --+  | otherwise+  = foldDimOp repr exe gamma aenv arr++{-# INLINE foldAllOp #-}+foldAllOp+    :: HasCallStack+    => TypeR e+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Vector e)+    -> Par Native (Future (Scalar e))+foldAllOp tp NativeR{..} gamma aenv arr = do+  Native{..}  <- gets llvmTarget+  future      <- new+  result      <- allocateRemote (ArrayR dim0 tp) ()+  let+      minsize = 4096+      splits  = numWorkers workers+      ranges  = divideWork1 splits minsize ((), 0) sh (,,)+      steps   = Seq.length ranges+      sh      = delayedShape arr+  --+  if steps <= 1+    then+      let param = TupRsingle (ParamRarray $ ArrayR dim0 tp) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray $ ArrayR dim1 tp)+      in  scheduleOpUsing ranges (nativeExecutable !# "foldAllS") gamma aenv dim1 param (result, manifest arr)+            `andThen` do putIO workers future result+                         touchLifetime nativeExecutable++    else do+      let param1 = TupRsingle (ParamRarray $ ArrayR dim1 tp) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray $ ArrayR dim1 tp)+      let param2 = TupRsingle (ParamRarray $ ArrayR dim1 tp) `TupRpair` TupRsingle (ParamRarray $ ArrayR dim0 tp)+      tmp   <- allocateRemote (ArrayR dim1 tp) ((), steps)+      job2  <- mkJobUsing (Seq.singleton (0, ((), 0), ((), steps))) (nativeExecutable !# "foldAllP2") gamma aenv dim1 param2 (tmp, result)+                 `andThen` do putIO workers future result+                              touchLifetime nativeExecutable++      job1  <- mkJobUsingIndex ranges (nativeExecutable !# "foldAllP1") gamma aenv dim1 param1 (tmp, manifest arr)+                 `andThen` do schedule workers job2++      liftIO $ schedule workers job1+  --+  return future+++{-# INLINE foldDimOp #-}+foldDimOp+    :: HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array sh e))+foldDimOp repr NativeR{..} gamma aenv arr@(delayedShape -> (sh, _)) = do+  Native{..}  <- gets llvmTarget+  future      <- new+  result      <- allocateRemote repr sh+  let+      ArrayR shr tp = repr+      fun     = nativeExecutable !# "fold"+      splits  = numWorkers workers+      minsize = 1+      param   = TupRsingle (ParamRarray repr) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray $ ArrayR (ShapeRsnoc shr) tp)+  --+  scheduleOpWith splits minsize fun gamma aenv shr sh param (result, manifest arr)+    `andThen` do putIO workers future result+                 touchLifetime nativeExecutable+  return future+++{-# INLINE foldSegOp #-}+foldSegOp+    :: HasCallStack+    => IntegralType i+    -> ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Delayed (Segments i)+    -> Par Native (Future (Array (sh, Int) e))+foldSegOp int repr NativeR{..} gamma aenv input@(delayedShape -> (sh, _)) segments@(delayedShape -> ((), ss)) = do+  Native{..}  <- gets llvmTarget+  future      <- new+  let+      n       = ss-1+      splits  = numWorkers workers+      minsize = 1+      shR     = arrayRshape repr+      segR    = ArrayR dim1 $ TupRsingle $ SingleScalarType $ NumSingleType $ IntegralNumType int+      param   = TupRsingle (ParamRarray repr) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray segR)+  --+  result  <- allocateRemote repr (sh, n)+  scheduleOpWith splits minsize (nativeExecutable !# "foldSegP") gamma aenv shR (sh, n) param ((result, manifest input), manifest segments)+    `andThen` do putIO workers future result+                 touchLifetime nativeExecutable++  return future+++{-# INLINE scanOp #-}+scanOp+    :: HasCallStack+    => ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array (sh, Int) e))+scanOp repr exe gamma aenv arr@(delayedShape -> (sz, n)) =+  case n of+    0 -> generateOp repr exe gamma aenv (sz, 1)+    _ -> scanCore   repr exe gamma aenv (n+1) arr++{-# INLINE scan1Op #-}+scan1Op+    :: HasCallStack+    => ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array (sh, Int) e))+scan1Op repr exe gamma aenv arr@(delayedShape -> (_, n))+  = boundsCheck "empty array" (n > 0)+  $ scanCore repr exe gamma aenv n arr++{-# INLINE scanCore #-}+scanCore+    :: HasCallStack+    => ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Int        -- output size of innermost dimension+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array (sh, Int) e))+scanCore repr NativeR{..} gamma aenv m input@(delayedShape -> (sz, n)) = do+  Native{..}  <- gets llvmTarget+  future      <- new+  result      <- allocateRemote repr (sz, m)+  --+  let paramA = TupRsingle $ ParamRarray repr+      param  = paramA `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+      shR    = arrayRshape (reduceRank repr)++  if isMultiDim $ arrayRshape repr+    -- This is a multidimensional scan. Each partial scan result is evaluated+    -- individually by a thread, so no inter-thread communication is required.+    then+      let+          fun     = nativeExecutable !# "scanS"+          splits  = numWorkers workers+          minsize = 1+      in+      scheduleOpWith splits minsize fun gamma aenv shR sz param (result, manifest input)+        `andThen` do putIO workers future result+                     touchLifetime nativeExecutable++    -- This is a one-dimensional scan. If the array is small just compute it+    -- sequentially using a single thread, otherwise we require multiple steps+    -- to execute it in parallel.+    else+      if n < 8192+        -- sequential execution+        then+          scheduleOpUsing (Seq.singleton (0, (), ())) (nativeExecutable !# "scanS") gamma aenv dim0 param (result, manifest input)+            `andThen` do putIO workers future result+                         touchLifetime nativeExecutable++        -- parallel execution+        else do+          let+              splits   = numWorkers workers+              minsize  = 8192+              ranges   = divideWork dim1 splits minsize ((), 0) ((), n) (,,)+              steps    = Seq.length ranges+              reprTmp  = ArrayR dim1 $ arrayRtype repr+              paramTmp = TupRsingle $ ParamRarray reprTmp+              param1   = TupRsingle ParamRint `TupRpair` paramA `TupRpair` paramTmp `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+              param3   = TupRsingle ParamRint `TupRpair` paramA `TupRpair` paramTmp+          --+          -- XXX: Should the sequential scan of the carry-in values just be+          -- executed immediately as part of the finalisation action?+          --+          tmp   <- allocateRemote (ArrayR dim1 $ arrayRtype repr) ((), steps)+          job3  <- mkJobUsingIndex ranges (nativeExecutable !# "scanP3") gamma aenv dim1 param3 ((steps, result), tmp)+                     `andThen` do putIO workers future result+                                  touchLifetime nativeExecutable+          job2  <- mkJobUsing (Seq.singleton (0, ((), 0), ((), steps))) (nativeExecutable !# "scanP2") gamma aenv dim1 paramTmp tmp+                     `andThen` schedule workers job3+          job1  <- mkJobUsingIndex ranges (nativeExecutable !# "scanP1") gamma aenv dim1 param1 (((steps, result), tmp), manifest input)+                     `andThen` schedule workers job2++          liftIO $ schedule workers job1+  --+  return future+++{-# INLINE scan'Op #-}+scan'Op+    :: HasCallStack+    => ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array (sh, Int) e, Array sh e))+scan'Op repr exe gamma aenv arr@(delayedShape -> (sz, n)) = do+  case n of+    0 -> do+      out     <- allocateRemote repr (sz, 0)+      sum     <- generateOp (reduceRank repr) exe gamma aenv sz+      future  <- new+      fork $ do sum' <- get sum+                put future (out, sum')+      return future+    --+    _ -> scan'Core repr exe gamma aenv arr++{-# INLINE scan'Core #-}+scan'Core+    :: forall aenv sh e. HasCallStack+    => ArrayR (Array (sh, Int) e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array (sh, Int) e)+    -> Par Native (Future (Array (sh, Int) e, Array sh e))+scan'Core repr NativeR{..} gamma aenv input@(delayedShape -> sh@(sz, n)) = do+  let+      ArrayR shR eR   = repr+      ShapeRsnoc shR' = shR+      repr'           = ArrayR shR' eR+      paramA          = TupRsingle $ ParamRarray repr+      paramA'         = TupRsingle $ ParamRarray repr'+  --+  Native{..}  <- gets llvmTarget+  future      <- new+  result      <- allocateRemote repr  sh+  sums        <- allocateRemote repr' sz+  --+  if isMultiDim shR+    -- This is a multidimensional scan. Each partial scan result is evaluated+    -- individually by a thread, so no inter-thread communication is required.+    --+    then+      let fun     = nativeExecutable !# "scanS"+          splits  = numWorkers workers+          minsize = 1+          param   = paramA `TupRpair` paramA' `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+      in+      scheduleOpWith splits minsize fun gamma aenv shR' sz param ((result, sums), manifest input)+        `andThen` do putIO workers future (result, sums)+                     touchLifetime nativeExecutable++    -- One dimensional scan. If the array is small just compute it sequentially+    -- with a single thread, otherwise we require multiple steps to execute it+    -- in parallel.+    --+    else+      if n < 8192+        -- sequential execution+        then+          let param = paramA `TupRpair` paramA' `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+          in  scheduleOpUsing (Seq.singleton (0, (), ())) (nativeExecutable !# "scanS") gamma aenv dim0 param ((result, sums), manifest input)+                `andThen` do putIO workers future (result, sums)+                             touchLifetime nativeExecutable++        -- parallel execution+        else do+          let+              splits   = numWorkers workers+              minsize  = 8192+              ranges   = divideWork1 splits minsize ((), 0) ((), n) (,,)+              steps    = Seq.length ranges+              reprTmp  = ArrayR dim1 eR+              paramTmp = TupRsingle $ ParamRarray reprTmp+              param1   = TupRsingle ParamRint `TupRpair` paramA `TupRpair` paramTmp `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+              param2   = paramA' `TupRpair` paramTmp+              param3   = TupRsingle ParamRint `TupRpair` paramA `TupRpair` paramTmp+          --+          tmp   <- allocateRemote reprTmp ((), steps)+          job3  <- mkJobUsingIndex ranges (nativeExecutable !# "scanP3") gamma aenv dim1 param3 ((steps, result), tmp)+                     `andThen` do putIO workers future (result, sums)+                                  touchLifetime nativeExecutable+          job2  <- mkJobUsing (Seq.singleton (0, ((), 0), ((), steps))) (nativeExecutable !# "scanP2") gamma aenv dim1 param2 (sums, tmp)+                     `andThen` schedule workers job3+          job1  <- mkJobUsingIndex ranges (nativeExecutable !# "scanP1") gamma aenv dim1 param1 (((steps, result), tmp), manifest input)+                     `andThen` schedule workers job2++          liftIO $ schedule workers job1+  --+  return future++isMultiDim :: ShapeR sh -> Bool+isMultiDim (ShapeRsnoc ShapeRz) = False+isMultiDim _                    = True++-- Forward permutation, specified by an indexing mapping into an array and a+-- combination function to combine elements.+--+{-# INLINE permuteOp #-}+permuteOp+    :: forall sh e sh' aenv. HasCallStack+    => Bool+    -> ArrayR (Array sh e)+    -> ShapeR sh'+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Array sh' e+    -> Delayed (Array sh e)+    -> Par Native (Future (Array sh' e))+permuteOp inplace repr shr' NativeR{..} gamma aenv defaults@(shape -> shOut) input@(delayedShape -> shIn) = do+  let+      ArrayR shr tp = repr+      repr' = ArrayR shr' tp+  Native{..}  <- gets llvmTarget+  future      <- new+  result      <- if inplace+                   then Debug.trace Debug.dump_exec               "exec: permute/inplace"                            $ return defaults+                   else Debug.timed Debug.dump_exec (\wall cpu -> "exec: permute/clone " ++ Debug.elapsedS wall cpu) $ liftPar (cloneArray repr' defaults)+  let+      splits  = numWorkers workers+      minsize = case shr of+                  ShapeRsnoc ShapeRz              -> 4096+                  ShapeRsnoc (ShapeRsnoc ShapeRz) -> 64+                  _                               -> 16+      ranges  = divideWork shr splits minsize (empty shr) shIn (,,)+      steps   = Seq.length ranges+      paramR = TupRsingle (ParamRarray repr') `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+  --+  if steps <= 1+    -- sequential execution does not require handling critical sections+    then+      scheduleOpUsing ranges (nativeExecutable !# "permuteS") gamma aenv shr paramR (result, manifest input)+        `andThen` do putIO workers future result+                     touchLifetime nativeExecutable++    -- parallel execution+    else+      case lookupFunction "permuteP_rmw" nativeExecutable of+        -- using atomic operations+        Just f ->+          scheduleOpUsing ranges f gamma aenv shr paramR (result, manifest input)+            `andThen` do putIO workers future result+                         touchLifetime nativeExecutable++        -- uses a temporary array of spin-locks to guard the critical section+        Nothing -> do+          let m           = size shr' shOut+              reprBarrier = ArrayR dim1 $ TupRsingle scalarTypeWord8+              paramR'     = TupRsingle (ParamRarray repr') `TupRpair` TupRsingle (ParamRarray reprBarrier) `TupRpair` TupRsingle (ParamRmaybe $ ParamRarray repr)+          --+          barrier@(Array _ adb) <- allocateRemote reprBarrier ((), m) :: Par Native (Vector Word8)+          liftIO $ memset (unsafeUniqueArrayPtr adb) 0 m+          scheduleOpUsing ranges (nativeExecutable !# "permuteP_mutex") gamma aenv shr paramR' ((result, barrier), manifest input)+            `andThen` do putIO workers future result+                         touchLifetime nativeExecutable+  --+  return future+++{-# INLINE stencil1Op #-}+stencil1Op+    :: HasCallStack+    => TypeR a+    -> ArrayR (Array sh b)+    -> sh+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array sh a)+    -> Par Native (Future (Array sh b))+stencil1Op tp repr halo exe gamma aenv input@(delayedShape -> sh) =+  stencilCore repr exe gamma aenv halo sh (TupRsingle $ ParamRmaybe $ ParamRarray $ ArrayR (arrayRshape repr) tp) (manifest input)++{-# INLINE stencil2Op #-}+stencil2Op+    :: forall aenv sh a b c. HasCallStack+    => TypeR a+    -> TypeR b+    -> ArrayR (Array sh c)+    -> sh+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> Delayed (Array sh a)+    -> Delayed (Array sh b)+    -> Par Native (Future (Array sh c))+stencil2Op t1 t2 repr halo exe gamma aenv input1@(delayedShape -> sh1) input2@(delayedShape -> sh2) =+  stencilCore repr exe gamma aenv halo (intersect (arrayRshape repr) sh1 sh2) (param t1 `TupRpair` param t2) (manifest input1, manifest input2)+  where+    shr = arrayRshape repr+    param :: TypeR t -> ParamsR Native (Maybe (Array sh t))+    param = TupRsingle . ParamRmaybe . ParamRarray . ArrayR shr++{-# INLINE stencilCore #-}+stencilCore+    :: forall aenv sh e params. HasCallStack+    => ArrayR (Array sh e)+    -> ExecutableR Native+    -> Gamma aenv+    -> Val aenv+    -> sh                       -- border dimensions (i.e. index of first interior element)+    -> sh                       -- output array size+    -> ParamsR Native params+    -> params+    -> Par Native (Future (Array sh e))+stencilCore repr NativeR{..} gamma aenv halo sh paramsR params = do+  Native{..} <- gets llvmTarget+  future     <- new+  result     <- allocateRemote repr sh+  let+      shr     = arrayRshape repr+      inside  = nativeExecutable !# "stencil_inside"+      border  = nativeExecutable !# "stencil_border"++      splits  = numWorkers workers+      minsize = case shr of+                  ShapeRsnoc ShapeRz              -> 4096+                  ShapeRsnoc (ShapeRsnoc ShapeRz) -> 64+                  _                               -> 16++      ins     = divideWork shr splits minsize halo (sub sh halo) (,,)+      outs    = asum . flip fmap (stencilBorders shr sh halo) $ \(u,v) -> divideWork shr splits minsize u v (,,)++      sub :: sh -> sh -> sh+      sub a b = go shr a b+        where+          go :: ShapeR t -> t -> t -> t+          go ShapeRz          ()      ()      = ()+          go (ShapeRsnoc shr') (xa,xb) (ya,yb) = (go shr' xa ya, xb - yb)++      paramsR' = TupRsingle (ParamRarray repr) `TupRpair` paramsR+  --+  jobsInside <- mkTasksUsing ins  inside gamma aenv shr paramsR' (result, params)+  jobsBorder <- mkTasksUsing outs border gamma aenv shr paramsR' (result, params)+  let jobTasks  = jobsInside Seq.>< jobsBorder+      jobDone   = Just $ do putIO workers future result+                            touchLifetime nativeExecutable+  --+  liftIO $ schedule workers =<< timed "stencil" Job{..}+  return future++-- Compute the stencil border regions, where we may need to evaluate the+-- boundary conditions.+--+{-# INLINE stencilBorders #-}+stencilBorders+    :: forall sh. HasCallStack+    => ShapeR sh+    -> sh+    -> sh+    -> Seq (sh, sh)+stencilBorders shr sh halo = Seq.fromFunction (2 * rank shr) face+  where+    face :: Int -> (sh, sh)+    face n = go n shr sh halo++    go :: Int -> ShapeR t -> t -> t -> (t, t)+    go _ ShapeRz          ()         ()         = ((), ())+    go n (ShapeRsnoc shr') (sha, sza) (shb, szb)+      = let+            (sha', shb')  = go (n-2) shr' sha shb+            (sza', szb')+              | n <  0    = (0,       sza)+              | n == 0    = (0,       szb)+              | n == 1    = (sza-szb, sza)+              | otherwise = (szb,     sza-szb)+        in+        ((sha', sza'), (shb', szb'))++{-# INLINE aforeignOp #-}+aforeignOp+    :: HasCallStack+    => String+    -> ArraysR as+    -> ArraysR bs+    -> (as -> Par Native (Future bs))+    -> as+    -> Par Native (Future bs)+aforeignOp name _ _ asm arr = do+  wallBegin <- liftIO getMonotonicTime+  result    <- Debug.timed Debug.dump_exec (\wall cpu -> printf "exec: %s %s" name (Debug.elapsedP wall cpu)) (asm arr)+  wallEnd   <- liftIO getMonotonicTime+  liftIO $ Debug.addProcessorTime Debug.Native (wallEnd - wallBegin)+  return result+++-- Skeleton execution+-- ------------------++(!#) :: HasCallStack => Lifetime FunctionTable -> ShortByteString -> Function+(!#) exe name+  = fromMaybe (internalError ("function not found: " ++ S8.unpack name))+  $ lookupFunction name exe++lookupFunction :: ShortByteString -> Lifetime FunctionTable -> Maybe Function+lookupFunction name nativeExecutable = do+  find (\(n,_) -> n == name) (functionTable (unsafeGetValue nativeExecutable))++andThen :: (Maybe a -> t) -> a -> t+andThen f g = f (Just g)++delayedShape :: Delayed (Array sh e) -> sh+delayedShape (Delayed sh) = sh+delayedShape (Manifest a) = shape a++manifest :: Delayed (Array sh e) -> Maybe (Array sh e)+manifest (Manifest a) = Just a+manifest Delayed{}    = Nothing+++{-# INLINABLE scheduleOp #-}+scheduleOp+    :: HasCallStack+    => Function+    -> Gamma aenv+    -> Val aenv+    -> ShapeR sh+    -> sh+    -> ParamsR Native params+    -> params+    -> Maybe Action+    -> Par Native ()+scheduleOp fun gamma aenv shr sz paramsR params done = do+  Native{..} <- gets llvmTarget+  let+      splits  = numWorkers workers+      minsize = case shr of+                  ShapeRsnoc ShapeRz              -> 4096+                  ShapeRsnoc (ShapeRsnoc ShapeRz) -> 64+                  _                               -> 16+  --+  scheduleOpWith splits minsize fun gamma aenv shr sz paramsR params done++-- Schedule an operation over the entire iteration space, specifying the number+-- of partitions and minimum dimension size.+--+{-# INLINABLE scheduleOpWith #-}+scheduleOpWith+    :: Int            -- # subdivisions (hint)+    -> Int            -- minimum size of a dimension (must be a power of two)+    -> Function       -- function to execute+    -> Gamma aenv+    -> Val aenv+    -> ShapeR sh+    -> sh+    -> ParamsR Native params+    -> params+    -> Maybe Action   -- run after the last piece completes+    -> Par Native ()+scheduleOpWith splits minsize fun gamma aenv shr sz paramsR params done = do+  Native{..} <- gets llvmTarget+  job        <- mkJob splits minsize fun gamma aenv shr (empty shr) sz paramsR params done+  liftIO $ schedule workers job++{-# INLINABLE scheduleOpUsing #-}+scheduleOpUsing+    :: Seq (Int, sh, sh)+    -> Function+    -> Gamma aenv+    -> Val aenv+    -> ShapeR sh+    -> ParamsR Native params+    -> params+    -> Maybe Action+    -> Par Native ()+scheduleOpUsing ranges fun gamma aenv shr paramsR params jobDone = do+  Native{..} <- gets llvmTarget+  job        <- mkJobUsing ranges fun gamma aenv shr paramsR params jobDone+  liftIO $ schedule workers job++{-# INLINABLE mkJob #-}+mkJob :: Int+      -> Int+      -> Function+      -> Gamma aenv+      -> Val aenv+      -> ShapeR sh+      -> sh+      -> sh+      -> ParamsR Native params+      -> params+      -> Maybe Action+      -> Par Native Job+mkJob splits minsize fun gamma aenv shr from to paramsR params jobDone =+  mkJobUsing (divideWork shr splits minsize from to (,,)) fun gamma aenv shr paramsR params jobDone++{-# INLINABLE mkJobUsing #-}+mkJobUsing+      :: Seq (Int, sh, sh)+      -> Function+      -> Gamma aenv+      -> Val aenv+      -> ShapeR sh+      -> ParamsR Native params+      -> params+      -> Maybe Action+      -> Par Native Job+mkJobUsing ranges fun@(name,_) gamma aenv shr paramsR params jobDone = do+  jobTasks <- mkTasksUsing ranges fun gamma aenv shr paramsR params+  liftIO    $ timed name Job {..}++{-# INLINABLE mkJobUsingIndex #-}+mkJobUsingIndex+      :: Seq (Int, sh, sh)+      -> Function+      -> Gamma aenv+      -> Val aenv+      -> ShapeR sh+      -> ParamsR Native params+      -> params+      -> Maybe Action+      -> Par Native Job+mkJobUsingIndex ranges fun@(name,_) gamma aenv shr paramsR params jobDone = do+  jobTasks <- mkTasksUsingIndex ranges fun gamma aenv shr paramsR params+  liftIO    $ timed name Job {..}++{-# INLINABLE mkTasksUsing #-}+mkTasksUsing+      :: Seq (Int, sh, sh)+      -> Function+      -> Gamma aenv+      -> Val aenv+      -> ShapeR sh+      -> ParamsR Native params+      -> params+      -> Par Native (Seq Action)+mkTasksUsing ranges (name, f) gamma aenv shr paramsR params = do+  arg <- marshalParams' @Native (paramsR `TupRpair` TupRsingle (ParamRenv gamma)) (params, aenv)+  return $ flip fmap ranges $ \(_,u,v) -> do+    sched $ printf "%s (%s) -> (%s)" (S8.unpack name) (showShape shr u) (showShape shr v)+    let argU = marshalShape' @Native shr u+    let argV = marshalShape' @Native shr v+    callFFI f retVoid $ DL.toList $ argU `DL.append` argV `DL.append` arg++{-# INLINABLE mkTasksUsingIndex #-}+mkTasksUsingIndex+      :: Seq (Int, sh, sh)+      -> Function+      -> Gamma aenv+      -> Val aenv+      -> ShapeR sh+      -> ParamsR Native params+      -> params+      -> Par Native (Seq Action)+mkTasksUsingIndex ranges (name, f) gamma aenv shr paramsR params = do+  arg <- marshalParams' @Native (paramsR `TupRpair` TupRsingle (ParamRenv gamma)) (params, aenv)+  return $ flip fmap ranges $ \(i,u,v) -> do+    sched $ printf "%s (%s) -> (%s)" (S8.unpack name) (showShape shr u) (showShape shr v)+    let argU = marshalShape' @Native shr u+    let argV = marshalShape' @Native shr v+    let argI = DL.singleton $ marshalInt @Native i+    callFFI f retVoid $ DL.toList $ argU `DL.append` argV `DL.append` argI `DL.append` arg+++-- Standard C functions+-- --------------------++memset :: Ptr Word8 -> Word8 -> Int -> IO ()+memset p w s = c_memset p (fromIntegral w) (fromIntegral s) >> return ()++foreign import ccall unsafe "string.h memset" c_memset+    :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8)+++-- Debugging+-- ---------++-- Since the (new) thread scheduler does not operate in block-synchronous mode,+-- it is a bit more difficult to track how long an individual operation took to+-- execute as we won't know when exactly it will begin. The following method+-- (where initial timing information is recorded as the first task) should give+-- reasonable results.+--+-- TLM: missing GC stats information (verbose mode) since we aren't using the+--      the default 'timed' helper.+--+timed :: ShortByteString -> Job -> IO Job+timed name job =+  case Debug.debuggingIsEnabled of+    False -> return job+    True  -> do+      yes <- if Debug.monitoringIsEnabled+               then return True+               else Debug.getFlag Debug.dump_exec+      --+      if yes+        then do+          ref1 <- newIORef 0+          ref2 <- newIORef 0+          let start = do !wall0 <- getMonotonicTime+                         !cpu0  <- getCPUTime+                         writeIORef ref1 wall0+                         writeIORef ref2 cpu0++              end   = do !cpu1  <- getCPUTime+                         !wall1 <- getMonotonicTime+                         !wall0 <- readIORef ref1+                         !cpu0  <- readIORef ref2+                         --+                         let wallTime = wall1 - wall0+                             cpuTime  = fromIntegral (cpu1 - cpu0) * 1E-12+                         --+                         Debug.addProcessorTime Debug.Native cpuTime+                         Debug.traceIO Debug.dump_exec $ printf "exec: %s %s" (S8.unpack name) (Debug.elapsedP wallTime cpuTime)+              --+          return $ Job { jobTasks = start Seq.<| jobTasks job+                       , jobDone  = case jobDone job of+                                      Nothing       -> Just end+                                      Just finished -> Just (finished >> end)+                       }+        else+          return job++-- accelerate/cbits/clock.c+foreign import ccall unsafe "clock_gettime_monotonic_seconds" getMonotonicTime :: IO Double+++sched :: String -> IO ()+sched msg+  = Debug.when Debug.verbose+  $ Debug.when Debug.dump_sched+  $ do tid <- myThreadId+       Debug.putTraceMsg $ printf "sched: %s %s" (show tid) msg 
src/Data/Array/Accelerate/LLVM/Native/Execute/Async.hs view
@@ -1,52 +1,164 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase                 #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE TypeFamilies               #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Execute.Async--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.LLVM.Native.Execute.Async ( -  Async, Stream, Event,-  module Data.Array.Accelerate.LLVM.Execute.Async,+  Async(..), Future(..), IVar(..), getArrays,+  evalPar, putIO,  ) where  -- accelerate-import Data.Array.Accelerate.LLVM.Execute.Async                     hiding ( Async )-import qualified Data.Array.Accelerate.LLVM.Execute.Async           as A-+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.LLVM.Execute.Async+import Data.Array.Accelerate.LLVM.Native.Execute.Scheduler import Data.Array.Accelerate.LLVM.Native.Target+import Data.Array.Accelerate.LLVM.State +-- standard library+import Control.Concurrent+import Control.Monad.Cont+import Control.Monad.State+import Data.IORef+import Data.Sequence                                                ( Seq )+import qualified Data.Sequence                                      as Seq -type Async a = A.AsyncR  Native a-type Stream  = A.StreamR Native-type Event   = A.EventR  Native --- The native backend does everything synchronously.+-- | Evaluate a parallel computation ---instance A.Async Native where-  type StreamR Native = ()-  type EventR  Native = ()+-- The worker threads execute the computation, while the calling thread+-- effectively sleeps waiting for the result.+--+{-# INLINEABLE evalPar #-}+evalPar :: Par Native a -> LLVM Native a+evalPar work = do+  result <- liftIO newEmptyMVar+  runContT (runPar work) (liftIO . putMVar result)+  liftIO $ takeMVar result -  {-# INLINE fork #-}-  fork = return ()+  -- XXX: Running the initial computation on the worker threads can lead to the+  -- workers becoming blocked, possibly waiting for the result MVars to be+  -- filled from previous (lazily evaluated) computations (speculation). This+  -- happened for example with the code from Issue255, when extracting the+  -- result at index > number of worker threads.+  --+  -- liftIO  $ do+  --   schedule (workers native)+  --     Job { jobTasks = Seq.singleton $ evalLLVM native (runContT (runPar work) (liftIO . putMVar result))+  --         , jobDone  = Nothing+  --         }+  --   takeMVar result -  {-# INLINE join #-}-  join () = return () -  {-# INLINE checkpoint #-}-  checkpoint () = return ()+-- Implementation+-- -------------- -  {-# INLINE after #-}-  after () () = return ()+data Future a = Future {-# UNPACK #-} !(IORef (IVar a)) -  {-# INLINE block #-}-  block () = return ()+data IVar a+    = Full    !a+    | Blocked !(Seq (a -> IO ()))+    | Empty++instance Async Native where+  type FutureR Native  = Future+  newtype Par Native a = Par { runPar :: ContT () (LLVM Native) a }+    deriving ( Functor, Applicative, Monad, MonadIO, MonadCont, MonadState Native )++  {-# INLINE new     #-}+  {-# INLINE newFull #-}+  new       = Future <$> liftIO (newIORef Empty)+  newFull v = Future <$> liftIO (newIORef (Full v))++  {-# INLINE fork  #-}+  {-# INLINE spawn #-}+  fork  = id+  spawn = id++  {-# INLINE get #-}+  get (Future ref) =+    callCC $ \k -> do+      native <- gets llvmTarget+      next   <- liftIO . atomicModifyIORef' ref $ \case+                  Empty      -> (Blocked (Seq.singleton (evalParIO native . k)), reschedule)+                  Blocked ks -> (Blocked (ks Seq.|>      evalParIO native . k),  reschedule)+                  Full a     -> (Full a,                                         return a)+      next++  {-# INLINE put #-}+  put future ref = do+    Native{..} <- gets llvmTarget+    liftIO (putIO workers future ref)++  {-# INLINE liftPar #-}+  liftPar = Par . lift++-- | Evaluate a continuation+--+{-# INLINE evalParIO #-}+evalParIO :: Native -> Par Native () -> IO ()+evalParIO native@Native{} work =+  evalLLVM native (runContT (runPar work) return)++-- | The value represented by a future is now available. Push any blocked+-- continuations to the worker threads.+--+{-# INLINEABLE putIO #-}+putIO :: HasCallStack => Workers -> Future a -> a -> IO ()+putIO workers (Future ref) v = do+  ks <- atomicModifyIORef' ref $ \case+          Empty      -> (Full v, Seq.empty)+          Blocked ks -> (Full v, ks)+          _          -> internalError "multiple put"+  --+  schedule workers Job { jobTasks = fmap ($ v) ks+                       , jobDone  = Nothing+                       }++-- | The worker threads should search for other work to execute+--+{-# INLINE reschedule #-}+reschedule :: Par Native a+reschedule = Par $ ContT (\_ -> return ())+++-- reschedule :: Par Native a+-- reschedule = Par $ ContT (const loop)+--   where+--     loop :: ReaderT Schedule (LLVM Native) ()+--     loop = do+--       queue <- ask+--       mwork <- liftIO $ tryPopR queue+--       case mwork of+--         Just work -> runContT (runPar work) (const loop)+--         Nothing   -> liftIO yield >> loop++-- pushL :: MVar (Seq a) -> a -> IO ()+-- pushL ref a =+--   mask_ $ do+--     ma <- tryTakeMVar ref+--     case ma of+--       Nothing -> putMVar ref (Seq.singleton a)+--       Just as -> putMVar ref (a Seq.<| as)++-- popR :: MVar (Seq a) -> IO a+-- popR ref = do+--   q <- takeMVar ref+--   case Seq.viewr q of+--     Seq.EmptyR  -> popR ref   -- should be impossible+--     as Seq.:> a -> putMVar ref as >> return a 
+ src/Data/Array/Accelerate/LLVM/Native/Execute/Divide.hs view
@@ -0,0 +1,178 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+-- |+-- Module      : Data.Array.Accelerate.LLVM.Native.Execute.Divide+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.LLVM.Native.Execute.Divide (++  divideWork, divideWork1++) where++import Data.Array.Accelerate.Representation.Shape++import Data.Bits+import Data.Sequence                                                ( Seq )+import qualified Data.Sequence                                      as Seq+import qualified Data.Vector.Unboxed                                as U+import qualified Data.Vector.Unboxed.Mutable                        as M+++-- Divide the given multidimensional index range into a sequence of work pieces.+-- Splits will be made on the outermost (left-most) index preferentially, so+-- that spans are longest on the innermost dimension (because caches).+--+-- No dimension will be made smaller than the given minimum.+--+-- The number of subdivisions a hint (at most, it should generate a number of+-- pieces rounded up to the next power-of-two).+--+-- Full pieces will occur first in the resulting sequence, with smaller pieces+-- at the end (suitable for work-stealing). Note that the pieces are not sorted+-- according by size, and are ordered in the resulting sequence depending only+-- on whether all dimensions are above the minimum threshold or not. The integer+-- parameter to the apply action can be used to access the chunks linearly (for+-- example, this is useful when evaluating non-commutative operations).+--+-- {-# INLINABLE divideWork #-}+divideWork+    :: ShapeR sh+    -> Int                        -- #subdivisions (hint)+    -> Int                        -- minimum size of a dimension (must be a power of two)+    -> sh                         -- start index (e.g. top-left)+    -> sh                         -- end index   (e.g. bottom-right)+    -> (Int -> sh -> sh -> a)     -- action given start/end index range, and split number in the range [0..]+    -> Seq a+divideWork ShapeRz              = divideWork0+divideWork (ShapeRsnoc ShapeRz) = divideWork1+divideWork shr                  = divideWorkN shr+  --+  -- It is slightly faster to use lists instead of a Sequence here (though the+  -- difference is <1us on 'divideWork empty (Z:.2000) nop 8 32'). However,+  -- later operations will benefit from more efficient append, etc.++divideWork0 :: Int -> Int -> DIM0 -> DIM0 -> (Int -> DIM0 -> DIM0 -> a) -> Seq a+divideWork0 _ _ () () action = Seq.singleton (action 0 () ())++divideWork1 :: Int -> Int -> DIM1 -> DIM1 -> (Int -> DIM1 -> DIM1 -> a) -> Seq a+divideWork1 !pieces !minsize ((), (!from)) ((), (!to)) action =+  let+      split 0 !u !v !i !f !s+        | v - u < minsize = (i+1, f, s Seq.|> apply i u v)+        | otherwise       = (i+1, f Seq.|> apply i u v, s)+      --+      split !s !u !v !i0 !f0 !s0 =+        case findSplitPoint1 u v minsize of+          Nothing       -> (i0+1, f0, s0 Seq.|> apply i0 u v)+          Just (u', v') ->+            let s'         = unsafeShiftR s 1+                (i1,f1,s1) = split s' u  v' i0 f0 s0+                (i2,f2,s2) = split s' u' v  i1 f1 s1+            in+            (i2, f2, s2)++      apply i u v = action i ((), u) ((), v)+      (_, fs, ss) = split pieces from to 0 Seq.empty Seq.empty+  in+  fs Seq.>< ss++{-# INLINE findSplitPoint1 #-}+findSplitPoint1+    :: Int+    -> Int+    -> Int+    -> Maybe (Int, Int)+findSplitPoint1 !u !v !minsize =+  let a = v - u in+  if a <= minsize+    then Nothing+    else+      let b = unsafeShiftR (a+1) 1+          c = minsize - 1+          d = (b+c) .&. complement c+      in+      Just (d+u, v-a+d)+++divideWorkN :: ShapeR sh -> Int -> Int -> sh -> sh -> (Int -> sh -> sh -> a) -> Seq a+divideWorkN !shr !pieces !minsize !from !to action =+  let+      -- Is it worth checking whether the piece is full? Doing so ensures that+      -- full pieces are assigned to threads first, with the non-full blocks+      -- being the ones at the end of the work queue to be stolen.+      --+      split 0 !u !v !i !f !s+        | U.any (< minsize) (U.zipWith (-) v u) = (i+1, f, s Seq.|> apply i u v)+        | otherwise                             = (i+1, f Seq.|> apply i u v, s)+      --+      split !s !u !v !i0 !f0 !s0 =+        case findSplitPointN u v minsize of+          Nothing       -> (i0+1, f0, s0 Seq.|> apply i0 u v)+          Just (u', v') ->+            let s'      = unsafeShiftR s 1+                (i1,f1,s1) = split s' u  v' i0 f0 s0+                (i2,f2,s2) = split s' u' v  i1 f1 s1+            in+            (i2, f2, s2)++      apply i u v = action i (vecToShape shr u) (vecToShape shr v)+      (_, fs, ss) = split pieces (shapeToVec shr from) (shapeToVec shr to) 0 Seq.empty Seq.empty+  in+  fs Seq.>< ss+++-- Determine if and where to split the given index range. Returns new start and+-- end indices if found.+--+{-# INLINE findSplitPointN #-}+findSplitPointN+    :: U.Vector Int           -- start+    -> U.Vector Int           -- end+    -> Int                    -- minimum size of a dimension (must be power of 2)+    -> Maybe (U.Vector Int, U.Vector Int)+findSplitPointN !from !to !minsize =+  let+      mix = U.ifoldr' combine Nothing+          $ U.zipWith (-) to from++      combine i v old =+        if v <= minsize+          then old+          else case old of+                 Nothing    -> Just (i,v)+                 Just (_,u) -> if v < u+                                 then Just (i,v)+                                 else old+  in+  case mix of+    Nothing     -> Nothing+    Just (i,a)  ->+      let b     = unsafeShiftR (a+1) 1    -- divide by 2 (rounded up)+          c     = minsize - 1+          d     = (b+c) .&. complement c  -- round up to next multiple of chunk size+          e     = U.unsafeIndex from i+          f     = U.unsafeIndex to   i+          --+          from' = U.modify (\mv -> M.unsafeWrite mv i (d+e))   from+          to'   = U.modify (\mv -> M.unsafeWrite mv i (f-a+d)) to+      in+      Just (from', to')++{-# INLINE vecToShape #-}+vecToShape :: ShapeR sh -> U.Vector Int -> sh+vecToShape shr = listToShape shr . U.toList++{-# INLINE shapeToVec #-}+shapeToVec :: ShapeR sh -> sh -> U.Vector Int+shapeToVec shr sh = U.fromListN (rank shr) (shapeToList shr sh)+
src/Data/Array/Accelerate/LLVM/Native/Execute/Environment.hs view
@@ -2,24 +2,23 @@ {-# LANGUAGE GADTs #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Execute.Environment--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.LLVM.Native.Execute.Environment ( -  Aval, aprj+  module Data.Array.Accelerate.LLVM.Execute.Environment,+  module Data.Array.Accelerate.LLVM.Native.Execute.Environment,  ) where --- accelerate import Data.Array.Accelerate.LLVM.Native.Target import Data.Array.Accelerate.LLVM.Execute.Environment -type Aval = AvalR Native+type Val = ValR Native 
− src/Data/Array/Accelerate/LLVM/Native/Execute/LBS.hs
@@ -1,34 +0,0 @@--- |--- Module      : Data.Array.Accelerate.LLVM.Native.Execute.LBS--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)--- License     : BSD3------ Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.LLVM.Native.Execute.LBS-  where---- Some default values for the profitable parallelism threshold (PPT). These are--- chosen as to reduce the frequency of deque checks. Since a deque check also--- requires returning from the foreign LLVM function back to the scheduler code,--- it is important to combine fine-grained iterations via the PPT.------ The large PPT is meant for operations such as @map@ and @generate@, where the--- input length equates the total number of elements to process. The small PPT--- is meant for operations such as multidimensional reduction, where each input--- index corresponds to a non-unit amount of work.------ These should really be dynamic values based on how long it took to execute--- the last chunk, increase or decrease the chunk size to ensure quick--- turnaround and also low scheduler overhead.----defaultLargePPT :: Int-defaultLargePPT = 4096--defaultSmallPPT :: Int-defaultSmallPPT = 64-
src/Data/Array/Accelerate/LLVM/Native/Execute/Marshal.hs view
@@ -1,108 +1,39 @@-{-# LANGUAGE CPP                   #-}+{-# LANGUAGE BangPatterns          #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE GADTs                 #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} {-# OPTIONS_GHC -fno-warn-orphans #-}-#if __GLASGOW_HASKELL__ <= 708-{-# LANGUAGE OverlappingInstances  #-}-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Execute.Marshal--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- -module Data.Array.Accelerate.LLVM.Native.Execute.Marshal (--  Marshalable, M.marshal--) where+module Data.Array.Accelerate.LLVM.Native.Execute.Marshal ( module M )+  where  -- accelerate-import Data.Array.Accelerate.LLVM.CodeGen.Environment           ( Gamma, Idx'(..) )-import qualified Data.Array.Accelerate.LLVM.Execute.Marshal     as M+import Data.Array.Accelerate.LLVM.Execute.Marshal               as M+import Data.Array.Accelerate.Array.Unique -import Data.Array.Accelerate.LLVM.Native.Array.Data-import Data.Array.Accelerate.LLVM.Native.Execute.Async-import Data.Array.Accelerate.LLVM.Native.Execute.Environment+import Data.Array.Accelerate.LLVM.Native.Execute.Async          () -- instance Async Native import Data.Array.Accelerate.LLVM.Native.Target  -- libraries-import Data.DList                                               ( DList ) import qualified Data.DList                                     as DL-import qualified Data.IntMap                                    as IM import qualified Foreign.LibFFI                                 as FFI ---- Instances for the Native backend----type Marshalable args       = M.Marshalable Native args-type instance M.ArgR Native = FFI.Arg----- Instances for handling concrete types in this backend, namely shapes and--- array data.----instance M.Marshalable Native Int where-  marshal' _ _ x = return $ DL.singleton (FFI.argInt x)--instance {-# OVERLAPS #-} M.Marshalable Native (Gamma aenv, Aval aenv) where-  marshal' t s (gamma, aenv)-    = fmap DL.concat-    $ mapM (\(_, Idx' idx) -> M.marshal' t s (sync (aprj idx aenv))) (IM.elems gamma)-    where-      sync (AsyncR () a) = a+instance Marshal Native where+  type ArgR Native = FFI.Arg -instance ArrayElt e => M.Marshalable Native (ArrayData e) where-  marshal' _ _ adata = return $ marshalR arrayElt adata-    where-      marshalR :: ArrayEltR e' -> ArrayData e' -> DList FFI.Arg-      marshalR ArrayEltRunit             _  = DL.empty-      marshalR (ArrayEltRpair aeR1 aeR2) ad =-        marshalR aeR1 (fstArrayData ad) `DL.append`-        marshalR aeR2 (sndArrayData ad)-      ---      marshalR (ArrayEltRvec2 ae)  (AD_V2 ad)  = marshalR ae ad-      marshalR (ArrayEltRvec3 ae)  (AD_V3 ad)  = marshalR ae ad-      marshalR (ArrayEltRvec4 ae)  (AD_V4 ad)  = marshalR ae ad-      marshalR (ArrayEltRvec8 ae)  (AD_V8 ad)  = marshalR ae ad-      marshalR (ArrayEltRvec16 ae) (AD_V16 ad) = marshalR ae ad-      ---      marshalR ArrayEltRint     ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRint8    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRint16   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRint32   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRint64   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRword    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRword8   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRword16  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRword32  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRword64  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRhalf    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRfloat   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRdouble  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRchar    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcshort  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcushort ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcint    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcuint   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRclong   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRculong  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcllong  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcullong ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcchar   ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcschar  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcuchar  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcfloat  ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRcdouble ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)-      marshalR ArrayEltRbool    ad = DL.singleton $ FFI.argPtr (ptrsOfArrayData ad)+  marshalInt = FFI.argInt+  marshalScalarData' _ = return . DL.singleton . FFI.argPtr . unsafeUniqueArrayPtr 
+ src/Data/Array/Accelerate/LLVM/Native/Execute/Scheduler.hs view
@@ -0,0 +1,258 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-}+{-# LANGUAGE UnboxedTuples       #-}+-- |+-- Module      : Data.Array.Accelerate.LLVM.Native.Execute.Scheduler+-- Copyright   : [2018..2020] The Accelerate Team+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.LLVM.Native.Execute.Scheduler (++  Action, Job(..), Workers,++  schedule,+  hireWorkers, hireWorkersOn, retireWorkers, fireWorkers, numWorkers,++) where++import qualified Data.Array.Accelerate.LLVM.Native.Debug            as D++import Control.Concurrent+import Control.DeepSeq+import Control.Exception+import Control.Monad+import Data.Concurrent.Queue.MichaelScott+import Data.IORef+import Data.Int+import Data.Sequence                                                ( Seq )+import Text.Printf+import qualified Data.Sequence                                      as Seq++import GHC.Base++#include "MachDeps.h"+++-- An individual computation is a job consisting of a sequence of actions to be+-- executed by the worker threads in parallel.+--+type Action = IO ()++data Task+  = Work Action+  | Retire++data Job = Job+  { jobTasks  :: !(Seq Action)    -- actions required to complete this job+  , jobDone   :: !(Maybe Action)  -- execute after the last action is completed+  }++data Workers = Workers+  { workerCount       :: {-# UNPACK #-} !Int                      -- number of worker threads (length workerThreadIds)+  , workerActive      :: {-# UNPACK #-} !(IORef (MVar ()))        -- fill to signal to the threads to wake up+  , workerTaskQueue   :: {-# UNPACK #-} !(LinkedQueue Task)       -- tasks currently being executed; may be from different jobs+  , workerThreadIds   :: ![ThreadId]                              -- to send signals to / kill+  , workerException   :: !(MVar (Seq (ThreadId, SomeException)))  -- XXX: what should we do with these?+  }+++-- Schedule a job to be executed by the worker threads. May be called+-- concurrently.+--+{-# INLINEABLE schedule #-}+schedule :: Workers -> Job -> IO ()+schedule workers Job{..} = do+  -- Generate the work list. If there is a finalisation action, there is a bit+  -- of extra work to do at each step.+  --+  tasks <- case jobDone of+             Nothing    -> return $ fmap Work jobTasks+             Just done  -> do+                -- The thread which finishes the last task runs the finalisation+                -- action, so keep track of how many items have been completed.+                --+                count <- newAtomic (Seq.length jobTasks)+                return $ flip fmap jobTasks $ \io -> Work $ do+                  _result   <- io+                  remaining <- fetchSubAtomic count -- returns old value+                  when (remaining == 1) done++  -- Submit the tasks to the queue to be executed by the worker threads.+  --+  pushTasks workers tasks+++-- Workers can either be executing tasks (real work), waiting for work, or+-- going into retirement (whence the thread will exit).+--+-- So that threads don't spin endlessly on an empty queue waiting for work,+-- they will automatically sleep waiting on the signal MVar after several+-- failed retries. Note that 'readMVar' is multiple wake up, so all threads+-- will be efficiently woken up when new work is added via 'submit'.+--+-- The MVar is stored in an IORef. When scheduling new work, we resolve the+-- old MVar by putting a value in it, and we put a new, at that moment+-- unresolved, MVar in the IORef. If the queue is empty in runWorker, then+-- we will after some attempts wait on an MVar. It is essential that we+-- first get the MVar out of the IORef, before trying to read from the+-- queue. If this would have been done the other way around, we could have+-- a race condition, where new work is pushed after we tried to dequeue+-- work and before we wait on an MVar. We then wait on the new MVar, which+-- may cause that this thread stalls forever.+--+runWorker :: ThreadId -> IORef (MVar ()) -> LinkedQueue Task -> IO ()+runWorker tid ref queue = loop 0+  where+    loop :: Int16 -> IO ()+    loop !retries = do+      -- Extract the activation MVar from the IORef, before trying to claim+      -- an item from the work queue+      var <- readIORef ref+      req <- tryPopR queue+      case req of+        -- The number of retries and thread delay on failure are knobs which can+        -- be tuned. Having these values too high results in busy work which+        -- will detract from time spent adding new work thus reducing+        -- productivity, whereas low values will reduce responsiveness and thus+        -- also reduce productivity.+        --+        -- TODO: Tune these values a bit+        --+        Nothing   -> if retries < 16+                       then loop (retries+1)+                       else do+                         -- This thread will sleep, by waiting on the MVar (var) we previously+                         -- extracted from the IORef (ref)+                         --+                         -- When some other thread pushes new work, it will also write to that MVar+                         -- and this thread will wake up.+                         message $ printf "sched: %s sleeping" (show tid)++                         -- blocking, wake-up when new work is available+                         () <- readMVar var+                         loop 0+        --+        Just task -> case task of+                       Work io -> io >> loop 0+                       Retire  -> message $ printf "sched: %s shutting down" (show tid)+++-- Spawn a new worker thread for each capability+--+hireWorkers :: IO Workers+hireWorkers = do+  ncpu    <- getNumCapabilities+  workers <- hireWorkersOn [0 .. ncpu-1]+  return workers++-- Spawn worker threads on the specified capabilities+--+hireWorkersOn :: [Int] -> IO Workers+hireWorkersOn caps = do+  active          <- newEmptyMVar+  workerActive    <- newIORef active+  workerException <- newEmptyMVar+  workerTaskQueue <- newQ+  workerThreadIds <- forM caps $ \cpu -> do+                       tid <- mask_ $ forkOnWithUnmask cpu $ \restore -> do+                                tid <- myThreadId+                                catch+                                  (restore $ runWorker tid workerActive workerTaskQueue)+                                  (appendMVar workerException . (tid,))+                       --+                       message $ printf "sched: fork %s on capability %d" (show tid) cpu+                       return tid+  --+  workerThreadIds `deepseq` return Workers { workerCount = length workerThreadIds, ..}+++-- Submit a job telling every worker to retire. Currently pending tasks will be+-- completed first.+--+retireWorkers :: Workers -> IO ()+retireWorkers workers@Workers{..} =+  pushTasks workers (Seq.replicate workerCount Retire)+++-- Pushes work to the task queue+--+-- Wakes up the worker threads if needed, by writing to the old MVar in+-- workerActive. We replace workerActive with a new, empty MVar, such that+-- we can wake them up later when we again have new work.+--+pushTasks :: Workers -> Seq Task -> IO ()+pushTasks Workers{..} tasks = do+  -- Push work to the queue+  mapM_ (pushL workerTaskQueue) tasks++  -- Create a new MVar, which we use in a later call to pushTasks to wake+  -- up the threads, then swap the MVar in the IORef workerActive, with the+  -- new MVar.+  --+  -- This must be atomic, to prevent race conditions when two threads are+  -- adding new work. Without the atomic, it may occur that some MVar is+  -- never resolved, causing that a worker thread which waits on that MVar+  -- to stall.+  new <- newEmptyMVar+  old <- atomicModifyIORef' workerActive (new,)++  -- Resolve the old MVar to wake up all waiting threads+  putMVar old ()+++-- Kill worker threads immediately.+--+fireWorkers :: Workers -> IO ()+fireWorkers Workers{..} =+  mapM_ killThread workerThreadIds++-- Number of workers+--+numWorkers :: Workers -> Int+numWorkers = workerCount+++-- Utility+-- -------++data Atomic = Atomic !(MutableByteArray# RealWorld)++{-# INLINE newAtomic #-}+newAtomic :: Int -> IO Atomic+newAtomic (I# n#) = IO $ \s0 ->+  case SIZEOF_HSINT                 of { I# size#       ->+  case newByteArray# size# s0       of { (# s1, mba# #) ->+  case writeIntArray# mba# 0# n# s1 of { s2             ->  -- non-atomic is ok+    (# s2, Atomic mba# #) }}}++{-# INLINE fetchSubAtomic #-}+fetchSubAtomic :: Atomic -> IO Int+fetchSubAtomic (Atomic mba#) = IO $ \s0 ->+  case fetchSubIntArray# mba# 0# 1# s0 of { (# s1, old# #) ->+    (# s1, I# old# #) }++{-# INLINE appendMVar #-}+appendMVar :: MVar (Seq a) -> a -> IO ()+appendMVar mvar a =+  mask_ $ do+    ma <- tryTakeMVar mvar+    case ma of+      Nothing -> putMVar mvar (Seq.singleton a)+      Just as -> putMVar mvar (as Seq.|> a)+++-- Debug+-- -----++message :: String -> IO ()+message = D.traceIO D.dump_sched+
src/Data/Array/Accelerate/LLVM/Native/Foreign.hs view
@@ -2,13 +2,14 @@ {-# LANGUAGE GADTs               #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving  #-}+{-# LANGUAGE TypeApplications    #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Foreign--- Copyright   : [2016..2017] Trevor L. McDonell+-- Copyright   : [2016..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -24,16 +25,18 @@   Native(..),   liftIO,   module Data.Array.Accelerate.LLVM.Native.Array.Data,+  module Data.Array.Accelerate.LLVM.Native.Execute.Async,  ) where -import qualified Data.Array.Accelerate.Array.Sugar                  as S+import qualified Data.Array.Accelerate.Sugar.Foreign                as S  import Data.Array.Accelerate.LLVM.State import Data.Array.Accelerate.LLVM.CodeGen.Sugar  import Data.Array.Accelerate.LLVM.Foreign import Data.Array.Accelerate.LLVM.Native.Array.Data+import Data.Array.Accelerate.LLVM.Native.Execute.Async import Data.Array.Accelerate.LLVM.Native.Target  import Control.Monad.State@@ -41,14 +44,15 @@   instance Foreign Native where-  foreignAcc _ (ff :: asm (a -> b))-    | Just (ForeignAcc _ asm :: ForeignAcc (a -> b)) <- cast ff = Just (const asm)-    | otherwise                                                 = Nothing--  foreignExp _ (ff :: asm (x -> y))-    | Just (ForeignExp _ asm :: ForeignExp (x -> y)) <- cast ff = Just asm-    | otherwise                                                 = Nothing+  foreignAcc (ff :: asm (a -> b))+    | Just Refl        <- eqT @asm @ForeignAcc+    , ForeignAcc _ asm <- ff = Just asm+    | otherwise              = Nothing +  foreignExp (ff :: asm (x -> y))+    | Just Refl        <- eqT @asm @ForeignExp+    , ForeignExp _ asm <- ff = Just asm+    | otherwise              = Nothing  instance S.Foreign ForeignAcc where   strForeign (ForeignAcc s _) = s@@ -63,13 +67,13 @@ -- data ForeignAcc f where   ForeignAcc :: String-             -> (a -> LLVM Native b)+             -> (a -> Par Native (Future b))              -> ForeignAcc (a -> b)  -- Foreign expressions in the Native backend. -- -- I'm not sure how useful this is; perhaps we want a way to splice in an--- arbitrary llvm-general term, which would give us access to instructions not+-- arbitrary llvm-hs term, which would give us access to instructions not -- currently encoded in Accelerate (i.e. SIMD operations, struct types, etc.) -- data ForeignExp f where
src/Data/Array/Accelerate/LLVM/Native/Link.hs view
@@ -4,10 +4,10 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -62,7 +62,7 @@  -- | Execute some operation with the supplied executable functions ---withExecutable :: ExecutableR Native -> (FunctionTable -> LLVM Native b) -> LLVM Native b+withExecutable :: MonadIO m => ExecutableR Native -> (FunctionTable -> m b) -> m b withExecutable NativeR{..} f = do   r <- f (unsafeGetValue nativeExecutable)   liftIO $ touchLifetime nativeExecutable
src/Data/Array/Accelerate/LLVM/Native/Link/COFF.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE TemplateHaskell #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link.COFF--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Link/Cache.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link.Cache--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Link/ELF.chs view
@@ -2,13 +2,12 @@ {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE MagicHash                #-} {-# LANGUAGE RecordWildCards          #-}-{-# LANGUAGE TemplateHaskell          #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link.ELF--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -39,12 +38,12 @@ import Foreign.Marshal import Foreign.Ptr import Foreign.Storable-import GHC.Prim                                           ( addr2Int#, int2Word#, int2Addr# )+import GHC.ForeignPtr                                     ( mallocPlainForeignPtrAlignedBytes )+import GHC.Prim                                           ( addr2Int#, int2Word# ) import GHC.Ptr                                            ( Ptr(..) ) import GHC.Word                                           ( Word64(..) ) import System.IO.Unsafe import System.Posix.DynamicLinker-import System.Posix.Types                                 ( COff(..) ) import Text.Printf import qualified Data.ByteString                          as B import qualified Data.ByteString.Char8                    as B8@@ -66,16 +65,18 @@ -- specified in the object file, and are ready to be executed on the target -- architecture. ---loadObject :: ByteString -> IO (FunctionTable, ObjectCode)+loadObject :: HasCallStack => ByteString -> IO (FunctionTable, ObjectCode) loadObject obj =   case parseObject obj of-    Left err                              -> $internalError "loadObject" err+    Left err                              -> internalError err     Right (secs, symbols, relocs, strtab) -> do       -- Load the sections into executable memory       --       (funtab, oc) <- loadSegment obj strtab secs symbols relocs -      -- Unmap the executable pages when they are no longer required+      -- The executable pages were allocated on the GC heap. When the pages+      -- are finalised, unset the executable bit and mark them as+      -- read/write so that the memory can be reused.       --       objectcode <- newLifetime [oc]       addFinalizer objectcode $ do@@ -83,7 +84,7 @@         case oc of           Segment vmsize oc_fp ->             withForeignPtr oc_fp $ \oc_p ->-              munmap oc_p vmsize+              mprotect oc_p vmsize ({#const PROT_READ#} .|. {#const PROT_WRITE#})        return (funtab, objectcode) @@ -102,7 +103,8 @@ -- properly. -- loadSegment-    :: ByteString+    :: HasCallStack+    => ByteString     -> ByteString     -> Vector SectionHeader     -> Vector Symbol@@ -144,44 +146,42 @@       vmsize'     = V.last offsets                                  -- bytes required to store all sections       vmsize      = pad pagesize (vmsize' + (V.length symtab * 16)) -- sections + jump tables -  -- Allocate new pages to store the executable code. This is allocated in-  -- the lower 2GB so that 32-bit relocations should work without needing-  -- to go via the jump tables.-  ---  -- The memory is implicitly initialised to zero (corresponding to NOP).-  -- This also takes care of .bss sections.-  ---  seg_p   <- mmap vmsize-  seg_fp  <- newForeignPtr_ seg_p+  seg_fp  <- mallocPlainForeignPtrAlignedBytes vmsize pagesize+  funtab  <- withForeignPtr seg_fp $ \seg_p -> do -  -- Jump tables are placed directly after the segment data-  let jump_p = seg_p `plusPtr` vmsize'-  V.imapM_ (makeJumpIsland jump_p) symtab+              -- Clear the segment data; this takes care of .bss sections+              fillBytes seg_p 0 vmsize -  -- Copy over section data-  V.izipWithM_ (loadSection obj strtab seg_p) offsets secs+              -- Jump tables are placed directly after the segment data+              let jump_p = seg_p `plusPtr` vmsize'+              V.imapM_ (makeJumpIsland jump_p) symtab -  -- Process relocations-  V.mapM_ (processRelocation symtab offsets seg_p jump_p) relocs+              -- Copy over section data+              V.izipWithM_ (loadSection obj strtab seg_p) offsets secs -  -- Mark the page as executable and read-only-  mprotect seg_p vmsize ({#const PROT_READ#} .|. {#const PROT_EXEC#})+              -- Process relocations+              V.mapM_ (processRelocation symtab offsets seg_p jump_p) relocs -  -- Resolve external symbols defined in the sections into function-  -- pointers.-  ---  -- Note that in order to support ahead-of-time compilation, the generated-  -- functions are given unique names by appending with an underscore followed-  -- by a unique ID. The execution phase doesn't need to know about this-  -- however, so un-mangle the name to the basic "map", "fold", etc.-  ---  let funtab              = FunctionTable $ V.toList (V.map resolve (V.filter extern symtab))-      extern Symbol{..}   = sym_binding == Global && sym_type == Func-      resolve Symbol{..}  =-        let name  = BS.toShort (B8.take (B8.length sym_name - 65) sym_name)-            addr  = castPtrToFunPtr (seg_p `plusPtr` (fromIntegral sym_value + offsets V.! sym_section))-        in-        (name, addr)+              -- Mark the page as executable and read-only+              mprotect seg_p vmsize ({#const PROT_READ#} .|. {#const PROT_EXEC#})++              -- Resolve external symbols defined in the sections into function+              -- pointers.+              --+              -- Note that in order to support ahead-of-time compilation, the generated+              -- functions are given unique names by appending with an underscore followed+              -- by a unique ID. The execution phase doesn't need to know about this+              -- however, so un-mangle the name to the basic "map", "fold", etc.+              --+              let funtab              = FunctionTable $ V.toList (V.map resolve (V.filter extern symtab))+                  extern Symbol{..}   = sym_binding == Global && sym_type == Func+                  resolve Symbol{..}  =+                    let name  = BS.toShort (B8.take (B8.length sym_name - 65) sym_name)+                        addr  = castPtrToFunPtr (seg_p `plusPtr` (fromIntegral sym_value + offsets V.! sym_section))+                    in+                    (name, addr)+              --+              return funtab   --   return (funtab, Segment vmsize seg_fp) @@ -204,7 +204,7 @@  -- Load the section at the correct offset into the given segment ---loadSection :: ByteString -> ByteString -> Ptr Word8 -> Int -> Int -> SectionHeader -> IO ()+loadSection :: HasCallStack => ByteString -> ByteString -> Ptr Word8 -> Int -> Int -> SectionHeader -> IO () loadSection obj strtab seg_p sec_num sec_addr SectionHeader{..} =   when (sh_type == ProgBits && sh_size > 0) $ do     message (printf "section %d: Mem: 0x%09x-0x%09x         %s" sec_num sec_addr (sec_addr+sh_size) (B8.unpack (indexStringTable strtab sh_name)))@@ -220,7 +220,7 @@  -- Process local and external relocations. ---processRelocation :: Vector Symbol -> Vector Int -> Ptr Word8 -> Ptr Word8 -> Relocation -> IO ()+processRelocation :: HasCallStack => Vector Symbol -> Vector Int -> Ptr Word8 -> Ptr Word8 -> Relocation -> IO () #ifdef x86_64_HOST_ARCH processRelocation symtab sec_offset seg_p jump_p Relocation{..} = do   message (printf "relocation: 0x%04x to symbol %d in section %d, type=%-14s value=%s%+d" r_offset r_symbol r_section (show r_type) (B8.unpack sym_name) r_addend)@@ -296,7 +296,7 @@       case sym_binding of         Local   -> castPtrToWord64 (seg_p `plusPtr` (sec_offset V.! sym_section + fromIntegral sym_value))         Global  -> sym_value-        Weak    -> $internalError "processRelocation" "unhandled weak symbol"+        Weak    -> internalError "unhandled weak symbol"      Symbol{..} = symtab V.! r_symbol @@ -305,7 +305,7 @@  #else precessRelocation =-  $internalError "processRelocation" "not defined for non-x86_64 architectures yet"+  internalError "not defined for non-x86_64 architectures yet" #endif  @@ -317,12 +317,12 @@ -- -- Actually loading the sections into executable memory happens separately. ---parseObject :: ByteString -> Either String (Vector SectionHeader, Vector Symbol, Vector Relocation, ByteString)+parseObject :: HasCallStack => ByteString -> Either String (Vector SectionHeader, Vector Symbol, Vector Relocation, ByteString) parseObject obj = do   (p, tph, tsec, strix) <- runGet readHeader obj    -- As this is an object file, we do not expect any program headers-  unless (tb_entries tph == 0) $ fail "unhandled program header(s)"+  unless (tb_entries tph == 0) $ Left "unhandled program header(s)"    -- Read the object file headers   secs    <- runGet (V.replicateM (tb_entries tsec) (readSectionHeader p)) (B.drop (tb_fileoff tsec) obj)@@ -592,7 +592,7 @@  readRelocations :: Peek -> ByteString -> SectionHeader -> Either String (Vector Relocation) readRelocations p@Peek{..} obj SectionHeader{..} = do-  unless (sh_type == Rel || sh_type == RelA) $ fail "expected relocation section"+  unless (sh_type == Rel || sh_type == RelA) $ Left "expected relocation section"   --   let nrel = sh_size `quot` sh_entsize   runGet (V.replicateM nrel (readRel p sh_type sh_info)) (B.drop sh_offset obj)@@ -622,7 +622,7 @@  readSymbolTable :: Peek -> Vector SectionHeader -> ByteString -> SectionHeader -> Either String (Vector Symbol) readSymbolTable p@Peek{..} secs obj SectionHeader{..} = do-  unless (sh_type == SymTab) $ fail "expected symbol table"+  unless (sh_type == SymTab) $ Left "expected symbol table"    let nsym    = sh_size `quot` sh_entsize       offset  = sh_offset + sh_entsize  -- First symbol in the table is always null; skip it.@@ -708,35 +708,22 @@   = throwErrnoIfMinus1_ "mprotect"   $ c_mprotect addr (fromIntegral len) (fromIntegral prot) --- Allocate memory pages in the lower 2GB----mmap :: Int -> IO (Ptr Word8)-mmap len-  = throwErrnoIf (== _MAP_FAILED) "mmap"-  $ c_mmap nullPtr (fromIntegral len) prot flags (-1) 0-  where-    prot        = {#const PROT_READ#} .|. {#const PROT_WRITE#}-    flags       = {#const MAP_ANONYMOUS#} .|. {#const MAP_PRIVATE#} .|. {#const MAP_32BIT#}-    _MAP_FAILED = Ptr (int2Addr# (-1#))---- Remove a memory mapping----munmap :: Ptr Word8 -> Int -> IO ()-munmap addr len-  = throwErrnoIfMinus1_ "munmap"-  $ c_munmap addr (fromIntegral len)- foreign import ccall unsafe "mprotect"   c_mprotect :: Ptr a -> CSize -> CInt -> IO CInt -foreign import ccall unsafe "mmap"-  c_mmap :: Ptr a -> CSize -> CInt -> CInt -> CInt -> COff -> IO (Ptr a)--foreign import ccall unsafe "munmap"-  c_munmap :: Ptr a -> CSize -> IO CInt- foreign import ccall unsafe "getpagesize"   c_getpagesize :: CInt++#if __GLASGOW_HASKELL__ <= 708+-- Fill a given number of bytes in memory. Added in base-4.8.0.0.+--+fillBytes :: Ptr a -> Word8 -> Int -> IO ()+fillBytes dest char size = do+  _ <- memset dest (fromIntegral char) (fromIntegral size)+  return ()++foreign import ccall unsafe "string.h" memset  :: Ptr a -> CInt  -> CSize -> IO (Ptr a)+#endif   -- Debug
src/Data/Array/Accelerate/LLVM/Native/Link/MachO.chs view
@@ -5,10 +5,10 @@ {-# LANGUAGE TemplateHaskell          #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link.MachO--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -74,17 +74,17 @@ -- specified in the object file, and are ready to be executed on the target -- architecture. ---loadObject :: ByteString -> IO (FunctionTable, ObjectCode)+loadObject :: HasCallStack => ByteString -> IO (FunctionTable, ObjectCode) loadObject obj =   case parseObject obj of-    Left err            -> $internalError "loadObject" err+    Left err            -> internalError err     Right (symtab, lcs) -> loadSegments obj symtab lcs   -- Execute the load segment commands and return function pointers to the -- executable code in the target memory space. ---loadSegments :: ByteString -> Vector Symbol -> Vector LoadSegment -> IO (FunctionTable, ObjectCode)+loadSegments :: HasCallStack => ByteString -> Vector Symbol -> Vector LoadSegment -> IO (FunctionTable, ObjectCode) loadSegments obj symtab lcs = do   -- Load the segments into executable memory.   --@@ -136,7 +136,7 @@ -- be. These would need to live in different pages in order to be mprotect-ed -- properly. ---loadSegment :: ByteString -> Vector Symbol -> LoadSegment -> IO Segment+loadSegment :: HasCallStack => ByteString -> Vector Symbol -> LoadSegment -> IO Segment loadSegment obj symtab seg@LoadSegment{..} = do   let       pagesize    = fromIntegral c_getpagesize@@ -184,7 +184,7 @@ -- Load a section at the correct offset into the given segment, and apply -- relocations. ---loadSection :: ByteString -> Vector Symbol -> LoadSegment -> Ptr Word8 -> Ptr Word8 -> LoadSection -> IO ()+loadSection :: HasCallStack => ByteString -> Vector Symbol -> LoadSegment -> Ptr Word8 -> Ptr Word8 -> LoadSection -> IO () loadSection obj symtab seg seg_p jump_p sec@LoadSection{..} = do   let (obj_fp, obj_offset, _) = B.toForeignPtr obj   --@@ -201,14 +201,14 @@ -- necessary since we load all sections into the same memory segment at the -- correct offsets. ---processRelocation :: Vector Symbol -> LoadSegment -> Ptr Word8 -> Ptr Word8 -> LoadSection -> RelocationInfo -> IO ()+processRelocation :: HasCallStack => Vector Symbol -> LoadSegment -> Ptr Word8 -> Ptr Word8 -> LoadSection -> RelocationInfo -> IO () #ifdef x86_64_HOST_ARCH-processRelocation symtab LoadSegment{..} seg_p jump_p sec RelocationInfo{..}+processRelocation symtab LoadSegment{} seg_p jump_p sec RelocationInfo{..}   -- Relocation through global offset table   --   | ri_type == X86_64_RELOC_GOT ||     ri_type == X86_64_RELOC_GOT_LOAD-  = $internalError "processRelocation" "Global offset table relocations not handled yet"+  = internalError "Global offset table relocations not handled yet"    -- External symbols, both those defined in the sections of this object, and   -- undefined externals. For the latter, the symbol might be outside of the@@ -257,11 +257,11 @@         0 -> let p' = castPtr pc :: Ptr Word8  in poke p' =<< addend p' x         1 -> let p' = castPtr pc :: Ptr Word16 in poke p' =<< addend p' x         2 -> let p' = castPtr pc :: Ptr Word32 in poke p' =<< addend p' x-        _ -> $internalError "processRelocation" "unhandled relocation size"+        _ -> internalError "unhandled relocation size"  #else precessRelocation =-  $internalError "processRelocation" "not defined for non-x86_64 architectures yet"+  internalError "not defined for non-x86_64 architectures yet" #endif  @@ -718,17 +718,6 @@  foreign import ccall unsafe "getpagesize"   c_getpagesize :: CInt--#if __GLASGOW_HASKELL__ <= 708--- Fill a given number of bytes in memory. Added in base-4.8.0.0.----fillBytes :: Ptr a -> Word8 -> Int -> IO ()-fillBytes dest char size = do-  _ <- memset dest (fromIntegral char) (fromIntegral size)-  return ()--foreign import ccall unsafe "string.h" memset  :: Ptr a -> CInt  -> CSize -> IO (Ptr a)-#endif   -- Debug
src/Data/Array/Accelerate/LLVM/Native/Link/Object.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Link.Object--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Plugin.hs view
@@ -1,11 +1,13 @@ {-# LANGUAGE CPP             #-} {-# LANGUAGE RecordWildCards #-}+{-# OPTIONS_GHC -fno-warn-unused-imports   #-}+{-# OPTIONS_GHC -fno-warn-unused-top-binds #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Plugin--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,17 +18,18 @@  ) where -import GhcPlugins-import Linker-import SysTools+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.LLVM.Native.Plugin.Annotation+import Data.Array.Accelerate.LLVM.Native.Plugin.BuildInfo  import Control.Monad import Data.IORef import Data.List import qualified Data.Map                                           as Map -import Data.Array.Accelerate.LLVM.Native.Plugin.Annotation-import Data.Array.Accelerate.LLVM.Native.Plugin.BuildInfo+import GhcPlugins+import Linker+import SysTools   -- | This GHC plugin is required to support ahead-of-time compilation for the@@ -42,19 +45,19 @@ plugin :: Plugin plugin = defaultPlugin   { installCoreToDos = install+#if __GLASGOW_HASKELL__ >= 806+  , pluginRecompile  = purePlugin+#endif   } -install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]+install :: HasCallStack => [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo] install _ rest = do-#if __GLASGOW_HASKELL__ < 802-  reinitializeGlobals-#endif   let this (CoreDoPluginPass "accelerate-llvm-native" _) = True       this _                                             = False   --   return $ CoreDoPluginPass "accelerate-llvm-native" pass : filter (not . this) rest -pass :: ModGuts -> CoreM ModGuts+pass :: HasCallStack => ModGuts -> CoreM ModGuts pass guts = do   -- Determine the current build environment   --@@ -83,12 +86,10 @@             objs  = map optionOfPath paths         --         linkCmdLineLibs-#if __GLASGOW_HASKELL__ < 800-               $                       dynFlags { ldInputs = opts ++ objs }-#else                $ hscEnv { hsc_dflags = dynFlags { ldInputs = opts ++ objs }}-#endif +    -- This case is not necessary for GHC-8.6 and above.+    --     -- We are building to object code.     --     -- Because of separate compilation, we will only encounter the annotation@@ -99,7 +100,7 @@     -- objects required to build the entire project.     --     _ -> liftIO $ do-+#if __GLASGOW_HASKELL__ < 806       -- Read the object file index and update (we may have added or removed       -- objects for the given module)       --@@ -125,14 +126,10 @@               GnuGold   opts -> GnuGold   (nub (opts ++ allObjs))               DarwinLD  opts -> DarwinLD  (nub (opts ++ allObjs))               SolarisLD opts -> SolarisLD (nub (opts ++ allObjs))-#if __GLASGOW_HASKELL__ >= 800               AixLD     opts -> AixLD     (nub (opts ++ allObjs))-#endif-#if __GLASGOW_HASKELL__ >= 804               LlvmLLD   opts -> LlvmLLD   (nub (opts ++ allObjs))-#endif               UnknownLD      -> UnknownLD  -- no linking performed?-+#endif       return ()    return guts
src/Data/Array/Accelerate/LLVM/Native/Plugin/Annotation.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE DeriveDataTypeable #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Plugin.Annotation--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
src/Data/Array/Accelerate/LLVM/Native/Plugin/BuildInfo.hs view
@@ -1,12 +1,11 @@-{-# LANGUAGE CPP             #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Plugin.BuildInfo--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -29,7 +28,7 @@ mkBuildInfoFileName :: FilePath -> FilePath mkBuildInfoFileName path = path </> "accelerate-llvm-native.buildinfo" -readBuildInfo :: FilePath -> IO (Map Module [FilePath])+readBuildInfo :: HasCallStack => FilePath -> IO (Map Module [FilePath]) readBuildInfo path = do   exists <- doesFileExist path   if not exists@@ -37,7 +36,7 @@     else do       f <- B.readFile path       case decode f of-        Left err -> $internalError "readBuildInfo" err+        Left err -> internalError err         Right m  -> return m  writeBuildInfo :: FilePath -> Map Module [FilePath] -> IO ()@@ -51,15 +50,9 @@     n <- get     return (Module p n) -#if __GLASGOW_HASKELL__ < 800-instance Serialize PackageKey where-  put p = put (packageKeyString p)-  get = stringToPackageKey <$> get-#else instance Serialize UnitId where   put u = put (unitIdString u)   get   = stringToUnitId <$> get-#endif  instance Serialize ModuleName where   put m = put (moduleNameString m)
src/Data/Array/Accelerate/LLVM/Native/State.hs view
@@ -1,11 +1,10 @@ {-# LANGUAGE CPP #-} -- | -- Module      : Data.Array.Accelerate.LLVM.Native.State--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -15,28 +14,17 @@   evalNative,   createTarget, defaultTarget, -  Strategy,-  balancedParIO, unbalancedParIO,- ) where  -- accelerate-import Control.Parallel.Meta-import Control.Parallel.Meta.Worker-import qualified Control.Parallel.Meta.Trans.LBS                as LBS-import qualified Control.Parallel.Meta.Resource.SMP             as SMP-import qualified Control.Parallel.Meta.Resource.Single          as Single-import qualified Control.Parallel.Meta.Resource.Backoff         as Backoff- import Data.Array.Accelerate.LLVM.State import Data.Array.Accelerate.LLVM.Native.Target+import Data.Array.Accelerate.LLVM.Native.Execute.Scheduler import qualified Data.Array.Accelerate.LLVM.Native.Link.Cache   as LC import qualified Data.Array.Accelerate.LLVM.Native.Debug        as Debug  -- library-import Data.ByteString.Short.Char8                              ( ShortByteString, unpack ) import Data.Maybe-import Data.Monoid import System.Environment import System.IO.Unsafe import Text.Printf@@ -53,20 +41,17 @@   -- | Create a Native execution target by spawning a worker thread on each of the--- given capabilities, and using the given strategy to load balance the workers--- when executing parallel operations.+-- given capabilities. -- createTarget-    :: [Int]              -- ^ CPU IDs to launch worker threads on-    -> Strategy           -- ^ Strategy to balance parallel workloads+    :: [Int]              -- ^ CPUs to launch worker threads on     -> IO Native-createTarget caps parallelIO = do-  let size = length caps-  gang   <- forkGangOn caps-  linker <- LC.new-  return $! Native size linker (sequentialIO gang) (parallelIO gang) (size > 1)-+createTarget cpus = do+  gang    <- hireWorkersOn cpus+  linker  <- LC.new+  return  $! Native linker gang +{-- -- | The strategy for balancing work amongst the available worker threads. -- type Strategy = Gang -> Executable@@ -103,6 +88,7 @@     --     let resource = LBS.mkResource ppt (SMP.mkResource retries <> Backoff.mkResource)     in  timed name $ runParIO resource gang range fill+--}   -- Top-level mutable state@@ -120,11 +106,10 @@ -- This globally shared thread gang is auto-initialised on startup and shared by -- all computations (unless the user chooses to 'run' with a different gang). ----- In a data parallel setting, it does not help to have multiple gangs running--- at the same time. This is because a single data parallel computation should--- already be able to keep all threads busy. If we had multiple gangs running at--- the same time, then the system as a whole would run slower as the gangs--- contend for cache and thrash the scheduler.+-- It does not help to have multiple gangs running at the same time, as then the+-- system as a whole may run slower as the threads contend for cache. The+-- scheduler is able to execute operations from multiple sources concurrently,+-- so multiple gangs should not be necessary. -- {-# NOINLINE defaultTarget #-} defaultTarget :: Native@@ -144,11 +129,10 @@   setNumCapabilities (max ncaps nthreads)    Debug.traceIO Debug.dump_gc (printf "gc: initialise native target with %d worker threads" nthreads)-  case nthreads of-    1 -> createTarget [0]        sequentialIO-    n -> createTarget [0 .. n-1] (balancedParIO n)+  createTarget [0 .. nthreads-1]  +{-- -- Debugging -- --------- @@ -159,4 +143,5 @@ {-# INLINE elapsed #-} elapsed :: ShortByteString -> Double -> Double -> String elapsed name x y = printf "exec: %s %s" (unpack name) (Debug.elapsedP x y)+--} 
src/Data/Array/Accelerate/LLVM/Native/Target.hs view
@@ -1,10 +1,9 @@ -- | -- Module      : Data.Array.Accelerate.LLVM.Native.Target--- Copyright   : [2014..2017] Trevor L. McDonell---               [2014..2014] Vinod Grover (NVIDIA Corporation)+-- Copyright   : [2014..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -16,7 +15,7 @@  ) where --- llvm-general+-- llvm-hs import LLVM.Target                                                  hiding ( Target ) import LLVM.AST.DataLayout                                          ( DataLayout ) import qualified LLVM.Relocation                                    as RelocationModel@@ -25,8 +24,8 @@  -- accelerate import Data.Array.Accelerate.LLVM.Native.Link.Cache                 ( LinkCache )+import Data.Array.Accelerate.LLVM.Native.Execute.Scheduler          ( Workers ) import Data.Array.Accelerate.LLVM.Target                            ( Target(..) )-import Control.Parallel.Meta                                        ( Executable )  -- standard library import Data.ByteString                                              ( ByteString )@@ -37,16 +36,13 @@ -- | Native machine code JIT execution target -- data Native = Native-  { gangSize      :: {-# UNPACK #-} !Int-  , linkCache     :: {-# UNPACK #-} !LinkCache-  , fillS         :: {-# UNPACK #-} !Executable-  , fillP         :: {-# UNPACK #-} !Executable-  , segmentOffset :: !Bool+  { linkCache     :: !LinkCache+  , workers       :: !Workers   }  instance Target Native where-  targetTriple     _ = Just nativeTargetTriple-  targetDataLayout _ = Just nativeDataLayout+  targetTriple     = Just nativeTargetTriple+  targetDataLayout = Just nativeDataLayout   -- | String that describes the native target@@ -90,7 +86,7 @@         nativeCPUName         nativeCPUFeatures         targetOptions-        RelocationModel.DynamicNoPIC+        RelocationModel.PIC         CodeModel.Default         CodeOptimisation.Default         k
test/nofib/Main.hs view
@@ -1,9 +1,9 @@ -- | -- Module      : nofib-llvm-native--- Copyright   : [2017] Trevor L. McDonell+-- Copyright   : [2017..2020] The Accelerate Team -- License     : BSD3 ----- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --