packages feed

futhark 0.16.3 → 0.16.4

raw patch · 46 files changed

+799/−670 lines, 46 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Futhark.IR.Prop.Types: shapeMapping :: [TypeBase Shape u0] -> [TypeBase Shape u1] -> Map VName (Set SubExp)
- Futhark.IR.Traversals: mapOnType :: Monad m => (SubExp -> m SubExp) -> Type -> m Type
- Futhark.Internalise.Bindings: type MatchPattern = SrcLoc -> [SubExp] -> InternaliseM [SubExp]
- Futhark.Internalise.Monad: data InternaliseTypeM a
- Futhark.Internalise.Monad: instance Control.Monad.Reader.Class.MonadReader Futhark.Internalise.Monad.TypeEnv Futhark.Internalise.Monad.InternaliseTypeM
- Futhark.Internalise.Monad: instance Control.Monad.State.Class.MonadState Futhark.Internalise.Monad.TypeState Futhark.Internalise.Monad.InternaliseTypeM
- Futhark.Internalise.Monad: instance GHC.Base.Applicative Futhark.Internalise.Monad.InternaliseTypeM
- Futhark.Internalise.Monad: instance GHC.Base.Functor Futhark.Internalise.Monad.InternaliseTypeM
- Futhark.Internalise.Monad: instance GHC.Base.Monad Futhark.Internalise.Monad.InternaliseTypeM
- Futhark.Internalise.Monad: liftInternaliseM :: InternaliseM a -> InternaliseTypeM a
- Futhark.Internalise.Monad: lookupDim :: VName -> InternaliseTypeM (Maybe ExtSize)
- Futhark.Internalise.Monad: runInternaliseTypeM :: InternaliseTypeM a -> InternaliseM a
- Futhark.Internalise.Monad: type DimTable = Map VName ExtSize
- Futhark.Internalise.Monad: withDims :: DimTable -> InternaliseTypeM a -> InternaliseTypeM a
- Futhark.Internalise.TypesValues: boundInTypes :: [TypeParam] -> BoundInTypes
- Futhark.Internalise.TypesValues: data BoundInTypes
- Futhark.Internalise.TypesValues: instance GHC.Base.Monoid Futhark.Internalise.TypesValues.BoundInTypes
- Futhark.Internalise.TypesValues: instance GHC.Base.Semigroup Futhark.Internalise.TypesValues.BoundInTypes
- Futhark.Pass.ExtractKernels.DistributeNests: instance Control.Monad.Trans.Class.MonadTrans (Futhark.Pass.ExtractKernels.DistributeNests.DistNestT lore)
+ Futhark.Actions: compileCAction :: FutharkConfig -> CompilerMode -> FilePath -> Action SeqMem
+ Futhark.Actions: compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem
+ Futhark.Actions: compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem
+ Futhark.IR.Prop.Types: isFree :: Ext a -> Maybe a
+ Futhark.IR.Prop.Types: mapOnExtType :: Monad m => (SubExp -> m SubExp) -> TypeBase ExtShape u -> m (TypeBase ExtShape u)
+ Futhark.IR.Prop.Types: mapOnType :: Monad m => (SubExp -> m SubExp) -> TypeBase Shape u -> m (TypeBase Shape u)
+ Futhark.IR.Syntax.Core: instance Data.Foldable.Foldable Futhark.IR.Syntax.Core.Ext
+ Futhark.IR.Syntax.Core: instance Data.Foldable.Foldable Futhark.IR.Syntax.Core.ShapeBase
+ Futhark.IR.Syntax.Core: instance Data.Traversable.Traversable Futhark.IR.Syntax.Core.Ext
+ Futhark.IR.Syntax.Core: instance Data.Traversable.Traversable Futhark.IR.Syntax.Core.ShapeBase
+ Futhark.Internalise.Bindings: bindingLoopParams :: [TypeParam] -> Pattern -> ([FParam] -> [FParam] -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.TypesValues: instance Control.Monad.State.Class.MonadState Futhark.Internalise.TypesValues.TypeState Futhark.Internalise.TypesValues.InternaliseTypeM
+ Futhark.Internalise.TypesValues: instance GHC.Base.Applicative Futhark.Internalise.TypesValues.InternaliseTypeM
+ Futhark.Internalise.TypesValues: instance GHC.Base.Functor Futhark.Internalise.TypesValues.InternaliseTypeM
+ Futhark.Internalise.TypesValues: instance GHC.Base.Monad Futhark.Internalise.TypesValues.InternaliseTypeM
+ Futhark.Internalise.TypesValues: internaliseLambdaReturnType :: TypeBase (DimDecl VName) () -> InternaliseM [TypeBase Shape NoUniqueness]
+ Futhark.Internalise.TypesValues: internaliseLoopParamType :: TypeBase (DimDecl VName) () -> InternaliseM [TypeBase Shape Uniqueness]
+ Futhark.Pass.ExtractKernels.DistributeNests: liftInner :: (LocalScope lore m, DistLore lore) => m a -> DistNestT lore m a
- Futhark.CodeGen.ImpGen.Kernels.Transpose: type TransposeArgs = (VName, Exp, VName, Exp, Exp, Exp, Exp, Exp, Exp, Exp, Exp, VName)
+ Futhark.CodeGen.ImpGen.Kernels.Transpose: type TransposeArgs = (VName, Exp, VName, Exp, Exp, Exp, Exp, Exp, Exp, VName)
- Futhark.Construct: cmpOpLambda :: (MonadBinder m, Bindable (Lore m)) => CmpOp -> PrimType -> m (Lambda (Lore m))
+ Futhark.Construct: cmpOpLambda :: (MonadBinder m, Bindable (Lore m)) => CmpOp -> m (Lambda (Lore m))
- Futhark.IR.Prop.Types: hasStaticShape :: ExtType -> Maybe Type
+ Futhark.IR.Prop.Types: hasStaticShape :: TypeBase ExtShape u -> Maybe (TypeBase Shape u)
- Futhark.IR.Traversals: Walker :: (SubExp -> m ()) -> (Body lore -> m ()) -> (VName -> m ()) -> (RetType lore -> m ()) -> (BranchType lore -> m ()) -> (FParam lore -> m ()) -> (LParam lore -> m ()) -> (Op lore -> m ()) -> Walker lore m
+ Futhark.IR.Traversals: Walker :: (SubExp -> m ()) -> (Scope lore -> Body lore -> m ()) -> (VName -> m ()) -> (RetType lore -> m ()) -> (BranchType lore -> m ()) -> (FParam lore -> m ()) -> (LParam lore -> m ()) -> (Op lore -> m ()) -> Walker lore m
- Futhark.IR.Traversals: [walkOnBody] :: Walker lore m -> Body lore -> m ()
+ Futhark.IR.Traversals: [walkOnBody] :: Walker lore m -> Scope lore -> Body lore -> m ()
- Futhark.Internalise.AccurateSizes: argShapes :: [VName] -> [TypeBase Shape u0] -> [TypeBase Shape u1] -> [SubExp]
+ Futhark.Internalise.AccurateSizes: argShapes :: (HasScope SOACS m, Monad m) => [VName] -> [FParam] -> [Type] -> m [SubExp]
- Futhark.Internalise.Bindings: stmPattern :: Pattern -> [ExtType] -> ([VName] -> MatchPattern -> InternaliseM a) -> InternaliseM a
+ Futhark.Internalise.Bindings: stmPattern :: Pattern -> [Type] -> ([VName] -> InternaliseM a) -> InternaliseM a
- Futhark.Internalise.Lambdas: type InternaliseLambda = Exp -> [Type] -> InternaliseM ([LParam], Body, [ExtType])
+ Futhark.Internalise.Lambdas: type InternaliseLambda = Exp -> [Type] -> InternaliseM ([LParam], Body, [Type])
- Futhark.Internalise.TypesValues: internaliseParamTypes :: BoundInTypes -> Map VName VName -> [TypeBase (DimDecl VName) ()] -> InternaliseM [[TypeBase ExtShape Uniqueness]]
+ Futhark.Internalise.TypesValues: internaliseParamTypes :: [TypeBase (DimDecl VName) ()] -> InternaliseM [[TypeBase Shape Uniqueness]]
- Futhark.Pass.ExtractKernels.DistributeNests: distribute :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distribute :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> DistNestT lore m (DistAcc lore)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeMap :: (MonadFreshNames m, DistLore lore) => MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeMap :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => MapLoop -> DistAcc lore -> DistNestT lore m (DistAcc lore)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeMapBodyStms :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> Stms SOACS -> DistNestT lore m (DistAcc lore)
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeMapBodyStms :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> Stms SOACS -> DistNestT lore m (DistAcc lore)
- Futhark.Pass.ExtractKernels.DistributeNests: distributeSingleStm :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> Stm SOACS -> DistNestT lore m (Maybe (PostStms lore, Result, KernelNest, DistAcc lore))
+ Futhark.Pass.ExtractKernels.DistributeNests: distributeSingleStm :: (MonadFreshNames m, LocalScope lore m, DistLore lore) => DistAcc lore -> Stm SOACS -> DistNestT lore m (Maybe (PostStms lore, Result, KernelNest, DistAcc lore))

Files

docs/language-reference.rst view
@@ -452,7 +452,7 @@       : | "(" `pat` ")"       : | "(" `pat` ("," `pat`)+ ")"       : | "{" "}"-      : | "{" `fieldid` ["=" `pat`] ["," `fieldid` ["=" `pat`]] "}"+      : | "{" `fieldid` ["=" `pat`] ("," `fieldid` ["=" `pat`])* "}"       : | `constructor` `pat`*       : | `pat` ":" `type`    loopform :   "for" `id` "<" `exp`@@ -1660,6 +1660,17 @@ ....................  Exploit only outer parallelism in the attributed SOAC.++``unroll``+..........++Fully unroll the attributed ``loop``.  If the compiler cannot+determine the exact number of iterations (possibly after other+optimisations and simplifications have taken place), then this+attribute has no code generation effect, but instead results in a+warning.  Be very careful with this attribute: it can massively+increase program size (possibly crashing the compiler) if the loop has+a huge number of iterations.  ``unsafe`` ..........
docs/usage.rst view
@@ -107,8 +107,7 @@ ~~~~~~~~~~~~~~~~  The following options are supported by executables generated with the-GPU backends (``opencl``, ``pyopencl``, ``csopencl``, and-``cuda``).+GPU backends (``opencl``, ``pyopencl``, and ``cuda``).    ``-d DEVICE`` @@ -142,7 +141,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~  The following options are supported by executables generated with the-OpenCL backends (``opencl``, ``pyopencl``, and ``csopencl``):+OpenCL backends (``opencl``, ``pyopencl``):    ``-P`` 
futhark.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4  name:           futhark-version:        0.16.3+version:        0.16.4 synopsis:       An optimising compiler for a functional, array-oriented language.  description:    Futhark is a small programming language designed to be compiled to
src/Futhark/Actions.hs view
@@ -6,13 +6,19 @@   , impCodeGenAction   , kernelImpCodeGenAction   , metricsAction+  , compileCAction+  , compileOpenCLAction+  , compileCUDAAction   ) where  import Control.Monad import Control.Monad.IO.Class+import System.Exit+import System.FilePath+import qualified System.Info -import Futhark.Pipeline+import Futhark.Compiler.CLI import Futhark.Analysis.Alias import Futhark.IR import Futhark.IR.Prop.Aliases@@ -20,7 +26,11 @@ import Futhark.IR.SeqMem (SeqMem) import qualified Futhark.CodeGen.ImpGen.Sequential as ImpGenSequential import qualified Futhark.CodeGen.ImpGen.Kernels as ImpGenKernels+import qualified Futhark.CodeGen.Backends.SequentialC as SequentialC+import qualified Futhark.CodeGen.Backends.CCUDA as CCUDA+import qualified Futhark.CodeGen.Backends.COpenCL as COpenCL import Futhark.Analysis.Metrics+import Futhark.Util (runProgramWithExitCode)  -- | Print the result to stdout, with alias annotations. printAction :: (ASTLore lore, CanBeAliased (Op lore)) => Action lore@@ -53,3 +63,104 @@          , actionDescription = "Translate program into imperative IL with kernels and write it on standard output."          , actionProcedure = liftIO . putStrLn . pretty . snd <=< ImpGenKernels.compileProgOpenCL          }++-- | The @futhark c@ action.+compileCAction :: FutharkConfig -> CompilerMode -> FilePath -> Action SeqMem+compileCAction fcfg mode outpath =+  Action { actionName = "Compile to OpenCL"+         , actionDescription = "Compile to OpenCL"+         , actionProcedure = helper }+  where+    helper prog = do+      cprog <- handleWarnings fcfg $ SequentialC.compileProg prog+      let cpath = outpath `addExtension` "c"+          hpath = outpath `addExtension` "h"++      case mode of+        ToLibrary -> do+          let (header, impl) = SequentialC.asLibrary cprog+          liftIO $ writeFile hpath header+          liftIO $ writeFile cpath impl+        ToExecutable -> do+          liftIO $ writeFile cpath $ SequentialC.asExecutable cprog+          ret <- liftIO $ runProgramWithExitCode "gcc"+                 [cpath, "-O3", "-std=c99", "-lm", "-o", outpath] mempty+          case ret of+            Left err ->+              externalErrorS $ "Failed to run gcc: " ++ show err+            Right (ExitFailure code, _, gccerr) ->+              externalErrorS $ "gcc failed with code " +++              show code ++ ":\n" ++ gccerr+            Right (ExitSuccess, _, _) ->+              return ()++-- | The @futhark opencl@ action.+compileOpenCLAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem+compileOpenCLAction fcfg mode outpath =+  Action { actionName = "Compile to OpenCL"+         , actionDescription = "Compile to OpenCL"+         , actionProcedure = helper }+  where+    helper prog = do+      cprog <- handleWarnings fcfg $ COpenCL.compileProg prog+      let cpath = outpath `addExtension` "c"+          hpath = outpath `addExtension` "h"+          extra_options+            | System.Info.os == "darwin" =+                ["-framework", "OpenCL"]+            | System.Info.os == "mingw32" =+                ["-lOpenCL64"]+            | otherwise =+                ["-lOpenCL"]++      case mode of+        ToLibrary -> do+          let (header, impl) = COpenCL.asLibrary cprog+          liftIO $ writeFile hpath header+          liftIO $ writeFile cpath impl+        ToExecutable -> do+          liftIO $ writeFile cpath $ COpenCL.asExecutable cprog+          ret <- liftIO $ runProgramWithExitCode "gcc"+                 ([cpath, "-O", "-std=c99", "-lm", "-o", outpath] ++ extra_options) mempty+          case ret of+            Left err ->+              externalErrorS $ "Failed to run gcc: " ++ show err+            Right (ExitFailure code, _, gccerr) ->+              externalErrorS $ "gcc failed with code " +++              show code ++ ":\n" ++ gccerr+            Right (ExitSuccess, _, _) ->+              return ()++-- | The @futhark cuda@ action.+compileCUDAAction :: FutharkConfig -> CompilerMode -> FilePath -> Action KernelsMem+compileCUDAAction fcfg mode outpath =+  Action { actionName = "Compile to CUDA"+         , actionDescription = "Compile to CUDA"+         , actionProcedure = helper }+  where+    helper prog = do+      cprog <- handleWarnings fcfg $ CCUDA.compileProg prog+      let cpath = outpath `addExtension` "c"+          hpath = outpath `addExtension` "h"+          extra_options = [ "-lcuda"+                          , "-lcudart"+                          , "-lnvrtc"+                          ]+      case mode of+        ToLibrary -> do+          let (header, impl) = CCUDA.asLibrary cprog+          liftIO $ writeFile hpath header+          liftIO $ writeFile cpath impl+        ToExecutable -> do+          liftIO $ writeFile cpath $ CCUDA.asExecutable cprog+          let args = [cpath, "-O", "-std=c99", "-lm", "-o", outpath]+                     ++ extra_options+          ret <- liftIO $ runProgramWithExitCode "gcc" args mempty+          case ret of+            Left err ->+              externalErrorS $ "Failed to run gcc: " ++ show err+            Right (ExitFailure code, _, gccerr) ->+              externalErrorS $ "gcc failed with code " +++              show code ++ ":\n" ++ gccerr+            Right (ExitSuccess, _, _) ->+              return ()
src/Futhark/CLI/C.hs view
@@ -2,39 +2,13 @@ -- | @futhark c@ module Futhark.CLI.C (main) where -import Control.Monad.IO.Class-import System.FilePath-import System.Exit--import Futhark.Pipeline-import Futhark.Passes-import qualified Futhark.CodeGen.Backends.SequentialC as SequentialC+import Futhark.Actions (compileCAction)+import Futhark.Passes (sequentialCpuPipeline) import Futhark.Compiler.CLI-import Futhark.Util  -- | Run @futhark c@ main :: String -> [String] -> IO () main = compilerMain () []        "Compile sequential C" "Generate sequential C code from optimised Futhark program."-       sequentialCpuPipeline $ \fcfg () mode outpath prog -> do-         cprog <- handleWarnings fcfg $ SequentialC.compileProg prog-         let cpath = outpath `addExtension` "c"-             hpath = outpath `addExtension` "h"--         case mode of-           ToLibrary -> do-             let (header, impl) = SequentialC.asLibrary cprog-             liftIO $ writeFile hpath header-             liftIO $ writeFile cpath impl-           ToExecutable -> do-             liftIO $ writeFile cpath $ SequentialC.asExecutable cprog-             ret <- liftIO $ runProgramWithExitCode "gcc"-                    [cpath, "-O3", "-std=c99", "-lm", "-o", outpath] mempty-             case ret of-               Left err ->-                 externalErrorS $ "Failed to run gcc: " ++ show err-               Right (ExitFailure code, _, gccerr) ->-                 externalErrorS $ "gcc failed with code " ++-                 show code ++ ":\n" ++ gccerr-               Right (ExitSuccess, _, _) ->-                 return ()+       sequentialCpuPipeline $ \fcfg () mode outpath prog ->+  actionProcedure (compileCAction fcfg mode outpath) prog
src/Futhark/CLI/CUDA.hs view
@@ -2,42 +2,13 @@ -- | @futhark cuda@ module Futhark.CLI.CUDA (main) where -import Control.Monad.IO.Class-import System.FilePath-import System.Exit--import Futhark.Passes-import qualified Futhark.CodeGen.Backends.CCUDA as CCUDA-import Futhark.Util+import Futhark.Actions (compileCUDAAction)+import Futhark.Passes (gpuPipeline) import Futhark.Compiler.CLI  -- | Run @futhark cuda@. main :: String -> [String] -> IO () main = compilerMain () []        "Compile CUDA" "Generate CUDA/C code from optimised Futhark program."-       gpuPipeline $ \fcfg () mode outpath prog -> do-         cprog <- handleWarnings fcfg $ CCUDA.compileProg prog-         let cpath = outpath `addExtension` "c"-             hpath = outpath `addExtension` "h"-             extra_options = [ "-lcuda"-                             , "-lcudart"-                             , "-lnvrtc"-                             ]-         case mode of-           ToLibrary -> do-             let (header, impl) = CCUDA.asLibrary cprog-             liftIO $ writeFile hpath header-             liftIO $ writeFile cpath impl-           ToExecutable -> do-             liftIO $ writeFile cpath $ CCUDA.asExecutable cprog-             let args = [cpath, "-O", "-std=c99", "-lm", "-o", outpath]-                        ++ extra_options-             ret <- liftIO $ runProgramWithExitCode "gcc" args mempty-             case ret of-               Left err ->-                 externalErrorS $ "Failed to run gcc: " ++ show err-               Right (ExitFailure code, _, gccerr) ->-                 externalErrorS $ "gcc failed with code " ++-                 show code ++ ":\n" ++ gccerr-               Right (ExitSuccess, _, _) ->-                 return ()+       gpuPipeline $ \fcfg () mode outpath prog ->+  actionProcedure (compileCUDAAction fcfg mode outpath) prog
src/Futhark/CLI/Dev.hs view
@@ -11,15 +11,15 @@ import System.IO import System.Exit import System.Console.GetOpt+import System.FilePath  import Prelude hiding (id) +import Futhark.Compiler.CLI import Futhark.Pass import Futhark.Actions-import Futhark.Compiler import Language.Futhark.Parser (parseFuthark) import Futhark.Util.Options-import Futhark.Pipeline import qualified Futhark.IR.SOACS as SOACS import qualified Futhark.IR.Kernels as Kernels import qualified Futhark.IR.Seq as Seq@@ -125,15 +125,15 @@  data UntypedAction = SOACSAction (Action SOACS.SOACS)                    | KernelsAction (Action Kernels.Kernels)-                   | KernelsMemAction (Action KernelsMem.KernelsMem)-                   | SeqMemAction (Action SeqMem.SeqMem)+                   | KernelsMemAction (FilePath -> Action KernelsMem.KernelsMem)+                   | SeqMemAction (FilePath -> Action SeqMem.SeqMem)                    | PolyAction AllActions  untypedActionName :: UntypedAction -> String untypedActionName (SOACSAction a) = actionName a untypedActionName (KernelsAction a) = actionName a-untypedActionName (SeqMemAction a) = actionName a-untypedActionName (KernelsMemAction a) = actionName a+untypedActionName (SeqMemAction a) = actionName $ a ""+untypedActionName (KernelsMemAction a) = actionName $ a "" untypedActionName (PolyAction a) = actionName (actionSOACS a)  instance Representation UntypedAction where@@ -319,12 +319,20 @@    , Option [] ["compile-imperative"]     (NoArg $ Right $ \opts ->-       opts { futharkAction = SeqMemAction impCodeGenAction })+       opts { futharkAction = SeqMemAction $ const impCodeGenAction })     "Translate program into the imperative IL and write it on standard output."   , Option [] ["compile-imperative-kernels"]     (NoArg $ Right $ \opts ->-       opts { futharkAction = KernelsMemAction kernelImpCodeGenAction })+       opts { futharkAction = KernelsMemAction $ const kernelImpCodeGenAction })     "Translate program into the imperative IL with kernels and write it on standard output."+  , Option [] ["compile-opencl"]+    (NoArg $ Right $ \opts ->+       opts { futharkAction = KernelsMemAction $ compileOpenCLAction newFutharkConfig ToExecutable })+    "Compile the program using the OpenCL backend."+  , Option [] ["compile-c"]+    (NoArg $ Right $ \opts ->+       opts { futharkAction = SeqMemAction $ compileCAction newFutharkConfig ToExecutable })+    "Compile the program using the C backend."   , Option "p" ["print"]     (NoArg $ Right $ \opts ->         opts { futharkAction = PolyAction $ AllActions printAction printAction printAction printAction printAction })@@ -439,11 +447,11 @@                 >>= Defunctionalise.transformProg             Pipeline{} -> do               prog <- runPipelineOnProgram (futharkConfig config) id file-              runPolyPasses config prog+              runPolyPasses config (file `replaceExtension` "") (SOACS prog) -runPolyPasses :: Config -> Prog SOACS.SOACS -> FutharkM ()-runPolyPasses config initial_prog = do-    end_prog <- foldM (runPolyPass pipeline_config) (SOACS initial_prog)+runPolyPasses :: Config -> FilePath -> UntypedPassState -> FutharkM ()+runPolyPasses config base initial_prog = do+    end_prog <- foldM (runPolyPass pipeline_config) initial_prog                 (getFutharkPipeline config)     logMsg $ "Running action " ++ untypedActionName (futharkAction config)     case (end_prog, futharkAction config) of@@ -452,9 +460,9 @@       (Kernels prog, KernelsAction action) ->         actionProcedure action prog       (SeqMem prog, SeqMemAction action) ->-        actionProcedure action prog+        actionProcedure (action base) prog       (KernelsMem prog, KernelsMemAction action) ->-        actionProcedure action prog+        actionProcedure (action base) prog        (SOACS soacs_prog, PolyAction acs) ->         actionProcedure (actionSOACS acs) soacs_prog
src/Futhark/CLI/OpenCL.hs view
@@ -2,47 +2,13 @@ -- | @futhark opencl@ module Futhark.CLI.OpenCL (main) where -import Control.Monad.IO.Class-import System.FilePath-import System.Exit-import qualified System.Info--import Futhark.Pipeline-import Futhark.Passes-import qualified Futhark.CodeGen.Backends.COpenCL as COpenCL-import Futhark.Util+import Futhark.Actions (compileOpenCLAction)+import Futhark.Passes (gpuPipeline) import Futhark.Compiler.CLI  -- | Run @futhark opencl@ main :: String -> [String] -> IO () main = compilerMain () []        "Compile OpenCL" "Generate OpenCL/C code from optimised Futhark program."-       gpuPipeline $ \fcfg () mode outpath prog -> do-         cprog <- handleWarnings fcfg $ COpenCL.compileProg prog-         let cpath = outpath `addExtension` "c"-             hpath = outpath `addExtension` "h"-             extra_options-               | System.Info.os == "darwin" =-                   ["-framework", "OpenCL"]-               | System.Info.os == "mingw32" =-                   ["-lOpenCL64"]-               | otherwise =-                   ["-lOpenCL"]--         case mode of-           ToLibrary -> do-             let (header, impl) = COpenCL.asLibrary cprog-             liftIO $ writeFile hpath header-             liftIO $ writeFile cpath impl-           ToExecutable -> do-             liftIO $ writeFile cpath $ COpenCL.asExecutable cprog-             ret <- liftIO $ runProgramWithExitCode "gcc"-                    ([cpath, "-O", "-std=c99", "-lm", "-o", outpath] ++ extra_options) mempty-             case ret of-               Left err ->-                 externalErrorS $ "Failed to run gcc: " ++ show err-               Right (ExitFailure code, _, gccerr) ->-                 externalErrorS $ "gcc failed with code " ++-                 show code ++ ":\n" ++ gccerr-               Right (ExitSuccess, _, _) ->-                 return ()+       gpuPipeline $ \fcfg () mode outpath prog ->+  actionProcedure (compileOpenCLAction fcfg mode outpath) prog
src/Futhark/CodeGen/Backends/GenericPython.hs view
@@ -436,7 +436,30 @@                           , "Futhark type: {}"                           , "Argument has Python type {} and value: {}"] +badInputType :: Int -> PyExp -> String -> PyExp -> PyExp -> PyStmt+badInputType i e t de dg =+  Raise $ simpleCall "TypeError"+  [Call (Field (String err_msg) "format")+   [Arg (String t), Arg $ simpleCall "type" [e], Arg e, Arg de, Arg dg]]+  where err_msg = unlines [ "Argument #" ++ show i ++ " has invalid value"+                          , "Futhark type: {}"+                          , "Argument has Python type {} and value: {}"+                          , "Expected array with elements of dtype: {}"+                          , "The array given has elements of dtype: {}"] +badInputDim :: Int -> PyExp -> String -> Int -> PyStmt+badInputDim i e typ dimf =+  Raise $ simpleCall "TypeError"+  [Call (Field (String err_msg) "format")+   [Arg eft, Arg aft]]+  where eft = String (concat (replicate dimf "[]") ++ typ)+        aft = BinOp "+" (BinOp "*" (String "[]") (Field e "ndim")) (String typ)+        err_msg = unlines [ "Argument #" ++ show i ++ " has invalid value"+                          , "Dimensionality mismatch"+                          , "Expected Futhark type: {}"+                          , "Bad Python value passed"+                          , "Actual Futhark type: {}"]+ entryPointInput :: (Int, Imp.ExternalValue, PyExp) -> CompilerM op s () entryPointInput (i, Imp.OpaqueValue desc vs, e) = do   let type_is_ok = BinOp "and" (simpleCall "isinstance" [e, Var "opaque"])@@ -470,14 +493,21 @@      prettySigned (ept==Imp.TypeUnsigned) bt]]  entryPointInput (i, Imp.TransparentValue (Imp.ArrayValue mem _ t s dims), e) = do-  let type_is_wrong =-        UnOp "not" $-        BinOp "and"-        (BinOp "in" (simpleCall "type" [e]) (List [Var "np.ndarray"]))-        (BinOp "==" (Field e "dtype") (Var (compilePrimToExtNp t s)))+  let type_is_wrong = UnOp "not" $ BinOp "in" (simpleCall "type" [e]) $ List [Var "np.ndarray"]+  let dtype_is_wrong = UnOp "not" $ BinOp "==" (Field e "dtype") $ Var $ compilePrimToExtNp t s+  let dim_is_wrong = UnOp "not" $ BinOp "==" (Field e "ndim") $ Integer $ toInteger $ length dims   stm $ If type_is_wrong     [badInput i e $ concat (replicate (length dims) "[]") ++      prettySigned (s==Imp.TypeUnsigned) t]+    []+  stm $ If dtype_is_wrong+    [badInputType i e+     (concat (replicate (length dims) "[]") ++ prettySigned (s==Imp.TypeUnsigned) t)+     (simpleCall "np.dtype" [Var (compilePrimToExtNp t s)])+     (Field e "dtype")]+    []+  stm $ If dim_is_wrong+    [badInputDim i e (prettySigned (s==Imp.TypeUnsigned) t ) (length dims)]     []    zipWithM_ (unpackDim e) dims [0..]
src/Futhark/CodeGen/Backends/SimpleRep.hs view
@@ -461,16 +461,16 @@ $esc:("#else") // FIXME: assumes GCC or clang.    static typename int32_t $id:(funName' "ctz8") (typename int8_t x) {-     return smin32(8, __builtin_ctz((typename uint32_t)x));+     return x == 0 ? 8 : __builtin_ctz((typename uint32_t)x);    }    static typename int32_t $id:(funName' "ctz16") (typename int16_t x) {-     return smin32(16, __builtin_ctz((typename uint32_t)x));+     return x == 0 ? 16 : __builtin_ctz((typename uint32_t)x);    }    static typename int32_t $id:(funName' "ctz32") (typename int32_t x) {-     return __builtin_ctz(x);+     return x == 0 ? 32 :  __builtin_ctz(x);    }    static typename int32_t $id:(funName' "ctz64") (typename int64_t x) {-     return __builtin_ctzl(x);+     return x == 0 ? 64 : __builtin_ctzl(x);    } $esc:("#endif")                 |]
src/Futhark/CodeGen/ImpCode.hs view
@@ -258,9 +258,10 @@  -- | Find those memory blocks that are used only lexically.  That is, -- are not used as the source or target of a 'SetMem', or are the--- result of the function.  This is interesting because such memory--- blocks do not need reference counting, but can be managed in a--- purely stack-like fashion.+-- result of the function, nor passed as arguments to other functions.+-- This is interesting because such memory blocks do not need+-- reference counting, but can be managed in a purely stack-like+-- fashion. -- -- We do not look inside any 'Op's.  We assume that no 'Op' is going -- to 'SetMem' a memory block declared outside it.@@ -283,6 +284,9 @@         declared x = go declared x          set (SetMem x y _) = namesFromList [x,y]+        set (Call _ _ args) = foldMap onArg args+          where onArg ExpArg{} = mempty+                onArg (MemArg x) = oneName x         set x = go set x  -- | The set of functions that are called by this code.  Assumes there
src/Futhark/CodeGen/ImpGen.hs view
@@ -110,6 +110,7 @@ import Futhark.Construct (fullSliceNum) import Futhark.MonadFreshNames import Futhark.Util+import Futhark.Util.Loc (noLoc) import Language.Futhark.Warnings  -- | How to compile an t'Op'.@@ -644,6 +645,10 @@ defCompileExp pat (BasicOp op) = defCompileBasicOp pat op  defCompileExp pat (DoLoop ctx val form body) = do+  attrs <- askAttrs+  when ("unroll" `inAttrs` attrs) $+    warn (noLoc::SrcLoc) [] "#[unroll] on loop with unknown number of iterations." -- FIXME: no location.+   dFParams mergepat   forM_ merge $ \(p, se) ->     when ((==0) $ arrayRank $ paramType p) $
src/Futhark/CodeGen/ImpGen/Kernels.hs view
@@ -210,15 +210,14 @@   destloc@(MemLocation destmem _ destIxFun) destslice   srcloc@(MemLocation srcmem srcshape srcIxFun) srcslice   | Just (destoffset, srcoffset,-          num_arrays, size_x, size_y,-          src_elems, dest_elems) <- isMapTransposeKernel bt destloc destslice srcloc srcslice = do+          num_arrays, size_x, size_y) <-+      isMapTransposeKernel bt destloc destslice srcloc srcslice = do        fname <- mapTransposeForType bt       emit $ Imp.Call [] fname         [Imp.MemArg destmem, Imp.ExpArg destoffset,          Imp.MemArg srcmem, Imp.ExpArg srcoffset,-         Imp.ExpArg num_arrays, Imp.ExpArg size_x, Imp.ExpArg size_y,-         Imp.ExpArg src_elems, Imp.ExpArg dest_elems]+         Imp.ExpArg num_arrays, Imp.ExpArg size_x, Imp.ExpArg size_y]    | bt_size <- primByteSize bt,     Just destoffset <-@@ -253,15 +252,14 @@    where params = [memparam destmem, intparam destoffset,                   memparam srcmem, intparam srcoffset,-                  intparam num_arrays, intparam x, intparam y,-                  intparam in_elems, intparam out_elems]+                  intparam num_arrays, intparam x, intparam y]          space = Space "device"         memparam v = Imp.MemParam v space         intparam v = Imp.ScalarParam v $ IntType Int32          [destmem, destoffset, srcmem, srcoffset,-         num_arrays, x, y, in_elems, out_elems,+         num_arrays, x, y,          mulx, muly, block] =            zipWith (VName . nameFromString)            ["destmem",@@ -271,8 +269,6 @@              "num_arrays",              "x_elems",              "y_elems",-             "in_elems",-             "out_elems",              -- The following is only used for low width/height              -- transpose kernels              "mulx",@@ -289,24 +285,12 @@         block_dim = 16          -- When an input array has either width==1 or height==1, performing a-        -- transpose will be the same as performing a copy.  If 'input_size' or-        -- 'output_size' is not equal to width*height, then this trick will not-        -- work when there are more than one array to process, as it is a per-        -- array limit. We could copy each array individually, but currently we-        -- do not.+        -- transpose will be the same as performing a copy.         can_use_copy =-          let in_out_eq = CmpOpExp (CmpEq $ IntType Int32) (v32 in_elems) (v32 out_elems)-              onearr = CmpOpExp (CmpEq $ IntType Int32) (v32 num_arrays) 1-              noprob_widthheight = CmpOpExp (CmpEq $ IntType Int32)-                                     (v32 x * v32 y)-                                     (v32 in_elems)+          let onearr = CmpOpExp (CmpEq $ IntType Int32) (v32 num_arrays) 1               height_is_one = CmpOpExp (CmpEq $ IntType Int32) (v32 y) 1               width_is_one = CmpOpExp (CmpEq $ IntType Int32) (v32 x) 1-          in BinOpExp LogAnd-               in_out_eq-               (BinOpExp LogAnd-                 (BinOpExp LogOr onearr noprob_widthheight)-                 (BinOpExp LogOr width_is_one height_is_one))+          in onearr .&&. (width_is_one .||. height_is_one)          transpose_code =           Imp.If input_is_empty mempty $ mconcat@@ -337,7 +321,7 @@          copy_code =           let num_bytes =-                v32 in_elems * Imp.LeafExp (Imp.SizeOf bt) (IntType Int32)+                v32 x * v32 y * Imp.LeafExp (Imp.SizeOf bt) (IntType Int32)           in Imp.Copy                destmem (Imp.Count $ v32 destoffset) space                srcmem (Imp.Count $ v32 srcoffset) space@@ -347,7 +331,7 @@           Imp.Op . Imp.CallKernel .           mapTransposeKernel (mapTransposeName bt) block_dim_int           (destmem, v32 destoffset, srcmem, v32 srcoffset,-            v32 x, v32 y, v32 in_elems, v32 out_elems,+            v32 x, v32 y,             v32 mulx, v32 muly, v32 num_arrays,             block) bt @@ -355,8 +339,7 @@                      -> MemLocation -> Slice Imp.Exp                      -> MemLocation -> Slice Imp.Exp                      -> Maybe (Imp.Exp, Imp.Exp,-                               Imp.Exp, Imp.Exp, Imp.Exp,-                               Imp.Exp, Imp.Exp)+                               Imp.Exp, Imp.Exp, Imp.Exp) isMapTransposeKernel bt   (MemLocation _ _ destIxFun) destslice   (MemLocation _ _ srcIxFun) srcslice@@ -364,12 +347,12 @@     (perm, destshape) <- unzip perm_and_destshape,     Just src_offset <- IxFun.linearWithOffset srcIxFun' bt_size,     Just (r1, r2, _) <- isMapTranspose perm =-      isOk (product destshape) destshape swap r1 r2 dest_offset src_offset+      isOk destshape swap r1 r2 dest_offset src_offset   | Just dest_offset <- IxFun.linearWithOffset destIxFun' bt_size,     Just (src_offset, perm_and_srcshape) <- IxFun.rearrangeWithOffset srcIxFun' bt_size,     (perm, srcshape) <- unzip perm_and_srcshape,     Just (r1, r2, _) <- isMapTranspose perm =-      isOk (product srcshape) srcshape id r1 r2 dest_offset src_offset+      isOk srcshape id r1 r2 dest_offset src_offset   | otherwise =       Nothing   where bt_size = primByteSize bt@@ -378,11 +361,10 @@         destIxFun' = IxFun.slice destIxFun destslice         srcIxFun' = IxFun.slice srcIxFun srcslice -        isOk elems shape f r1 r2 dest_offset src_offset = do+        isOk shape f r1 r2 dest_offset src_offset = do           let (num_arrays, size_x, size_y) = getSizes shape f r1 r2           return (dest_offset, src_offset,-                  num_arrays, size_x, size_y,-                  elems, elems)+                  num_arrays, size_x, size_y)          getSizes shape f r1 r2 =           let (mapped, notmapped) = splitAt r1 shape
src/Futhark/CodeGen/ImpGen/Kernels/SegScan.hs view
@@ -399,7 +399,7 @@                -> [SegBinOp KernelsMem]                -> KernelBody KernelsMem                -> CallKernelGen ()-compileSegScan pat lvl space scans kbody = do+compileSegScan pat lvl space scans kbody = sWhen (0 .<. n) $ do   emit $ Imp.DebugPrint "\n# SegScan" Nothing    -- Since stage 2 involves a group size equal to the number of groups@@ -421,3 +421,4 @@    scanStage2 pat stage1_num_threads elems_per_group stage1_num_groups crossesSegment space scans   scanStage3 pat (segNumGroups lvl) (segGroupSize lvl) elems_per_group crossesSegment space scans+  where n = product $ map (toExp' int32) $ segSpaceDims space
src/Futhark/CodeGen/ImpGen/Kernels/Transpose.hs view
@@ -24,7 +24,7 @@ -- | The types of the arguments accepted by a transposition function. type TransposeArgs = (VName, Exp,                       VName, Exp,-                      Exp, Exp, Exp, Exp,+                      Exp, Exp,                       Exp, Exp, Exp,                       VName) @@ -51,7 +51,7 @@       , dec index_in $ v32 y_index * width + v32 x_index       , dec index_out $ v32 x_index * height + v32 y_index -      , If (v32 get_global_id_0 .<. input_size)+      , If (v32 get_global_id_0 .<. width * height * num_arrays)         (Write odata (elements $ v32 odata_offset + v32 index_out) t (Space "global") Nonvolatile $          index idata (elements $ v32 idata_offset + v32 index_in) t (Space "global") Nonvolatile)         mempty@@ -83,8 +83,7 @@         For j Int32 elemsPerThread $         let i = v32 j * (tile_dim `quot` elemsPerThread)         in mconcat [ dec index_in $ (v32 y_index + i) * width + v32 x_index-                   , when (v32 y_index + i .<. height .&&.-                           v32 index_in .<. input_size) $+                   , when (v32 y_index + i .<. height) $                      Write block (elements $ (v32 get_local_id_1 + i) * (tile_dim+1)                                              + v32 get_local_id_0)                      t (Space "local") Nonvolatile $@@ -97,8 +96,7 @@         For j Int32 elemsPerThread $         let i = v32 j * (tile_dim `quot` elemsPerThread)         in mconcat [ dec index_out $ (v32 y_index + i) * height + v32 x_index-                   , when (v32 y_index + i .<. width .&&.-                           v32 index_out .<. output_size) $+                   , when (v32 y_index + i .<. width) $                      Write odata (elements $ v32 odata_offset + v32 index_out)                      t (Space "global") Nonvolatile $                      index block (elements $ v32 get_local_id_0 * (tile_dim+1)@@ -114,8 +112,8 @@         when a b = If a b mempty          (odata, basic_odata_offset, idata, basic_idata_offset,-         width, height, input_size, output_size,-         mulx, muly, _num_arrays, block) = args+         width, height,+         mulx, muly, num_arrays, block) = args          -- Be extremely careful when editing this list to ensure that         -- the names match up.  Also, be careful that the tags on@@ -168,7 +166,7 @@           [ dec x_index x_in_index           , dec y_index y_in_index           , dec index_in $ v32 y_index * width + v32 x_index-          , when (v32 x_index .<. width .&&. v32 y_index .<. height .&&. v32 index_in .<. input_size) $+          , when (v32 x_index .<. width .&&. v32 y_index .<. height) $             Write block (elements $ v32 get_local_id_1 * (block_dim+1) + v32 get_local_id_0)             t (Space "local") Nonvolatile $             index idata (elements $ v32 idata_offset + v32 index_in)@@ -177,7 +175,7 @@           , SetScalar x_index x_out_index           , SetScalar y_index y_out_index           , dec index_out $ v32 y_index * height + v32 x_index-          , when (v32 x_index .<. height .&&. v32 y_index .<. width .&&. v32 index_out .<. output_size) $+          , when (v32 x_index .<. height .&&. v32 y_index .<. width) $             Write odata (elements $ v32 odata_offset + v32 index_out)             t (Space "global") Nonvolatile $             index block (elements $ v32 get_local_id_0 * (block_dim+1) + v32 get_local_id_1)@@ -207,10 +205,6 @@ -- of block_dim*2 by block_dim*2+1 elements. Padding each row with -- an additional element prevents bank conflicts from occuring when -- the tile is accessed column-wise.------ Note that input_size and output_size may not equal width*height if--- we are dealing with a truncated array - this happens sometimes for--- coalescing optimisations. mapTransposeKernel :: String -> Integer -> TransposeArgs -> PrimType -> TransposeType                    -> Kernel mapTransposeKernel desc block_dim_int args t kind =@@ -235,7 +229,7 @@         block_dim = fromInteger block_dim_int          (odata, basic_odata_offset, idata, basic_idata_offset,-         width, height, input_size, output_size,+         width, height,          mulx, muly, num_arrays,          block) = args @@ -258,7 +252,7 @@         uses = map (`ScalarUse` int32)                (namesToList $ mconcat $ map freeIn                 [basic_odata_offset, basic_idata_offset, num_arrays,-                 width, height, input_size, output_size, mulx, muly]) +++                 width, height, mulx, muly]) ++                map MemoryUse [odata, idata]          name =
src/Futhark/Construct.hs view
@@ -328,7 +328,7 @@ -- | Construct an unspecified value of the given type. eBlank :: MonadBinder m => Type -> m (Exp (Lore m)) eBlank (Prim t) = return $ BasicOp $ SubExp $ Constant $ blankPrimValue t-eBlank (Array pt shape _) = return $ BasicOp $ Scratch pt $ shapeDims shape+eBlank (Array t shape _) = return $ BasicOp $ Scratch t $ shapeDims shape eBlank Mem{} = error "eBlank: cannot create blank memory"  -- | Sign-extend to the given integer type.@@ -375,8 +375,8 @@  -- | As 'binOpLambda', but for t'CmpOp's. cmpOpLambda :: (MonadBinder m, Bindable (Lore m)) =>-               CmpOp -> PrimType -> m (Lambda (Lore m))-cmpOpLambda cop t = binLambda (CmpOp cop) t Bool+               CmpOp -> m (Lambda (Lore m))+cmpOpLambda cop = binLambda (CmpOp cop) (cmpOpType cop) Bool  binLambda :: (MonadBinder m, Bindable (Lore m)) =>              (SubExp -> SubExp -> BasicOp) -> PrimType -> PrimType
src/Futhark/IR/Primitive.hs view
@@ -210,9 +210,29 @@ -- | A floating-point value. data FloatValue = Float32Value !Float                 | Float64Value !Double-               deriving (Eq, Ord, Show)+               deriving (Show) +instance Eq FloatValue where+  Float32Value x == Float32Value y = isNaN x && isNaN y || x == y+  Float64Value x == Float64Value y = isNaN x && isNaN y || x == y+  Float32Value _ == Float64Value _ = False+  Float64Value _ == Float32Value _ = False +-- The derived Ord instance does not handle NaNs correctly.+instance Ord FloatValue where+  Float32Value x <= Float32Value y = x <= y+  Float64Value x <= Float64Value y = x <= y+  Float32Value _ <= Float64Value _ = True+  Float64Value _ <= Float32Value _ = False++  Float32Value x < Float32Value y = x < y+  Float64Value x < Float64Value y = x < y+  Float32Value _ < Float64Value _ = True+  Float64Value _ < Float32Value _ = False++  (>) = flip (<)+  (>=) = flip (<=)+ instance Pretty FloatValue where   ppr (Float32Value v)     | isInfinite v, v >= 0 = text "f32.inf"@@ -790,6 +810,8 @@  -- | Compare any two primtive values for exact equality. doCmpEq :: PrimValue -> PrimValue -> Bool+doCmpEq (FloatValue (Float32Value v1)) (FloatValue (Float32Value v2)) = v1 == v2+doCmpEq (FloatValue (Float64Value v1)) (FloatValue (Float64Value v2)) = v1 == v2 doCmpEq v1 v2 = v1 == v2  -- | Unsigned less than.
src/Futhark/IR/Prop/Names.hs view
@@ -131,7 +131,9 @@               Walker lore (State FV) freeWalker = identityWalker {                walkOnSubExp = modify . (<>) . freeIn'-             , walkOnBody = modify . (<>) . freeIn'+             , walkOnBody = \scope body -> do+                 modify $ (<>) $ freeIn' body+                 modify $ fvBind (namesFromList (M.keys scope))              , walkOnVName = modify . (<>) . fvName              , walkOnOp = modify . (<>) . freeIn'              }
src/Futhark/IR/Prop/Types.hs view
@@ -34,6 +34,9 @@        , transposeType        , rearrangeType +       , mapOnExtType+       , mapOnType+        , diet         , subtypeOf@@ -43,12 +46,12 @@        , fromDecl         , isExt+       , isFree        , extractShapeContext        , shapeContext        , hasStaticShape        , generaliseExtTypes        , existentialiseExtTypes-       , shapeMapping        , shapeExtMapping           -- * Abbreviations@@ -281,6 +284,28 @@   t `setArrayShape` Shape (rearrangeShape perm' $ arrayDims t)   where perm' = perm ++ [length perm .. arrayRank t - 1] +-- | Transform any t'SubExp's in the type.+mapOnExtType :: Monad m =>+                (SubExp -> m SubExp)+             -> TypeBase ExtShape u+             -> m (TypeBase ExtShape u)+mapOnExtType _ (Prim bt) =+  return $ Prim bt+mapOnExtType _ (Mem space) =+  pure $ Mem space+mapOnExtType f (Array t shape u) =+  Array t <$> (Shape <$> mapM (traverse f) (shapeDims shape)) <*> pure u++-- | Transform any t'SubExp's in the type.+mapOnType :: Monad m =>+             (SubExp -> m SubExp)+          -> TypeBase Shape u+          -> m (TypeBase Shape u)+mapOnType _ (Prim bt) = return $ Prim bt+mapOnType _ (Mem space) = pure $ Mem space+mapOnType f (Array t shape u) =+  Array t <$> (Shape <$> mapM f (shapeDims shape)) <*> pure u+ -- | @diet t@ returns a description of how a function parameter of -- type @t@ might consume its argument. diet :: TypeBase shape Uniqueness -> Diet@@ -333,6 +358,11 @@ isExt (Ext i) = Just i isExt _ = Nothing +-- | If a known size, then return that size.+isFree :: Ext a -> Maybe a+isFree (Free d) = Just d+isFree _ = Nothing+ -- | Given the existential return type of a function, and the shapes -- of the values returned by the function, return the existential -- shape context.  That is, those sizes that are existential in the@@ -357,15 +387,13 @@   where ext (Ext x)  = Just x         ext (Free _) = Nothing --- | If all dimensions of the given 'ExtType' are statically known,--- return the corresponding list of 'Type'.-hasStaticShape :: ExtType -> Maybe Type+-- | If all dimensions of the given 'ExtShape' are statically known,+-- change to the corresponding 'Shape'.+hasStaticShape :: TypeBase ExtShape u -> Maybe (TypeBase Shape u) hasStaticShape (Prim bt) = Just $ Prim bt hasStaticShape (Mem space) = Just $ Mem space hasStaticShape (Array bt (Shape shape) u) =   Array bt <$> (Shape <$> mapM isFree shape) <*> pure u-  where isFree (Free s) = Just s-        isFree (Ext _)  = Nothing  -- | Given two lists of 'ExtType's of the same length, return a list -- of 'ExtType's that is a subtype of the two operands.@@ -406,26 +434,7 @@               Ext i         checkDim d = d --- | In the call @shapeMapping ts1 ts2@, the lists @ts1@ and @ts@ must--- be of equal length and their corresponding elements have the same--- types modulo exact dimensions (but matching array rank is--- important).  The result is a mapping from named dimensions of @ts1@--- to a set of the corresponding dimensions in @ts2@ (because they may--- not fit exactly).------ This function is useful when @ts1@ are the value parameters of some--- function and @ts2@ are the value arguments, and we need to figure--- out which shape context to pass.-shapeMapping :: [TypeBase Shape u0] -> [TypeBase Shape u1] -> M.Map VName (S.Set SubExp)-shapeMapping ts = shapeMapping' ts . map arrayDims---- | Like @shapeMapping@, but works with explicit dimensions.-shapeMapping' :: Ord a => [TypeBase Shape u] -> [[a]] -> M.Map VName (S.Set a)-shapeMapping' = dimMapping arrayDims id match (M.unionWith (<>))-  where match Constant{} _ = M.empty-        match (Var v) dim  = M.singleton v $ S.singleton dim---- | Like 'shapeMapping', but produces a mapping for the dimensions context.+-- | Produce a mapping for the dimensions context. shapeExtMapping :: [TypeBase ExtShape u] -> [TypeBase Shape u1] -> M.Map Int SubExp shapeExtMapping = dimMapping arrayExtDims arrayDims match mappend   where match Free{} _ =  mempty
src/Futhark/IR/SOACS/Simplify.hs view
@@ -656,7 +656,7 @@         onOp = execWriter . mapSOACM identitySOACMapper { mapOnSOACLambda = onLambda }         onLambda lam = do tell $ arrayOps $ lambdaBody lam                           return lam-        walker = identityWalker { walkOnBody = modify . (<>) . arrayOps+        walker = identityWalker { walkOnBody = const $ modify . (<>) . arrayOps                                 , walkOnOp = modify . (<>) . onOp }  replaceArrayOps :: M.Map ArrayOp ArrayOp
src/Futhark/IR/SegOp.hs view
@@ -648,7 +648,7 @@  mapOnSegOpType :: Monad m =>                   SegOpMapper lvl flore tlore m -> Type -> m Type-mapOnSegOpType _tv (Prim pt) = pure $ Prim pt+mapOnSegOpType _tv t@Prim{} = pure t mapOnSegOpType tv (Array pt shape u) = Array pt <$> f shape <*> pure u   where f (Shape dims) = Shape <$> mapM (mapOnSegOpSubExp tv) dims mapOnSegOpType _tv (Mem s) = pure $ Mem s
src/Futhark/IR/Syntax/Core.hs view
@@ -67,6 +67,21 @@ newtype ShapeBase d = Shape { shapeDims :: [d] }                     deriving (Eq, Ord, Show) +instance Functor ShapeBase where+  fmap = fmapDefault++instance Foldable ShapeBase where+  foldMap = foldMapDefault++instance Traversable ShapeBase where+  traverse f = fmap Shape . traverse f . shapeDims++instance Semigroup (ShapeBase d) where+  Shape l1 <> Shape l2 = Shape $ l1 `mappend` l2++instance Monoid (ShapeBase d) where+  mempty = Shape mempty+ -- | The size of an array as a list of subexpressions.  If a variable, -- that variable must be in scope where this array is used. type Shape = ShapeBase SubExp@@ -77,9 +92,15 @@            deriving (Eq, Ord, Show)  instance Functor Ext where-  fmap _ (Ext i) = Ext i-  fmap f (Free a) = Free $ f a+  fmap = fmapDefault +instance Foldable Ext where+  foldMap = foldMapDefault++instance Traversable Ext where+  traverse _ (Ext i) = pure $ Ext i+  traverse f (Free v) = Free <$> f v+ -- | The size of this dimension. type ExtSize = Ext SubExp @@ -101,15 +122,6 @@   stripDims :: Int -> a -> a   -- | Check whether one shape if a subset of another shape.   subShapeOf :: a -> a -> Bool--instance Semigroup (ShapeBase d) where-  Shape l1 <> Shape l2 = Shape $ l1 `mappend` l2--instance Monoid (ShapeBase d) where-  mempty = Shape mempty--instance Functor ShapeBase where-  fmap f = Shape . map f . shapeDims  instance ArrayShape (ShapeBase SubExp) where   shapeRank (Shape l) = length l
src/Futhark/IR/Traversals.hs view
@@ -29,7 +29,6 @@   , identityMapper   , mapExpM   , mapExp-  , mapOnType    -- * Walking   , Walker(..)@@ -45,6 +44,7 @@  import Futhark.IR.Syntax import Futhark.IR.Prop.Scope+import Futhark.IR.Prop.Types (mapOnType)  -- | Express a monad mapping operation on a syntax node.  Each element -- of this structure expresses the operation to be performed on a@@ -162,20 +162,12 @@ mapExp :: Mapper flore tlore Identity -> Exp flore -> Exp tlore mapExp m = runIdentity . mapExpM m --- | Transform any t'SubExp's in the type.-mapOnType :: Monad m =>-             (SubExp -> m SubExp) -> Type -> m Type-mapOnType _ (Prim bt) = return $ Prim bt-mapOnType _ (Mem space) = pure $ Mem space-mapOnType f (Array bt shape u) =-  Array bt <$> (Shape <$> mapM f (shapeDims shape)) <*> pure u- -- | Express a monad expression on a syntax node.  Each element of -- this structure expresses the action to be performed on a given -- child. data Walker lore m = Walker {     walkOnSubExp :: SubExp -> m ()-  , walkOnBody :: Body lore -> m ()+  , walkOnBody :: Scope lore -> Body lore -> m ()   , walkOnVName :: VName -> m ()   , walkOnRetType :: RetType lore -> m ()   , walkOnBranchType :: BranchType lore -> m ()@@ -188,7 +180,7 @@ identityWalker :: Monad m => Walker lore m identityWalker = Walker {                    walkOnSubExp = const $ return ()-                 , walkOnBody = const $ return ()+                 , walkOnBody = const $ const $ return ()                  , walkOnVName = const $ return ()                  , walkOnRetType = const $ return ()                  , walkOnBranchType = const $ return ()@@ -200,11 +192,10 @@ walkOnShape :: Monad m => Walker lore m -> Shape -> m () walkOnShape tv (Shape ds) = mapM_ (walkOnSubExp tv) ds -walkOnType :: Monad m =>-             (SubExp -> m ()) -> Type -> m ()+walkOnType :: Monad m => Walker lore m -> Type -> m () walkOnType _ Prim{} = return () walkOnType _ Mem{} = return ()-walkOnType f (Array _ shape _) = mapM_ f $ shapeDims shape+walkOnType tv (Array _ shape _) = walkOnShape tv shape  walkOnLoopForm :: Monad m => Walker lore m -> LoopForm lore -> m () walkOnLoopForm tv (ForLoop i _ bound loop_vars) =@@ -219,7 +210,7 @@ walkExpM tv (BasicOp (SubExp se)) =   walkOnSubExp tv se walkExpM tv (BasicOp (ArrayLit els rowt)) =-  mapM_ (walkOnSubExp tv) els >> walkOnType (walkOnSubExp tv) rowt+  mapM_ (walkOnSubExp tv) els >> walkOnType tv rowt walkExpM tv (BasicOp (BinOp _ x y)) =   walkOnSubExp tv x >> walkOnSubExp tv y walkExpM tv (BasicOp (CmpOp _ x y)) =@@ -228,9 +219,11 @@   walkOnSubExp tv x walkExpM tv (BasicOp (UnOp _ x)) =   walkOnSubExp tv x-walkExpM tv (If c texp fexp (IfDec ts _)) =-  walkOnSubExp tv c >> walkOnBody tv texp >>-  walkOnBody tv fexp >> mapM_ (walkOnBranchType tv) ts+walkExpM tv (If c texp fexp (IfDec ts _)) = do+  walkOnSubExp tv c+  walkOnBody tv mempty texp+  walkOnBody tv mempty fexp+  mapM_ (walkOnBranchType tv) ts walkExpM tv (Apply _ args ret _) =   mapM_ (walkOnSubExp tv . fst) args >> mapM_ (walkOnRetType tv) ret walkExpM tv (BasicOp (Index arr slice)) =@@ -267,7 +260,8 @@   walkOnLoopForm tv form   mapM_ (walkOnSubExp tv) ctxinits   mapM_ (walkOnSubExp tv) valinits-  walkOnBody tv loopbody+  let scope = scopeOfFParams (ctxparams++valparams) <> scopeOf form+  walkOnBody tv scope loopbody   where (ctxparams,ctxinits) = unzip ctxmerge         (valparams,valinits) = unzip valmerge walkExpM tv (Op op) =
src/Futhark/Internalise.hs view
@@ -2,8 +2,8 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Safe #-} {-# LANGUAGE Strict #-}+{-# LANGUAGE Safe #-} -- | -- -- This module implements a transformation from source to core@@ -73,24 +73,26 @@ internaliseValBind :: E.ValBind -> InternaliseM () internaliseValBind fb@(E.ValBind entry fname retdecl (Info (rettype, _)) tparams params body _ attrs loc) = do   localConstsScope $ bindingParams tparams params $ \shapeparams params' -> do-    rettype_bad <- internaliseReturnType rettype-    let rettype' = zeroExts rettype_bad-     let shapenames = map I.paramName shapeparams         normal_params = shapenames ++ map I.paramName (concat params')         normal_param_names = namesFromList normal_params      fname' <- internaliseFunName fname params -    body' <- do-      msg <- case retdecl of-               Just dt -> errorMsg .-                          ("Function return value does not match shape of type ":) <$>-                          typeExpForError dt-               Nothing -> return $ errorMsg ["Function return value does not match shape of declared return type."]-      internaliseBody body >>=-        ensureResultExtShape msg loc (map I.fromDecl rettype')+    msg <- case retdecl of+             Just dt -> errorMsg .+                        ("Function return value does not match shape of type ":) <$>+                        typeExpForError dt+             Nothing -> return $ errorMsg ["Function return value does not match shape of declared return type."] +    ((rettype', body_res), body_stms) <- collectStms $ do+      body_res <- internaliseExp "res" body+      rettype_bad <- internaliseReturnType rettype+      let rettype' = zeroExts rettype_bad+      return (rettype', body_res)+    body' <- ensureResultExtShape msg loc (map I.fromDecl rettype') $+             mkBody body_stms body_res+     constants <- allConsts     let free_in_fun = freeIn body'                       `namesSubtract` normal_param_names@@ -131,7 +133,8 @@ allDimsFreshInType = bitraverse onDim pure   where onDim (E.NamedDim v) =           E.NamedDim . E.qualName <$> newVName (baseString $ E.qualLeaf v)-        onDim _ = pure AnyDim+        onDim _ =+          E.NamedDim . E.qualName <$> newVName "size"  -- | Replace all named dimensions with a fresh name, and remove all -- constant dimensions.  The point is to remove the constraints, but@@ -327,8 +330,8 @@         letSubExp desc $ I.BasicOp $ I.Reshape new_shape' flat_arr    | otherwise = do-      arr_t_ext <- internaliseReturnType $ E.toStruct arr_t       es' <- mapM (internaliseExp "arr_elem") es+      arr_t_ext <- internaliseReturnType (E.toStruct arr_t)        rowtypes <-         case mapM (fmap rowType . hasStaticShape . I.fromDecl) arr_t_ext of@@ -535,8 +538,8 @@   bindExtSizes ret retext ses   return ses -internaliseExp desc (E.LetPat pat e body (Info ret, Info retext) loc) = do-  ses <- internalisePat desc pat e body loc (internaliseExp desc)+internaliseExp desc (E.LetPat pat e body (Info ret, Info retext) _) = do+  ses <- internalisePat desc pat e body (internaliseExp desc)   bindExtSizes (E.toStruct ret) retext ses   return ses @@ -553,11 +556,9 @@   addStms initstms   mergeinit_ts' <- mapM subExpType mergeinit' -  let ctxinit = argShapes-                (map I.paramName shapepat)-                (map I.paramType mergepat')-                mergeinit_ts'-      ctxmerge = zip shapepat ctxinit+  ctxinit <- argShapes (map I.paramName shapepat) mergepat' mergeinit_ts'++  let ctxmerge = zip shapepat ctxinit       valmerge = zip mergepat' mergeinit'       dropCond = case form of E.While{} -> drop 1                               _         -> id@@ -578,23 +579,20 @@         loc (map (I.paramName . fst) ctxmerge) merge_ts     =<< bodyBind loopbody' -  loop_res <- map I.Var . dropCond <$>-              letTupExp desc (I.DoLoop ctxmerge valmerge form' loopbody'')+  attrs <- asks envAttrs+  loop_res <- map I.Var . dropCond <$> attributing attrs+              (letTupExp desc (I.DoLoop ctxmerge valmerge form' loopbody''))   bindExtSizes (E.toStruct ret) retext loop_res   return loop_res    where     sparams' = map (`TypeParamDim` mempty) sparams -    forLoop nested_mergepat shapepat mergeinit form' = do-      let mergepat' = concat nested_mergepat+    forLoop mergepat' shapepat mergeinit form' =       bodyFromStms $ inScopeOf form' $ do         ses <- internaliseExp "loopres" loopbody         sets <- mapM subExpType ses-        let shapeargs = argShapes-                        (map I.paramName shapepat)-                        (map I.paramType mergepat')-                        sets+        shapeargs <- argShapes (map I.paramName shapepat) mergepat' sets         return (shapeargs ++ ses,                 (form',                  shapepat,@@ -608,11 +606,11 @@        i <- newVName "i" -      bindingParams sparams' [mergepat] $-        \shapepat nested_mergepat ->+      bindingLoopParams sparams' mergepat $+        \shapepat mergepat' ->         bindingLambdaParams [x] (map rowType arr_ts) $ \x_params -> do           let loopvars = zip x_params arr'-          forLoop nested_mergepat shapepat mergeinit $+          forLoop mergepat' shapepat mergeinit $             I.ForLoop i Int32 w loopvars      handleForm mergeinit (E.For i num_iterations) = do@@ -623,30 +621,26 @@               I.Prim (IntType it) -> return it               _                   -> error "internaliseExp DoLoop: invalid type" -      bindingParams sparams' [mergepat] $-        \shapepat nested_mergepat ->-          forLoop nested_mergepat shapepat mergeinit $+      bindingLoopParams sparams' mergepat $+        \shapepat mergepat' ->+          forLoop mergepat' shapepat mergeinit $           I.ForLoop i' it num_iterations' []      handleForm mergeinit (E.While cond) =-      bindingParams sparams' [mergepat] $ \shapepat nested_mergepat -> do+      bindingLoopParams sparams' mergepat $ \shapepat mergepat' -> do         mergeinit_ts <- mapM subExpType mergeinit-        let mergepat' = concat nested_mergepat         -- We need to insert 'cond' twice - once for the initial         -- condition (do we enter the loop at all?), and once with the         -- result values of the loop (do we continue into the next         -- iteration?).  This is safe, as the type rules for the         -- external language guarantees that 'cond' does not consume         -- anything.-        let shapeinit = argShapes-                        (map I.paramName shapepat)-                        (map I.paramType mergepat')-                        mergeinit_ts+        shapeinit <- argShapes (map I.paramName shapepat) mergepat' mergeinit_ts          (loop_initial_cond, init_loop_cond_bnds) <- collectStms $ do           forM_ (zip shapepat shapeinit) $ \(p, se) ->             letBindNames [paramName p] $ BasicOp $ SubExp se-          forM_ (zip (concat nested_mergepat) mergeinit) $ \(p, se) ->+          forM_ (zip mergepat' mergeinit) $ \(p, se) ->             unless (se == I.Var (paramName p)) $             letBindNames [paramName p] $ BasicOp $             case se of I.Var v | not $ primType $ paramType p ->@@ -660,17 +654,14 @@           ses <- internaliseExp "loopres" loopbody           sets <- mapM subExpType ses           loop_while <- newParam "loop_while" $ I.Prim I.Bool-          let shapeargs = argShapes-                          (map I.paramName shapepat)-                          (map I.paramType mergepat')-                          sets+          shapeargs <- argShapes (map I.paramName shapepat) mergepat' sets            -- Careful not to clobber anything.           loop_end_cond_body <- renameBody <=< insertStmsM $ do             forM_ (zip shapepat shapeargs) $ \(p, se) ->               unless (se == I.Var (paramName p)) $               letBindNames [paramName p] $ BasicOp $ SubExp se-            forM_ (zip (concat nested_mergepat) ses) $ \(p, se) ->+            forM_ (zip mergepat' ses) $ \(p, se) ->               unless (se == I.Var (paramName p)) $               letBindNames [paramName p] $ BasicOp $               case se of I.Var v | not $ primType $ paramType p ->@@ -770,14 +761,14 @@   ses <- internaliseExp (desc ++ "_scrutinee") e   res <-     case NE.uncons cs of-    (CasePat pCase eCase locCase, Nothing) -> do+    (CasePat pCase eCase _, Nothing) -> do       (_, pertinent) <- generateCond pCase ses-      internalisePat' pCase pertinent eCase locCase (internaliseExp desc)+      internalisePat' pCase pertinent eCase (internaliseExp desc)     (c, Just cs') -> do-      let CasePat pLast eLast locLast = NE.last cs'+      let CasePat pLast eLast _ = NE.last cs'       bFalse <- do         (_, pertinent) <- generateCond pLast ses-        eLast' <- internalisePat' pLast pertinent eLast locLast internaliseBody+        eLast' <- internalisePat' pLast pertinent eLast internaliseBody         foldM (\bf c' -> eBody $ return $ generateCaseIf ses c' bf) eLast' $           reverse $ NE.init cs'       letTupExp' desc =<< generateCaseIf ses c bFalse@@ -871,7 +862,7 @@     -- Literals are always primitive values.     compares (E.PatternLit e _ _) (se:ses) = do       e' <- internaliseExp1 "constant" e-      t' <- I.elemType <$> subExpType se+      t' <- elemType <$> subExpType se       cmp <- letSubExp "match_lit" $ I.BasicOp $ I.CmpOp (I.CmpEq t') e' se       return ([cmp], [se], ses) @@ -922,29 +913,28 @@               ses'')  generateCaseIf :: [I.SubExp] -> Case -> I.Body -> InternaliseM I.Exp-generateCaseIf ses (CasePat p eCase loc) bFail = do+generateCaseIf ses (CasePat p eCase _) bFail = do   (cond, pertinent) <- generateCond p ses-  eCase' <- internalisePat' p pertinent eCase loc internaliseBody+  eCase' <- internalisePat' p pertinent eCase internaliseBody   eIf (eSubExp cond) (return eCase') (return bFail)  internalisePat :: String -> E.Pattern -> E.Exp-               -> E.Exp -> SrcLoc -> (E.Exp -> InternaliseM a)+               -> E.Exp -> (E.Exp -> InternaliseM a)                -> InternaliseM a-internalisePat desc p e body loc m = do+internalisePat desc p e body m = do   ses <- internaliseExp desc' e-  internalisePat' p ses body loc m+  internalisePat' p ses body m   where desc' = case S.toList $ E.patternIdents p of                   [v] -> baseString $ E.identName v                   _ -> desc  internalisePat' :: E.Pattern -> [I.SubExp]-                -> E.Exp -> SrcLoc -> (E.Exp -> InternaliseM a)+                -> E.Exp -> (E.Exp -> InternaliseM a)                 -> InternaliseM a-internalisePat' p ses body loc m = do-  t <- I.staticShapes <$> mapM I.subExpType ses-  stmPattern p t $ \pat_names match -> do-    ses' <- match loc ses-    forM_ (zip pat_names ses') $ \(v,se) ->+internalisePat' p ses body m = do+  ses_ts <- mapM subExpType ses+  stmPattern p ses_ts $ \pat_names -> do+    forM_ (zip pat_names ses) $ \(v,se) ->       letBindNames [v] $ I.BasicOp $ I.SubExp se     m body @@ -1389,9 +1379,9 @@  internaliseLambda (E.Lambda params body _ (Info (_, rettype)) _) rowtypes =   bindingLambdaParams params rowtypes $ \params' -> do-    rettype' <- internaliseReturnType rettype     body' <- internaliseBody body-    return (params', body', map I.fromDecl rettype')+    rettype' <- internaliseLambdaReturnType rettype+    return (params', body', rettype')  internaliseLambda e _ = error $ "internaliseLambda: unexpected expression:\n" ++ pretty e @@ -1482,7 +1472,7 @@                       y_flat <- letExp "y_flat" $ I.BasicOp $ I.Reshape [I.DimNew x_num_elems] y'                        -- Compare the elements.-                      cmp_lam <- cmpOpLambda (I.CmpEq (elemType x_t)) (elemType x_t)+                      cmp_lam <- cmpOpLambda $ I.CmpEq (elemType x_t)                       cmps <- letExp "cmps" $ I.Op $                               I.Screma x_num_elems (I.mapSOAC cmp_lam) [x_flat, y_flat] @@ -1625,6 +1615,7 @@            <*> internaliseExp (desc ++ "_zip_y") y      handleRest [x] "unzip" = Just $ flip internaliseExp x+     handleRest [x] "trace" = Just $ flip internaliseExp x     handleRest [x] "break" = Just $ flip internaliseExp x @@ -1726,16 +1717,13 @@   (fname', closure, shapes, value_paramts, fun_params, rettype_fun) <-     lookupFunction fname   argts <- mapM subExpType args-  closure_ts <- mapM lookupType closure-  let shapeargs = argShapes shapes value_paramts argts-      diets = replicate (length closure + length shapeargs) I.ObservePrim ++++  shapeargs <- argShapes shapes fun_params argts+  let diets = replicate (length closure + length shapeargs) I.ObservePrim ++               map I.diet value_paramts-      constOrShape = const $ I.Prim int32-      paramts = closure_ts ++-                map constOrShape shapeargs ++ map I.fromDecl value_paramts   args' <- ensureArgShapes "function arguments of wrong shape"            loc (map I.paramName fun_params)-           paramts (map I.Var closure ++ shapeargs ++ args)+           (map I.paramType fun_params) (map I.Var closure ++ shapeargs ++ args)   argts' <- mapM subExpType args'   case rettype_fun $ zip args' argts' of     Nothing -> error $ "Cannot apply " ++ pretty fname ++ " to arguments\n " ++@@ -1756,8 +1744,7 @@ -- language. bindExtSizes :: E.StructType -> [VName] -> [SubExp] -> InternaliseM () bindExtSizes ret retext ses = do-  ts <- concat <$>-        internaliseParamTypes mempty (M.fromList $ zip retext retext) [ret]+  ts <- internaliseType ret   ses_ts <- mapM subExpType ses    let combine t1 t2 =
src/Futhark/Internalise/AccurateSizes.hs view
@@ -10,21 +10,40 @@   where  import Control.Monad+import Data.Maybe import qualified Data.Map.Strict as M-import qualified Data.Set as S  import Futhark.Construct import Futhark.Internalise.Monad import Futhark.IR.SOACS+import Futhark.Util (takeLast) -argShapes :: [VName] -> [TypeBase Shape u0] -> [TypeBase Shape u1] -> [SubExp]-argShapes shapes valts valargts =-  map addShape shapes-  where mapping = shapeMapping valts valargts-        addShape name =-          case M.lookup name mapping of-            Just s | se:_ <- S.toList s -> se-            _ -> intConst Int32 0+shapeMapping :: HasScope SOACS m =>+                [FParam] -> [Type]+             -> m (M.Map VName SubExp)+shapeMapping all_params value_arg_types =+  mconcat <$> zipWithM f value_params value_arg_types+  where value_params = takeLast (length value_arg_types) all_params++        f (Param _ t1@Array{}) t2@Array{} =+          pure $ M.fromList $ mapMaybe match $ zip (arrayDims t1) (arrayDims t2)+        f _ _ =+          pure mempty++        match (Var v, se) = Just (v, se)+        match _ = Nothing++argShapes :: (HasScope SOACS m, Monad m) =>+             [VName] -> [FParam] -> [Type] -> m [SubExp]+argShapes shapes all_params valargts = do+  mapping <- shapeMapping all_params valargts+  let addShape name =+        case M.lookup name mapping of+          Just se -> se+          _ -> intConst Int32 0 -- FIXME: we only need this because+                                -- the defunctionaliser throws away+                                -- sizes.+  return $ map addShape shapes  ensureResultShape :: ErrorMsg SubExp -> SrcLoc -> [Type] -> Body                   -> InternaliseM Body
src/Futhark/Internalise/Bindings.hs view
@@ -1,28 +1,25 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE Safe #-}+-- | Internalising bindings. module Futhark.Internalise.Bindings   (-  -- * Internalising bindings     bindingParams+  , bindingLoopParams   , bindingLambdaParams   , stmPattern-  , MatchPattern   )   where  import Control.Monad.State  hiding (mapM) import Control.Monad.Reader hiding (mapM)-import Control.Monad.Writer hiding (mapM)  import qualified Data.Map.Strict as M-import qualified Data.Set as S  import Language.Futhark as E hiding (matchDims) import qualified Futhark.IR.SOACS as I import Futhark.MonadFreshNames import Futhark.Internalise.Monad import Futhark.Internalise.TypesValues-import Futhark.Internalise.AccurateSizes import Futhark.Util  bindingParams :: [E.TypeParam] -> [E.Pattern]@@ -30,43 +27,44 @@               -> InternaliseM a bindingParams tparams params m = do   flattened_params <- mapM flattenPattern params-  let (params_idents, params_types) = unzip $ concat flattened_params-      bound = boundInTypes tparams-      param_names = M.fromList [ (E.identName x, y) | (x,y) <- params_idents ]-  params_ts <- internaliseParamTypes bound param_names params_types+  let params_idents = concat flattened_params+  params_ts <-+    internaliseParamTypes $+    map (flip E.setAliases () . E.unInfo . E.identType) params_idents   let num_param_idents = map length flattened_params       num_param_ts = map (sum . map length) $ chunks num_param_idents params_ts -  (params_ts', unnamed_shape_params) <--    fmap unzip $ forM params_ts $ \param_ts -> do-      (param_ts', param_unnamed_dims) <- instantiateShapesWithDecls mempty param_ts+  let shape_params = [ I.Param v $ I.Prim I.int32 | E.TypeParamDim v _ <- tparams ]+      shape_subst = M.fromList [ (I.paramName p, [I.Var $ I.paramName p]) | p <- shape_params ]+  bindingFlatPattern params_idents (concat params_ts) $ \valueparams ->+    I.localScope (I.scopeOfFParams $ shape_params++concat valueparams) $+    substitutingVars shape_subst $ m shape_params $+    chunks num_param_ts (concat valueparams) -      return (param_ts',-              param_unnamed_dims)+bindingLoopParams :: [E.TypeParam] -> E.Pattern+                  -> ([I.FParam] -> [I.FParam] -> InternaliseM a)+                  -> InternaliseM a+bindingLoopParams tparams pat m = do+  pat_idents <- flattenPattern pat+  pat_ts <- internaliseLoopParamType (E.patternStructType pat) -  let named_shape_params = [ I.Param v $ I.Prim I.int32 | E.TypeParamDim v _ <- tparams ]-      shape_params = named_shape_params ++ concat unnamed_shape_params+  let shape_params = [ I.Param v $ I.Prim I.int32 | E.TypeParamDim v _ <- tparams ]       shape_subst = M.fromList [ (I.paramName p, [I.Var $ I.paramName p]) | p <- shape_params ]-  bindingFlatPattern params_idents (concat params_ts') $ \valueparams ->++  bindingFlatPattern pat_idents pat_ts $ \valueparams ->     I.localScope (I.scopeOfFParams $ shape_params++concat valueparams) $-    substitutingVars shape_subst $ m shape_params $ chunks num_param_ts (concat valueparams)+    substitutingVars shape_subst $ m shape_params $ concat valueparams  bindingLambdaParams :: [E.Pattern] -> [I.Type]                     -> ([I.LParam] -> InternaliseM a)                     -> InternaliseM a bindingLambdaParams params ts m = do-  (params_idents, params_types) <--    unzip . concat <$> mapM flattenPattern params-  let param_names = M.fromList [ (E.identName x, y) | (x,y) <- params_idents ]-  params_ts <- internaliseParamTypes mempty param_names params_types--  let ascript_substs = lambdaShapeSubstitutions (concat params_ts) ts+  params_idents <- concat <$> mapM flattenPattern params    bindingFlatPattern params_idents ts $ \params' ->-    local (\env -> env { envSubsts = ascript_substs `M.union` envSubsts env }) $     I.localScope (I.scopeOfLParams $ concat params') $ m $ concat params' -processFlatPattern :: Show t => [(E.Ident,VName)] -> [t]+processFlatPattern :: Show t => [E.Ident] -> [t]                    -> InternaliseM ([[I.Param t]], VarSubstitutions) processFlatPattern x y = processFlatPattern' [] x y   where@@ -76,8 +74,8 @@           idents = reverse vs       return (idents, substs') -    processFlatPattern' pat ((p,name):rest) ts = do-      (ps, subst, rest_ts) <- handleMapping ts <$> internaliseBindee (p, name)+    processFlatPattern' pat (p:rest) ts = do+      (ps, subst, rest_ts) <- handleMapping ts <$> internaliseBindee p       processFlatPattern' ((ps, (E.identName p, map (I.Var . I.paramName) subst)) : pat) rest rest_ts      handleMapping ts [] =@@ -87,26 +85,21 @@             (pss, repss, ts'') = handleMapping ts' rs         in (ps++pss, reps:repss, ts'') -    handleMapping' (t:ts) (vname,_) =+    handleMapping' (t:ts) vname =       let v' = I.Param vname t       in ([v'], v', ts)     handleMapping' [] _ =       error $ "processFlatPattern: insufficient identifiers in pattern." ++ show (x, y) -    internaliseBindee :: (E.Ident, VName) -> InternaliseM [(VName, I.DeclExtType)]-    internaliseBindee (bindee, name) = do-      tss <- internaliseParamTypes nothing_bound mempty-             [flip E.setAliases () $ E.unInfo $ E.identType bindee]-      case concat tss of-        [t] -> return [(name, t)]-        tss' -> forM tss' $ \t -> do-          name' <- newVName $ baseString name-          return (name', t)--    -- Fixed up later.-    nothing_bound = boundInTypes []+    internaliseBindee :: E.Ident -> InternaliseM [VName]+    internaliseBindee bindee = do+      let name = E.identName bindee+      n <- internalisedTypeSize $ flip E.setAliases () $ E.unInfo $ E.identType bindee+      case n of+        1 -> return [name]+        _ -> replicateM n $ newVName $ baseString name -bindingFlatPattern :: Show t => [(E.Ident, VName)] -> [t]+bindingFlatPattern :: Show t => [E.Ident] -> [t]                    -> ([[I.Param t]] -> InternaliseM a)                    -> InternaliseM a bindingFlatPattern idents ts m = do@@ -116,17 +109,15 @@  -- | Flatten a pattern.  Returns a list of identifiers.  The -- structural type of each identifier is returned separately.-flattenPattern :: MonadFreshNames m => E.Pattern -> m [((E.Ident, VName), E.StructType)]+flattenPattern :: MonadFreshNames m => E.Pattern -> m [E.Ident] flattenPattern = flattenPattern'   where flattenPattern' (E.PatternParens p _) =           flattenPattern' p         flattenPattern' (E.Wildcard t loc) = do           name <- newVName "nameless"           flattenPattern' $ E.Id name t loc-        flattenPattern' (E.Id v (Info t) loc) = do-          new_name <- newVName $ baseString v-          return [((E.Ident v (Info t) loc, new_name),-                   t `E.setAliases` ())]+        flattenPattern' (E.Id v (Info t) loc) =+          return [E.Ident v (Info t) loc]         -- XXX: treat empty tuples and records as bool.         flattenPattern' (E.TuplePattern [] loc) =           flattenPattern' (E.Wildcard (Info $ E.Scalar $ E.Prim E.Bool) loc)@@ -143,63 +134,11 @@         flattenPattern' (E.PatternConstr _ _ ps _) =           concat <$> mapM flattenPattern' ps -type MatchPattern = SrcLoc -> [I.SubExp] -> InternaliseM [I.SubExp]--stmPattern :: E.Pattern -> [I.ExtType]-           -> ([VName] -> MatchPattern -> InternaliseM a)+stmPattern :: E.Pattern -> [I.Type]+           -> ([VName] -> InternaliseM a)            -> InternaliseM a stmPattern pat ts m = do-  (pat', pat_types) <- unzip <$> flattenPattern pat-  (ts',_) <- instantiateShapes' ts-  pat_types' <- internaliseParamTypes mempty mempty pat_types-  let pat_types'' = map I.fromDecl $ concat pat_types'+  pat' <- flattenPattern pat   let addShapeStms l =-        m (map I.paramName $ concat l) (matchPattern pat_types'')-  bindingFlatPattern pat' ts' addShapeStms--matchPattern :: [I.ExtType] -> MatchPattern-matchPattern exts loc ses =-  forM (zip exts ses) $ \(et, se) -> do-  se_t <- I.subExpType se-  et' <- unExistentialise mempty et se_t-  ensureExtShape (I.ErrorMsg [I.ErrorString "value cannot match pattern"])-    loc et' "correct_shape" se--unExistentialise :: S.Set VName -> I.ExtType -> I.Type -> InternaliseM I.ExtType-unExistentialise tparam_names et t = do-  new_dims <- zipWithM inspectDim (I.shapeDims $ I.arrayShape et) (I.arrayDims t)-  return $ t `I.setArrayShape` I.Shape new_dims-  where inspectDim (I.Free (I.Var v)) d-          | v `S.member` tparam_names = do-              letBindNames [v] $ I.BasicOp $ I.SubExp d-              return $ I.Free $ I.Var v-        inspectDim ed _ = return ed--instantiateShapesWithDecls :: MonadFreshNames m =>-                              M.Map Int I.Ident-                           -> [I.DeclExtType]-                           -> m ([I.DeclType], [I.FParam])-instantiateShapesWithDecls ctx ts =-  runWriterT $ instantiateShapes instantiate ts-  where instantiate x-          | Just v <- M.lookup x ctx =-            return $ I.Var $ I.identName v--          | otherwise = do-            v <- lift $ nonuniqueParamFromIdent <$> newIdent "size" (I.Prim I.int32)-            tell [v]-            return $ I.Var $ I.paramName v--lambdaShapeSubstitutions :: [I.TypeBase I.ExtShape Uniqueness]-                         -> [I.Type]-                         -> VarSubstitutions-lambdaShapeSubstitutions param_ts ts =-  mconcat $ zipWith matchTypes param_ts ts-  where matchTypes pt t =-          mconcat $ zipWith matchDims (I.shapeDims $ I.arrayShape pt) (I.arrayDims t)-        matchDims (I.Free (I.Var v)) d = M.singleton v [d]-        matchDims _ _ = mempty--nonuniqueParamFromIdent :: I.Ident -> I.FParam-nonuniqueParamFromIdent (I.Ident name t) =-  I.Param name $ I.toDecl t Nonunique+        m (map I.paramName $ concat l)+  bindingFlatPattern pat' ts addShapeStms
src/Futhark/Internalise/Defunctionalise.hs view
@@ -6,9 +6,11 @@   ( transformProg ) where  import qualified Control.Arrow as Arrow+import           Control.Monad.Identity import           Control.Monad.State import           Control.Monad.RWS hiding (Sum) import           Data.Bifunctor+import           Data.Bitraversable import           Data.Foldable import           Data.List (sortOn, nub, partition, tails) import qualified Data.List.NonEmpty as NE@@ -19,6 +21,7 @@  import           Futhark.MonadFreshNames import           Language.Futhark+import           Language.Futhark.Traversals import           Futhark.IR.Pretty ()  -- | An expression or an extended 'Lambda' (with size parameters,@@ -125,7 +128,11 @@ arraySizes (Scalar Arrow{}) = mempty arraySizes (Scalar (Record fields)) = foldMap arraySizes fields arraySizes (Scalar (Sum cs)) = foldMap (foldMap arraySizes) cs-arraySizes (Scalar TypeVar{}) = mempty+arraySizes (Scalar (TypeVar _ _ _ targs)) =+  mconcat $ map f targs+  where f (TypeArgDim (NamedDim d) _) = S.singleton $ qualLeaf d+        f TypeArgDim{} = mempty+        f (TypeArgType t _) = arraySizes t arraySizes (Scalar Prim{}) = mempty arraySizes (Array _ _ t shape) =   arraySizes (Scalar t) <> foldMap dimName (shapeDims shape)@@ -176,7 +183,7 @@    -- The closure parts that are sizes are proactively turned into size   -- parameters.-  let sizes_of_arrays = foldMap (arraySizes . toStruct . typeFromSV) used_env <>+  let sizes_of_arrays = foldMap (arraySizes . toStruct . typeFromSV') used_env <>                         patternArraySizes pat       notSize = not . (`S.member` sizes_of_arrays)       (fields, env) = unzip $ map closureFromDynamicFun $@@ -184,8 +191,11 @@       env' = M.fromList env       closure_dims = S.toList sizes_of_arrays +  global <- asks fst+   return (RecordLit fields loc,-          LambdaSV (nub $ dims<>closure_dims) pat ret' e0' env')+          LambdaSV (nub $ filter (`S.notMember` global) $+                    dims<>closure_dims) pat ret' e0' env')    where closureFromDynamicFun (vn, DynamicFun (clsr_env, sv) _) =           let name = nameFromString $ pretty vn@@ -193,7 +203,7 @@          closureFromDynamicFun (vn, sv) =           let name = nameFromString $ pretty vn-              tp' = typeFromSV sv+              tp' = typeFromSV' sv           in (RecordFieldExplicit name                (Var (qualName vn) (Info tp') mempty) mempty, (vn, sv)) @@ -243,7 +253,7 @@                                                 (vn', sv'))             -- The field may refer to a functional expression, so we get the             -- type from the static value and not the one from the AST.-            _ -> let tp = Info $ typeFromSV sv+            _ -> let tp = Info $ typeFromSV' sv                  in return (RecordFieldImplicit vn tp loc', (baseName vn, sv))  defuncExp (ArrayLit es t@(Info t') loc) = do@@ -268,7 +278,7 @@     IntrinsicSV -> do       (pats, body, tp) <- etaExpand (typeOf e) e       defuncExp $ Lambda pats body Nothing (Info (mempty, tp)) mempty-    _ -> let tp = typeFromSV sv+    _ -> let tp = typeFromSV' sv          in return (Var qn (Info tp) loc, sv)  defuncExp (Ascript e0 tydecl loc)@@ -284,7 +294,7 @@ defuncExp (LetPat pat e1 e2 (Info t, retext) loc) = do   (e1', sv1) <- defuncExp e1   let env  = matchPatternSV pat sv1-      pat' = updatePattern pat sv1+      pat' = updatePattern' pat sv1   (e2', sv2) <- localEnv env $ defuncExp e2   -- To maintain any sizes going out of scope, we need to compute the   -- old size substitution induced by retext and also apply it to the@@ -295,13 +305,20 @@   return (LetPat pat' e1' e2' (Info t', retext) loc, sv2)  -- Local functions are handled by rewriting them to lambdas, so that--- the same machinery can be re-used.-defuncExp (LetFun vn (dims, pats, _, Info ret, e1) e2 _ loc) = do-  (e1', sv1) <- defuncFun dims pats e1 (mempty, ret) loc-  (e2', sv2) <- localEnv (M.singleton vn sv1) $ defuncExp e2-  return (LetPat (Id vn (Info (typeOf e1')) loc) e1' e2' (Info $ typeOf e2', Info []) loc,-          sv2)+-- the same machinery can be re-used.  But we may have to eta-expand+-- first.+defuncExp (LetFun vn (dims, pats, _, Info ret, e1) e2 let_t loc)+  | Scalar Arrow{} <- ret = do+      (body_pats, e1', ret') <- etaExpand (fromStruct ret) e1+      let f = (dims, pats <> body_pats, Nothing, Info ret', e1')+      defuncExp $ LetFun vn f e2 let_t loc +  | otherwise = do+      (e1', sv1) <- defuncFun dims pats e1 (mempty, ret) loc+      (e2', sv2) <- localEnv (M.singleton vn sv1) $ defuncExp e2+      return (LetPat (Id vn (Info (typeOf e1')) loc) e1' e2' (Info $ typeOf e2', Info []) loc,+              sv2)+ defuncExp (If e1 e2 e3 tp loc) = do   (e1', _ ) <- defuncExp e1   (e2', sv) <- defuncExp e2@@ -361,7 +378,7 @@   (e0', sv0) <- defuncExp e0   case sv0 of     RecordSV svs -> case lookup vn svs of-      Just sv -> return (Project vn e0' (Info $ typeFromSV sv) loc, sv)+      Just sv -> return (Project vn e0' (Info $ typeFromSV' sv) loc, sv)       Nothing -> error "Invalid record projection."     Dynamic _ -> return (Project vn e0' tp loc, Dynamic tp')     _ -> error $ "Projection of an expression with static value " ++ show sv0@@ -391,7 +408,7 @@   (e1', sv1) <- defuncExp e1   (e2', sv2) <- defuncExp e2   let sv = staticField sv1 sv2 fs-  return (RecordUpdate e1' fs e2' (Info $ typeFromSV sv1) loc,+  return (RecordUpdate e1' fs e2' (Info $ typeFromSV' sv1) loc,           sv)   where staticField (RecordSV svs) sv2 (f:fs') =           case lookup f svs of@@ -411,7 +428,7 @@   (es', svs) <- unzip <$> mapM defuncExp es   let sv = SumSV name svs $ M.toList $            name `M.delete` M.map (map defuncType) all_fs-  return (Constr name es' (Info (typeFromSV sv)) loc, sv)+  return (Constr name es' (Info (typeFromSV' sv)) loc, sv)   where defuncType :: Monoid als =>                       TypeBase (DimDecl VName) als                    -> TypeBase (DimDecl VName) als@@ -453,7 +470,7 @@  defuncCase :: StaticVal -> Case -> DefM (Case, StaticVal) defuncCase sv (CasePat p e loc) = do-  let p'  = updatePattern p sv+  let p'  = updatePattern' p sv       env = matchPatternSV p sv   (e', sv') <- localEnv env $ defuncExp e   return (CasePat p' e' loc, sv')@@ -534,6 +551,16 @@           RecordSV $ M.toList $ M.intersectionWith imposeType (M.fromList fs1) fs2         imposeType sv _ = sv +sizesForAll :: MonadFreshNames m => [Pattern] -> m ([VName], [Pattern])+sizesForAll params = do+  (params', sizes) <- runStateT (mapM (astMap tv) params) []+  return (sizes, params')+  where tv = identityMapper { mapOnPatternType = bitraverse onDim pure }+        onDim AnyDim = do v <- lift $ newVName "size"+                          modify (v:)+                          pure $ NamedDim $ qualName v+        onDim d = pure d+ -- | Defunctionalize an application expression at a given depth of application. -- Calls to dynamic (first-order) functions are preserved at much as possible, -- but a new lifted function is created if a dynamic function is only partially@@ -553,6 +580,8 @@       let closure_pat = buildEnvPattern closure_env           pat' = updatePattern pat sv2 +      globals <- asks fst+       -- Lift lambda to top-level function definition.  We put in       -- a lot of effort to try to infer the uniqueness attributes       -- of the lifted function, but this is ultimately all a sham@@ -563,7 +592,7 @@           svParams _                         = []           rettype = buildRetType closure_env params_for_rettype e0_t $ typeOf e0' -          already_bound = S.fromList dims <>+          already_bound = globals <> S.fromList dims <>                           S.map identName (foldMap patternIdents params)           more_dims = S.toList $                       S.filter (`S.notMember` already_bound) $@@ -578,8 +607,14 @@             liftedName (i+1) f           liftedName _ _ = "lifted" +      -- Ensure that no parameter sizes are AnyDim.  The internaliser+      -- expects this.  This is easy, because they are all+      -- first-order.+      (missing_dims, params') <- sizesForAll params+       fname <- newNameFromString $ liftedName (0::Int) e1-      liftValDec fname rettype (dims ++ more_dims) params e0'+      liftValDec fname rettype (dims ++ more_dims ++ missing_dims)+        params' e0'        let t1 = toStruct $ typeOf e1'           t2 = toStruct $ typeOf e2'@@ -655,7 +690,7 @@        IntrinsicSV -> return (e, IntrinsicSV) -      _ -> return (Var qn (Info (typeFromSV sv)) loc, sv)+      _ -> return (Var qn (Info (typeFromSV' sv)) loc, sv)  defuncApply depth (Parens e _) = defuncApply depth e @@ -741,7 +776,7 @@ buildEnvPattern env = RecordPattern (map buildField $ M.toList env) mempty   where buildField (vn, sv) =           (nameFromString (pretty vn),-           Id vn (Info $ typeFromSV sv) mempty)+           Id vn (Info $ snd $ typeFromSV sv) mempty)  -- | Given a closure environment pattern and the type of a term, -- construct the type of that term, where uniqueness is set to@@ -772,29 +807,38 @@         descend t = t  -- | Compute the corresponding type for a given static value.-typeFromSV :: StaticVal -> PatternType-typeFromSV (Dynamic tp) = tp+typeFromSV :: StaticVal -> ([VName], PatternType)+typeFromSV (Dynamic tp) =+  (mempty, tp) typeFromSV (LambdaSV sizes _ _ _ env) =-  unscopeType (S.fromList sizes) $ typeFromEnv env+  (sizes <> env_sizes,+   Scalar $ Record $ M.fromList $ map (fmap snd) env')+  where env' = map (bimap (nameFromString . pretty) typeFromSV) $ M.toList env+        env_sizes = concatMap (fst . snd) env' typeFromSV (RecordSV ls) =-  Scalar $ Record $ M.fromList $ map (fmap typeFromSV) ls+  let ts = map (fmap typeFromSV) ls+  in (concatMap (fst . snd) ts,+      Scalar $ Record $ M.fromList $ map (fmap snd) ts) typeFromSV (DynamicFun (_, sv) _) =   typeFromSV sv typeFromSV (SumSV name svs fields) =-  Scalar $ Sum $ M.insert name (map typeFromSV svs) $ M.fromList fields+  let (sizes, svs') = unzip $ map typeFromSV svs+  in (concat sizes,+      Scalar $ Sum $ M.insert name svs' $ M.fromList fields) typeFromSV IntrinsicSV =   error "Tried to get the type from the static value of an intrinsic." -typeFromEnv :: Env -> PatternType-typeFromEnv = Scalar . Record . M.fromList .-              map (bimap (nameFromString . pretty) typeFromSV) . M.toList+typeFromSV' :: StaticVal -> PatternType+typeFromSV' sv =+  let (sizes, t) = typeFromSV sv+  in unscopeType (S.fromList sizes) t  -- | Construct the type for a fully-applied dynamic function from its -- static value and the original types of its arguments. dynamicFunType :: StaticVal -> [PatternType] -> ([PatternType], PatternType) dynamicFunType (DynamicFun _ sv) (p:ps) =   let (ps', ret) = dynamicFunType sv ps in (p : ps', ret)-dynamicFunType sv _ = ([], typeFromSV sv)+dynamicFunType sv _ = ([], typeFromSV' sv)  -- | Match a pattern with its static value. Returns an environment with -- the identifier components of the pattern mapped to the corresponding@@ -850,7 +894,7 @@ updatePattern (PatternParens pat loc) sv =   PatternParens (updatePattern pat sv) loc updatePattern (Id vn (Info tp) loc) sv =-  Id vn (Info $ comb tp (typeFromSV sv  `setUniqueness` Nonunique)) loc+  Id vn (Info $ comb tp (snd (typeFromSV sv)  `setUniqueness` Nonunique)) loc   -- Preserve any original zeroth-order types.   where comb (Scalar Arrow{}) t2 = t2         comb (Scalar (Record m1)) (Scalar (Record m2)) =@@ -860,7 +904,7 @@         comb t1 _ = t1 -- t1 must be array or prim. updatePattern pat@(Wildcard (Info tp) loc) sv   | orderZero tp = pat-  | otherwise = Wildcard (Info $ typeFromSV sv) loc+  | otherwise = Wildcard (Info $ snd $ typeFromSV sv) loc updatePattern (PatternAscription pat tydecl loc) sv   | orderZero . unInfo $ expandedType tydecl =       PatternAscription (updatePattern pat sv) tydecl loc@@ -869,7 +913,7 @@ updatePattern pat@(PatternConstr c1 (Info t) ps loc) sv@(SumSV _ svs _)   | orderZero t = pat   | otherwise = PatternConstr c1 (Info t') ps' loc-  where t' = typeFromSV sv `setUniqueness` Nonunique+  where t' = snd (typeFromSV sv) `setUniqueness` Nonunique         ps' = zipWith updatePattern ps svs updatePattern (PatternConstr c1 _ ps loc) (Dynamic t) =   PatternConstr c1 (Info t) ps loc@@ -878,6 +922,18 @@   error $ "Tried to update pattern " ++ pretty pat        ++ "to reflect the static value " ++ show sv +-- Like updatePattern, but discard sizes.  This is used for+-- let-bindings, where we might otherwise introduce sizes that are+-- free.+updatePattern' :: Pattern -> StaticVal -> Pattern+updatePattern' pat sv =+  let pat' = updatePattern pat sv+      (sizes, _) = typeFromSV sv+      tr = identityMapper { mapOnPatternType =+                              pure . unscopeType (S.fromList sizes)+                          }+  in runIdentity $ astMap tr pat'+ -- | Convert a record (or tuple) type to a record static value. This is used for -- "unwrapping" tuples and records that are nested in 'Dynamic' static values. svFromType :: PatternType -> StaticVal@@ -1003,17 +1059,20 @@ defuncValBind valbind@(ValBind _ name retdecl (Info (rettype, retext)) tparams params body _ _ _) = do   (tparams', params', body', sv) <- defuncLet tparams params body rettype   let rettype' = combineTypeShapes rettype $ anySizes $ toStruct $ typeOf body'+  (missing_dims, params'') <- sizesForAll params'   return ( valbind { valBindRetDecl    = retdecl                    , valBindRetType    = Info (if null params'                                                then rettype' `setUniqueness` Nonunique                                                else rettype',                                                retext)-                   , valBindTypeParams = tparams'-                   , valBindParams     = params'+                   , valBindTypeParams = tparams' +++                                         map (`TypeParamDim` mempty) missing_dims+                   , valBindParams     = params''                    , valBindBody       = body'                    }          , M.singleton name sv          , case sv of DynamicFun{} -> True+                      Dynamic{}    -> True                       _            -> False)  -- | Defunctionalize a list of top-level declarations.
src/Futhark/Internalise/Defunctorise.hs view
@@ -176,7 +176,7 @@         let forward (k,v) = (lookupSubst k outer_substs, v)             p_substs' = M.fromList $ map forward $ M.toList p_substs             abs_substs = M.filterWithKey (const . flip S.member abs) $-                         p_substs' <>+                         M.map (`lookupSubst` scopeSubsts (modScope arg_mod)) p_substs' <>                          scopeSubsts f_closure <>                          scopeSubsts (modScope arg_mod)         extendScope (Scope abs_substs (M.singleton (modParamName f_p) $
src/Futhark/Internalise/Lambdas.hs view
@@ -17,7 +17,7 @@  -- | A function for internalising lambdas. type InternaliseLambda =-  E.Exp -> [I.Type] -> InternaliseM ([I.LParam], I.Body, [I.ExtType])+  E.Exp -> [I.Type] -> InternaliseM ([I.LParam], I.Body, [I.Type])  internaliseMapLambda :: InternaliseLambda                      -> E.Exp@@ -27,12 +27,11 @@   argtypes <- mapM I.subExpType args   let rowtypes = map I.rowType argtypes   (params, body, rettype) <- internaliseLambda lam rowtypes-  (rettype', _) <- instantiateShapes' rettype   body' <- localScope (scopeOfLParams params) $            ensureResultShape            (ErrorMsg [ErrorString "not all iterations produce same shape"])-           (srclocOf lam) rettype' body-  return $ I.Lambda params body' rettype'+           (srclocOf lam) rettype body+  return $ I.Lambda params body' rettype  internaliseStreamMapLambda :: InternaliseLambda                            -> E.Exp@@ -50,13 +49,12 @@     body <- runBodyBinder $ do       letBindNames [paramName orig_chunk_param] $ I.BasicOp $ I.SubExp $ I.Var chunk_size       return orig_body-    (rettype', _) <- instantiateShapes' rettype     body' <- localScope (scopeOfLParams params) $ insertStmsM $ do       letBindNames [paramName orig_chunk_param] $ I.BasicOp $ I.SubExp $ I.Var chunk_size       ensureResultShape         (ErrorMsg [ErrorString "not all iterations produce same shape"])-        (srclocOf lam) (map outer rettype') body-    return $ I.Lambda (chunk_param:params) body' (map outer rettype')+        (srclocOf lam) (map outer rettype) body+    return $ I.Lambda (chunk_param:params) body' (map outer rettype)  internaliseFoldLambda :: InternaliseLambda                       -> E.Exp
src/Futhark/Internalise/Monad.hs view
@@ -29,14 +29,6 @@    , assert -  -- * Type Handling-  , InternaliseTypeM-  , liftInternaliseM-  , runInternaliseTypeM-  , lookupDim-  , withDims-  , DimTable-     -- * Convenient reexports   , module Futhark.Tools   )@@ -216,29 +208,3 @@ assertingOne :: InternaliseM VName              -> InternaliseM Certificates assertingOne m = asserting $ Certificates . pure <$> m--type DimTable = M.Map VName ExtSize--newtype TypeEnv = TypeEnv { typeEnvDims  :: DimTable }--type TypeState = Int--newtype InternaliseTypeM a =-  InternaliseTypeM (ReaderT TypeEnv (StateT TypeState InternaliseM) a)-  deriving (Functor, Applicative, Monad,-            MonadReader TypeEnv,-            MonadState TypeState)--liftInternaliseM :: InternaliseM a -> InternaliseTypeM a-liftInternaliseM = InternaliseTypeM . lift . lift--runInternaliseTypeM :: InternaliseTypeM a-                    -> InternaliseM a-runInternaliseTypeM (InternaliseTypeM m) =-  evalStateT (runReaderT m (TypeEnv mempty)) 0--withDims :: DimTable -> InternaliseTypeM a -> InternaliseTypeM a-withDims dtable = local $ \env -> env { typeEnvDims = dtable <> typeEnvDims env }--lookupDim :: VName -> InternaliseTypeM (Maybe ExtSize)-lookupDim name = asks $ M.lookup name . typeEnvDims
src/Futhark/Internalise/Monomorphise.hs view
@@ -197,6 +197,16 @@            then second (mconcat . map replace . S.toList) t            else t +sizesForPat :: MonadFreshNames m => Pattern -> m ([VName], Pattern)+sizesForPat pat = do+  (params', sizes) <- runStateT (astMap tv pat) []+  return (sizes, params')+  where tv = identityMapper { mapOnPatternType = bitraverse onDim pure }+        onDim AnyDim = do v <- lift $ newVName "size"+                          modify (v:)+                          pure $ NamedDim $ qualName v+        onDim d = pure d+ -- Monomorphization of expressions. transformExp :: Exp -> MonoM Exp transformExp e@Literal{} = return e@@ -329,7 +339,11 @@     ForIn pat2 e2 -> ForIn pat2 <$> transformExp e2     While e2      -> While <$> transformExp e2   e3' <- transformExp e3-  return $ DoLoop sparams pat e1' form' e3' ret loc+  -- Maybe monomorphisation introduced new arrays to the loop, and+  -- maybe they have AnyDim sizes.  This is not allowed.  Invent some+  -- sizes for them.+  (pat_sizes, pat') <- sizesForPat pat+  return $ DoLoop (sparams++pat_sizes) pat' e1' form' e3' ret loc  transformExp (BinOp (fname, oploc) (Info t) (e1, d1) (e2, d2) tp ext loc) = do   fname' <- transformFName loc fname $ toStruct t
src/Futhark/Internalise/TypesValues.hs view
@@ -4,12 +4,12 @@ module Futhark.Internalise.TypesValues   (    -- * Internalising types-    BoundInTypes-  , boundInTypes-  , internaliseReturnType+    internaliseReturnType+  , internaliseLambdaReturnType   , internaliseEntryReturnType-  , internaliseParamTypes   , internaliseType+  , internaliseParamTypes+  , internaliseLoopParamType   , internalisePrimType   , internalisedTypeSize   , internaliseSumType@@ -18,12 +18,11 @@   , internalisePrimValue   )   where-+import Control.Monad.Reader import Control.Monad.State import Data.List (delete, find, foldl')-import qualified Data.Map.Strict as M-import qualified Data.Set as S import Data.Maybe+import qualified Data.Map.Strict as M  import qualified Language.Futhark as E import Futhark.IR.SOACS as I@@ -33,39 +32,50 @@ internaliseUniqueness E.Nonunique = I.Nonunique internaliseUniqueness E.Unique = I.Unique --- | The names that are bound for some types, either implicitly or--- explicitly.-newtype BoundInTypes = BoundInTypes (S.Set VName)-                       deriving (Semigroup, Monoid)+type TypeState = Int --- | Determine the names bound for some types.-boundInTypes :: [E.TypeParam] -> BoundInTypes-boundInTypes = BoundInTypes . S.fromList . mapMaybe isTypeParam-  where isTypeParam (E.TypeParamDim v _) = Just v-        isTypeParam _ = Nothing+newtype InternaliseTypeM a =+  InternaliseTypeM (StateT TypeState InternaliseM a)+  deriving (Functor, Applicative, Monad, MonadState TypeState) -internaliseParamTypes :: BoundInTypes-                      -> M.Map VName VName-                      -> [E.TypeBase (E.DimDecl VName) ()]-                      -> InternaliseM [[I.TypeBase ExtShape Uniqueness]]-internaliseParamTypes (BoundInTypes bound) pnames ts =-  runInternaliseTypeM $ withDims (bound' <> M.map (Free . Var) pnames) $-  mapM internaliseTypeM ts-  where bound' = M.fromList (zip (S.toList bound)-                                 (map (Free . Var) $ S.toList bound))+liftInternaliseM :: InternaliseM a -> InternaliseTypeM a+liftInternaliseM = InternaliseTypeM . lift +runInternaliseTypeM :: InternaliseTypeM a+                    -> InternaliseM a+runInternaliseTypeM (InternaliseTypeM m) =+  evalStateT m 0++internaliseParamTypes :: [E.TypeBase (E.DimDecl VName) ()]+                      -> InternaliseM [[I.TypeBase Shape Uniqueness]]+internaliseParamTypes ts =+  runInternaliseTypeM $ mapM (fmap (map onType) . internaliseTypeM) ts+  where onType = fromMaybe bad . hasStaticShape+        bad = error $ "internaliseParamTypes: " ++ pretty ts++internaliseLoopParamType :: E.TypeBase (E.DimDecl VName) ()+                         -> InternaliseM [I.TypeBase Shape Uniqueness]+internaliseLoopParamType et =+  concat <$> internaliseParamTypes [et]+ internaliseReturnType :: E.TypeBase (E.DimDecl VName) ()                       -> InternaliseM [I.TypeBase ExtShape Uniqueness]-internaliseReturnType = fmap concat . internaliseEntryReturnType+internaliseReturnType et =+  runInternaliseTypeM (internaliseTypeM et) +internaliseLambdaReturnType :: E.TypeBase (E.DimDecl VName) ()+                            -> InternaliseM [I.TypeBase Shape NoUniqueness]+internaliseLambdaReturnType = fmap (map fromDecl) . internaliseLoopParamType+ -- | As 'internaliseReturnType', but returns components of a top-level -- tuple type piecemeal. internaliseEntryReturnType :: E.TypeBase (E.DimDecl VName) ()                            -> InternaliseM [[I.TypeBase ExtShape Uniqueness]]-internaliseEntryReturnType t = do-  let ts = case E.isTupleRecord t of Just tts | not $ null tts -> tts-                                     _ -> [t]-  runInternaliseTypeM $ mapM internaliseTypeM ts+internaliseEntryReturnType et =+  runInternaliseTypeM $ mapM internaliseTypeM $+  case E.isTupleRecord et of+    Just ets | not $ null ets -> ets+    _ -> [et]  internaliseType :: E.TypeBase (E.DimDecl VName) ()                 -> InternaliseM [I.TypeBase I.ExtShape Uniqueness]@@ -85,11 +95,8 @@     E.NamedDim name -> namedDim name   where namedDim (E.QualName _ name) = do           subst <- liftInternaliseM $ lookupSubst name-          is_dim <- lookupDim name--          case (is_dim, subst) of-            (Just dim, _) -> return dim-            (Nothing, Just [v]) -> return $ I.Free v+          case subst of+            Just [v] -> return $ I.Free v             _ -> return $ I.Free $ I.Var name  internaliseTypeM :: E.StructType
src/Futhark/Optimise/InliningDeadFun.hs view
@@ -30,6 +30,10 @@ import Futhark.Pass  parMapM :: MonadFreshNames m => (a -> State VNameSource b) -> [a] -> m [b]+-- The special-casing of [] is quite important here!  If 'as' is+-- empty, then we might otherwise create an empty name source below,+-- which can wreak all kinds of havoc.+parMapM _ [] = pure [] parMapM f as =   modifyNameSource $ \src ->   let f' a = runState (f a) src@@ -125,14 +129,10 @@     (bodyResult (funDefBody fun))   let res_stms =         certify (stmAuxCerts aux) <$>-        zipWith (reshapeIfNecessary (patternNames pat))-        (patternIdents pat) res+        zipWith bindSubExp (patternIdents pat) res   pure $ stmsToList stms <> res_stms-  where param_names =-          map paramName $ funDefParams fun--        param_stms =-          zipWith (reshapeIfNecessary param_names)+  where param_stms =+          zipWith bindSubExp           (map paramIdent $ funDefParams fun) (map fst args)          body_stms =@@ -140,13 +140,11 @@           addLocations (stmAuxAttrs aux) safety (filter notmempty (loc:locs)) $           bodyStms $ funDefBody fun -        reshapeIfNecessary dim_names ident se-          | t@Array{} <- identType ident,-            any (`elem` dim_names) (subExpVars $ arrayDims t),-            Var v <- se =-              mkLet [] [ident] $ shapeCoerce (arrayDims t) v-          | otherwise =-              mkLet [] [ident] $ BasicOp $ SubExp se+        -- Note that the sizes of arrays may not be correct at this+        -- point - it is crucial that we run copy propagation before+        -- the type checker sees this!+        bindSubExp ident se =+          mkLet [] [ident] $ BasicOp $ SubExp se          notmempty = (/=mempty) . locOf 
src/Futhark/Optimise/Simplify/Rules.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE Safe #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE OverloadedStrings #-} -- | This module defines a collection of simplification rules, as per -- "Futhark.Optimise.Simplify.Rule".  They are used in the -- simplifier.@@ -34,13 +35,14 @@ import Futhark.Analysis.PrimExp.Convert import Futhark.IR import Futhark.IR.Prop.Aliases+import Futhark.Transform.Rename import Futhark.Construct import Futhark.Util  topDownRules :: (BinderOps lore, Aliased lore) => [TopDownRule lore] topDownRules = [ RuleDoLoop hoistLoopInvariantMergeVariables                , RuleDoLoop simplifyClosedFormLoop-               , RuleDoLoop simplifKnownIterationLoop+               , RuleDoLoop simplifyKnownIterationLoop                , RuleDoLoop simplifyLoopVariables                , RuleGeneric constantFoldPrimFun                , RuleIf ruleIf@@ -76,7 +78,7 @@ -- perfect, but it should suffice for many cases, and should never -- generate wrong code. removeRedundantMergeVariables :: BinderOps lore => BottomUpRuleDoLoop lore-removeRedundantMergeVariables (_, used) pat _ (ctx, val, form, body)+removeRedundantMergeVariables (_, used) pat aux (ctx, val, form, body)   | not $ all (usedAfterLoop . fst) val,     null ctx = -- FIXME: things get tricky if we can remove all vals                -- but some ctxs are still used.  We take the easy way@@ -126,7 +128,7 @@          mapM_ (uncurry letBindNames) $ dummyStms discard_ctx          mapM_ (uncurry letBindNames) $ dummyStms discard_val          return body'-       letBind pat' $ DoLoop ctx' val' form body''+       auxing aux $ letBind pat' $ DoLoop ctx' val' form body''   where pat_used = map (`UT.isUsedDirectly` used) $ patternValueNames pat         used_vals = map fst $ filter snd $ zip (map (paramName . fst) val) pat_used         usedAfterLoop = flip elem used_vals . paramName@@ -147,7 +149,7 @@ -- We may change the type of the loop if we hoist out a shape -- annotation, in which case we also need to tweak the bound pattern. hoistLoopInvariantMergeVariables :: BinderOps lore => TopDownRuleDoLoop lore-hoistLoopInvariantMergeVariables _ pat _ (ctx, val, form, loopbody) =+hoistLoopInvariantMergeVariables _ pat aux (ctx, val, form, loopbody) =     -- Figure out which of the elements of loopresult are     -- loop-invariant, and hoist them out.   case foldr checkInvariance ([], explpat, [], []) $@@ -168,7 +170,7 @@           (ctx', val') = splitAt (length implpat') merge'       forM_ (invariant ++ implinvariant') $ \(v1,v2) ->         letBindNames [identName v1] $ BasicOp $ SubExp v2-      letBind (Pattern implpat'' explpat'') $+      auxing aux $ letBind (Pattern implpat'' explpat'') $         DoLoop ctx' val' form loopbody'   where merge = ctx ++ val         res = bodyResult loopbody@@ -250,7 +252,7 @@ simplifyClosedFormLoop _ _ _ _ = Skip  simplifyLoopVariables :: (BinderOps lore, Aliased lore) => TopDownRuleDoLoop lore-simplifyLoopVariables vtable pat _ (ctx, val, form@(ForLoop i it num_iters loop_vars), body)+simplifyLoopVariables vtable pat aux (ctx, val, form@(ForLoop i it num_iters loop_vars), body)   | simplifiable <- map checkIfSimplifiable loop_vars,     not $ all isNothing simplifiable = Simplify $ do       -- Check if the simplifications throw away more information than@@ -263,7 +265,7 @@         else do body' <- insertStmsM $ do                   addStms $ mconcat body_prefix_stms                   resultBodyM =<< bodyBind body-                letBind pat $ DoLoop ctx val+                auxing aux $ letBind pat $ DoLoop ctx val                   (ForLoop i it num_iters $ catMaybes maybe_loop_vars) body'    where seType (Var v)@@ -310,30 +312,46 @@         notIndex _                 = True simplifyLoopVariables _ _ _ _ = Skip -simplifKnownIterationLoop :: BinderOps lore => TopDownRuleDoLoop lore-simplifKnownIterationLoop _ pat _ (ctx, val, ForLoop i it (Constant iters) loop_vars, body)-  | zeroIsh iters = Simplify $ do-      let bindResult p r = letBindNames [patElemName p] $ BasicOp $ SubExp r-      zipWithM_ bindResult (patternContextElements pat) (map snd ctx)-      zipWithM_ bindResult (patternValueElements pat) (map snd val)+unroll :: BinderOps lore =>+          Integer+       -> [(FParam lore, SubExp)]+       -> (VName, IntType, Integer)+       -> [(LParam lore, VName)]+       -> Body lore+       -> RuleM lore [SubExp]+unroll n merge (iv, it, i) loop_vars body+  | i >= n =+      return $ map snd merge+  | otherwise = do+      iter_body <- insertStmsM $ do+        forM_ merge $ \(mergevar, mergeinit) ->+          letBindNames [paramName mergevar] $ BasicOp $ SubExp mergeinit -  | oneIsh iters = Simplify $ do+        letBindNames [iv] $ BasicOp $ SubExp $ intConst it i -  forM_ (ctx++val) $ \(mergevar, mergeinit) ->-    letBindNames [paramName mergevar] $ BasicOp $ SubExp mergeinit+        forM_ loop_vars $ \(p,arr) ->+          letBindNames [paramName p] $ BasicOp $ Index arr $+          DimFix (intConst Int32 i) : fullSlice (paramType p) [] -  letBindNames [i] $ BasicOp $ SubExp $ intConst it 0+        -- Some of the sizes in the types here might be temporarily wrong+        -- until copy propagation fixes it up.+        pure body -  forM_ loop_vars $ \(p,arr) ->-    letBindNames [paramName p] $ BasicOp $ Index arr $-    DimFix (intConst Int32 0) : fullSlice (paramType p) []+      iter_body' <- renameBody iter_body+      addStms $ bodyStms iter_body' -  -- Some of the sizes in the types here might be temporarily wrong-  -- until copy propagation fixes it up.-  res <- bodyBind body-  forM_ (zip (patternNames pat) res) $ \(v, se) ->-    letBindNames [v] $ BasicOp $ SubExp se-simplifKnownIterationLoop _ _ _ _ =+      let merge' = zip (map fst merge) $ bodyResult iter_body'+      unroll n merge' (iv, it, i+1) loop_vars body++simplifyKnownIterationLoop :: BinderOps lore => TopDownRuleDoLoop lore+simplifyKnownIterationLoop _ pat aux (ctx, val, ForLoop i it (Constant iters) loop_vars, body)+  | IntValue n <- iters,+    zeroIshInt n || oneIshInt n || "unroll" `inAttrs` stmAuxAttrs aux = Simplify $ do+      res <- unroll (valueIntegral n) (ctx++val) (i, it, 0) loop_vars body+      forM_ (zip (patternNames pat) res) $ \(v, se) ->+        letBindNames [v] $ BasicOp $ SubExp se++simplifyKnownIterationLoop _ _ _ _ =   Skip  -- | Turn @copy(x)@ into @x@ iff @x@ is not used after this copy@@ -662,7 +680,9 @@             fmap (SubExpResult cs) $ letSubExp "slice_iota" $               BasicOp $ Iota i_n i_offset'' i_stride'' to_it -    Just (Rotate offsets a, cs) -> Just $ do+    -- A rotate cannot be simplified away if we are slicing a rotated dimension.+    Just (Rotate offsets a, cs)+      | not $ or $ zipWith rotateAndSlice offsets inds -> Just $ do       dims <- arrayDims <$> lookupType a       let adjustI i o d = do             i_p_o <- letSubExp "i_p_o" $ BasicOp $ BinOp (Add Int32 OverflowWrap) i o@@ -672,6 +692,8 @@           adjust (DimSlice i n s, o, d) =             DimSlice <$> adjustI i o d <*> pure n <*> pure s       IndexResult cs a <$> mapM adjust (zip3 inds offsets dims)+        where rotateAndSlice r DimSlice{} = not $ isCt0 r+              rotateAndSlice _ _ = False      Just (Index aa ais, cs) ->       Just $ IndexResult cs aa <$>
src/Futhark/Optimise/Sink.hs view
@@ -67,11 +67,12 @@ multiplicity stm =   case stmExp stm of     If cond tbranch fbranch _ ->-      free cond 1 <> M.unionWith (+) (free tbranch 1) (free fbranch 1)+      free cond 1 `comb` free tbranch 1 `comb` free fbranch 1     Op{} -> free stm 2     DoLoop{} -> free stm 2     _ -> free stm 1   where free x k = M.fromList $ zip (namesToList $ freeIn x) $ repeat k+        comb = M.unionWith (+)  optimiseBranch :: SymbolTable -> Sinking -> Body SinkLore                -> (Body SinkLore, Sunk)@@ -95,7 +96,7 @@   in (stmsFromList all_stms', sunk)   where     multiplicities = foldl' (M.unionWith (+))-                     (M.fromList (zip (namesToList free_in_res) [1..]))+                     (M.fromList (zip (namesToList free_in_res) (repeat 1)))                      (map multiplicity $ stmsToList all_stms)      optimiseStms' _ _ [] = ([], mempty)
src/Futhark/Optimise/TileLoops.hs view
@@ -485,7 +485,7 @@                   localScope (scopeOfFParams $ map fst merge) $ do          -- Collectively read a tile.-        tile <- tilingReadTile tiling TileFull privstms (Var tile_id) arrs_and_perms+        tile <- tilingReadTile tiling TilePartial privstms (Var tile_id) arrs_and_perms          -- Now each thread performs a traversal of the tile and         -- updates its accumulator.
src/Futhark/Pass/ExtractKernels.hs view
@@ -583,7 +583,7 @@           | DoLoop _ _ _ body <- stmExp stm =               bodyInterest body * 10           | If _ tbody fbody _ <- stmExp stm =-              bodyInterest tbody + bodyInterest fbody -- Ad-hoc.+              max (bodyInterest tbody) (bodyInterest fbody)           | Op (Screma w (ScremaForm _ _ lam') _) <- stmExp stm =               zeroIfTooSmall w + bodyInterest (lambdaBody lam')           | Op (Stream _ (Sequential _) lam' _) <- stmExp stm =@@ -637,9 +637,8 @@  onTopLevelStms :: KernelPath -> Stms SOACS                -> DistNestT Out.Kernels DistribM KernelsStms-onTopLevelStms path stms = do-  scope <- askScope-  lift $ localScope scope $ transformStms path $ stmsToList stms+onTopLevelStms path stms =+  liftInner $ transformStms path $ stmsToList stms  onMap :: KernelPath -> MapLoop -> DistribM KernelsStms onMap path (MapLoop pat aux w lam arrs) = do@@ -788,9 +787,8 @@       -- parallelism.       dist_env <- ask       let extra_scope = targetsScope $ distTargets acc'-      scope <- (extra_scope<>) <$> askScope -      stms <- lift $ localScope scope $ do+      stms <- liftInner $ localScope extra_scope $ do         let maploop' = MapLoop pat aux w lam arrs              exploitInnerParallelism path' = do
src/Futhark/Pass/ExtractKernels/DistributeNests.hs view
@@ -20,6 +20,7 @@   , DistAcc (..)   , runDistNestT   , DistNestT+  , liftInner    , distributeMap @@ -43,6 +44,7 @@ import Control.Monad.Trans.Maybe import Data.Maybe import Data.List (find, partition, tails)+import qualified Data.Map as M  import Futhark.IR import qualified Futhark.IR.SOACS as SOACS@@ -134,8 +136,12 @@             MonadReader (DistEnv lore m),             MonadWriter (DistRes lore)) -instance MonadTrans (DistNestT lore) where-  lift = DistNestT . lift . lift+liftInner :: (LocalScope lore m, DistLore lore) => m a -> DistNestT lore m a+liftInner m = do+  outer_scope <- askScope+  DistNestT $ lift $ lift $ do+    inner_scope <- askScope+    localScope (outer_scope `M.difference` inner_scope) m  instance MonadFreshNames m => MonadFreshNames (DistNestT lore m) where   getNameSource = DistNestT $ lift getNameSource@@ -283,7 +289,8 @@ lambdaContainsParallelism :: Lambda SOACS -> Bool lambdaContainsParallelism = bodyContainsParallelism . lambdaBody -distributeMapBodyStms :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> Stms SOACS -> DistNestT lore m (DistAcc lore)+distributeMapBodyStms :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+                         DistAcc lore -> Stms SOACS -> DistNestT lore m (DistAcc lore) distributeMapBodyStms orig_acc = distribute <=< onStms orig_acc . stmsToList   where     onStms acc [] = return acc@@ -312,7 +319,7 @@   f <- asks distOnTopLevelStms   postStm =<< f stms -maybeDistributeStm :: (MonadFreshNames m, DistLore lore) =>+maybeDistributeStm :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                       Stm SOACS -> DistAcc lore                    -> DistNestT lore m (DistAcc lore) @@ -596,7 +603,7 @@ maybeDistributeStm bnd acc =   addStmToAcc bnd acc -distributeSingleUnaryStm :: (MonadFreshNames m, DistLore lore) =>+distributeSingleUnaryStm :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                             DistAcc lore -> Stm SOACS                          -> (KernelNest -> PatternT Type -> VName -> DistNestT lore m (Stms lore))                          -> DistNestT lore m (DistAcc lore)@@ -624,20 +631,22 @@           | otherwise =               False -distribute :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> DistNestT lore m (DistAcc lore)+distribute :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+              DistAcc lore -> DistNestT lore m (DistAcc lore) distribute acc =   fromMaybe acc <$> distributeIfPossible acc -mkSegLevel :: (MonadFreshNames m, DistLore lore) => DistNestT lore m (MkSegLevel lore (DistNestT lore m))+mkSegLevel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+              DistNestT lore m (MkSegLevel lore (DistNestT lore m)) mkSegLevel = do   mk_lvl <- asks distSegLevel   return $ \w desc r -> do-    scope <- askScope-    (lvl, stms) <- lift $ lift $ runBinderT (mk_lvl w desc r) scope+    (lvl, stms) <- lift $ liftInner $ runBinderT' $ mk_lvl w desc r     addStms stms     return lvl -distributeIfPossible :: (MonadFreshNames m, DistLore lore) => DistAcc lore -> DistNestT lore m (Maybe (DistAcc lore))+distributeIfPossible :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>+                        DistAcc lore -> DistNestT lore m (Maybe (DistAcc lore)) distributeIfPossible acc = do   nest <- asks distNest   mk_lvl <- mkSegLevel@@ -649,7 +658,7 @@                             , distStms = mempty                             } -distributeSingleStm :: (MonadFreshNames m, DistLore lore) =>+distributeSingleStm :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                        DistAcc lore -> Stm SOACS                     -> DistNestT lore m (Maybe (PostStms lore,                                                 Result,@@ -671,7 +680,7 @@                                  , distStms = mempty                                  }) -segmentedScatterKernel :: (MonadFreshNames m, DistLore lore) =>+segmentedScatterKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                           KernelNest                        -> [Int]                        -> PatternT Type@@ -737,7 +746,7 @@           [ (map DimFix $ map Var (init gtids)++[i], v) | (i,v) <- is_vs ]           where (gtids,ws) = unzip ispace -segmentedUpdateKernel :: (MonadFreshNames m, DistLore lore) =>+segmentedUpdateKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                          KernelNest                       -> [Int]                       -> Certificates@@ -781,7 +790,7 @@      letBind pat $ Op $ segOp k -segmentedGatherKernel :: (MonadFreshNames m, DistLore lore) =>+segmentedGatherKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                          KernelNest                       -> Certificates                       -> VName@@ -814,7 +823,7 @@      letBind pat $ Op $ segOp k -segmentedHistKernel :: (MonadFreshNames m, DistLore lore) =>+segmentedHistKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                        KernelNest                     -> [Int]                     -> Certificates@@ -841,10 +850,9 @@     <*> pure op    mk_lvl <- asks distSegLevel-  scope <- askScope   onLambda <- asks distOnSOACSLambda   let onLambda' = fmap fst . runBinder . onLambda-  lift $ flip runBinderT_ scope $ do+  liftInner $ runBinderT'_ $ do     -- It is important not to launch unnecessarily many threads for     -- histograms, because it may mean we unnecessarily need to reduce     -- subhistograms as well.@@ -905,7 +913,7 @@       in (Shape [w] <> shape, lam')   | otherwise = (mempty, lam) -segmentedScanomapKernel :: (MonadFreshNames m, DistLore lore) =>+segmentedScanomapKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                            KernelNest                         -> [Int]                         -> SubExp@@ -921,7 +929,7 @@     addStms =<< traverse renameStm =<<       segScan lvl pat segment_size [scan_op] map_lam arrs ispace inps -regularSegmentedRedomapKernel :: (MonadFreshNames m, DistLore lore) =>+regularSegmentedRedomapKernel :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                                  KernelNest                               -> [Int]                               -> SubExp -> Commutativity@@ -937,7 +945,7 @@       addStms =<< traverse renameStm =<<         segRed lvl pat segment_size [red_op] map_lam arrs ispace inps -isSegmentedOp :: (MonadFreshNames m, DistLore lore) =>+isSegmentedOp :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                  KernelNest               -> [Int]               -> Names -> Names@@ -988,9 +996,8 @@   nes' <- mapM prepareNe nes    mk_arrs <- mapM prepareArr arrs-  scope <- lift askScope -  lift $ lift $ flip runBinderT_ scope $ do+  lift $ liftInner $ runBinderT'_ $ do     nested_arrs <- sequence mk_arrs      let pat = Pattern [] $ rearrangeShape perm $@@ -1041,7 +1048,7 @@   postStm $ fmap (certify cs) bnds   return acc' -distributeMap :: (MonadFreshNames m, DistLore lore) =>+distributeMap :: (MonadFreshNames m, LocalScope lore m, DistLore lore) =>                  MapLoop -> DistAcc lore               -> DistNestT lore m (DistAcc lore) distributeMap (MapLoop pat aux w lam arrs) acc =
src/Futhark/Pass/ExtractKernels/Intragroup.hs view
@@ -63,8 +63,12 @@     intraGroupParalleliseBody intra_lvl body    outside_scope <- lift askScope-  unless (all (`M.member` outside_scope) $ namesToList $-          freeIn (wss_min ++ wss_avail)) $+  -- outside_scope may also contain the inputs, even though those are+  -- not actually available outside the kernel.+  let available v =+        v `M.member` outside_scope &&+        v `notElem` map kernelInputName inps+  unless (all available $ namesToList $ freeIn (wss_min ++ wss_avail)) $     fail "Irregular parallelism"    ((intra_avail_par, kspace, read_input_stms), prelude_stms) <- lift $ runBinder $ do@@ -144,7 +148,7 @@  intraGroupBody :: SegLevel -> Body -> IntraGroupM (Out.Body Out.Kernels) intraGroupBody lvl body = do-  stms <- collectStms_ $ mapM_ (intraGroupStm lvl) $ bodyStms body+  stms <- collectStms_ $ intraGroupStms lvl $ bodyStms body   return $ mkBody stms $ bodyResult body  intraGroupStm :: SegLevel -> Stm -> IntraGroupM ()@@ -171,7 +175,7 @@      Op soac       | "sequential_outer" `inAttrs` stmAuxAttrs aux ->-          mapM_ (intraGroupStm lvl) . fmap (certify (stmAuxCerts aux)) =<<+          intraGroupStms lvl . fmap (certify (stmAuxCerts aux)) =<<           runBinder_ (FOT.transformSOAC pat soac)      Op (Screma w form arrs)@@ -185,7 +189,7 @@                         , distOnInnerMap =                             distributeMap                         , distOnTopLevelStms =-                            lift . collectStms_ . intraGroupStms lvl+                            liftInner . collectStms_ . intraGroupStms lvl                         , distSegLevel = \minw _ _ -> do                             lift $ parallelMin minw                             return lvl@@ -240,7 +244,7 @@           replace se = se           replaceSets (Acc x y log) =             Acc (S.map (map replace) x) (S.map (map replace) y) log-      censor replaceSets $ mapM_ (intraGroupStm lvl) stream_bnds+      censor replaceSets $ intraGroupStms lvl stream_bnds      Op (Scatter w lam ivs dests) -> do       write_i <- newVName "write_i"
src/Futhark/Transform/Rename.hs view
@@ -216,7 +216,10 @@     ctxinit' <- mapM rename ctxinit     valinit' <- mapM rename valinit     case form of-      ForLoop loopvar it boundexp loop_vars -> do+      -- It is important that 'i' is renamed before the loop_vars, as+      -- 'i' may be used in the annotations for loop_vars (e.g. index+      -- functions).+      ForLoop i it boundexp loop_vars -> bind [i] $ do         let (loop_params, loop_arrs) = unzip loop_vars         boundexp' <- rename boundexp         loop_arrs' <- rename loop_arrs@@ -225,13 +228,12 @@           ctxparams' <- mapM rename ctxparams           valparams' <- mapM rename valparams           loop_params' <- mapM rename loop_params-          bind [loopvar] $ do-            loopvar'  <- rename loopvar-            loopbody' <- rename loopbody-            return $ DoLoop-              (zip ctxparams' ctxinit') (zip valparams' valinit')-              (ForLoop loopvar' it boundexp' $-               zip loop_params' loop_arrs') loopbody'+          i' <- rename i+          loopbody' <- rename loopbody+          return $ DoLoop+            (zip ctxparams' ctxinit') (zip valparams' valinit')+            (ForLoop i' it boundexp' $+             zip loop_params' loop_arrs') loopbody'       WhileLoop cond ->         bind (map paramName $ ctxparams++valparams) $ do           ctxparams' <- mapM rename ctxparams
src/Futhark/TypeCheck.hs view
@@ -507,18 +507,9 @@  checkFunParams :: Checkable lore =>                   [FParam lore] -> TypeM lore ()-checkFunParams params = foldM_ check mempty params-  where param_bound = namesFromList $ map paramName params-        check prev param =-          context ("In function parameter " ++ pretty param) $ do-            checkFParamLore (paramName param) (paramDec param)-            case namesToList $-                 (freeIn param `namesIntersection` param_bound)-                 `namesSubtract` prev of-              [] -> return ()-              v:_ ->-                bad $ TypeError $ pretty v ++ " bound in a later parameter."-            return $ oneName (paramName param) <> prev+checkFunParams = mapM_ $ \param ->+  context ("In function parameter " ++ pretty param) $+    checkFParamLore (paramName param) (paramDec param)  checkLambdaParams :: Checkable lore =>                      [LParam lore] -> TypeM lore ()
src/Language/Futhark/Interpreter.hs view
@@ -1354,7 +1354,7 @@         _ ->           error $ "Invalid arguments to map intrinsic:\n" ++           unlines [pretty t, pretty v]-      where typeRowShape = traverse id . structTypeShape mempty . stripArray 1+      where typeRowShape = sequenceA . structTypeShape mempty . stripArray 1      def s | "reduce" `isPrefixOf` s = Just $ fun3t $ \f ne xs ->       foldM (apply2 noLoc mempty f) ne $ snd $ fromArray xs
src/Language/Futhark/Parser/Parser.y view
@@ -23,7 +23,6 @@ import Control.Monad.Except import Control.Monad.Reader import Control.Monad.Trans.State-import Control.Arrow import Data.Array import qualified Data.Text as T import Codec.Binary.UTF8.String (encode)@@ -38,6 +37,7 @@ import Language.Futhark.Prop import Language.Futhark.Pretty import Language.Futhark.Parser.Lexer+import Futhark.Util.Pretty import Futhark.Util.Loc hiding (L) -- Lexer has replacements.  }@@ -610,9 +610,7 @@      | Apply_ { $1 }  Apply_ :: { UncheckedExp }-       : ApplyList { case $1 of-                       ((Constr n [] _ loc1):_) -> Constr n (tail $1) NoInfo (srcspan loc1 (last $1))-                       _                -> foldl1 (\f x -> Apply f x NoInfo (NoInfo, NoInfo) (srcspan f x)) $1 }+       : ApplyList {% applyExp $1 }  ApplyList :: { [UncheckedExp] }           : ApplyList Atom %prec juxtprec@@ -725,7 +723,7 @@  LetExp :: { UncheckedExp }      : let Pattern '=' Exp LetBody-                      { LetPat $2 $4 $5 (NoInfo, NoInfo) (srcspan $1 $>) }+       { LetPat $2 $4 $5 (NoInfo, NoInfo) (srcspan $1 $>) }       | let id TypeParams FunParams1 maybeAscription(TypeExpDecl) '=' Exp LetBody        { let L _ (ID name) = $2@@ -733,24 +731,26 @@             $8 NoInfo (srcspan $1 $>) }       | let VarSlice '=' Exp LetBody-                      { let ((v,_),slice,loc) = $2; ident = Ident v NoInfo loc-                        in LetWith ident ident slice $4 $5 NoInfo (srcspan $1 $>) }+       { let ((v,_),slice,loc) = $2; ident = Ident v NoInfo loc+         in LetWith ident ident slice $4 $5 NoInfo (srcspan $1 $>) }  LetBody :: { UncheckedExp }     : in Exp %prec letprec { $2 }     | LetExp %prec letprec { $1 }+    | error {% throwError "Unexpected end of file - missing \"in\"?" }  MatchExp :: { UncheckedExp }-          : match Exp Cases  { let loc = srcspan $1 (NE.toList $>)-                               in Match $2 $> (NoInfo, NoInfo) loc  }+          : match Exp Cases+            { let loc = srcspan $1 (NE.toList $>)+              in Match $2 $> (NoInfo, NoInfo) loc  }  Cases :: { NE.NonEmpty (CaseBase NoInfo Name) }        : Case  %prec caseprec { $1 NE.:| [] }        | Case Cases           { NE.cons $1 $2 }  Case :: { CaseBase NoInfo Name }-      : case CPattern '->' Exp       { let loc = srcspan $1 $>-                                       in CasePat $2 $> loc }+      : case CPattern '->' Exp+        { let loc = srcspan $1 $> in CasePat $2 $> loc }  CPattern :: { PatternBase NoInfo Name }           : CInnerPattern ':' TypeExpDecl { PatternAscription $1 $3 (srcspan $1 $>) }@@ -815,8 +815,8 @@  VarSlice :: { ((Name, SrcLoc), [UncheckedDimIndex], SrcLoc) }           : 'id[' DimIndices ']'-              { let L vloc (INDEXING v) = $1-                in ((v, vloc), $2, srcspan $1 $>) }+            { let L vloc (INDEXING v) = $1+              in ((v, vloc), $2, srcspan $1 $>) }  QualVarSlice :: { ((QualName Name, SrcLoc), [UncheckedDimIndex], SrcLoc) }               : VarSlice@@ -873,7 +873,7 @@               : FieldId '=' Pattern                 { (fst $1, $3) }               | FieldId ':' TypeExpDecl-              { (fst $1, PatternAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }+                { (fst $1, PatternAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }               | FieldId                 { (fst $1, Id (fst $1) NoInfo (snd $1)) } @@ -1083,6 +1083,20 @@  arrayFromList :: [a] -> Array Int a arrayFromList l = listArray (0, length l-1) l++applyExp :: [UncheckedExp] -> ParserMonad UncheckedExp+applyExp all@((Constr n [] _ loc1):es) =+  return $ Constr n es NoInfo (srcspan loc1 (last all))+applyExp es =+  foldM ap (head es) (tail es)+  where+     ap (Index e is _ floc) (ArrayLit xs _ xloc) =+       parseErrorAt (srcspan floc xloc) $+       Just $ pretty $ "Incorrect syntax for multi-dimensional indexing." </>+       "Use" <+> align (ppr index)+       where index = Index e (is++map DimFix xs) (NoInfo, NoInfo) xloc+     ap f x =+        return $ Apply f x NoInfo (NoInfo, NoInfo) (srcspan f x)  patternExp :: UncheckedPattern -> ParserMonad UncheckedExp patternExp (Id v _ loc) = return $ Var (qualName v) NoInfo loc
src/Language/Futhark/Pretty.hs view
@@ -222,9 +222,9 @@   pprPrec _ (Parens e _) = align $ parens $ ppr e   pprPrec _ (QualParens (v, _) e _) = ppr v <> text "." <> align (parens $ ppr e)   pprPrec p (Ascript e t _) =-    parensIf (p /= -1) $ pprPrec 0 e <+> text ":" <+> pprPrec 0 t+    parensIf (p /= -1) $ pprPrec 0 e <+> text ":" <+> align (pprPrec 0 t)   pprPrec p (Coerce e t _ _) =-    parensIf (p /= -1) $ pprPrec 0 e <+> text ":>" <+> pprPrec 0 t+    parensIf (p /= -1) $ pprPrec 0 e <+> text ":>" <+> align (pprPrec 0 t)   pprPrec _ (Literal v _) = ppr v   pprPrec _ (IntLit v _ _) = ppr v   pprPrec _ (FloatLit v _ _) = ppr v@@ -281,7 +281,7 @@     retdecl' <+> equals </> indent 2 (ppr e) </>     letBody body     where retdecl' = case (ppr <$> unAnnot rettype) `mplus` (ppr <$> retdecl) of-                       Just rettype' -> text ":" <+> rettype'+                       Just rettype' -> colon <+> align rettype'                        Nothing       -> mempty   pprPrec _ (LetWith dest src idxs ve body _ _)     | dest == src =@@ -349,10 +349,10 @@     text "while" <+> ppr cond  instance (Eq vn, IsName vn, Annot f) => Pretty (PatternBase f vn) where-  ppr (PatternAscription p t _) = ppr p <> text ":" <+> ppr t+  ppr (PatternAscription p t _) = ppr p <> colon <+> align (ppr t)   ppr (PatternParens p _)       = parens $ ppr p   ppr (Id v t _)                = case unAnnot t of-                                    Just t' -> parens $ pprName v <> colon <+> ppr t'+                                    Just t' -> parens $ pprName v <> colon <+> align (ppr t')                                     Nothing -> pprName v   ppr (TuplePattern pats _)     = parens $ commasep $ map ppr pats   ppr (RecordPattern fs _)      = braces $ commasep $ map ppField fs@@ -365,7 +365,7 @@  ppAscription :: Pretty t => Maybe t -> Doc ppAscription Nothing  = mempty-ppAscription (Just t) = text ":" <> ppr t+ppAscription (Just t) = colon <> align (ppr t)  instance (Eq vn, IsName vn, Annot f) => Pretty (ProgBase f vn) where   ppr = stack . punctuate line . map ppr . progDecs@@ -415,7 +415,7 @@     where fun | isJust entry = "entry"               | otherwise    = "let"           retdecl' = case (ppr . fst <$> unAnnot rettype) `mplus` (ppr <$> retdecl) of-                       Just rettype' -> text ":" <+> rettype'+                       Just rettype' -> colon <+> align rettype'                        Nothing       -> mempty  instance (Eq vn, IsName vn, Annot f) => Pretty (SpecBase f vn) where
src/Language/Futhark/Prop.hs view
@@ -399,6 +399,11 @@       Scalar $ Record $ M.map (uncurry combineTypeShapes) (M.intersectionWith (,) ts1 ts2) combineTypeShapes (Scalar (Arrow als1 p1 a1 b1)) (Scalar (Arrow als2 _p2 a2 b2)) =   Scalar $ Arrow (als1<>als2) p1 (combineTypeShapes a1 a2) (combineTypeShapes b1 b2)+combineTypeShapes (Scalar (TypeVar als1 u1 v targs1)) (Scalar (TypeVar als2 _ _ targs2)) =+  Scalar $ TypeVar (als1<>als2) u1 v $ zipWith f targs1 targs2+  where f (TypeArgType t1 loc) (TypeArgType t2 _) =+          TypeArgType (combineTypeShapes t1 t2) loc+        f targ _ = targ combineTypeShapes (Array als1 u1 et1 shape1) (Array als2 _u2 et2 _shape2) =   arrayOfWithAliases (combineTypeShapes (Scalar et1) (Scalar et2)                        `setAliases` mempty)
src/Language/Futhark/Syntax.hs view
@@ -994,8 +994,11 @@   | ModImport FilePath (f FilePath) SrcLoc     -- ^ The contents of another file as a module.   | ModDecs [DecBase f vn] SrcLoc-  | ModApply (ModExpBase f vn) (ModExpBase f vn) (f (M.Map VName VName)) (f (M.Map VName VName)) SrcLoc-    -- ^ Functor application.+  | ModApply (ModExpBase f vn) (ModExpBase f vn)+    (f (M.Map VName VName)) (f (M.Map VName VName)) SrcLoc+    -- ^ Functor application.  The first mapping is from parameter+    -- names to argument names, while the second maps names in the+    -- constructed module to the names inside the functor.   | ModAscript (ModExpBase f vn) (SigExpBase f vn) (f (M.Map VName VName)) SrcLoc   | ModLambda (ModParamBase f vn)     (Maybe (SigExpBase f vn, f (M.Map VName VName)))