packages feed

futhark 0.25.30 → 0.25.31

raw patch · 84 files changed

+2337/−1233 lines, 84 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Futhark.Analysis.HORep.SOAC: ReshapeInner :: Certs -> ReshapeKind -> Shape -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: ReshapeOuter :: Certs -> ReshapeKind -> Shape -> ArrayTransform
- Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty Futhark.IR.Syntax.Core.ExtShape
- Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty Futhark.IR.Syntax.Core.Shape
- Futhark.IR.Syntax: ReshapeArbitrary :: ReshapeKind
- Futhark.IR.Syntax: ReshapeCoerce :: ReshapeKind
- Futhark.IR.Syntax: data ReshapeKind
- Futhark.IR.Syntax: instance GHC.Classes.Eq Futhark.IR.Syntax.ReshapeKind
- Futhark.IR.Syntax: instance GHC.Classes.Ord Futhark.IR.Syntax.ReshapeKind
- Futhark.IR.Syntax: instance GHC.Show.Show Futhark.IR.Syntax.ReshapeKind
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.TypeParamBase vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.AppExpBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.CaseBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.DecBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.DimIndexBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ExpBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.FieldBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.LoopFormBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.LoopInitBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModBindBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModExpBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModParamBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModTypeBindBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModTypeExpBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ProgBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.SpecBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.TypeBindBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ValBindBase f vn)
- Language.Futhark.Pretty: instance (GHC.Classes.Eq vn, Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f, Prettyprinter.Internal.Pretty t) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.PatBase f vn t)
+ Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty d => Prettyprinter.Internal.Pretty (Futhark.IR.Syntax.Core.ShapeBase d)
+ Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty d => Prettyprinter.Internal.Pretty (Futhark.IR.Syntax.DimSplice d)
+ Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty d => Prettyprinter.Internal.Pretty (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Pretty: instance Prettyprinter.Internal.Pretty dec => Prettyprinter.Internal.Pretty (Futhark.IR.Syntax.StmAux dec)
+ Futhark.IR.Prop.Names: instance Futhark.IR.Prop.Names.FreeIn d => Futhark.IR.Prop.Names.FreeIn (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Prop.Reshape: ReshapeArbitrary :: ReshapeKind
+ Futhark.IR.Prop.Reshape: ReshapeCoerce :: ReshapeKind
+ Futhark.IR.Prop.Reshape: applySplice :: ShapeBase d -> DimSplice d -> ShapeBase d
+ Futhark.IR.Prop.Reshape: data ReshapeKind
+ Futhark.IR.Prop.Reshape: flipRearrangeReshape :: [Int] -> NewShape d -> Maybe (NewShape d, [Int])
+ Futhark.IR.Prop.Reshape: flipReshapeRearrange :: Eq d => [d] -> [d] -> [Int] -> Maybe [Int]
+ Futhark.IR.Prop.Reshape: instance GHC.Classes.Eq Futhark.IR.Prop.Reshape.ReshapeKind
+ Futhark.IR.Prop.Reshape: instance GHC.Classes.Ord Futhark.IR.Prop.Reshape.ReshapeKind
+ Futhark.IR.Prop.Reshape: instance GHC.Show.Show Futhark.IR.Prop.Reshape.ReshapeKind
+ Futhark.IR.Prop.Reshape: newShape :: NewShape d -> ShapeBase d
+ Futhark.IR.Prop.Reshape: newshapeInner :: Shape -> NewShape SubExp -> NewShape SubExp
+ Futhark.IR.Prop.Reshape: reshapeAll :: ArrayShape old => old -> ShapeBase new -> NewShape new
+ Futhark.IR.Prop.Reshape: reshapeCoerce :: ShapeBase new -> NewShape new
+ Futhark.IR.Prop.Reshape: reshapeKind :: NewShape SubExp -> ReshapeKind
+ Futhark.IR.Prop.Reshape: simplifyNewShape :: Eq d => ShapeBase d -> NewShape d -> Maybe (NewShape d)
+ Futhark.IR.Syntax: DimSplice :: Int -> Int -> ShapeBase d -> DimSplice d
+ Futhark.IR.Syntax: NewShape :: [DimSplice d] -> ShapeBase d -> NewShape d
+ Futhark.IR.Syntax: [dimSplices] :: NewShape d -> [DimSplice d]
+ Futhark.IR.Syntax: [newShape] :: NewShape d -> ShapeBase d
+ Futhark.IR.Syntax: data DimSplice d
+ Futhark.IR.Syntax: data NewShape d
+ Futhark.IR.Syntax: instance Data.Foldable.Foldable Futhark.IR.Syntax.DimSplice
+ Futhark.IR.Syntax: instance Data.Foldable.Foldable Futhark.IR.Syntax.NewShape
+ Futhark.IR.Syntax: instance Data.Traversable.Traversable Futhark.IR.Syntax.DimSplice
+ Futhark.IR.Syntax: instance Data.Traversable.Traversable Futhark.IR.Syntax.NewShape
+ Futhark.IR.Syntax: instance GHC.Base.Functor Futhark.IR.Syntax.DimSplice
+ Futhark.IR.Syntax: instance GHC.Base.Functor Futhark.IR.Syntax.NewShape
+ Futhark.IR.Syntax: instance GHC.Base.Monoid dec => GHC.Base.Monoid (Futhark.IR.Syntax.StmAux dec)
+ Futhark.IR.Syntax: instance GHC.Base.Semigroup (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Syntax: instance GHC.Classes.Eq d => GHC.Classes.Eq (Futhark.IR.Syntax.DimSplice d)
+ Futhark.IR.Syntax: instance GHC.Classes.Eq d => GHC.Classes.Eq (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Syntax: instance GHC.Classes.Ord d => GHC.Classes.Ord (Futhark.IR.Syntax.DimSplice d)
+ Futhark.IR.Syntax: instance GHC.Classes.Ord d => GHC.Classes.Ord (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Syntax: instance GHC.Show.Show d => GHC.Show.Show (Futhark.IR.Syntax.DimSplice d)
+ Futhark.IR.Syntax: instance GHC.Show.Show d => GHC.Show.Show (Futhark.IR.Syntax.NewShape d)
+ Futhark.IR.Syntax: prettyStringOneLine :: Pretty a => a -> String
+ Futhark.IR.Syntax: prettyTextOneLine :: Pretty a => a -> Text
+ Futhark.IR.Syntax.Core: dropDims :: Int -> ShapeBase d -> ShapeBase d
+ Futhark.IR.Syntax.Core: takeDims :: Int -> ShapeBase d -> ShapeBase d
+ Futhark.Optimise.TileLoops.Shared: initialIxFnEnv :: Scope GPU -> IxFnEnv
+ Futhark.Transform.Substitute: instance Futhark.Transform.Substitute.Substitute d => Futhark.Transform.Substitute.Substitute (Futhark.IR.Syntax.NewShape d)
+ Language.Futhark.Interpreter.Values: arrayValueShape :: forall (m :: Type -> Type). Value m -> ValueShape
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.AppExpBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.CaseBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.DecBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.DimIndexBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ExpBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.FieldBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.LoopFormBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.LoopInitBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModBindBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModExpBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModParamBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModTypeBindBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ModTypeExpBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ProgBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.SpecBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.TypeBindBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.ValBindBase f vn)
+ Language.Futhark.Pretty: instance (Language.Futhark.Pretty.IsName vn, Language.Futhark.Pretty.Annot f, Prettyprinter.Internal.Pretty t) => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.PatBase f vn t)
+ Language.Futhark.Pretty: instance Language.Futhark.Pretty.IsName vn => Prettyprinter.Internal.Pretty (Language.Futhark.Syntax.TypeParamBase vn)
+ Language.Futhark.Pretty: symbolName :: Name -> Bool
- Futhark.Analysis.HORep.MapNest: reshape :: MonadFreshNames m => Certs -> Shape -> MapNest -> m MapNest
+ Futhark.Analysis.HORep.MapNest: reshape :: MonadFreshNames m => StmAux () -> Shape -> MapNest -> m MapNest
- Futhark.Analysis.HORep.SOAC: Index :: Certs -> Slice SubExp -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Index :: StmAux () -> Slice SubExp -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: Rearrange :: Certs -> [Int] -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Rearrange :: StmAux () -> [Int] -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: Replicate :: Certs -> Shape -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Replicate :: StmAux () -> Shape -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: Reshape :: Certs -> ReshapeKind -> Shape -> ArrayTransform
+ Futhark.Analysis.HORep.SOAC: Reshape :: StmAux () -> NewShape SubExp -> ArrayTransform
- Futhark.Analysis.HORep.SOAC: transformFromExp :: Certs -> Exp rep -> Maybe (VName, ArrayTransform)
+ Futhark.Analysis.HORep.SOAC: transformFromExp :: StmAux () -> Exp rep -> Maybe (VName, ArrayTransform)
- Futhark.Analysis.HORep.SOAC: transformToExp :: (Monad m, HasScope rep m) => ArrayTransform -> VName -> m (Certs, Exp rep)
+ Futhark.Analysis.HORep.SOAC: transformToExp :: (Monad m, HasScope rep m) => ArrayTransform -> VName -> m (StmAux (), Exp rep)
- Futhark.Analysis.SymbolTable: index :: ASTRep rep => VName -> [SubExp] -> SymbolTable rep -> Maybe Indexed
+ Futhark.Analysis.SymbolTable: index :: VName -> [SubExp] -> SymbolTable rep -> Maybe Indexed
- Futhark.IR.Syntax: Manifest :: [Int] -> VName -> BasicOp
+ Futhark.IR.Syntax: Manifest :: VName -> [Int] -> BasicOp
- Futhark.IR.Syntax: Rearrange :: [Int] -> VName -> BasicOp
+ Futhark.IR.Syntax: Rearrange :: VName -> [Int] -> BasicOp
- Futhark.IR.Syntax: Reshape :: ReshapeKind -> Shape -> VName -> BasicOp
+ Futhark.IR.Syntax: Reshape :: VName -> NewShape SubExp -> BasicOp
- Futhark.IR.TypeCheck: SlicingError :: Int -> Int -> ErrorCase rep
+ Futhark.IR.TypeCheck: SlicingError :: Shape -> Int -> ErrorCase rep
- Futhark.Pass.ExtractKernels.ISRWIM: rwimPossible :: Lambda SOACS -> Maybe (Pat Type, Certs, SubExp, Lambda SOACS)
+ Futhark.Pass.ExtractKernels.ISRWIM: rwimPossible :: Lambda SOACS -> Maybe (Pat Type, StmAux (), SubExp, Lambda SOACS)
- Language.Futhark.Pretty: class IsName v
+ Language.Futhark.Pretty: class Eq v => IsName v
- Language.Futhark.TypeChecker.Modules: refineEnv :: SrcLoc -> TySet -> Env -> QualName Name -> [TypeParam] -> StructType -> TypeM (QualName VName, TySet, Env)
+ Language.Futhark.TypeChecker.Modules: refineEnv :: SrcLoc -> TySet -> Env -> QualName Name -> [TypeParam] -> StructRetType -> TypeM (QualName VName, TySet, Env)

Files

CHANGELOG.md view
@@ -5,6 +5,55 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.25.31]++### Added++* GPU backends: more efficient atomic operations on 8-bit and 16-bit quantities.+  This helps histograms on these types, as well as AD on programs that use+  `f16`.++* Improved handling of long chains of `flatten`/`unflatten`/`transpose`+  operations.++* New attributes: `#[blank]` and `#[scratch]`.++* A module type `with`-refinement may now have an existentially quantified size+  on its right-hand side.++* Value specs in module types can now use section binding notation for symbolic+  names, and in fact this is the preferred form that is also used by `futhark+  fmt`. (#2266)++* `futhark profile` now also prints proportion of total runtime for each cost centre.++* Futhark no longer warns about entry points with opaque types.++* Types such as `foo.bar` are now turned into `foo_bar` in the C API, rather+  than an ugly hash.++### Fixed++* Interpreter: some tricky aspects of size-lifted types (#2258).++* Incorrect unused-name warning for named parameters in module types.++* Size-lifted abstract types with hidden sizes could result in different sizes+  being incorrectly treated as the same size.++* It was possible to make size-lifted types appear unlifted by using parametric+  types (#2268).++* The same type would be mentioned twice in some type errors.++* The type checker neglected to detect some cases of invalid references from+  return types to names bound in parameter patterns. (#2271)++* Incorrect handling of projections used in size expressions.++* Subtle interactions of modules and sizes in the interpreter and compiler+  (#2273).+ ## [0.25.30]  ### Added
docs/language-reference.rst view
@@ -1645,6 +1645,7 @@  .. productionlist::    spec:   "val" `name` `type_param`* ":" `type`+       : | "val" "(" `symbol` ")" ":" `type`        : | "val" `symbol` `type_param`* ":" `type`        : | ("type" | "type^" | "type~") `name` `type_param`* "=" `type`        : | ("type" | "type^" | "type~") `name` `type_param`*@@ -1742,6 +1743,16 @@  The following expression attributes are supported. +``blank``+.........++Indicates that the value computed by the expression does not matter, and that+the expression can be replaced with an arbitrary other expression of the same+type. This is useful for constructing arrays that will eventually be filled with+``scatter`` or similar operations. Note that this can subvert type-based+invariants safety if the blank value is used, but it cannot subvert memory+safety.+ ``trace`` ......... @@ -1801,6 +1812,13 @@ Do not inline the attributed function application.  If used within a parallel construct (e.g. ``map``), this will likely prevent the GPU backends from generating working code.++``scratch``+...........++Like ``blank``, but the resulting values (if arrays) will comprise initialised+memory. Reading from such arrays is potentially dangerous, as the elements are+completely undefined until they are updated with a ``scatter`` or similar.  ``sequential`` ..............
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name:           futhark-version:        0.25.30+version:        0.25.31 synopsis:       An optimising compiler for a functional, array-oriented language.  description:    Futhark is a small programming language designed to be compiled to@@ -36,7 +36,10 @@ extra-source-files: -- Cabal's recompilation tracking doesn't work when we use wildcards -- here, so for now we spell out every single file.-    rts/c/atomics.h+    rts/c/atomics8.h+    rts/c/atomics16.h+    rts/c/atomics32.h+    rts/c/atomics64.h     rts/c/context.h     rts/c/context_prototypes.h     rts/c/backends/c.h
prelude/math.fut view
@@ -29,21 +29,21 @@ module type numeric = {   include from_prim -  val + : t -> t -> t-  val - : t -> t -> t-  val * : t -> t -> t-  val / : t -> t -> t-  val % : t -> t -> t-  val ** : t -> t -> t+  val (+) : t -> t -> t+  val (-) : t -> t -> t+  val (*) : t -> t -> t+  val (/) : t -> t -> t+  val (%) : t -> t -> t+  val (**) : t -> t -> t    val to_i64 : t -> i64 -  val == : t -> t -> bool-  val < : t -> t -> bool-  val > : t -> t -> bool-  val <= : t -> t -> bool-  val >= : t -> t -> bool-  val != : t -> t -> bool+  val (==) : t -> t -> bool+  val (<) : t -> t -> bool+  val (>) : t -> t -> bool+  val (<=) : t -> t -> bool+  val (>=) : t -> t -> bool+  val (!=) : t -> t -> bool    -- | Arithmetic negation (use `!` for bitwise negation).   val neg : t -> t@@ -83,32 +83,32 @@    -- | Like `/`@term, but rounds towards zero.  This only matters when   -- one of the operands is negative.  May be more efficient.-  val // : t -> t -> t+  val (//) : t -> t -> t    -- | Like `%`@term, but rounds towards zero.  This only matters when   -- one of the operands is negative.  May be more efficient.-  val %% : t -> t -> t+  val (%%) : t -> t -> t    -- | Bitwise and.-  val & : t -> t -> t+  val (&) : t -> t -> t    -- | Bitwise or.-  val | : t -> t -> t+  val (|) : t -> t -> t    -- | Bitwise xor.-  val ^ : t -> t -> t+  val (^) : t -> t -> t    -- | Bitwise negation.   val not : t -> t    -- | Left shift; inserting zeroes.-  val << : t -> t -> t+  val (<<) : t -> t -> t    -- | Arithmetic right shift, using sign extension for the leftmost bits.-  val >> : t -> t -> t+  val (>>) : t -> t -> t    -- | Logical right shift, inserting zeroes for the leftmost bits.-  val >>> : t -> t -> t+  val (>>>) : t -> t -> t    val num_bits : i32   val get_bit : i32 -> t -> i32
prelude/soacs.fut view
@@ -255,6 +255,6 @@   let flags = map (\x -> if p x then 1 else 0) as   let offsets = scan (+) 0 flags   let m = if n == 0 then 0 else offsets[n - 1]-  in scatter (map (\x -> x) as[:m])+  in scatter (#[scratch] map (\x -> x) as[:m])              (map2 (\f o -> if f == 1 then o - 1 else -1) flags offsets)              as
− rts/c/atomics.h
@@ -1,519 +0,0 @@-// Start of atomics.h--SCALAR_FUN_ATTR int32_t atomic_xchg_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_xchg_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_global(volatile __global int32_t *p,-                                                         int32_t cmp, int32_t val);-SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_shared(volatile __local int32_t *p,-                                                        int32_t cmp, int32_t val);-SCALAR_FUN_ATTR int32_t atomic_add_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_add_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR float atomic_fadd_f32_global(volatile __global float *p, float x);-SCALAR_FUN_ATTR float atomic_fadd_f32_shared(volatile __local float *p, float x);-SCALAR_FUN_ATTR int32_t atomic_smax_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_smax_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_smin_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_smin_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR uint32_t atomic_umax_i32_global(volatile __global uint32_t *p, uint32_t x);-SCALAR_FUN_ATTR uint32_t atomic_umax_i32_shared(volatile __local uint32_t *p, uint32_t x);-SCALAR_FUN_ATTR uint32_t atomic_umin_i32_global(volatile __global uint32_t *p, uint32_t x);-SCALAR_FUN_ATTR uint32_t atomic_umin_i32_shared(volatile __local uint32_t *p, uint32_t x);-SCALAR_FUN_ATTR int32_t atomic_and_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_and_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_or_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_or_i32_shared(volatile __local int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_xor_i32_global(volatile __global int32_t *p, int32_t x);-SCALAR_FUN_ATTR int32_t atomic_xor_i32_shared(volatile __local int32_t *p, int32_t x);--SCALAR_FUN_ATTR int32_t atomic_xchg_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicExch((int32_t*)p, x);-#else-  return atomic_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_xchg_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicExch((int32_t*)p, x);-#else-  return atomic_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_global(volatile __global int32_t *p,-                                                         int32_t cmp, int32_t val) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicCAS((int32_t*)p, cmp, val);-#else-  return atomic_cmpxchg(p, cmp, val);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_shared(volatile __local int32_t *p,-                                                        int32_t cmp, int32_t val) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicCAS((int32_t*)p, cmp, val);-#else-  return atomic_cmpxchg(p, cmp, val);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_add_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((int32_t*)p, x);-#else-  return atomic_add(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_add_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((int32_t*)p, x);-#else-  return atomic_add(p, x);-#endif-}--SCALAR_FUN_ATTR float atomic_fadd_f32_global(volatile __global float *p, float x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((float*)p, x);-  // On OpenCL, use technique from-  // https://pipinspace.github.io/blog/atomic-float-addition-in-opencl.html-#elif defined(cl_nv_pragma_unroll)-  // use hardware-supported atomic addition on Nvidia GPUs with inline-  // PTX assembly-  float ret;-  asm volatile("atom.global.add.f32 %0,[%1],%2;":"=f"(ret):"l"(p),"f"(x):"memory");-  return ret;-#elif defined(__opencl_c_ext_fp32_global_atomic_add)-  // use hardware-supported atomic addition on some Intel GPUs-  return atomic_fetch_add_explicit((volatile __global atomic_float*)p,-                                   x,-                                   memory_order_relaxed);-#elif __has_builtin(__builtin_amdgcn_global_atomic_fadd_f32)-  // use hardware-supported atomic addition on some AMD GPUs-  return __builtin_amdgcn_global_atomic_fadd_f32(p, x);-#else-  // fallback emulation:-  // https://forums.developer.nvidia.com/t/atomicadd-float-float-atomicmul-float-float/14639/5-  float old = x;-  float ret;-  while ((old=atomic_xchg(p, ret=atomic_xchg(p, 0.0f)+old))!=0.0f);-  return ret;-#endif-}--SCALAR_FUN_ATTR float atomic_fadd_f32_shared(volatile __local float *p, float x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((float*)p, x);-#else-  union { int32_t i; float f; } old;-  union { int32_t i; float f; } assumed;-  old.f = *p;-  do {-    assumed.f = old.f;-    old.f = old.f + x;-    old.i = atomic_cmpxchg_i32_shared((volatile __local int32_t*)p, assumed.i, old.i);-  } while (assumed.i != old.i);-  return old.f;-#endif-}--SCALAR_FUN_ATTR int32_t atomic_smax_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((int32_t*)p, x);-#else-  return atomic_max(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_smax_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((int32_t*)p, x);-#else-  return atomic_max(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_smin_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((int32_t*)p, x);-#else-  return atomic_min(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_smin_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((int32_t*)p, x);-#else-  return atomic_min(p, x);-#endif-}--SCALAR_FUN_ATTR uint32_t atomic_umax_i32_global(volatile __global uint32_t *p, uint32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((uint32_t*)p, x);-#else-  return atomic_max(p, x);-#endif-}--SCALAR_FUN_ATTR uint32_t atomic_umax_i32_shared(volatile __local uint32_t *p, uint32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((uint32_t*)p, x);-#else-  return atomic_max(p, x);-#endif-}--SCALAR_FUN_ATTR uint32_t atomic_umin_i32_global(volatile __global uint32_t *p, uint32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((uint32_t*)p, x);-#else-  return atomic_min(p, x);-#endif-}--SCALAR_FUN_ATTR uint32_t atomic_umin_i32_shared(volatile __local uint32_t *p, uint32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((uint32_t*)p, x);-#else-  return atomic_min(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_and_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAnd((int32_t*)p, x);-#else-  return atomic_and(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_and_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAnd((int32_t*)p, x);-#else-  return atomic_and(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_or_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicOr((int32_t*)p, x);-#else-  return atomic_or(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_or_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicOr((int32_t*)p, x);-#else-  return atomic_or(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_xor_i32_global(volatile __global int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicXor((int32_t*)p, x);-#else-  return atomic_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int32_t atomic_xor_i32_shared(volatile __local int32_t *p, int32_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicXor((int32_t*)p, x);-#else-  return atomic_xor(p, x);-#endif-}--// Start of 64 bit atomics--#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP) || defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)--SCALAR_FUN_ATTR int64_t atomic_xchg_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_xchg_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_global(volatile __global int64_t *p,-                                                         int64_t cmp, int64_t val);-SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_shared(volatile __local int64_t *p,-                                                        int64_t cmp, int64_t val);-SCALAR_FUN_ATTR int64_t atomic_add_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_add_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_smax_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_smax_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_smin_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_smin_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR uint64_t atomic_umax_i64_global(volatile __global uint64_t *p, uint64_t x);-SCALAR_FUN_ATTR uint64_t atomic_umax_i64_shared(volatile __local uint64_t *p, uint64_t x);-SCALAR_FUN_ATTR uint64_t atomic_umin_i64_global(volatile __global uint64_t *p, uint64_t x);-SCALAR_FUN_ATTR uint64_t atomic_umin_i64_shared(volatile __local uint64_t *p, uint64_t x);-SCALAR_FUN_ATTR int64_t atomic_and_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_and_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_or_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_or_i64_shared(volatile __local int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_xor_i64_global(volatile __global int64_t *p, int64_t x);-SCALAR_FUN_ATTR int64_t atomic_xor_i64_shared(volatile __local int64_t *p, int64_t x);--#ifdef FUTHARK_F64_ENABLED-SCALAR_FUN_ATTR double atomic_fadd_f64_global(volatile __global double *p, double x);-SCALAR_FUN_ATTR double atomic_fadd_f64_shared(volatile __local double *p, double x);-#endif--SCALAR_FUN_ATTR int64_t atomic_xchg_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicExch((unsigned long long*)p, x);-#else-  return atom_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_xchg_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicExch((unsigned long long*)p, x);-#else-  return atom_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_global(volatile __global int64_t *p,-                                                         int64_t cmp, int64_t val) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicCAS((unsigned long long*)p, cmp, val);-#else-  return atom_cmpxchg(p, cmp, val);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_shared(volatile __local int64_t *p,-                                                        int64_t cmp, int64_t val) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicCAS((unsigned long long*)p, cmp, val);-#else-  return atom_cmpxchg(p, cmp, val);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_add_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((unsigned long long*)p, x);-#else-  return atom_add(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_add_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAdd((unsigned long long*)p, x);-#else-  return atom_add(p, x);-#endif-}--#ifdef FUTHARK_F64_ENABLED--SCALAR_FUN_ATTR double atomic_fadd_f64_global(volatile __global double *p, double x) {-#if defined(FUTHARK_CUDA) && __CUDA_ARCH__ >= 600 || defined(FUTHARK_HIP)-  return atomicAdd((double*)p, x);-  // On OpenCL, use technique from-  // https://pipinspace.github.io/blog/atomic-float-addition-in-opencl.html-#elif defined(cl_nv_pragma_unroll)-  // use hardware-supported atomic addition on Nvidia GPUs with inline-  // PTX assembly-  double ret;-  asm volatile("atom.global.add.f64 %0,[%1],%2;":"=d"(ret):"l"(p),"d"(x):"memory");-  return ret;-#elif __has_builtin(__builtin_amdgcn_global_atomic_fadd_f64)-  // use hardware-supported atomic addition on some AMD GPUs-  return __builtin_amdgcn_global_atomic_fadd_f64(p, x);-#else-  // fallback emulation:-  // https://forums.developer.nvidia.com/t/atomicadd-float-float-atomicmul-float-float/14639/5-  union {int64_t i; double f;} old;-  union {int64_t i; double f;} ret;-  old.f = x;-  while (1) {-    ret.i = atom_xchg((volatile __global int64_t*)p, (int64_t)0);-    ret.f += old.f;-    old.i = atom_xchg((volatile __global int64_t*)p, ret.i);-    if (old.i == 0) {-      break;-    }-  }-  return ret.f;-#endif-}--SCALAR_FUN_ATTR double atomic_fadd_f64_shared(volatile __local double *p, double x) {-#if defined(FUTHARK_CUDA) && __CUDA_ARCH__ >= 600 || defined(FUTHARK_HIP)-  return atomicAdd((double*)p, x);-#else-  union { int64_t i; double f; } old;-  union { int64_t i; double f; } assumed;-  old.f = *p;-  do {-    assumed.f = old.f;-    old.f = old.f + x;-    old.i = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed.i, old.i);-  } while (assumed.i != old.i);-  return old.f;-#endif-}--#endif--SCALAR_FUN_ATTR int64_t atomic_smax_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA)-  return atomicMax((long long*)p, x);-#elif defined(FUTHARK_HIP)-  // Currentely missing in HIP; probably a temporary oversight.-  int64_t old = *p, assumed;-  do {-    assumed = old;-    old = smax64(old, x);-    old = atomic_cmpxchg_i64_global((volatile __global int64_t*)p, assumed, old);-  } while (assumed != old);-  return old;-#else-  return atom_max(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_smax_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA)-  return atomicMax((long long*)p, x);-#elif defined(FUTHARK_HIP)-  // Currentely missing in HIP; probably a temporary oversight.-  int64_t old = *p, assumed;-  do {-    assumed = old;-    old = smax64(old, x);-    old = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed, old);-  } while (assumed != old);-  return old;-#else-  return atom_max(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_smin_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA)-  return atomicMin((long long*)p, x);-#elif defined(FUTHARK_HIP)-  // Currentely missing in HIP; probably a temporary oversight.-  int64_t old = *p, assumed;-  do {-    assumed = old;-    old = smin64(old, x);-    old = atomic_cmpxchg_i64_global((volatile __global int64_t*)p, assumed, old);-  } while (assumed != old);-  return old;-#else-  return atom_min(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_smin_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA)-  return atomicMin((long long*)p, x);-#elif defined(FUTHARK_HIP)-  // Currentely missing in HIP; probably a temporary oversight.-  int64_t old = *p, assumed;-  do {-    assumed = old;-    old = smin64(old, x);-    old = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed, old);-  } while (assumed != old);-  return old;-#else-  return atom_min(p, x);-#endif-}--SCALAR_FUN_ATTR uint64_t atomic_umax_i64_global(volatile __global uint64_t *p, uint64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((unsigned long long*)p, x);-#else-  return atom_max(p, x);-#endif-}--SCALAR_FUN_ATTR uint64_t atomic_umax_i64_shared(volatile __local uint64_t *p, uint64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMax((unsigned long long*)p, x);-#else-  return atom_max(p, x);-#endif-}--SCALAR_FUN_ATTR uint64_t atomic_umin_i64_global(volatile __global uint64_t *p, uint64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((unsigned long long*)p, x);-#else-  return atom_min(p, x);-#endif-}--SCALAR_FUN_ATTR uint64_t atomic_umin_i64_shared(volatile __local uint64_t *p, uint64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicMin((unsigned long long*)p, x);-#else-  return atom_min(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_and_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAnd((unsigned long long*)p, x);-#else-  return atom_and(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_and_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicAnd((unsigned long long*)p, x);-#else-  return atom_and(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_or_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicOr((unsigned long long*)p, x);-#else-  return atom_or(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_or_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicOr((unsigned long long*)p, x);-#else-  return atom_or(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_xor_i64_global(volatile __global int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicXor((unsigned long long*)p, x);-#else-  return atom_xor(p, x);-#endif-}--SCALAR_FUN_ATTR int64_t atomic_xor_i64_shared(volatile __local int64_t *p, int64_t x) {-#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)-  return atomicXor((unsigned long long*)p, x);-#else-  return atom_xor(p, x);-#endif-}--#endif // defined(FUTHARK_CUDA) || defined(FUTHARK_HIP) || defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)--// End of atomics.h
+ rts/c/atomics16.h view
@@ -0,0 +1,177 @@+// Start of atomics16.h++SCALAR_FUN_ATTR int16_t atomic_cmpxchg_i16_global(volatile __global int16_t *p,+                                                  int16_t cmp, int16_t val);+SCALAR_FUN_ATTR int16_t atomic_cmpxchg_i16_shared(volatile __local int16_t *p,+                                                  int16_t cmp, int16_t val);+SCALAR_FUN_ATTR int16_t atomic_add_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_add_i16_shared(volatile __local int16_t *p, int16_t x);+SCALAR_FUN_ATTR f16 atomic_fadd_f16_global(volatile __global uint16_t *p, f16 x);+SCALAR_FUN_ATTR f16 atomic_fadd_f16_shared(volatile __local uint16_t *p, f16 x);+SCALAR_FUN_ATTR int16_t atomic_smax_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_smax_i16_shared(volatile __local int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_smin_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_smin_i16_shared(volatile __local int16_t *p, int16_t x);+SCALAR_FUN_ATTR uint16_t atomic_umax_i16_global(volatile __global uint16_t *p, uint16_t x);+SCALAR_FUN_ATTR uint16_t atomic_umax_i16_shared(volatile __local uint16_t *p, uint16_t x);+SCALAR_FUN_ATTR uint16_t atomic_umin_i16_global(volatile __global uint16_t *p, uint16_t x);+SCALAR_FUN_ATTR uint16_t atomic_umin_i16_shared(volatile __local uint16_t *p, uint16_t x);+SCALAR_FUN_ATTR int16_t atomic_and_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_and_i16_shared(volatile __local int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_or_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_or_i16_shared(volatile __local int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_xor_i16_global(volatile __global int16_t *p, int16_t x);+SCALAR_FUN_ATTR int16_t atomic_xor_i16_shared(volatile __local int16_t *p, int16_t x);++SCALAR_FUN_ATTR int16_t atomic_cmpxchg_i16_global(volatile __global int16_t *p,+                                                  int16_t cmp, int16_t val) {+  int offset = ((uintptr_t)p >> 1 & 1);+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);++  int shift = offset * 16;+  int32_t mask = 0xffff << shift;+  int32_t shifted_val = val << shift;+  int32_t shifted_cmp = cmp << shift;++  uint32_t old = shifted_cmp;+  uint32_t upd = shifted_val;+  uint32_t got;++  while ((got=atomic_cmpxchg_i32_global(p32, old, upd)) != old) {+    old = got;+    upd = (old & ~mask) | shifted_val;+  }++  return old >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_cmpxchg_i16_shared(volatile __local int16_t *p,+                                                  int16_t cmp, int16_t val) {+  int offset = ((uintptr_t)p >> 1 & 1);+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);++  int shift = offset * 16;+  int32_t mask = 0xffff << shift;+  int32_t shifted_val = val << shift;+  int32_t shifted_cmp = cmp << shift;++  uint32_t old = shifted_cmp;+  uint32_t upd = shifted_val;+  uint32_t got;++  while ((got=atomic_cmpxchg_i32_shared(p32, old, upd)) != old) {+    old = got;+    upd = (old & ~mask) | shifted_val;+  }++  return old >> shift;+}++// Convenience macro for arithmetic.+#define DEFINE_16BIT_ATOMIC(name, T, op)                                \+  SCALAR_FUN_ATTR T                                                     \+  atomic_##name##_i16_global(volatile __global T *p, T val) {           \+    int offset = ((uintptr_t)p >> 1 & 1);                               \+    volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3); \+    int shift = offset * 16;                                            \+    int32_t mask = 0xffff << shift;                                     \+    int32_t old = 0;                                                    \+    int32_t upd = mask & (op(old >> shift, val) << shift);              \+    int32_t saw;                                                        \+    while ((saw=atomic_cmpxchg_i32_global(p32, old, upd)) != old) {     \+      old = saw;                                                        \+      upd = (old & ~mask) | ((op(old >> shift, val)) << shift);         \+    }                                                                   \+    return old >> shift;                                                \+  }                                                                     \+  SCALAR_FUN_ATTR T                                                     \+  atomic_##name##_i16_shared(volatile __local T *p, T val) {            \+    int offset = ((uintptr_t)p >> 1 & 1);                               \+    volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3); \+    int shift = offset * 16;                                            \+    int32_t mask = 0xffff << shift;                                     \+    int32_t old = 0;                                                    \+    int32_t upd = mask & ((op(old >> shift, val)) << shift);            \+    int32_t saw;                                                        \+    while ((saw=atomic_cmpxchg_i32_shared(p32, old, upd)) != old) {     \+      old = saw;                                                        \+      upd = (old & ~mask) | ((op(old >> shift, val)) << shift);         \+    }                                                                   \+    return old >> shift;                                                \+  }++DEFINE_16BIT_ATOMIC(add, int16_t, add16);+DEFINE_16BIT_ATOMIC(smax, int16_t, smax16);+DEFINE_16BIT_ATOMIC(smin, int16_t, smin16);+DEFINE_16BIT_ATOMIC(umax, uint16_t, umax16);+DEFINE_16BIT_ATOMIC(umin, uint16_t, umin16);++SCALAR_FUN_ATTR int16_t atomic_and_i16_global(volatile __global int16_t *p, int16_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  int32_t mask = 0xffff << shift;+  return atomic_and_i32_global(p32, ~mask | (val<<shift)) >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_and_i16_shared(volatile __local int16_t *p, int16_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  int32_t mask = 0xffff << shift;+  return atomic_and_i32_shared(p32, ~mask | (val<<shift)) >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_or_i16_global(volatile __global int16_t *p, int16_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  return atomic_or_i32_global(p32, (uint16_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_or_i16_shared(volatile __local int16_t *p, int16_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  return atomic_or_i32_shared(p32, (uint16_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_xor_i16_global(volatile __global int16_t *p, int16_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  return atomic_xor_i32_global(p32, (uint16_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int16_t atomic_xor_i16_shared(volatile __local int16_t *p, int16_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p >> 1 & 1) * 16;+  return atomic_xor_i32_shared(p32, (uint16_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR f16 atomic_fadd_f16_global(volatile __global uint16_t *p, f16 val) {+  int offset = ((uintptr_t)p >> 1 & 1);+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = offset * 16;+  int32_t mask = 0xffff << shift;+  int32_t old = 0;+  int32_t upd = mask & ((int32_t)futrts_to_bits16(val) << shift);+  int32_t saw;+  while ((saw=atomic_cmpxchg_i32_global(p32, old, upd)) != old) {+    old = saw;+    upd = (old & ~mask) | (int32_t)futrts_to_bits16(futrts_from_bits16((uint32_t)old >> shift) + val) << shift;+  }+  return futrts_from_bits16((uint32_t)old >> shift);+}++SCALAR_FUN_ATTR f16 atomic_fadd_f16_shared(volatile __local uint16_t *p, f16 val) {+  int offset = ((uintptr_t)p >> 1 & 1);+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = offset * 16;+  int32_t mask = 0xffff << shift;+  int32_t old = 0;+  int32_t upd = mask & ((int32_t)futrts_to_bits16(val) << shift);+  int32_t saw;+  while ((saw=atomic_cmpxchg_i32_shared(p32, old, upd)) != old) {+    old = saw;+    upd = (old & ~mask) | (int32_t)futrts_to_bits16(futrts_from_bits16((uint32_t)old >> shift) + val) << shift;+  }+  return futrts_from_bits16((uint32_t)old >> shift);+}++// End of atomics16.h
+ rts/c/atomics32.h view
@@ -0,0 +1,235 @@+// Start of atomics.h++SCALAR_FUN_ATTR int32_t atomic_xchg_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_xchg_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_global(volatile __global int32_t *p,+                                                  int32_t cmp, int32_t val);+SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_shared(volatile __local int32_t *p,+                                                  int32_t cmp, int32_t val);+SCALAR_FUN_ATTR int32_t atomic_add_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_add_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR float atomic_fadd_f32_global(volatile __global float *p, float x);+SCALAR_FUN_ATTR float atomic_fadd_f32_shared(volatile __local float *p, float x);+SCALAR_FUN_ATTR int32_t atomic_smax_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_smax_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_smin_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_smin_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR uint32_t atomic_umax_i32_global(volatile __global uint32_t *p, uint32_t x);+SCALAR_FUN_ATTR uint32_t atomic_umax_i32_shared(volatile __local uint32_t *p, uint32_t x);+SCALAR_FUN_ATTR uint32_t atomic_umin_i32_global(volatile __global uint32_t *p, uint32_t x);+SCALAR_FUN_ATTR uint32_t atomic_umin_i32_shared(volatile __local uint32_t *p, uint32_t x);+SCALAR_FUN_ATTR int32_t atomic_and_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_and_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_or_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_or_i32_shared(volatile __local int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_xor_i32_global(volatile __global int32_t *p, int32_t x);+SCALAR_FUN_ATTR int32_t atomic_xor_i32_shared(volatile __local int32_t *p, int32_t x);++SCALAR_FUN_ATTR int32_t atomic_xchg_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicExch((int32_t*)p, x);+#else+  return atomic_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_xchg_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicExch((int32_t*)p, x);+#else+  return atomic_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_global(volatile __global int32_t *p,+                                                  int32_t cmp, int32_t val) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicCAS((int32_t*)p, cmp, val);+#else+  return atomic_cmpxchg(p, cmp, val);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_cmpxchg_i32_shared(volatile __local int32_t *p,+                                                  int32_t cmp, int32_t val) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicCAS((int32_t*)p, cmp, val);+#else+  return atomic_cmpxchg(p, cmp, val);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_add_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((int32_t*)p, x);+#else+  return atomic_add(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_add_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((int32_t*)p, x);+#else+  return atomic_add(p, x);+#endif+}++SCALAR_FUN_ATTR float atomic_fadd_f32_global(volatile __global float *p, float x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((float*)p, x);+  // On OpenCL, use technique from+  // https://pipinspace.github.io/blog/atomic-float-addition-in-opencl.html+#elif defined(cl_nv_pragma_unroll)+  // use hardware-supported atomic addition on Nvidia GPUs with inline+  // PTX assembly+  float ret;+  asm volatile("atom.global.add.f32 %0,[%1],%2;":"=f"(ret):"l"(p),"f"(x):"memory");+  return ret;+#elif defined(__opencl_c_ext_fp32_global_atomic_add)+  // use hardware-supported atomic addition on some Intel GPUs+  return atomic_fetch_add_explicit((volatile __global atomic_float*)p,+                                   x,+                                   memory_order_relaxed);+#elif __has_builtin(__builtin_amdgcn_global_atomic_fadd_f32)+  // use hardware-supported atomic addition on some AMD GPUs+  return __builtin_amdgcn_global_atomic_fadd_f32(p, x);+#else+  // fallback emulation:+  // https://forums.developer.nvidia.com/t/atomicadd-float-float-atomicmul-float-float/14639/5+  float old = x;+  float ret;+  while ((old=atomic_xchg(p, ret=atomic_xchg(p, 0.0f)+old))!=0.0f);+  return ret;+#endif+}++SCALAR_FUN_ATTR float atomic_fadd_f32_shared(volatile __local float *p, float x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((float*)p, x);+#else+  union { int32_t i; float f; } old;+  union { int32_t i; float f; } assumed;+  old.f = *p;+  do {+    assumed.f = old.f;+    old.f = old.f + x;+    old.i = atomic_cmpxchg_i32_shared((volatile __local int32_t*)p, assumed.i, old.i);+  } while (assumed.i != old.i);+  return old.f;+#endif+}++SCALAR_FUN_ATTR int32_t atomic_smax_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((int32_t*)p, x);+#else+  return atomic_max(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_smax_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((int32_t*)p, x);+#else+  return atomic_max(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_smin_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((int32_t*)p, x);+#else+  return atomic_min(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_smin_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((int32_t*)p, x);+#else+  return atomic_min(p, x);+#endif+}++SCALAR_FUN_ATTR uint32_t atomic_umax_i32_global(volatile __global uint32_t *p, uint32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((uint32_t*)p, x);+#else+  return atomic_max(p, x);+#endif+}++SCALAR_FUN_ATTR uint32_t atomic_umax_i32_shared(volatile __local uint32_t *p, uint32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((uint32_t*)p, x);+#else+  return atomic_max(p, x);+#endif+}++SCALAR_FUN_ATTR uint32_t atomic_umin_i32_global(volatile __global uint32_t *p, uint32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((uint32_t*)p, x);+#else+  return atomic_min(p, x);+#endif+}++SCALAR_FUN_ATTR uint32_t atomic_umin_i32_shared(volatile __local uint32_t *p, uint32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((uint32_t*)p, x);+#else+  return atomic_min(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_and_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAnd((int32_t*)p, x);+#else+  return atomic_and(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_and_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAnd((int32_t*)p, x);+#else+  return atomic_and(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_or_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicOr((int32_t*)p, x);+#else+  return atomic_or(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_or_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicOr((int32_t*)p, x);+#else+  return atomic_or(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_xor_i32_global(volatile __global int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicXor((int32_t*)p, x);+#else+  return atomic_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int32_t atomic_xor_i32_shared(volatile __local int32_t *p, int32_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicXor((int32_t*)p, x);+#else+  return atomic_xor(p, x);+#endif+}++// End of atomics.h
+ rts/c/atomics64.h view
@@ -0,0 +1,285 @@+// Start of atomics64.h++#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP) || defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)++SCALAR_FUN_ATTR int64_t atomic_xchg_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_xchg_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_global(volatile __global int64_t *p,+                                                         int64_t cmp, int64_t val);+SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_shared(volatile __local int64_t *p,+                                                        int64_t cmp, int64_t val);+SCALAR_FUN_ATTR int64_t atomic_add_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_add_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_smax_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_smax_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_smin_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_smin_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR uint64_t atomic_umax_i64_global(volatile __global uint64_t *p, uint64_t x);+SCALAR_FUN_ATTR uint64_t atomic_umax_i64_shared(volatile __local uint64_t *p, uint64_t x);+SCALAR_FUN_ATTR uint64_t atomic_umin_i64_global(volatile __global uint64_t *p, uint64_t x);+SCALAR_FUN_ATTR uint64_t atomic_umin_i64_shared(volatile __local uint64_t *p, uint64_t x);+SCALAR_FUN_ATTR int64_t atomic_and_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_and_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_or_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_or_i64_shared(volatile __local int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_xor_i64_global(volatile __global int64_t *p, int64_t x);+SCALAR_FUN_ATTR int64_t atomic_xor_i64_shared(volatile __local int64_t *p, int64_t x);++#ifdef FUTHARK_F64_ENABLED+SCALAR_FUN_ATTR double atomic_fadd_f64_global(volatile __global double *p, double x);+SCALAR_FUN_ATTR double atomic_fadd_f64_shared(volatile __local double *p, double x);+#endif++SCALAR_FUN_ATTR int64_t atomic_xchg_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicExch((unsigned long long*)p, x);+#else+  return atom_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_xchg_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicExch((unsigned long long*)p, x);+#else+  return atom_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_global(volatile __global int64_t *p,+                                                         int64_t cmp, int64_t val) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicCAS((unsigned long long*)p, cmp, val);+#else+  return atom_cmpxchg(p, cmp, val);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_cmpxchg_i64_shared(volatile __local int64_t *p,+                                                        int64_t cmp, int64_t val) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicCAS((unsigned long long*)p, cmp, val);+#else+  return atom_cmpxchg(p, cmp, val);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_add_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((unsigned long long*)p, x);+#else+  return atom_add(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_add_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAdd((unsigned long long*)p, x);+#else+  return atom_add(p, x);+#endif+}++#ifdef FUTHARK_F64_ENABLED++SCALAR_FUN_ATTR double atomic_fadd_f64_global(volatile __global double *p, double x) {+#if defined(FUTHARK_CUDA) && __CUDA_ARCH__ >= 600 || defined(FUTHARK_HIP)+  return atomicAdd((double*)p, x);+  // On OpenCL, use technique from+  // https://pipinspace.github.io/blog/atomic-float-addition-in-opencl.html+#elif defined(cl_nv_pragma_unroll)+  // use hardware-supported atomic addition on Nvidia GPUs with inline+  // PTX assembly+  double ret;+  asm volatile("atom.global.add.f64 %0,[%1],%2;":"=d"(ret):"l"(p),"d"(x):"memory");+  return ret;+#elif __has_builtin(__builtin_amdgcn_global_atomic_fadd_f64)+  // use hardware-supported atomic addition on some AMD GPUs+  return __builtin_amdgcn_global_atomic_fadd_f64(p, x);+#else+  // fallback emulation:+  // https://forums.developer.nvidia.com/t/atomicadd-float-float-atomicmul-float-float/14639/5+  union {int64_t i; double f;} old;+  union {int64_t i; double f;} ret;+  old.f = x;+  while (1) {+    ret.i = atom_xchg((volatile __global int64_t*)p, (int64_t)0);+    ret.f += old.f;+    old.i = atom_xchg((volatile __global int64_t*)p, ret.i);+    if (old.i == 0) {+      break;+    }+  }+  return ret.f;+#endif+}++SCALAR_FUN_ATTR double atomic_fadd_f64_shared(volatile __local double *p, double x) {+#if defined(FUTHARK_CUDA) && __CUDA_ARCH__ >= 600 || defined(FUTHARK_HIP)+  return atomicAdd((double*)p, x);+#else+  union { int64_t i; double f; } old;+  union { int64_t i; double f; } assumed;+  old.f = *p;+  do {+    assumed.f = old.f;+    old.f = old.f + x;+    old.i = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed.i, old.i);+  } while (assumed.i != old.i);+  return old.f;+#endif+}++#endif++SCALAR_FUN_ATTR int64_t atomic_smax_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA)+  return atomicMax((long long*)p, x);+#elif defined(FUTHARK_HIP)+  // Currentely missing in HIP; probably a temporary oversight.+  int64_t old = *p, assumed;+  do {+    assumed = old;+    old = smax64(old, x);+    old = atomic_cmpxchg_i64_global((volatile __global int64_t*)p, assumed, old);+  } while (assumed != old);+  return old;+#else+  return atom_max(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_smax_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA)+  return atomicMax((long long*)p, x);+#elif defined(FUTHARK_HIP)+  // Currentely missing in HIP; probably a temporary oversight.+  int64_t old = *p, assumed;+  do {+    assumed = old;+    old = smax64(old, x);+    old = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed, old);+  } while (assumed != old);+  return old;+#else+  return atom_max(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_smin_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA)+  return atomicMin((long long*)p, x);+#elif defined(FUTHARK_HIP)+  // Currentely missing in HIP; probably a temporary oversight.+  int64_t old = *p, assumed;+  do {+    assumed = old;+    old = smin64(old, x);+    old = atomic_cmpxchg_i64_global((volatile __global int64_t*)p, assumed, old);+  } while (assumed != old);+  return old;+#else+  return atom_min(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_smin_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA)+  return atomicMin((long long*)p, x);+#elif defined(FUTHARK_HIP)+  // Currentely missing in HIP; probably a temporary oversight.+  int64_t old = *p, assumed;+  do {+    assumed = old;+    old = smin64(old, x);+    old = atomic_cmpxchg_i64_shared((volatile __local int64_t*)p, assumed, old);+  } while (assumed != old);+  return old;+#else+  return atom_min(p, x);+#endif+}++SCALAR_FUN_ATTR uint64_t atomic_umax_i64_global(volatile __global uint64_t *p, uint64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((unsigned long long*)p, x);+#else+  return atom_max(p, x);+#endif+}++SCALAR_FUN_ATTR uint64_t atomic_umax_i64_shared(volatile __local uint64_t *p, uint64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMax((unsigned long long*)p, x);+#else+  return atom_max(p, x);+#endif+}++SCALAR_FUN_ATTR uint64_t atomic_umin_i64_global(volatile __global uint64_t *p, uint64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((unsigned long long*)p, x);+#else+  return atom_min(p, x);+#endif+}++SCALAR_FUN_ATTR uint64_t atomic_umin_i64_shared(volatile __local uint64_t *p, uint64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicMin((unsigned long long*)p, x);+#else+  return atom_min(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_and_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAnd((unsigned long long*)p, x);+#else+  return atom_and(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_and_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicAnd((unsigned long long*)p, x);+#else+  return atom_and(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_or_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicOr((unsigned long long*)p, x);+#else+  return atom_or(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_or_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicOr((unsigned long long*)p, x);+#else+  return atom_or(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_xor_i64_global(volatile __global int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicXor((unsigned long long*)p, x);+#else+  return atom_xor(p, x);+#endif+}++SCALAR_FUN_ATTR int64_t atomic_xor_i64_shared(volatile __local int64_t *p, int64_t x) {+#if defined(FUTHARK_CUDA) || defined(FUTHARK_HIP)+  return atomicXor((unsigned long long*)p, x);+#else+  return atom_xor(p, x);+#endif+}++#endif // defined(FUTHARK_CUDA) || defined(FUTHARK_HIP) || defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)++// End of atomics64.h
+ rts/c/atomics8.h view
@@ -0,0 +1,145 @@+// Start of atomics8.h++SCALAR_FUN_ATTR int8_t atomic_cmpxchg_i8_global(volatile __global int8_t *p,+                                                int8_t cmp, int8_t val);+SCALAR_FUN_ATTR int8_t atomic_cmpxchg_i8_shared(volatile __local int8_t *p,+                                                int8_t cmp, int8_t val);+SCALAR_FUN_ATTR int8_t atomic_add_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_add_i8_shared(volatile __local int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_smax_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_smax_i8_shared(volatile __local int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_smin_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_smin_i8_shared(volatile __local int8_t *p, int8_t x);+SCALAR_FUN_ATTR uint8_t atomic_umax_i8_global(volatile __global uint8_t *p, uint8_t x);+SCALAR_FUN_ATTR uint8_t atomic_umax_i8_shared(volatile __local uint8_t *p, uint8_t x);+SCALAR_FUN_ATTR uint8_t atomic_umin_i8_global(volatile __global uint8_t *p, uint8_t x);+SCALAR_FUN_ATTR uint8_t atomic_umin_i8_shared(volatile __local uint8_t *p, uint8_t x);+SCALAR_FUN_ATTR int8_t atomic_and_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_and_i8_shared(volatile __local int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_or_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_or_i8_shared(volatile __local int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_xor_i8_global(volatile __global int8_t *p, int8_t x);+SCALAR_FUN_ATTR int8_t atomic_xor_i8_shared(volatile __local int8_t *p, int8_t x);++SCALAR_FUN_ATTR int8_t atomic_cmpxchg_i8_global(volatile __global int8_t *p,+                                                int8_t cmp, int8_t val) {+  int offset = ((uintptr_t)p & 3);+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);++  int shift = offset * 8;+  int32_t mask = 0xff << shift;+  int32_t shifted_val = val << shift;+  int32_t shifted_cmp = cmp << shift;++  uint32_t old = shifted_cmp;+  uint32_t upd = shifted_val;+  uint32_t got;++  while ((got=atomic_cmpxchg_i32_global(p32, old, upd)) != old) {+    old = got;+    upd = (old & ~mask) | shifted_val;+  }++  return old >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_cmpxchg_i8_shared(volatile __local int8_t *p,+                                                int8_t cmp, int8_t val) {+  int offset = ((uintptr_t)p >> 1 & 3);+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);++  int shift = offset * 8;+  int32_t mask = 0xff << shift;+  int32_t shifted_val = val << shift;+  int32_t shifted_cmp = cmp << shift;++  uint32_t old = shifted_cmp;+  uint32_t upd = shifted_val;+  uint32_t got;++  while ((got=atomic_cmpxchg_i32_shared(p32, old, upd)) != old) {+    old = got;+    upd = (old & ~mask) | shifted_val;+  }++  return old >> shift;+}++// Convenience macro for arithmetic.+#define DEFINE_8BIT_ATOMIC(name, T, op)                                 \+  SCALAR_FUN_ATTR T                                                     \+  atomic_##name##_i8_global(volatile __global T *p, T val) {            \+    int offset = ((uintptr_t)p & 3);                                    \+    volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3); \+    int shift = offset * 8;                                             \+    int32_t mask = 0xff << shift;                                       \+    int32_t old = 0;                                                    \+    int32_t upd = mask & (op(old >> shift, val) << shift);              \+    int32_t saw;                                                        \+    while ((saw=atomic_cmpxchg_i32_global(p32, old, upd)) != old) {     \+      old = saw;                                                        \+      upd = (old & ~mask) | ((op(old >> shift, val)) << shift);         \+    }                                                                   \+    return old >> shift;                                                \+  }                                                                     \+  SCALAR_FUN_ATTR T                                                     \+  atomic_##name##_i8_shared(volatile __local T *p, T val) {             \+    int offset = ((uintptr_t)p & 3);                                    \+    volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3); \+    int shift = offset * 8;                                             \+    int32_t mask = 0xff << shift;                                       \+    int32_t old = 0;                                                    \+    int32_t upd = mask & ((op(old >> shift, val)) << shift);            \+    int32_t saw;                                                        \+    while ((saw=atomic_cmpxchg_i32_shared(p32, old, upd)) != old) {     \+      old = saw;                                                        \+      upd = (old & ~mask) | ((op(old >> shift, val)) << shift);         \+    }                                                                   \+    return old >> shift;                                                \+  }++DEFINE_8BIT_ATOMIC(add, int8_t, add8);+DEFINE_8BIT_ATOMIC(smax, int8_t, smax8);+DEFINE_8BIT_ATOMIC(smin, int8_t, smin8);+DEFINE_8BIT_ATOMIC(umax, uint8_t, umax8);+DEFINE_8BIT_ATOMIC(umin, uint8_t, umin8);++SCALAR_FUN_ATTR int8_t atomic_and_i8_global(volatile __global int8_t *p, int8_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  int32_t mask = 0xff << shift;+  return atomic_and_i32_global(p32, ~mask | (val<<shift)) >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_and_i8_shared(volatile __local int8_t *p, int8_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  int32_t mask = 0xff << shift;+  return atomic_and_i32_shared(p32, ~mask | (val<<shift)) >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_or_i8_global(volatile __global int8_t *p, int8_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  return atomic_or_i32_global(p32, (uint8_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_or_i8_shared(volatile __local int8_t *p, int8_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  return atomic_or_i32_shared(p32, (uint8_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_xor_i8_global(volatile __global int8_t *p, int8_t val) {+  volatile __global int32_t *p32 = (volatile __global int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  return atomic_xor_i32_global(p32, (uint8_t)val<<shift) >> shift;+}++SCALAR_FUN_ATTR int8_t atomic_xor_i8_shared(volatile __local int8_t *p, int8_t val) {+  volatile __local int32_t *p32 = (volatile __local int32_t*)((uintptr_t)p & ~0x3);+  int shift = ((uintptr_t)p & 3) * 8;+  return atomic_xor_i32_shared(p32, (uint8_t)val<<shift) >> shift;+}++// End of atomics8.h
rts/c/gpu.h view
@@ -242,6 +242,10 @@     min_size = sizeof(int);   } +  // Round up the allocation to be at least divisible by 4, because that is+  // assumed by the code generator.+  min_size = (min_size+3) & ~3;+   gpu_mem* memptr;   if (free_list_find(&ctx->gpu_free_list, min_size, tag, size_out, (fl_mem*)&memptr) == 0) {     // Successfully found a free block.  Is it big enough?
rts/cuda/prelude.cu view
@@ -25,6 +25,14 @@ typedef unsigned long uint64_t; #endif +#if defined(__CUDACC_RTC__)+typedef uint64_t uintptr_t;+#endif++#if defined(__HIPCC_RTC__)+typedef uint64_t uintptr_t;+#endif+ #define __global #define __local #define __private
rts/python/opencl.py view
@@ -368,8 +368,10 @@   def opencl_alloc(self, min_size, tag):-    min_size = 1 if min_size == 0 else min_size+    min_size = 4 if min_size == 0 else min_size     assert min_size > 0+    # Round up to a multiple of four.+    min_size = ((min_size + 3) // 4) * 4     return self.pool.allocate(min_size)  
src/Futhark/AD/Fwd.hs view
@@ -226,9 +226,9 @@       arr_tan <- tangent arr       arrs_tans <- mapM tangent arrs       addStm $ Let pat_tan aux $ BasicOp $ Concat d (arr_tan :| arrs_tans) w-    Manifest ds arr -> do+    Manifest arr ds -> do       arr_tan <- tangent arr-      addStm $ Let pat_tan aux $ BasicOp $ Manifest ds arr_tan+      addStm $ Let pat_tan aux $ BasicOp $ Manifest arr_tan ds     Iota n _ _ it -> do       addStm $ Let pat_tan aux $ BasicOp $ Replicate (Shape [n]) (intConst it 0)     Replicate n x -> do@@ -236,12 +236,12 @@       addStm $ Let pat_tan aux $ BasicOp $ Replicate n x_tan     Scratch t shape ->       addStm $ Let pat_tan aux $ BasicOp $ Scratch t shape-    Reshape k reshape arr -> do+    Reshape arr reshape -> do       arr_tan <- tangent arr-      addStm $ Let pat_tan aux $ BasicOp $ Reshape k reshape arr_tan-    Rearrange perm arr -> do+      addStm $ Let pat_tan aux $ BasicOp $ Reshape arr_tan reshape+    Rearrange arr perm -> do       arr_tan <- tangent arr-      addStm $ Let pat_tan aux $ BasicOp $ Rearrange perm arr_tan+      addStm $ Let pat_tan aux $ BasicOp $ Rearrange arr_tan perm     _ -> error $ "basicFwd: Unsupported op " ++ prettyString op  fwdLambda :: Lambda SOACS -> ADM (Lambda SOACS)
src/Futhark/AD/Rev.hs view
@@ -117,20 +117,20 @@       (_pat_v, pat_adj) <- commonBasicOp pat aux e m       returnSweepCode $ updateSubExpAdj se pat_adj     ---    Reshape k _ arr -> do+    Reshape arr newshape -> do       (_pat_v, pat_adj) <- commonBasicOp pat aux e m       returnSweepCode $ do         arr_shape <- arrayShape <$> lookupType arr         void $           updateAdj arr <=< letExp "adj_reshape" . BasicOp $-            Reshape k arr_shape pat_adj+            Reshape pat_adj (reshapeAll (newShape newshape) arr_shape)     ---    Rearrange perm arr -> do+    Rearrange arr perm -> do       (_pat_v, pat_adj) <- commonBasicOp pat aux e m       returnSweepCode $         void $           updateAdj arr <=< letExp "adj_rearrange" . BasicOp $-            Rearrange (rearrangeInverse perm) pat_adj+            Rearrange pat_adj (rearrangeInverse perm)     --     Replicate (Shape []) (Var se) -> do       (_pat_v, pat_adj) <- commonBasicOp pat aux e m@@ -145,7 +145,7 @@         n <- letSubExp "rep_size" =<< foldBinOp (Mul Int64 OverflowUndef) (intConst Int64 1) ns         pat_adj_flat <-           letExp (baseString pat_adj <> "_flat") . BasicOp $-            Reshape ReshapeArbitrary (Shape $ n : arrayDims x_t) pat_adj+            Reshape pat_adj (reshapeAll (Shape ns) (Shape $ n : arrayDims x_t))         reduce <- reduceSOAC [Reduce Commutative lam [ne]]         updateSubExpAdj x           =<< letExp "rep_contrib" (Op $ Screma n [pat_adj_flat] reduce)@@ -170,7 +170,7 @@          zipWithM_ updateAdj (arr : arrs) slices     ---    Manifest _ se -> do+    Manifest se _ -> do       (_pat_v, pat_adj) <- commonBasicOp pat aux e m       returnSweepCode $ void $ updateAdj se pat_adj     --
src/Futhark/AD/Rev/Hist.hs view
@@ -304,8 +304,10 @@   scatter_inps <- do     -- traverse (letExp "flat" . BasicOp . Reshape [DimNew q]) $ inds ++ [vs_bar_p]     -- ToDo: Cosmin asks: is the below the correct translation of the line above?-    traverse (letExp "flat" . BasicOp . Reshape ReshapeArbitrary (Shape [q])) $-      inds ++ [vs_bar_p]+    forM (inds ++ [vs_bar_p]) $ \v -> do+      v_t <- lookupType v+      letExp "flat" . BasicOp . Reshape v $+        reshapeAll (arrayShape v_t) (Shape [q])    f'' <- mkIdentityLambda $ replicate nr_dims (Prim int64) ++ [Prim t]   vs_bar' <-@@ -553,8 +555,8 @@     rank <- arrayRank <$> lookupType vss     let dims = [1, 0] ++ drop 2 [0 .. rank - 1] -    dstT <- letExp "dstT" $ BasicOp $ Rearrange dims dst-    vssT <- letExp "vssT" $ BasicOp $ Rearrange dims vss+    dstT <- letExp "dstT" $ BasicOp $ Rearrange dst dims+    vssT <- letExp "vssT" $ BasicOp $ Rearrange vss dims     t_dstT <- lookupType dstT     t_vssT <- lookupType vssT     t_nes <- lookupType nes@@ -578,11 +580,10 @@               [HistOp (Shape [w]) rf [dst_col_cpy] [Var $ paramName ne] op]               f     histT <--      letExp "histT" $-        Op $-          Screma (arraySize 0 t_dstT) [dstT, vssT, nes] $-            mapSOAC map_lam-    auxing aux . letBindNames [x] . BasicOp $ Rearrange dims histT+      letExp "histT" . Op $+        Screma (arraySize 0 t_dstT) [dstT, vssT, nes] $+          mapSOAC map_lam+    auxing aux . letBindNames [x] . BasicOp $ Rearrange histT dims   foldr (vjpStm ops) m stms  --
src/Futhark/AD/Rev/Reduce.hs view
@@ -208,7 +208,7 @@     rank <- arrayRank <$> lookupType as     let rear = [1, 0] ++ drop 2 [0 .. rank - 1] -    tran_as <- letExp "tran_as" $ BasicOp $ Rearrange rear as+    tran_as <- letExp "tran_as" $ BasicOp $ Rearrange as rear     ts <- lookupType tran_as     t_ne <- lookupType ne 
src/Futhark/AD/Rev/Scan.hs view
@@ -446,7 +446,7 @@      transp_as <-       forM as $ \a ->-        letExp (baseString a ++ "_transp") $ BasicOp $ Rearrange rear a+        letExp (baseString a ++ "_transp") $ BasicOp $ Rearrange a rear      ts <- traverse lookupType transp_as     let n = arraysSize 0 ts@@ -465,7 +465,7 @@         Screma n (transp_as ++ subExpVars ne) (mapSOAC map_lam)      forM (zip ys transp_ys) $ \(y, x) ->-      auxing aux $ letBindNames [y] $ BasicOp $ Rearrange rear x+      auxing aux $ letBindNames [y] $ BasicOp $ Rearrange x rear    foldr (vjpStm ops) m stmts 
src/Futhark/Analysis/AccessPattern.hs view
@@ -478,12 +478,13 @@           error $ "unhandled: Update (This should NEVER happen) onto " ++ prettyString name         -- Technically, do we need this case?         Concat _ _ length_subexp -> varInfoFromSubExp length_subexp-        Manifest _dim name -> varInfoFromNames ctx $ oneName name+        Manifest name _dim -> varInfoFromNames ctx $ oneName name         Iota end start stride _ -> concatVariableInfos mempty [end, start, stride]         Replicate (Shape shape) value' -> concatVariableInfos mempty (value' : shape)         Scratch _ sers -> concatVariableInfos mempty sers-        Reshape _ (Shape shape_subexp) name -> concatVariableInfos (oneName name) shape_subexp-        Rearrange _ name -> varInfoFromNames ctx $ oneName name+        Reshape name newshape ->+          concatVariableInfos (oneName name) (shapeDims (newShape newshape))+        Rearrange name _ -> varInfoFromNames ctx $ oneName name         UpdateAcc _ name lsubexprs rsubexprs ->           concatVariableInfos (oneName name) (lsubexprs ++ rsubexprs)         FlatIndex name _ -> varInfoFromNames ctx $ oneName name
src/Futhark/Analysis/HORep/MapNest.hs view
@@ -215,14 +215,15 @@ -- | Reshape a map nest. It is assumed that any validity tests have -- already been done. Will automatically reshape the inputs -- appropriately.-reshape :: (MonadFreshNames m) => Certs -> Shape -> MapNest -> m MapNest-reshape cs shape (MapNest _ map_lam _ inps) =+reshape :: (MonadFreshNames m) => StmAux () -> Shape -> MapNest -> m MapNest+reshape aux shape (MapNest _ map_lam _ inps) =   descend [] $ stripDims 1 shape   where     w = shapeSize 0 shape     transform p inp =       let shape' = shape <> arrayShape p-          tr = SOAC.Reshape cs ReshapeArbitrary shape'+          inp_shape = arrayShape (SOAC.inputType inp)+          tr = SOAC.Reshape aux $ reshapeAll inp_shape shape'        in SOAC.addTransform tr inp     inps' = zipWith transform (map paramType $ lambdaParams map_lam) inps 
src/Futhark/Analysis/HORep/SOAC.hs view
@@ -100,36 +100,26 @@ -- create a list, use 'ArrayTransforms' instead. data ArrayTransform   = -- | A permutation of an otherwise valid input.-    Rearrange Certs [Int]+    Rearrange (StmAux ()) [Int]   | -- | A reshaping of an otherwise valid input.-    Reshape Certs ReshapeKind Shape-  | -- | A reshaping of the outer dimension.-    ReshapeOuter Certs ReshapeKind Shape-  | -- | A reshaping of everything but the outer dimension.-    ReshapeInner Certs ReshapeKind Shape+    Reshape (StmAux ()) (NewShape SubExp)   | -- | Replicate the rows of the array a number of times.-    Replicate Certs Shape+    Replicate (StmAux ()) Shape   | -- | An array indexing operation.-    Index Certs (Slice SubExp)+    Index (StmAux ()) (Slice SubExp)   deriving (Show, Eq, Ord)  instance FreeIn ArrayTransform where   freeIn' (Rearrange cs _) = freeIn' cs-  freeIn' (Reshape cs _ shape) = freeIn' cs <> freeIn' shape-  freeIn' (ReshapeOuter cs _ shape) = freeIn' cs <> freeIn' shape-  freeIn' (ReshapeInner cs _ shape) = freeIn' cs <> freeIn' shape+  freeIn' (Reshape cs shape) = freeIn' cs <> freeIn' shape   freeIn' (Replicate cs shape) = freeIn' cs <> freeIn' shape   freeIn' (Index cs slice) = freeIn' cs <> freeIn' slice  instance Substitute ArrayTransform where   substituteNames substs (Rearrange cs xs) =     Rearrange (substituteNames substs cs) xs-  substituteNames substs (Reshape cs k ses) =-    Reshape (substituteNames substs cs) k (substituteNames substs ses)-  substituteNames substs (ReshapeOuter cs k ses) =-    ReshapeOuter (substituteNames substs cs) k (substituteNames substs ses)-  substituteNames substs (ReshapeInner cs k ses) =-    ReshapeInner (substituteNames substs cs) k (substituteNames substs ses)+  substituteNames substs (Reshape cs newshape) =+    Reshape (substituteNames substs cs) (substituteNames substs newshape)   substituteNames substs (Replicate cs se) =     Replicate (substituteNames substs cs) (substituteNames substs se)   substituteNames substs (Index cs slice) =@@ -242,11 +232,11 @@ -- an input transformation of an array variable.  If so, return the -- variable and the transformation.  Only 'Rearrange' and 'Reshape' -- are possible to express this way.-transformFromExp :: Certs -> Exp rep -> Maybe (VName, ArrayTransform)-transformFromExp cs (BasicOp (Futhark.Rearrange perm v)) =+transformFromExp :: StmAux () -> Exp rep -> Maybe (VName, ArrayTransform)+transformFromExp cs (BasicOp (Futhark.Rearrange v perm)) =   Just (v, Rearrange cs perm)-transformFromExp cs (BasicOp (Futhark.Reshape k shape v)) =-  Just (v, Reshape cs k shape)+transformFromExp cs (BasicOp (Futhark.Reshape v shape)) =+  Just (v, Reshape cs shape) transformFromExp cs (BasicOp (Futhark.Replicate shape (Var v))) =   Just (v, Replicate cs shape) transformFromExp cs (BasicOp (Futhark.Index v slice)) =@@ -254,20 +244,14 @@ transformFromExp _ _ = Nothing  -- | Turn an array transform on an array back into an expression.-transformToExp :: (Monad m, HasScope rep m) => ArrayTransform -> VName -> m (Certs, Exp rep)+transformToExp :: (Monad m, HasScope rep m) => ArrayTransform -> VName -> m (StmAux (), Exp rep) transformToExp (Replicate cs n) ia =   pure (cs, BasicOp $ Futhark.Replicate n (Var ia)) transformToExp (Rearrange cs perm) ia = do   r <- arrayRank <$> lookupType ia-  pure (cs, BasicOp $ Futhark.Rearrange (perm ++ [length perm .. r - 1]) ia)-transformToExp (Reshape cs k shape) ia = do-  pure (cs, BasicOp $ Futhark.Reshape k shape ia)-transformToExp (ReshapeOuter cs k shape) ia = do-  shape' <- reshapeOuter shape 1 . arrayShape <$> lookupType ia-  pure (cs, BasicOp $ Futhark.Reshape k shape' ia)-transformToExp (ReshapeInner cs k shape) ia = do-  shape' <- reshapeInner shape 1 . arrayShape <$> lookupType ia-  pure (cs, BasicOp $ Futhark.Reshape k shape' ia)+  pure (cs, BasicOp $ Futhark.Rearrange ia (perm ++ [length perm .. r - 1]))+transformToExp (Reshape cs shape) ia = do+  pure (cs, BasicOp $ Futhark.Reshape ia shape) transformToExp (Index cs slice) ia = do   pure (cs, BasicOp $ Futhark.Index ia slice) @@ -310,8 +294,10 @@ isVarishInput :: Input -> Maybe VName isVarishInput (Input ts v t)   | nullTransforms ts = Just v-  | Reshape cs ReshapeCoerce (Shape [_]) :< ts' <- viewf ts,-    cs == mempty =+  | Reshape aux newshape :< ts' <- viewf ts,+    ReshapeCoerce <- reshapeKind newshape,+    1 <- shapeRank $ newShape newshape,+    stmAuxCerts aux == mempty =       isVarishInput $ Input ts' v t isVarishInput _ = Nothing @@ -327,15 +313,13 @@  applyTransform :: (MonadBuilder m) => ArrayTransform -> VName -> m VName applyTransform tr ia = do-  (cs, e) <- transformToExp tr ia-  certifying cs $ letExp s e+  (aux, e) <- transformToExp tr ia+  auxing aux $ letExp s e   where     s = case tr of       Replicate {} -> "replicate"       Rearrange {} -> "rearrange"       Reshape {} -> "reshape"-      ReshapeOuter {} -> "reshape_outer"-      ReshapeInner {} -> "reshape_inner"       Index {} -> "index"  applyTransforms :: (MonadBuilder m) => ArrayTransforms -> VName -> m VName@@ -367,14 +351,8 @@       arrayOfShape t shape     transformType t (Rearrange _ perm) =       rearrangeType perm t-    transformType t (Reshape _ _ shape) =-      t `setArrayShape` shape-    transformType t (ReshapeOuter _ _ shape) =-      let Shape oldshape = arrayShape t-       in t `setArrayShape` Shape (shapeDims shape ++ drop 1 oldshape)-    transformType t (ReshapeInner _ _ shape) =-      let Shape oldshape = arrayShape t-       in t `setArrayShape` Shape (take 1 oldshape ++ shapeDims shape)+    transformType t (Reshape _ shape) =+      t `setArrayShape` newShape shape     transformType t (Index _ slice) =       t `setArrayShape` sliceShape slice @@ -394,8 +372,11 @@   where     transformRows' inp (Rearrange cs perm) =       addTransform (Rearrange cs (0 : map (+ 1) perm)) inp-    transformRows' inp (Reshape cs k shape) =-      addTransform (ReshapeInner cs k shape) inp+    transformRows' inp (Reshape cs shape) =+      addTransform (Reshape cs newshape) inp+      where+        newshape = reshapeAll inp_shape $ Shape [shapeSize 0 inp_shape] <> newShape shape+        inp_shape = arrayShape $ inputType inp     transformRows' inp (Replicate cs n)       | inputRank inp == 1 =           Rearrange mempty [1, 0]@@ -714,18 +695,8 @@ ppArrayTransform :: PP.Doc a -> ArrayTransform -> PP.Doc a ppArrayTransform e (Rearrange cs perm) =   "rearrange" <> pretty cs <> PP.apply [PP.apply (map pretty perm), e]-ppArrayTransform e (Reshape cs ReshapeArbitrary shape) =+ppArrayTransform e (Reshape cs shape) =   "reshape" <> pretty cs <> PP.apply [pretty shape, e]-ppArrayTransform e (ReshapeOuter cs ReshapeArbitrary shape) =-  "reshape_outer" <> pretty cs <> PP.apply [pretty shape, e]-ppArrayTransform e (ReshapeInner cs ReshapeArbitrary shape) =-  "reshape_inner" <> pretty cs <> PP.apply [pretty shape, e]-ppArrayTransform e (Reshape cs ReshapeCoerce shape) =-  "coerce" <> pretty cs <> PP.apply [pretty shape, e]-ppArrayTransform e (ReshapeOuter cs ReshapeCoerce shape) =-  "coerce_outer" <> pretty cs <> PP.apply [pretty shape, e]-ppArrayTransform e (ReshapeInner cs ReshapeCoerce shape) =-  "coerce_inner" <> pretty cs <> PP.apply [pretty shape, e] ppArrayTransform e (Replicate cs ne) =   "replicate" <> pretty cs <> PP.apply [pretty ne, e] ppArrayTransform e (Index cs slice) =
src/Futhark/Analysis/SymbolTable.hs view
@@ -287,20 +287,6 @@ subExpAvailable (Var name) = available name subExpAvailable Constant {} = const True -index ::-  (ASTRep rep) =>-  VName ->-  [SubExp] ->-  SymbolTable rep ->-  Maybe Indexed-index name is table = do-  is' <- mapM asPrimExp is-  index' name is' table-  where-    asPrimExp i = do-      Prim t <- lookupSubExpType i table-      pure $ TPrimExp $ primExpFromSubExp t i- index' ::   VName ->   [TPrimExp Int64 VName] ->@@ -311,14 +297,33 @@   case entryType entry of     LetBound entry'       | Just k <--          elemIndex name . patNames . stmPat $-            letBoundStm entry' ->+          elemIndex name . patNames . stmPat $ letBoundStm entry' ->           letBoundIndex entry' k is     FreeVar entry' ->       freeVarIndex entry' name is     LParam entry' -> lparamIndex entry' is     _ -> Nothing +-- | @index arr is vtable@ fully indexes the array @arr@ at position @is@ using+-- information in @vtable@, and produces the symbolic result of the indexing if+-- it can be expressed. This is essentially a form of pull-array indexing.+index ::+  VName ->+  [SubExp] ->+  SymbolTable rep ->+  Maybe Indexed+index name = index' name . map pe64++-- | Like 'index'', but always succeeds, simply returning an 'IndexedArray' of+-- the input if nothing else is possible.+indexNext ::+  VName ->+  [TPrimExp Int64 VName] ->+  SymbolTable rep ->+  Indexed+indexNext name is vtable =+  fromMaybe (IndexedArray mempty name is) $ index' name is vtable+ class IndexOp op where   indexOp ::     (ASTRep rep, IndexOp (Op rep)) =>@@ -335,17 +340,16 @@   (IndexOp (Op rep), ASTRep rep) =>   SymbolTable rep ->   Exp rep ->+  -- | Index of result being indexed in case the expression produces more than+  -- one.   Int ->   IndexArray indexExp vtable (Op op) k is =   indexOp vtable k op is indexExp _ (BasicOp (Iota _ x s to_it)) _ [i] =-  Just $-    Indexed mempty $-      ( sExt to_it (untyped i)-          `mul` primExpFromSubExp (IntType to_it) s-      )-        `add` primExpFromSubExp (IntType to_it) x+  Just . Indexed mempty $+    (sExt to_it (untyped i) `mul` primExpFromSubExp (IntType to_it) s)+      `add` primExpFromSubExp (IntType to_it) x   where     mul = BinOpExp (Mul to_it OverflowWrap)     add = BinOpExp (Add to_it OverflowWrap)@@ -355,20 +359,21 @@       Just $ Indexed mempty $ primExpFromSubExp t v indexExp table (BasicOp (Replicate s (Var v))) _ is = do   guard $ v `available` table-  guard $ s /= mempty-  index' v (drop (shapeRank s) is) table-indexExp table (BasicOp (Reshape _ newshape v)) _ is+  Just $ indexNext v (drop (shapeRank s) is) table+indexExp table (BasicOp (Reshape v newshape)) _ is   | Just oldshape <- arrayDims <$> lookupType v table =       -- TODO: handle coercions more efficiently.       let is' =             reshapeIndex               (map pe64 oldshape)-              (map pe64 $ shapeDims newshape)+              (map pe64 $ shapeDims $ newShape newshape)               is-       in index' v is' table+       in Just $ indexNext v is' table+indexExp table (BasicOp (Rearrange v perm)) _ is =+  Just $ indexNext v (rearrangeShape (rearrangeInverse perm) is) table indexExp table (BasicOp (Index v slice)) _ is = do   guard $ v `available` table-  index' v (adjust (unSlice slice) is) table+  Just $ indexNext v (adjust (unSlice slice) is) table   where     adjust (DimFix j : js') is' =       pe64 j : adjust js' is'
src/Futhark/CLI/Profile.hs view
@@ -54,18 +54,19 @@     numpad = 15     mkRows rows =       let longest = foldl max numpad $ map (T.length . fst) rows+          total = sum $ map (evSum . snd) rows           header = headerRow longest           splitter = T.map (const '-') header           bottom =             T.unwords               [ showText (sum (map (evCount . snd) rows)),                 "events with a total runtime of",-                T.pack $ printf "%.2fμs" $ sum $ map (evSum . snd) rows+                T.pack $ printf "%.2fμs" total               ]        in T.unlines $             header               : splitter-              : map (mkRow longest) rows+              : map (mkRow longest total) rows                 <> [splitter, bottom]     headerRow longest =       T.unwords@@ -74,16 +75,18 @@           padLeft numpad "sum",           padLeft numpad "avg",           padLeft numpad "min",-          padLeft numpad "max"+          padLeft numpad "max",+          padLeft numpad "fraction"         ]-    mkRow longest (name, ev) =+    mkRow longest total (name, ev) =       T.unwords         [ padRight longest name,           padLeft numpad (showText (evCount ev)),           padLeft numpad $ T.pack $ printf "%.2fμs" (evSum ev),           padLeft numpad $ T.pack $ printf "%.2fμs" $ evSum ev / fromInteger (evCount ev),           padLeft numpad $ T.pack $ printf "%.2fμs" (evMin ev),-          padLeft numpad $ T.pack $ printf "%.2fμs" (evMax ev)+          padLeft numpad $ T.pack $ printf "%.2fμs" (evMax ev),+          padLeft numpad $ T.pack $ printf "%.4f" (evSum ev / total)         ]  timeline :: [ProfilingEvent] -> T.Text
src/Futhark/CLI/Test.hs view
@@ -194,7 +194,7 @@     maybePipeline SeqMemPipeline = "(seq-mem) "     maybePipeline GpuMemPipeline = "(gpu-mem) "     maybePipeline MCMemPipeline = "(mc-mem) "-    maybePipeline NoPipeline = ""+    maybePipeline NoPipeline = " "      ok (AstMetrics metrics) (name, expected_occurences) =       case M.lookup name metrics of@@ -203,7 +203,7 @@               throwError $                 name                   <> maybePipeline pipeline-                  <> " should have occurred "+                  <> "should have occurred "                   <> showText expected_occurences                   <> " times, but did not occur at all in optimised program."         Just actual_occurences@@ -211,7 +211,7 @@               throwError $                 name                   <> maybePipeline pipeline-                  <> " should have occurred "+                  <> "should have occurred "                   <> showText expected_occurences                   <> " times, but occurred "                   <> showText actual_occurences
src/Futhark/CodeGen/Backends/GenericC.hs view
@@ -516,7 +516,7 @@        headerDecl InitDecl [C.cedecl|struct futhark_context;|]       headerDecl InitDecl [C.cedecl|struct futhark_context* futhark_context_new(struct futhark_context_config* cfg);|]-      headerDecl InitDecl [C.cedecl|void futhark_context_free(struct futhark_context* cfg);|]+      headerDecl InitDecl [C.cedecl|void futhark_context_free(struct futhark_context* ctx);|]       headerDecl MiscDecl [C.cedecl|int futhark_context_sync(struct futhark_context* ctx);|]        generateTuningParams params
src/Futhark/CodeGen/Backends/SimpleRep.hs view
@@ -146,15 +146,22 @@   either (Left . errorBundlePretty) Right . parse (p <* eof) "type name"   where     p :: Parsec Void T.Text T.Text-    p = choice [pArr, pTup, pAtom]+    p = choice [pArr, pTup, pQual]     pArr = do       dims <- some "[]"       (("arr" <> showText (length dims) <> "d_") <>) <$> p     pTup = between "(" ")" $ do       ts <- p `sepBy` pComma       pure $ "tup" <> showText (length ts) <> "_" <> T.intercalate "_" ts-    pAtom = T.pack <$> some (satisfy (`notElem` ("[]{}()," :: String)))+    pAtom = T.pack <$> some (satisfy (`notElem` ("[]{}(),." :: String)))     pComma = void $ "," <* space+    -- Rewrite 'x.y' to 'x_y'.+    pQual = do+      x <- pAtom+      choice+        [ "." >> ((x <> "_") <>) <$> pAtom,+          pure x+        ]  -- | The name of exposed opaque types. opaqueName :: Name -> T.Text
src/Futhark/CodeGen/ImpGen.hs view
@@ -941,7 +941,7 @@         BinOpExp (Add it OverflowUndef) e' $           BinOpExp (Mul it OverflowUndef) i' s'     copyDWIMFix (patElemName pe) [i] (Var (tvVar x)) []-defCompileBasicOp (Pat [pe]) (Manifest _ src) =+defCompileBasicOp (Pat [pe]) (Manifest src _) =   copyDWIM (patElemName pe) [] (Var src) [] defCompileBasicOp (Pat [pe]) (Concat i (x :| ys) _) = do   offs_glb <- dPrimV "tmp_offs" 0
src/Futhark/CodeGen/ImpGen/GPU.hs view
@@ -65,7 +65,28 @@         (Or Int32, Imp.AtomicOr Int32),         (Xor Int32, Imp.AtomicXor Int32)       ]-    opencl = opencl32 ++ opencl64+    opencl16 =+      [ (Add Int16 OverflowUndef, Imp.AtomicAdd Int16),+        (FAdd Float16, Imp.AtomicFAdd Float16),+        (SMax Int16, Imp.AtomicSMax Int16),+        (SMin Int16, Imp.AtomicSMin Int16),+        (UMax Int16, Imp.AtomicUMax Int16),+        (UMin Int16, Imp.AtomicUMin Int16),+        (And Int16, Imp.AtomicAnd Int16),+        (Or Int16, Imp.AtomicOr Int16),+        (Xor Int16, Imp.AtomicXor Int16)+      ]+    opencl8 =+      [ (Add Int8 OverflowUndef, Imp.AtomicAdd Int8),+        (SMax Int8, Imp.AtomicSMax Int8),+        (SMin Int8, Imp.AtomicSMin Int8),+        (UMax Int8, Imp.AtomicUMax Int8),+        (UMin Int8, Imp.AtomicUMin Int8),+        (And Int8, Imp.AtomicAnd Int8),+        (Or Int8, Imp.AtomicOr Int8),+        (Xor Int8, Imp.AtomicXor Int8)+      ]+    opencl = opencl8 <> opencl16 <> opencl32 <> opencl64     cuda = opencl  compileProg ::
src/Futhark/CodeGen/ImpGen/GPU/Base.hs view
@@ -744,13 +744,13 @@   AtomicUpdate GPUMem KernelEnv atomicUpdateLocking atomicBinOp lam   | Just ops_and_ts <- lamIsBinOp lam,-    all (\(_, t, _, _) -> primBitSize t `elem` [32, 64]) ops_and_ts =+    all (\(_, t, _, _) -> primBitSize t `elem` [8, 16, 32, 64]) ops_and_ts =       primOrCas ops_and_ts $ \space arrs bucket ->-        -- If the operator is a vectorised binary operator on 32/64-bit-        -- values, we can use a particularly efficient-        -- implementation. If the operator has an atomic implementation-        -- we use that, otherwise it is still a binary operator which-        -- can be implemented by atomic compare-and-swap if 32/64 bits.+        -- If the operator is a vectorised binary operator on single values, we+        -- can use a particularly efficient implementation. If the operator has+        -- an atomic implementation we use that, otherwise it is still a binary+        -- operator which can be implemented by atomic compare-and-swap if 32/64+        -- bits.         forM_ (zip arrs ops_and_ts) $ \(a, (op, t, x, y)) -> do           -- Common variables.           old <- dPrimS "old" t@@ -771,15 +771,19 @@       | all isPrim ops = AtomicPrim       | otherwise = AtomicCAS -    isPrim (op, _, _, _) = isJust $ atomicBinOp op+    -- Only operators of at least 32-bit integers are actually truly atomic with+    -- our current GPU backends - the rest are emulated with CAS-loops in their+    -- implementation.+    isPrim (op, _, _, _) =+      isJust (atomicBinOp op)+        && primByteSize (binOpType op) >= (4 :: Int) --- If the operator functions purely on single 32/64-bit values, we can--- use an implementation based on CAS, no matter what the operator--- does.+-- If the operator functions purely on single single values, we can use an+-- implementation based on CAS, no matter what the operator does. atomicUpdateLocking _ op   | [Prim t] <- lambdaReturnType op,     [xp, _] <- lambdaParams op,-    primBitSize t `elem` [32, 64] = AtomicCAS $ \space [arr] bucket -> do+    primBitSize t `elem` [8, 16, 32, 64] = AtomicCAS $ \space [arr] bucket -> do       old <- dPrimS "old" t       atomicUpdateCAS space t arr old bucket (paramName xp) $         compileBody' [xp] (lambdaBody op)
src/Futhark/CodeGen/ImpGen/GPU/ToOpenCL.hs view
@@ -669,7 +669,7 @@       ind' <- GC.compileExp $ untyped $ unCount ind       val' <- GC.compileExp val       cast <- atomicCast s ty-      GC.stm [C.cstm|$id:old = $id:op'(&(($ty:cast *)$id:arr)[$exp:ind'], ($ty:ty) $exp:val');|]+      GC.stm [C.cstm|$id:old = $id:op'(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:val');|]       where         op' = op ++ "_" ++ prettyString t ++ "_" ++ atomicSpace s @@ -688,7 +688,7 @@       GC.stm [C.cstm|$id:old = $id:op(&(($ty:cast *)$id:arr)[$exp:ind'], $exp:val');|]       where         op = "atomic_chg_" ++ prettyString t ++ "_" ++ atomicSpace s-    -- First the 64-bit operations.+    -- 64-bit operations     atomicOps s (AtomicAdd Int64 old arr ind val) =       doAtomic s Int64 old arr ind val "atomic_add" [C.cty|typename int64_t|]     atomicOps s (AtomicFAdd Float64 old arr ind val) =@@ -698,9 +698,9 @@     atomicOps s (AtomicSMin Int64 old arr ind val) =       doAtomic s Int64 old arr ind val "atomic_smin" [C.cty|typename int64_t|]     atomicOps s (AtomicUMax Int64 old arr ind val) =-      doAtomic s Int64 old arr ind val "atomic_umax" [C.cty|unsigned int64_t|]+      doAtomic s Int64 old arr ind val "atomic_umax" [C.cty|typename uint64_t|]     atomicOps s (AtomicUMin Int64 old arr ind val) =-      doAtomic s Int64 old arr ind val "atomic_umin" [C.cty|unsigned int64_t|]+      doAtomic s Int64 old arr ind val "atomic_umin" [C.cty|typename uint64_t|]     atomicOps s (AtomicAnd Int64 old arr ind val) =       doAtomic s Int64 old arr ind val "atomic_and" [C.cty|typename int64_t|]     atomicOps s (AtomicOr Int64 old arr ind val) =@@ -711,29 +711,74 @@       doAtomicCmpXchg s (IntType Int64) old arr ind cmp val [C.cty|typename int64_t|]     atomicOps s (AtomicXchg (IntType Int64) old arr ind val) =       doAtomicXchg s (IntType Int64) old arr ind val [C.cty|typename int64_t|]-    ---    atomicOps s (AtomicAdd t old arr ind val) =-      doAtomic s t old arr ind val "atomic_add" [C.cty|int|]-    atomicOps s (AtomicFAdd t old arr ind val) =-      doAtomic s t old arr ind val "atomic_fadd" [C.cty|float|]-    atomicOps s (AtomicSMax t old arr ind val) =-      doAtomic s t old arr ind val "atomic_smax" [C.cty|int|]-    atomicOps s (AtomicSMin t old arr ind val) =-      doAtomic s t old arr ind val "atomic_smin" [C.cty|int|]-    atomicOps s (AtomicUMax t old arr ind val) =-      doAtomic s t old arr ind val "atomic_umax" [C.cty|unsigned int|]-    atomicOps s (AtomicUMin t old arr ind val) =-      doAtomic s t old arr ind val "atomic_umin" [C.cty|unsigned int|]-    atomicOps s (AtomicAnd t old arr ind val) =-      doAtomic s t old arr ind val "atomic_and" [C.cty|int|]-    atomicOps s (AtomicOr t old arr ind val) =-      doAtomic s t old arr ind val "atomic_or" [C.cty|int|]-    atomicOps s (AtomicXor t old arr ind val) =-      doAtomic s t old arr ind val "atomic_xor" [C.cty|int|]-    atomicOps s (AtomicCmpXchg t old arr ind cmp val) =-      doAtomicCmpXchg s t old arr ind cmp val [C.cty|int|]-    atomicOps s (AtomicXchg t old arr ind val) =-      doAtomicXchg s t old arr ind val [C.cty|int|]+    -- 32 bit operations+    atomicOps s (AtomicAdd Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_add" [C.cty|int|]+    atomicOps s (AtomicFAdd Float32 old arr ind val) =+      doAtomic s Float32 old arr ind val "atomic_fadd" [C.cty|float|]+    atomicOps s (AtomicSMax Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_smax" [C.cty|int|]+    atomicOps s (AtomicSMin Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_smin" [C.cty|int|]+    atomicOps s (AtomicUMax Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_umax" [C.cty|unsigned int|]+    atomicOps s (AtomicUMin Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_umin" [C.cty|unsigned int|]+    atomicOps s (AtomicAnd Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_and" [C.cty|int|]+    atomicOps s (AtomicOr Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_or" [C.cty|int|]+    atomicOps s (AtomicXor Int32 old arr ind val) =+      doAtomic s Int32 old arr ind val "atomic_xor" [C.cty|int|]+    atomicOps s (AtomicCmpXchg (IntType Int32) old arr ind cmp val) =+      doAtomicCmpXchg s Int32 old arr ind cmp val [C.cty|int|]+    atomicOps s (AtomicXchg (IntType Int32) old arr ind val) =+      doAtomicXchg s Int32 old arr ind val [C.cty|int|]+    -- 16 bit operations+    atomicOps s (AtomicAdd Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_add" [C.cty|typename int16_t|]+    atomicOps s (AtomicFAdd Float16 old arr ind val) =+      doAtomic s Float16 old arr ind val "atomic_fadd" [C.cty|typename uint16_t|]+    atomicOps s (AtomicSMax Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_smax" [C.cty|typename int16_t|]+    atomicOps s (AtomicSMin Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_smin" [C.cty|typename int16_t|]+    atomicOps s (AtomicUMax Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_umax" [C.cty|typename uint16_t|]+    atomicOps s (AtomicUMin Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_umin" [C.cty|typename uint16_t|]+    atomicOps s (AtomicAnd Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_and" [C.cty|typename int16_t|]+    atomicOps s (AtomicOr Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_or" [C.cty|typename int16_t|]+    atomicOps s (AtomicXor Int16 old arr ind val) =+      doAtomic s Int16 old arr ind val "atomic_xor" [C.cty|typename int16_t|]+    atomicOps s (AtomicCmpXchg (IntType Int16) old arr ind cmp val) =+      doAtomicCmpXchg s Int16 old arr ind cmp val [C.cty|typename int16_t|]+    atomicOps s (AtomicXchg (IntType Int16) old arr ind val) =+      doAtomicXchg s Int16 old arr ind val [C.cty|typename int16_t|]+    -- 8 bit operations+    atomicOps s (AtomicAdd Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_add" [C.cty|typename int8_t|]+    atomicOps s (AtomicSMax Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_smax" [C.cty|typename int8_t|]+    atomicOps s (AtomicSMin Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_smin" [C.cty|typename int8_t|]+    atomicOps s (AtomicUMax Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_umax" [C.cty|typename uint8_t|]+    atomicOps s (AtomicUMin Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_umin" [C.cty|typename uint8_t|]+    atomicOps s (AtomicAnd Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_and" [C.cty|typename int8_t|]+    atomicOps s (AtomicOr Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_or" [C.cty|typename int8_t|]+    atomicOps s (AtomicXor Int8 old arr ind val) =+      doAtomic s Int8 old arr ind val "atomic_xor" [C.cty|typename int8_t|]+    atomicOps s (AtomicCmpXchg (IntType Int8) old arr ind cmp val) =+      doAtomicCmpXchg s Int8 old arr ind cmp val [C.cty|typename int8_t|]+    atomicOps s (AtomicXchg (IntType Int8) old arr ind val) =+      doAtomicXchg s Int8 old arr ind val [C.cty|typename int8_t|]+    -- General     atomicOps s (AtomicWrite t arr ind val) = do       ind' <- GC.compileExp $ untyped $ unCount ind       val' <- toStorage t <$> GC.compileExp val@@ -745,6 +790,8 @@         case s of           Space "shared" -> [C.cstm|mem_fence_local();|]           _ -> [C.cstm|mem_fence_global();|]+    atomicOps _ op =+      error $ "atomicOp: unsupported " <> show op      cannotAllocate :: GC.Allocate KernelOp KernelState     cannotAllocate _ =
src/Futhark/CodeGen/RTS/C.hs view
@@ -40,7 +40,15 @@  -- | @rts/c/atomics.h@ atomicsH :: T.Text-atomicsH = $(embedStringFile "rts/c/atomics.h")+atomicsH =+  -- The order matters, as e.g. atomics16.h is implemented in terms of 32-bit+  -- atomics.+  mconcat+    [ $(embedStringFile "rts/c/atomics64.h"),+      $(embedStringFile "rts/c/atomics32.h"),+      $(embedStringFile "rts/c/atomics16.h"),+      $(embedStringFile "rts/c/atomics8.h")+    ] {-# NOINLINE atomicsH #-}  -- | @rts/c/uniform.h@
src/Futhark/Doc/Generator.hs view
@@ -372,7 +372,9 @@   pure $     H.span ! A.id (fromString ("synopsis:" <> vname_id)) $       H.a ! A.href (fromString ("#" ++ vname_id)) $-        renderName (baseName vname)+        if symbolName (baseName vname)+          then parens (renderName (baseName vname))+          else renderName (baseName vname)  synopsisValBind :: ValBind -> Maybe (DocM Html) synopsisValBind vb = Just $ do
src/Futhark/Fmt/Printer.hs view
@@ -1,3 +1,4 @@+-- | The actual implementation of @futhark fmt@. module Futhark.Fmt.Printer   ( fmtToText,     fmtToDoc,@@ -510,8 +511,12 @@     addComments loc $ fmt doc <> "val" <+> sub <+> ":" </> stdIndent (fmt te)     where       sub-        | null ps = fmtName bindingStyle name-        | otherwise = fmtName bindingStyle name <+> align (sep space $ map fmt ps)+        | null ps = name'+        | otherwise = name' <+> align (sep space $ map fmt ps)+      name' =+        if symbolName name+          then parens $ fmtName bindingStyle name+          else fmtName bindingStyle name   fmt (ModSpec name mte doc loc) =     addComments loc $ fmt doc <> "module" <+> fmtName bindingStyle name <> ":" <+> fmt mte   fmt (IncludeSpec mte loc) = addComments loc $ "include" <+> fmt mte
src/Futhark/IR/Mem.hs view
@@ -1046,12 +1046,12 @@   Just . pure <$> subExpReturns se expReturns (BasicOp (Opaque _ (Var v))) =   Just . pure <$> varReturns v-expReturns (BasicOp (Reshape k newshape v)) = do+expReturns (BasicOp (Reshape v newshape)) = do   (et, _, mem, lmad) <- arrayVarReturns v-  case reshaper k lmad $ map pe64 $ shapeDims newshape of+  case reshaper (reshapeKind newshape) lmad $ map pe64 $ shapeDims $ newShape newshape of     Just lmad' ->       pure . Just $-        [ MemArray et (fmap Free newshape) NoUniqueness . Just $+        [ MemArray et (Free <$> newShape newshape) NoUniqueness . Just $             ReturnsInBlock mem (existentialiseLMAD [] lmad')         ]     Nothing -> pure Nothing@@ -1060,7 +1060,7 @@       LMAD.reshape lmad     reshaper ReshapeCoerce lmad =       Just . LMAD.coerce lmad-expReturns (BasicOp (Rearrange perm v)) = do+expReturns (BasicOp (Rearrange v perm)) = do   (et, Shape dims, mem, lmad) <- arrayVarReturns v   let lmad' = LMAD.permute lmad perm       dims' = rearrangeShape perm dims
src/Futhark/IR/Mem/Simplify.hs view
@@ -101,16 +101,6 @@       Engine.isAllocation = isAlloc mempty mempty     } --- | Standard collection of simplification rules for representations--- with memory.-memRuleBook :: (SimplifyMemory rep inner) => RuleBook (Wise rep)-memRuleBook =-  standardRules-    <> ruleBook-      [ RuleOp decertifySafeAlloc-      ]-      []- -- If an allocation is statically known to be safe, then we can remove -- the certificates on it.  This can help hoist things that would -- otherwise be stuck inside loops or branches.@@ -121,3 +111,36 @@     safeOp op =       Simplify $ attributing attrs $ letBind pat $ Op op decertifySafeAlloc _ _ _ _ = Skip++--+-- copy(reshape(manifest(v0),s)) can be rewritten to just reshape(manifest(v0),s).+--+-- This is a pattern that can be produced by ExplicitAllocations when the+-- reshape would otherwise produce a layout that is not representable as an+-- LMAD. We have to be careful that the manifest writes to the same memory that+-- the original copy put it in.+copyManifest :: (SimplifyMemory rep inner) => TopDownRuleBasicOp (Wise rep)+copyManifest vtable pat aux (Replicate (Shape []) (Var v2))+  | Just (Reshape v1 s, v2_cs) <- ST.lookupBasicOp v2 vtable,+    Just (Manifest v0 perm, v1_cs) <- ST.lookupBasicOp v1 vtable,+    Pat [PatElem _ (_, MemArray _ _ _ (ArrayIn mem _))] <- pat =+      Simplify $ do+        ~(MemArray pt shape u (ArrayIn _ v1_lmad)) <- lookupMemInfo v1+        v0' <- newVName (baseString v1 <> "_manifest")+        let manifest_pat =+              Pat [PatElem v0' $ MemArray pt shape u $ ArrayIn mem v1_lmad]+            stm = mkWiseStm manifest_pat mempty $ BasicOp $ Manifest v0 perm+        certifying (v1_cs <> v2_cs) $ addStm stm+        auxing aux $ letBind pat $ BasicOp $ Reshape v0' s+copyManifest _ _ _ _ = Skip++-- | Standard collection of simplification rules for representations+-- with memory.+memRuleBook :: (SimplifyMemory rep inner) => RuleBook (Wise rep)+memRuleBook =+  standardRules+    <> ruleBook+      [ RuleOp decertifySafeAlloc,+        RuleBasicOp copyManifest+      ]+      []
src/Futhark/IR/Parse.hs view
@@ -260,6 +260,12 @@               <*> pure t           ) +pDimSplice :: Parser (DimSplice SubExp)+pDimSplice = DimSplice <$> pInt <* lexeme "::" <*> pInt <* lexeme "=>" <*> pShape++pNewShape :: Parser (NewShape SubExp)+pNewShape = parens $ NewShape <$> (pDimSplice `sepBy` pComma) <* pSemi <*> pShape+ pBasicOp :: Parser BasicOp pBasicOp =   choice@@ -280,17 +286,15 @@       keyword "replicate"         *> parens (Replicate <$> pShape <* pComma <*> pSubExp),       keyword "reshape"-        *> parens (Reshape ReshapeArbitrary <$> pShape <* pComma <*> pVName),-      keyword "coerce"-        *> parens (Reshape ReshapeCoerce <$> pShape <* pComma <*> pVName),+        *> parens (Reshape <$> pVName <* pComma <*> pNewShape),       keyword "scratch"         *> parens (Scratch <$> pPrimType <*> many (pComma *> pSubExp)),       keyword "rearrange"         *> parens-          (Rearrange <$> parens (pInt `sepBy` pComma) <* pComma <*> pVName),+          (Rearrange <$> pVName <* pComma <*> parens (pInt `sepBy` pComma)),       keyword "manifest"         *> parens-          (Manifest <$> parens (pInt `sepBy` pComma) <* pComma <*> pVName),+          (Manifest <$> pVName <* pComma <*> parens (pInt `sepBy` pComma)),       keyword "concat" *> do         d <- "@" *> L.decimal         parens $ do
src/Futhark/IR/Pretty.hs view
@@ -1,9 +1,8 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} --- | Futhark prettyprinter.  This module defines 'Pretty' instances--- for the AST defined in "Futhark.IR.Syntax",--- but also a number of convenience functions if you don't want to use--- the interface from 'Pretty'.+-- | Futhark prettyprinter. This module defines 'Pretty' instances for the AST+-- defined in "Futhark.IR.Syntax", but also a number of convenience functions if+-- you don't want to use the interface from 'Pretty'. module Futhark.IR.Pretty   ( prettyTuple,     prettyTupleLines,@@ -43,7 +42,7 @@   pretty Commutative = "commutative"   pretty Noncommutative = "noncommutative" -instance Pretty Shape where+instance (Pretty d) => Pretty (ShapeBase d) where   pretty = mconcat . map (brackets . pretty) . shapeDims  instance Pretty Rank where@@ -53,9 +52,6 @@   pretty (Free e) = pretty e   pretty (Ext x) = "?" <> pretty (show x) -instance Pretty ExtShape where-  pretty = mconcat . map (brackets . pretty) . shapeDims- instance Pretty Space where   pretty DefaultSpace = mempty   pretty (Space s) = "@" <> pretty s@@ -152,6 +148,10 @@ instance Pretty Attrs where   pretty = hsep . attrAnnots +instance (Pretty dec) => Pretty (StmAux dec) where+  pretty (StmAux cs attrs dec) =+    braces $ mconcat $ punctuate semi [pretty cs, pretty attrs, pretty dec]+ instance (Pretty t) => Pretty (Pat t) where   pretty (Pat xs) = braces $ commastack $ map pretty xs @@ -187,6 +187,13 @@ instance (Pretty a) => Pretty (FlatSlice a) where   pretty (FlatSlice offset xs) = brackets (pretty offset <> ";" <+> commasep (map pretty xs)) +instance (Pretty d) => Pretty (DimSplice d) where+  pretty (DimSplice i k shape) = pretty i <> "::" <> pretty k <> "=>" <> pretty shape++instance (Pretty d) => Pretty (NewShape d) where+  pretty (NewShape ds shape) =+    parens $ align $ commastack (map pretty ds) <> semi </> pretty shape+ instance Pretty BasicOp where   pretty (SubExp se) = pretty se   pretty (Opaque OpaqueNil e) = "opaque" <> apply [pretty e]@@ -228,15 +235,14 @@     "replicate" <> apply [pretty ne, align (pretty ve)]   pretty (Scratch t shape) =     "scratch" <> apply (pretty t : map pretty shape)-  pretty (Reshape ReshapeArbitrary shape e) =-    "reshape" <> apply [pretty shape, pretty e]-  pretty (Reshape ReshapeCoerce shape e) =-    "coerce" <> apply [pretty shape, pretty e]-  pretty (Rearrange perm e) =-    "rearrange" <> apply [apply (map pretty perm), pretty e]+  pretty (Reshape reshape e) =+    "reshape" <> parens (align $ commastack [pretty reshape, pretty e])+  pretty (Rearrange v perm) =+    "rearrange" <> apply [pretty v, apply (map pretty perm)]   pretty (Concat i (x :| xs) w) =     "concat" <> "@" <> pretty i <> apply (pretty w : pretty x : map pretty xs)-  pretty (Manifest perm e) = "manifest" <> apply [apply (map pretty perm), pretty e]+  pretty (Manifest v perm) =+    "manifest" <> apply [pretty v, apply (map pretty perm)]   pretty (Assert e msg (loc, _)) =     "assert" <> apply [pretty e, pretty msg, pretty $ show $ locStr loc]   pretty (UpdateAcc safety acc is v) =
src/Futhark/IR/Prop/Aliases.hs view
@@ -71,8 +71,8 @@ basicOpAliases Iota {} = [mempty] basicOpAliases Replicate {} = [mempty] basicOpAliases Scratch {} = [mempty]-basicOpAliases (Reshape _ _ e) = [vnameAliases e]-basicOpAliases (Rearrange _ e) = [vnameAliases e]+basicOpAliases (Reshape v _) = [vnameAliases v]+basicOpAliases (Rearrange v _) = [vnameAliases v] basicOpAliases Concat {} = [mempty] basicOpAliases Manifest {} = [mempty] basicOpAliases Assert {} = [mempty]
src/Futhark/IR/Prop/Names.hs view
@@ -345,6 +345,9 @@ instance (FreeIn d) => FreeIn (ShapeBase d) where   freeIn' = freeIn' . shapeDims +instance (FreeIn d) => FreeIn (NewShape d) where+  freeIn' = foldMap freeIn'+ instance (FreeIn d) => FreeIn (Ext d) where   freeIn' (Free x) = freeIn' x   freeIn' (Ext _) = mempty
src/Futhark/IR/Prop/Reshape.hs view
@@ -3,30 +3,56 @@ module Futhark.IR.Prop.Reshape   ( -- * Construction     shapeCoerce,+    reshapeAll,+    reshapeCoerce,      -- * Execution     reshapeOuter,     reshapeInner,+    newshapeInner,+    applySplice,      -- * Simplification+    flipReshapeRearrange,+    flipRearrangeReshape,+    simplifyNewShape,      -- * Shape calculations     reshapeIndex,     flattenIndex,     unflattenIndex,     sliceSizes,++    -- * Analysis+    ReshapeKind (..),+    reshapeKind,+    newShape,   ) where +import Control.Monad (guard, mplus) import Data.Foldable+import Data.Maybe+import Futhark.IR.Prop.Rearrange (isMapTranspose, rearrangeInverse, rearrangeShape) import Futhark.IR.Syntax+import Futhark.Util (focusNth, mapAccumLM, takeLast) import Futhark.Util.IntegralExp import Prelude hiding (product, quot, sum) +-- | Construct a 'NewShape' that completely reshapes the initial shape.+reshapeAll :: (ArrayShape old) => old -> ShapeBase new -> NewShape new+reshapeAll old new = NewShape [DimSplice 0 (shapeRank old) new] new++-- | Construct a 'NewShape' that coerces the shape.+reshapeCoerce :: ShapeBase new -> NewShape new+reshapeCoerce shape = NewShape (zipWith dim (shapeDims shape) [0 ..]) shape+  where+    dim x i = DimSplice i 1 $ Shape [x]+ -- | Construct a 'Reshape' that is a 'ReshapeCoerce'. shapeCoerce :: [SubExp] -> VName -> Exp rep shapeCoerce newdims arr =-  BasicOp $ Reshape ReshapeCoerce (Shape newdims) arr+  BasicOp $ Reshape arr (reshapeCoerce (Shape newdims))  -- | @reshapeOuter newshape n oldshape@ returns a 'Reshape' expression -- that replaces the outer @n@ dimensions of @oldshape@ with @newshape@.@@ -34,13 +60,24 @@ reshapeOuter newshape n oldshape =   newshape <> Shape (drop n (shapeDims oldshape)) --- | @reshapeInner newshape n oldshape@ returns a 'Reshape' expression--- that replaces the inner @m-n@ dimensions (where @m@ is the rank of--- @oldshape@) of @src@ with @newshape@.+-- | @reshapeInner newshape n oldshape@ produces a shape that replaces the inner+-- @m-n@ dimensions (where @m@ is the rank of @oldshape@) of @src@ with+-- @newshape@. reshapeInner :: Shape -> Int -> Shape -> Shape reshapeInner newshape n oldshape =   Shape (take n (shapeDims oldshape)) <> newshape +-- | @newshapeInner outershape newshape@ bumps all the dimensions in @newshape@+-- by the rank of @outershape@, essentially making them operate on the inner+-- dimensions of a larger array, and also updates the shape of @newshape@ to+-- have @outershape@ outermost.+newshapeInner :: Shape -> NewShape SubExp -> NewShape SubExp+newshapeInner outershape (NewShape ss oldshape) =+  NewShape (map f ss) (outershape <> oldshape)+  where+    r = shapeRank outershape+    f (DimSplice i k shape) = DimSplice (r + i) k shape+ -- | @reshapeIndex to_dims from_dims is@ transforms the index list -- @is@ (which is into an array of shape @from_dims@) into an index -- list @is'@, which is into an array of shape @to_dims@.  @is@ must@@ -101,3 +138,228 @@   product (n : ns) : sliceSizes ns  {- HLINT ignore sliceSizes -}++-- | Interchange a reshape and rearrange. Essentially, rewrite composition+--+-- @+-- let v1 = reshape(v0, v1_shape)+-- let v2 = rearrange(v1, perm)+-- @+--+-- into+--+-- @+-- let v1' = rearrange(v0, perm')+-- let v2' = reshape(v1', v1_shape')+-- @+--+-- The function is given the shape of @v0@, @v1@, and the @perm@, and returns+-- @perm'@. This is a meaningful operation when @v2@ is itself reshaped, as the+-- reshape-reshape can be fused. This can significantly simplify long chains of+-- reshapes and rearranges.+flipReshapeRearrange ::+  (Eq d) =>+  [d] ->+  [d] ->+  [Int] ->+  Maybe [Int]+flipReshapeRearrange v0_shape v1_shape perm = do+  (num_map_dims, num_a_dims, num_b_dims) <- isMapTranspose perm+  guard $ num_a_dims == 1+  guard $ num_b_dims == 1+  let map_dims = take num_map_dims v0_shape+      num_b_dims_expanded = length v0_shape - num_map_dims - num_a_dims+      num_a_dims_expanded = length v0_shape - num_map_dims - num_b_dims+      caseA = do+        guard $ take num_a_dims v0_shape == take num_b_dims v1_shape+        let perm' =+              [0 .. num_map_dims - 1]+                ++ map (+ num_map_dims) ([1 .. num_b_dims_expanded] ++ [0])+        Just perm'+      caseB = do+        guard $ takeLast num_b_dims v0_shape == takeLast num_b_dims v1_shape+        let perm' =+              [0 .. num_map_dims - 1]+                ++ map+                  (+ num_map_dims)+                  (num_a_dims_expanded : [0 .. num_a_dims_expanded - 1])+        Just perm'++  guard $ map_dims == take num_map_dims v1_shape++  caseA `mplus` caseB++-- | Interchange a reshape and rearrange. Essentially, rewrite composition+--+-- @+-- let v1 = rearrange(v0, perm)+-- let v2 = reshape(v1, v1_shape)+-- @+--+-- into+--+-- @+-- let v1' = reshape(v0, v1_shape')+-- let v2' = rearrange(v1', perm')+-- @+--+-- The function is given @perm@ and @v1_shape@, and returns @perm'@ and+-- @v1_shape'@. This is a meaningful operation when @v2@ is itself rearranged+-- (or @v0@ the result of a reshape), as this enables fusion.+flipRearrangeReshape :: [Int] -> NewShape d -> Maybe (NewShape d, [Int])+flipRearrangeReshape orig_perm (NewShape ss shape) = do+  (perm', ss') <- mapAccumLM f orig_perm ss+  let shape' = Shape $ rearrangeShape (rearrangeInverse perm') (shapeDims shape)+  Just (NewShape ss' shape', perm')+  where+    f perm (DimSplice i 1 s) = do+      (perm_bef, j, perm_aft) <- focusNth i perm+      let adj l = if l > j then l + length s - 1 else l+      Just+        ( map adj perm_bef ++ [j .. j + length s - 1] ++ map adj perm_aft,+          DimSplice j 1 s+        )+    f _ _ = Nothing++-- | Which kind of reshape is this?+data ReshapeKind+  = -- | New shape is dynamically same as original.+    ReshapeCoerce+  | -- | Any kind of reshaping.+    ReshapeArbitrary+  deriving (Eq, Ord, Show)++-- | Determine whether this might be a coercion.+reshapeKind :: NewShape SubExp -> ReshapeKind+reshapeKind (NewShape ss _)+  | all unit ss = ReshapeCoerce+  | otherwise = ReshapeArbitrary+  where+    unit (DimSplice _ 1 (Shape [_])) = True+    unit _ = False++-- | Apply the splice to a shape.+applySplice :: ShapeBase d -> DimSplice d -> ShapeBase d+applySplice shape_bef (DimSplice i k shape) =+  takeDims i shape_bef <> shape <> stripDims (i + k) shape_bef++-- | @dimSpan i n s@ gets @n@ dimensions starting from @i@ from @s@.+dimSpan :: Int -> Int -> ShapeBase d -> ShapeBase d+dimSpan i n = takeDims n . dropDims i++next ::+  (Eq d) =>+  ShapeBase d ->+  DimSplice d ->+  DimSplice d ->+  [DimSplice d] ->+  Maybe [DimSplice d]+next shape x y ss =+  (x :) <$> move (applySplice shape x, y) ss++move ::+  (Eq d) =>+  (ShapeBase d, DimSplice d) ->+  [DimSplice d] ->+  Maybe [DimSplice d]+--+-- A coercion that does not do anything.+move (shape_bef, DimSplice i1 n1 shape) ss+  | dimSpan i1 n1 shape_bef == shape =+      Just ss+--+-- See if we can find some redundancy.+move (shape, DimSplice i1 n1 s1) ss+  -- Check for redundant prefix.+  | match <-+      takeWhile (uncurry (==)) $+        zip (shapeDims (dimSpan i1 n1 shape)) (shapeDims s1),+    not $ null match,+    length match /= n1 =+      let k = length match+       in Just $ DimSplice (i1 + k) (n1 - k) (dropDims k s1) : ss+  -- Check for redundant suffix.+  | match <-+      takeWhile (uncurry (==)) $+        zip+          (reverse (shapeDims (dimSpan i1 n1 shape)))+          (reverse (shapeDims s1)),+    not $ null match,+    length match /= n1 =+      let k = length match+       in Just $ DimSplice i1 (n1 - k) (takeDims (length s1 - k) s1) : ss+--+-- Base case.+move _ [] = Nothing+--+-- A coercion can be fused with anything.+move (_, DimSplice i1 1 (Shape [_])) (DimSplice i2 n2 s2 : ss)+  | i1 == i2 =+      Just $ DimSplice i2 n2 s2 : ss+--+-- A flatten with an inverse unflatten turns into nothing.+move (shape_bef, DimSplice i1 n1 _s1) (DimSplice i2 _n2 s2 : ss)+  | i1 == i2,+    dimSpan i1 n1 shape_bef == s2 =+      Just ss+--+-- An unflatten where one of the dimensions is then further unflattened.+move (_, DimSplice i1 n1 s1) (DimSplice i2 n2 s2 : ss)+  | i2 >= i1,+    i2 < i1 + length s1,+    n1 == 1,+    n2 == 1 =+      Just $ DimSplice i1 1 (s1_bef <> s2 <> s1_aft) : ss+  where+    s1_bef = takeDims (i2 - i1) s1+    s1_aft = dropDims (i2 - i1 + 1) s1++--+-- Flatten followed by a flattening of overlapping dimensions.+move (_, DimSplice i1 n1 s1) (DimSplice i2 n2 s2 : ss)+  | length s1 == 1,+    length s2 == 1,+    i1 == i2 + 1,+    n2 > 1 =+      Just $ DimSplice i2 (n2 + n1 - length s1) s2 : ss+--+-- Flatten into an unflatten.+move (_, DimSplice i1 n1 (Shape [_])) (DimSplice i2 1 s2 : ss)+  | i1 == i2 =+      Just $ DimSplice i1 n1 s2 : ss+--+-- These cases are for updating dimensions as we move across intervening+-- operations.+move (shape, DimSplice i1 n1 s1) (DimSplice i2 n2 s2 : ss)+  | i1 > i2 + n2 =+      next shape (DimSplice i2 n2 s2) (DimSplice (i1 - n2 + length s2) n1 s1) ss+  | i2 > i1 + n1 =+      next shape (DimSplice (i2 - n1 + length s1) n2 s2) (DimSplice i1 n2 s1) ss+  | otherwise = Nothing++-- This is a quadratic-time function that looks for a DimSplice that can be+-- combined with a move DimSlice (and then does so). Since these lists are+-- usually small, this should not be a problem. It is called to convergence by+-- 'improve'.+improveOne :: (Eq d) => ShapeBase d -> [DimSplice d] -> Maybe [DimSplice d]+improveOne _ [] = Nothing+improveOne shape (s : ss) =+  move (shape, s) ss `mplus` ((s :) <$> improveOne (applySplice shape s) ss)++-- | Try to simplify the given 'NewShape'. Returns 'Nothing' if no improvement+-- is possible.+simplifyNewShape :: (Eq d) => ShapeBase d -> NewShape d -> Maybe (NewShape d)+simplifyNewShape shape_bef (NewShape ss shape) =+  NewShape <$> (improve <$> improveOne shape_bef ss) <*> pure shape+  where+    improve ss' = maybe ss' improve $ improveOne shape_bef ss'++{-# NOINLINE flipReshapeRearrange #-}++{-# NOINLINE flipRearrangeReshape #-}++{-# NOINLINE reshapeKind #-}++{-# NOINLINE simplifyNewShape #-}++{-# NOINLINE newshapeInner #-}
src/Futhark/IR/Prop/TypeOf.hs view
@@ -101,23 +101,19 @@   pure . flip arrayOfShape shape <$> subExpType e basicOpType (Scratch t shape) =   pure [arrayOf (Prim t) (Shape shape) NoUniqueness]-basicOpType (Reshape _ (Shape []) e) =-  result <$> lookupType e-  where-    result t = [Prim $ elemType t]-basicOpType (Reshape _ shape e) =+basicOpType (Reshape e shape) =   result <$> lookupType e   where-    result t = [t `setArrayShape` shape]-basicOpType (Rearrange perm e) =-  result <$> lookupType e+    result t = [t `setArrayShape` newShape shape]+basicOpType (Rearrange v perm) =+  result <$> lookupType v   where     result t = [rearrangeType perm t] basicOpType (Concat i (x :| _) ressize) =   result <$> lookupType x   where     result xt = [setDimSize i xt ressize]-basicOpType (Manifest _ v) =+basicOpType (Manifest v _) =   pure <$> lookupType v basicOpType Assert {} =   pure [Prim Unit]
src/Futhark/IR/SOACS/Simplify.hs view
@@ -35,7 +35,7 @@ import Futhark.Analysis.SymbolTable qualified as ST import Futhark.Analysis.UsageTable qualified as UT import Futhark.IR.Prop.Aliases-import Futhark.IR.SOACS+import Futhark.IR.SOACS hiding (reshapeInner) import Futhark.MonadFreshNames import Futhark.Optimise.Simplify qualified as Simplify import Futhark.Optimise.Simplify.Engine qualified as Engine@@ -295,12 +295,10 @@                   { lambdaBody = (lambdaBody fun) {bodyResult = subExpsRes ses'},                     lambdaReturnType = rettype'                   }-          mapM_ (uncurry letBind) invariant-          auxing aux $-            letBindNames (map patElemName pat') $-              Op $-                soacOp $-                  Screma w arrs (mapSOAC fun')+          auxing aux $ do+            mapM_ (uncurry letBind) invariant+            letBindNames (map patElemName pat') . Op $+              soacOp (Screma w arrs (mapSOAC fun')) liftIdentityMapping _ _ _ _ = Skip  liftIdentityStreaming :: BottomUpRuleOp (Wise SOACS)@@ -459,9 +457,10 @@                       { lambdaBody = (lambdaBody fun) {bodyResult = ses'},                         lambdaReturnType = ts'                       }-              auxing aux $ letBind (Pat pes') $ Op $ Screma w arrs $ mapSOAC fun'-              forM_ copies $ \(from, to) ->-                letBind (Pat [to]) $ BasicOp $ Replicate mempty $ Var $ patElemName from+              auxing aux $ do+                letBind (Pat pes') $ Op $ Screma w arrs $ mapSOAC fun'+                forM_ copies $ \(from, to) ->+                  letBind (Pat [to]) $ BasicOp $ Replicate mempty $ Var $ patElemName from   where     checkForDuplicates (ses_ts_pes', copies) (se, t, pe)       | Just (_, _, pe') <- find (\(x, _, _) -> resSubExp x == resSubExp se) ses_ts_pes' =@@ -471,27 +470,33 @@       | otherwise = (ses_ts_pes' ++ [(se, t, pe)], copies) removeDuplicateMapOutput _ _ _ _ = Skip +reshapeInner :: SubExp -> NewShape SubExp -> NewShape SubExp+reshapeInner w new_shape =+  reshapeCoerce outer <> newshapeInner outer new_shape+  where+    outer = Shape [w]+ -- Mapping some operations becomes an extension of that operation. mapOpToOp :: BottomUpRuleOp (Wise SOACS) mapOpToOp (_, used) pat aux1 e-  | Just (map_pe, cs, w, BasicOp (Reshape k newshape reshape_arr), [p], [arr]) <-+  | Just (map_pe, cs, w, BasicOp (Reshape reshape_arr newshape), [p], [arr]) <-       isMapWithOp pat e,     paramName p == reshape_arr,     not $ UT.isConsumed (patElemName map_pe) used = Simplify $ do       certifying (stmAuxCerts aux1 <> cs) . letBind pat . BasicOp $-        Reshape k (Shape [w] <> newshape) arr+        Reshape arr (reshapeInner w newshape)   | Just (_, cs, _, BasicOp (Concat d (arr :| arrs) dw), ps, outer_arr : outer_arrs) <-       isMapWithOp pat e,     (arr : arrs) == map paramName ps =       Simplify . certifying (stmAuxCerts aux1 <> cs) . letBind pat . BasicOp $         Concat (d + 1) (outer_arr :| outer_arrs) dw   | Just-      (map_pe, cs, _, BasicOp (Rearrange perm rearrange_arr), [p], [arr]) <-+      (map_pe, cs, _, BasicOp (Rearrange rearrange_arr perm), [p], [arr]) <-       isMapWithOp pat e,     paramName p == rearrange_arr,     not $ UT.isConsumed (patElemName map_pe) used =       Simplify . certifying (stmAuxCerts aux1 <> cs) . letBind pat . BasicOp $-        Rearrange (0 : map (1 +) perm) arr+        Rearrange arr (0 : map (1 +) perm) mapOpToOp _ _ _ _ = Skip  isMapWithOp ::@@ -625,9 +630,10 @@         y_ws <- mapM sizeOf ys         guard $ all (x_w ==) y_ws         pure (x_w, x : ys, cs)-      Just (BasicOp (Reshape ReshapeCoerce _ arr), cs) -> do-        (a, b, cs') <- isConcat arr-        pure (a, b, cs <> cs')+      Just (BasicOp (Reshape arr newshape), cs)+        | ReshapeCoerce <- reshapeKind newshape -> do+            (a, b, cs') <- isConcat arr+            pure (a, b, cs <> cs')       _ -> Nothing fuseConcatScatter _ _ _ _ = Skip @@ -718,7 +724,7 @@ data ArrayOp   = ArrayIndexing Certs VName (Slice SubExp)   | ArrayRearrange Certs VName [Int]-  | ArrayReshape Certs VName ReshapeKind Shape+  | ArrayReshape Certs VName (NewShape SubExp)   | ArrayCopy Certs VName   | -- | Never constructed.     ArrayVar Certs VName@@ -727,24 +733,24 @@ arrayOpArr :: ArrayOp -> VName arrayOpArr (ArrayIndexing _ arr _) = arr arrayOpArr (ArrayRearrange _ arr _) = arr-arrayOpArr (ArrayReshape _ arr _ _) = arr+arrayOpArr (ArrayReshape _ arr _) = arr arrayOpArr (ArrayCopy _ arr) = arr arrayOpArr (ArrayVar _ arr) = arr  arrayOpCerts :: ArrayOp -> Certs arrayOpCerts (ArrayIndexing cs _ _) = cs arrayOpCerts (ArrayRearrange cs _ _) = cs-arrayOpCerts (ArrayReshape cs _ _ _) = cs+arrayOpCerts (ArrayReshape cs _ _) = cs arrayOpCerts (ArrayCopy cs _) = cs arrayOpCerts (ArrayVar cs _) = cs  isArrayOp :: Certs -> Exp rep -> Maybe ArrayOp isArrayOp cs (BasicOp (Index arr slice)) =   Just $ ArrayIndexing cs arr slice-isArrayOp cs (BasicOp (Rearrange perm arr)) =+isArrayOp cs (BasicOp (Rearrange arr perm)) =   Just $ ArrayRearrange cs arr perm-isArrayOp cs (BasicOp (Reshape k new_shape arr)) =-  Just $ ArrayReshape cs arr k new_shape+isArrayOp cs (BasicOp (Reshape arr new_shape)) =+  Just $ ArrayReshape cs arr new_shape isArrayOp cs (BasicOp (Replicate (Shape []) (Var arr))) =   Just $ ArrayCopy cs arr isArrayOp _ _ =@@ -752,8 +758,8 @@  fromArrayOp :: ArrayOp -> (Certs, Exp rep) fromArrayOp (ArrayIndexing cs arr slice) = (cs, BasicOp $ Index arr slice)-fromArrayOp (ArrayRearrange cs arr perm) = (cs, BasicOp $ Rearrange perm arr)-fromArrayOp (ArrayReshape cs arr k new_shape) = (cs, BasicOp $ Reshape k new_shape arr)+fromArrayOp (ArrayRearrange cs arr perm) = (cs, BasicOp $ Rearrange arr perm)+fromArrayOp (ArrayReshape cs arr new_shape) = (cs, BasicOp $ Reshape arr new_shape) fromArrayOp (ArrayCopy cs arr) = (cs, BasicOp $ Replicate mempty $ Var arr) fromArrayOp (ArrayVar cs arr) = (cs, BasicOp $ SubExp $ Var arr) @@ -953,7 +959,7 @@       arr `elem` map_param_names         && all (`ST.elem` vtable) (namesToList $ freeIn cs)         && not (null perm)-    arrayIsMapParam (_, ArrayReshape cs arr _ new_shape) =+    arrayIsMapParam (_, ArrayReshape cs arr new_shape) =       arr `elem` map_param_names         && all (`ST.elem` vtable) (namesToList $ freeIn cs <> freeIn new_shape)     arrayIsMapParam (_, ArrayCopy cs arr) =@@ -973,9 +979,9 @@                 ArrayIndexing _ _ (Slice slice) ->                   BasicOp $ Index arr $ Slice $ whole_dim : slice                 ArrayRearrange _ _ perm ->-                  BasicOp $ Rearrange (0 : map (+ 1) perm) arr-                ArrayReshape _ _ k new_shape ->-                  BasicOp $ Reshape k (Shape [w] <> new_shape) arr+                  BasicOp $ Rearrange arr (0 : map (+ 1) perm)+                ArrayReshape _ _ new_shape ->+                  BasicOp $ Reshape arr $ reshapeInner w new_shape                 ArrayCopy {} ->                   BasicOp $ Replicate mempty $ Var arr                 ArrayVar {} ->@@ -1046,12 +1052,12 @@      invariantToMap = all (`ST.elem` vtable) . namesToList . freeIn -    onStm (transformed, map_infos, stms) (Let (Pat [pe]) aux (BasicOp (Reshape k new_shape arr)))+    onStm (transformed, map_infos, stms) (Let (Pat [pe]) aux (BasicOp (Reshape arr new_shape)))       | ([(res, _, screma_pe)], map_pesres') <- partition matches map_infos,         Just t <- typeOf <$> M.lookup arr scope,-        invariantToMap t =+        invariantToMap (t, new_shape) =           let cs = stmAuxCerts aux <> resCerts res-              transform = (arr, cs, BasicOp . Reshape k (Shape [w] <> new_shape))+              transform = (arr, cs, BasicOp . flip Reshape (reshapeInner w new_shape))            in ((t, screma_pe, transform) : transformed, map_pesres', stms)       where         matches (r, _, _) = resSubExp r == Var (patElemName pe)
src/Futhark/IR/Syntax.hs view
@@ -99,7 +99,9 @@ module Futhark.IR.Syntax   ( module Language.Futhark.Core,     prettyString,+    prettyStringOneLine,     prettyText,+    prettyTextOneLine,     Pretty,     module Futhark.IR.Rep,     module Futhark.IR.Syntax.Core,@@ -130,7 +132,8 @@     CmpOp (..),     ConvOp (..),     OpaqueOp (..),-    ReshapeKind (..),+    DimSplice (..),+    NewShape (..),     WithAccInput,     Exp (..),     Case (..),@@ -173,7 +176,7 @@ import Data.Traversable (fmapDefault, foldMapDefault) import Futhark.IR.Rep import Futhark.IR.Syntax.Core-import Futhark.Util.Pretty (Pretty, prettyString, prettyText)+import Futhark.Util.Pretty (Pretty, prettyString, prettyStringOneLine, prettyText, prettyTextOneLine) import Language.Futhark.Core import Prelude hiding (id, (.)) @@ -205,6 +208,9 @@   }   deriving (Ord, Show, Eq) +instance (Monoid dec) => Monoid (StmAux dec) where+  mempty = StmAux mempty mempty mempty+ instance (Semigroup dec) => Semigroup (StmAux dec) where   StmAux cs1 attrs1 dec1 <> StmAux cs2 attrs2 dec2 =     StmAux (cs1 <> cs2) (attrs1 <> attrs2) (dec1 <> dec2)@@ -305,14 +311,41 @@     OpaqueTrace T.Text   deriving (Eq, Ord, Show) --- | Which kind of reshape is this?-data ReshapeKind-  = -- | New shape is dynamically same as original.-    ReshapeCoerce-  | -- | Any kind of reshaping.-    ReshapeArbitrary-  deriving (Eq, Ord, Show)+-- | Split or join a range of dimensions. A reshaping operation consists of a+-- sequence of these. The purpose is to maintain information about the original+-- operations (flatten/unflatten), which can then be used for algebraic+-- optimisations.+data DimSplice d+  = -- | @DimSplice i k s@ modifies dimensions @i@ to @i+k-1@ to instead have+    -- shape @s@.+    --+    -- If @k@ is 1 and the rank of @s@ is greater than 1, then this is+    -- equivalent to unflattening a dimension.+    --+    -- If @k@ is greater than 1 and the rank of @s@ is 1, then this is+    -- equivalent to flattening adjacent dimensions.+    --+    -- If @k@ is 1 and the rank of @s@ is 1, then it is a coercion - a change+    -- that only affects the type, but does not have any semantic effect.+    --+    -- Other cases can do arbitrary changes, but are harder for the compiler to+    -- analyse.+    DimSplice Int Int (ShapeBase d)+  deriving (Eq, Ord, Show, Functor, Foldable, Traversable) +-- | A reshaping operation consists of a sequence of splices, as well as an+-- annotation indicating the final shape.+data NewShape d = NewShape+  { -- | The changes to perform.+    dimSplices :: [DimSplice d],+    -- | The resulting shape.+    newShape :: ShapeBase d+  }+  deriving (Eq, Ord, Show, Functor, Foldable, Traversable)++instance Semigroup (NewShape d) where+  NewShape ss1 _ <> NewShape ss2 shape = NewShape (ss1 <> ss2) shape+ -- | A primitive operation that returns something of known size and -- does not itself contain any bindings. data BasicOp@@ -365,7 +398,7 @@     Concat Int (NonEmpty VName) SubExp   | -- | Manifest an array with dimensions represented in the given     -- order.  The result will not alias anything.-    Manifest [Int] VName+    Manifest VName [Int]   | -- Array construction.      -- | @iota(n, x, s) = [x,x+s,..,x+(n-1)*s]@.@@ -378,13 +411,13 @@     Replicate Shape SubExp   | -- | Create array of given type and shape, with undefined elements.     Scratch PrimType [SubExp]-  | -- | 1st arg is the new shape, 2nd arg is the input array.-    Reshape ReshapeKind Shape VName+  | -- | 1st arg is the input array, 2nd arg is new shape.+    Reshape VName (NewShape SubExp)   | -- | Permute the dimensions of the input array.  The list     -- of integers is a list of dimensions (0-indexed), which     -- must be a permutation of @[0,n-1]@, where @n@ is the     -- number of dimensions in the input array.-    Rearrange [Int] VName+    Rearrange VName [Int]   | -- | Update an accumulator at the given index with the given     -- value. Consumes the accumulator and produces a new one. If     -- 'Safe', perform a run-time bounds check and ignore the write if
src/Futhark/IR/Syntax/Core.hs view
@@ -15,6 +15,8 @@     ShapeBase (..),     Shape,     stripDims,+    dropDims,+    takeDims,     Ext (..),     ExtSize,     ExtShape,@@ -123,10 +125,19 @@ instance Monoid (ShapeBase d) where   mempty = Shape mempty --- | @stripDims n shape@ strips the outer @n@ dimensions from--- @shape@.+-- | Alias for 'dropDims' stripDims :: Int -> ShapeBase d -> ShapeBase d-stripDims n (Shape dims) = Shape $ drop n dims+stripDims = dropDims++-- | @dropDims n shape@ strips the outer @n@ dimensions from+-- @shape@.+dropDims :: Int -> ShapeBase d -> ShapeBase d+dropDims n (Shape dims) = Shape $ drop n dims++-- | @takeDims n shape@ takes the outer @n@ dimensions from @shape@, up to the+-- number of dimensions in @shape@.+takeDims :: Int -> ShapeBase d -> ShapeBase d+takeDims n (Shape dims) = Shape $ take n dims  -- | The size of an array as a list of subexpressions.  If a variable, -- that variable must be in scope where this array is used.
src/Futhark/IR/Traversals.hs view
@@ -149,21 +149,21 @@   BasicOp <$> (Replicate <$> mapOnShape tv shape <*> mapOnSubExp tv vexp) mapExpM tv (BasicOp (Scratch t shape)) =   BasicOp <$> (Scratch t <$> mapM (mapOnSubExp tv) shape)-mapExpM tv (BasicOp (Reshape kind shape arrexp)) =+mapExpM tv (BasicOp (Reshape arrexp newshape)) =   BasicOp-    <$> ( Reshape kind-            <$> mapM (mapOnSubExp tv) shape-            <*> mapOnVName tv arrexp+    <$> ( Reshape+            <$> mapOnVName tv arrexp+            <*> mapM (mapOnSubExp tv) newshape         )-mapExpM tv (BasicOp (Rearrange perm e)) =-  BasicOp <$> (Rearrange perm <$> mapOnVName tv e)+mapExpM tv (BasicOp (Rearrange e perm)) =+  BasicOp <$> (Rearrange <$> mapOnVName tv e <*> pure perm) mapExpM tv (BasicOp (Concat i (x :| ys) size)) = do   x' <- mapOnVName tv x   ys' <- mapM (mapOnVName tv) ys   size' <- mapOnSubExp tv size   pure $ BasicOp $ Concat i (x' :| ys') size'-mapExpM tv (BasicOp (Manifest perm e)) =-  BasicOp <$> (Manifest perm <$> mapOnVName tv e)+mapExpM tv (BasicOp (Manifest v perm)) =+  BasicOp <$> (Manifest <$> mapOnVName tv v <*> pure perm) mapExpM tv (BasicOp (Assert e msg loc)) =   BasicOp <$> (Assert <$> mapOnSubExp tv e <*> traverse (mapOnSubExp tv) msg <*> pure loc) mapExpM tv (BasicOp (Opaque op e)) =@@ -319,14 +319,14 @@   walkOnShape tv shape >> walkOnSubExp tv vexp walkExpM tv (BasicOp (Scratch _ shape)) =   mapM_ (walkOnSubExp tv) shape-walkExpM tv (BasicOp (Reshape _ shape arrexp)) =+walkExpM tv (BasicOp (Reshape arrexp shape)) =   mapM_ (walkOnSubExp tv) shape >> walkOnVName tv arrexp-walkExpM tv (BasicOp (Rearrange _ e)) =-  walkOnVName tv e+walkExpM tv (BasicOp (Rearrange v _)) =+  walkOnVName tv v walkExpM tv (BasicOp (Concat _ (x :| ys) size)) =   walkOnVName tv x >> mapM_ (walkOnVName tv) ys >> walkOnSubExp tv size-walkExpM tv (BasicOp (Manifest _ e)) =-  walkOnVName tv e+walkExpM tv (BasicOp (Manifest v _)) =+  walkOnVName tv v walkExpM tv (BasicOp (Assert e msg _)) =   walkOnSubExp tv e >> traverse_ (walkOnSubExp tv) msg walkExpM tv (BasicOp (Opaque _ e)) =
src/Futhark/IR/TypeCheck.hs view
@@ -73,7 +73,7 @@   | UnknownVariableError VName   | UnknownFunctionError Name   | ParameterMismatch (Maybe Name) [Type] [Type]-  | SlicingError Int Int+  | SlicingError Shape Int   | BadAnnotation String Type Type   | ReturnAliased Name VName   | UniqueReturnAliased Name@@ -143,7 +143,7 @@       ngot = length got       fname' = maybe "anonymous function" (("function " ++) . nameToString) fname   show (SlicingError dims got) =-    show got ++ " indices given, but type of indexee has " ++ show dims ++ " dimension(s)."+    show got ++ " indices given, but type of indexee has shape " ++ prettyString dims   show (BadAnnotation desc expected got) =     "Annotation of \""       ++ desc@@ -834,9 +834,12 @@ checkSlice :: (Checkable rep) => Type -> Slice SubExp -> TypeM rep () checkSlice vt (Slice idxes) = do   when (arrayRank vt /= length idxes) . bad $-    SlicingError (arrayRank vt) (length idxes)+    SlicingError (arrayShape vt) (length idxes)   mapM_ (traverse $ require [Prim int64]) idxes +checkShape :: (Checkable rep) => Shape -> TypeM rep ()+checkShape = mapM_ (require [Prim int64])+ checkBasicOp :: (Checkable rep) => BasicOp -> TypeM rep () checkBasicOp (SubExp es) =   void $ checkSubExp es@@ -883,15 +886,11 @@ checkBasicOp (FlatIndex ident slice) = do   vt <- lookupType ident   observe ident-  when (arrayRank vt /= 1) $-    bad $-      SlicingError (arrayRank vt) 1+  when (arrayRank vt /= 1) $ bad $ SlicingError (arrayShape vt) 1   checkFlatSlice slice checkBasicOp (FlatUpdate src slice v) = do   (src_shape, src_pt) <- checkArrIdent src-  when (shapeRank src_shape /= 1) $-    bad $-      SlicingError (shapeRank src_shape) 1+  when (shapeRank src_shape /= 1) $ bad $ SlicingError src_shape 1    v_aliases <- lookupAliases v   when (src `nameIn` v_aliases) $@@ -909,17 +908,23 @@   mapM_ (require [Prim int64]) dims   void $ checkSubExp valexp checkBasicOp (Scratch _ shape) =-  mapM_ checkSubExp shape-checkBasicOp (Reshape k newshape arrexp) = do-  rank <- shapeRank . fst <$> checkArrIdent arrexp-  mapM_ (require [Prim int64]) $ shapeDims newshape-  case k of-    ReshapeCoerce ->-      when (shapeRank newshape /= rank) . bad $-        TypeError "Coercion changes rank of array."-    ReshapeArbitrary ->-      pure ()-checkBasicOp (Rearrange perm arr) = do+  checkShape $ Shape shape+checkBasicOp (Reshape arrexp newshape) = do+  (arr_shape, _) <- checkArrIdent arrexp+  checkShape $ newShape newshape+  spliced_shape <- foldM checkSplice arr_shape $ dimSplices newshape+  when (spliced_shape /= newShape newshape) . bad . TypeError $+    "Splice produces shape "+      <> prettyText spliced_shape+      <> " but annotation is shape "+      <> prettyText (newShape newshape)+  where+    checkSplice arr_shape sp@(DimSplice i k shape) = do+      checkShape shape+      when (i < 0 || i + k > shapeRank arr_shape) . bad . TypeError $+        "Splice " <> prettyText sp <> " cannot be applied to shape " <> prettyText arr_shape+      pure $ applySplice arr_shape sp+checkBasicOp (Rearrange arr perm) = do   arrt <- lookupType arr   let rank = arrayRank arrt   when (length perm /= rank || sort perm /= [0 .. rank - 1]) $@@ -933,8 +938,8 @@     bad $       TypeError "Types of arguments to concat do not match."   require [Prim int64] ressize-checkBasicOp (Manifest perm arr) =-  checkBasicOp $ Rearrange perm arr -- Basically same thing!+checkBasicOp (Manifest arr perm) =+  checkBasicOp $ Rearrange arr perm -- Basically same thing! checkBasicOp (Assert e (ErrorMsg parts) _) = do   require [Prim Bool] e   mapM_ checkPart parts
src/Futhark/Internalise/Exps.hs view
@@ -518,12 +518,11 @@           forM_ (zip mergepat' mergeinit) $ \(p, se) ->             unless (se == I.Var (I.paramName p)) $               letBindNames [I.paramName p] $-                BasicOp $-                  case se of-                    I.Var v-                      | not $ primType $ paramType p ->-                          Reshape I.ReshapeCoerce (I.arrayShape $ paramType p) v-                    _ -> SubExp se+                case se of+                  I.Var v+                    | not $ primType $ paramType p ->+                        shapeCoerce (I.arrayDims $ paramType p) v+                  _ -> BasicOp $ SubExp se            -- As the condition expression is inserted twice, we have to           -- avoid shadowing (#1935).@@ -551,12 +550,11 @@             forM_ (zip mergepat' ses) $ \(p, se) ->               unless (se == I.Var (I.paramName p)) $                 letBindNames [I.paramName p] $-                  BasicOp $-                    case se of-                      I.Var v-                        | not $ primType $ paramType p ->-                            Reshape I.ReshapeCoerce (I.arrayShape $ paramType p) v-                      _ -> SubExp se+                  case se of+                    I.Var v+                      | not $ primType $ paramType p ->+                          shapeCoerce (I.arrayDims $ paramType p) v+                    _ -> BasicOp $ SubExp se             subExpsRes <$> internaliseExp "loop_cond" cond           loop_end_cond <- bodyBind loop_end_cond_body @@ -667,7 +665,7 @@                 (I.Shape $ map (intConst Int64 . toInteger) new_shape)                 1                 $ I.arrayShape flat_arr_t-        letSubExp desc $ I.BasicOp $ I.Reshape I.ReshapeArbitrary new_shape' flat_arr+        letSubExp desc $ I.BasicOp $ I.Reshape flat_arr (reshapeAll (I.arrayShape flat_arr_t) new_shape')   | otherwise = do       es' <- mapM (internaliseExp "arr_elem") es       let arr_t_ext = foldMap toList $ internaliseType $ E.toStruct arr_t@@ -794,6 +792,25 @@       traceRes (nameToText tag) e'     "opaque" ->       mapM (letSubExp desc . BasicOp . Opaque OpaqueNil) e'+    "scratch" -> do+      ts <- mapM subExpType e'+      forM (zip ts e') $ \(t, se) ->+        case t of+          I.Array pt shape _ ->+            letSubExp desc $ I.BasicOp $ I.Scratch pt $ I.shapeDims shape+          I.Prim pt ->+            pure $ constant $ blankPrimValue pt+          _ -> pure se+    "blank" -> do+      ts <- mapM subExpType e'+      forM (zip ts e') $ \(t, se) ->+        case t of+          I.Array pt shape _ ->+            letSubExp desc . I.BasicOp . I.Replicate shape . constant $+              blankPrimValue pt+          I.Prim pt ->+            pure $ constant $ blankPrimValue pt+          _ -> pure se     _ ->       pure e'   where@@ -1582,9 +1599,11 @@                     x' <- letExp "x" $ I.BasicOp $ I.SubExp x                     y' <- letExp "x" $ I.BasicOp $ I.SubExp y                     x_flat <--                      letExp "x_flat" $ I.BasicOp $ I.Reshape I.ReshapeArbitrary (I.Shape [x_num_elems]) x'+                      letExp "x_flat" . I.BasicOp $+                        I.Reshape x' (reshapeAll (I.arrayShape x_t) (I.Shape [x_num_elems]))                     y_flat <--                      letExp "y_flat" $ I.BasicOp $ I.Reshape I.ReshapeArbitrary (I.Shape [x_num_elems]) y'+                      letExp "y_flat" . I.BasicOp $+                        I.Reshape y' (reshapeAll (I.arrayShape x_t) (I.Shape [x_num_elems]))                      -- Compare the elements.                     cmp_lam <- cmpOpLambda $ I.CmpEq (elemType x_t)@@ -1760,17 +1779,17 @@         forM arrs $ \arr' -> do           arr_t <- lookupType arr'           letSubExp desc . I.BasicOp $-            I.Reshape-              I.ReshapeArbitrary-              (reshapeOuter (I.Shape [n', m']) 1 $ I.arrayShape arr_t)-              arr'+            I.Reshape arr' $+              reshapeAll (I.arrayShape arr_t) $+                reshapeOuter (I.Shape [n', m']) 1 $+                  I.arrayShape arr_t     handleRest [arr] "manifest" = Just $ \desc -> do       arrs <- internaliseExpToVars "flatten_arr" arr       forM arrs $ \arr' -> do         r <- I.arrayRank <$> lookupType arr'         if r == 0           then pure $ I.Var arr'-          else letSubExp desc $ I.BasicOp $ I.Manifest [0 .. r - 1] arr'+          else letSubExp desc $ I.BasicOp $ I.Manifest arr' [0 .. r - 1]     handleRest [arr] "flatten" = Just $ \desc -> do       arrs <- internaliseExpToVars "flatten_arr" arr       forM arrs $ \arr' -> do@@ -1779,10 +1798,10 @@             m = arraySize 1 arr_t         k <- letSubExp "flat_dim" $ I.BasicOp $ I.BinOp (Mul Int64 I.OverflowUndef) n m         letSubExp desc . I.BasicOp $-          I.Reshape-            I.ReshapeArbitrary-            (reshapeOuter (I.Shape [k]) 2 $ I.arrayShape arr_t)-            arr'+          I.Reshape arr' $+            reshapeAll (I.arrayShape arr_t) $+              reshapeOuter (I.Shape [k]) 2 $+                I.arrayShape arr_t     handleRest [x, y] "concat" = Just $ \desc -> do       xs <- internaliseExpToVars "concat_x" x       ys <- internaliseExpToVars "concat_y" y@@ -1801,7 +1820,7 @@     handleRest [e] "transpose" = Just $ \desc ->       internaliseOperation desc e $ \v -> do         r <- I.arrayRank <$> lookupType v-        pure $ I.Rearrange ([1, 0] ++ [2 .. r - 1]) v+        pure $ I.Rearrange v ([1, 0] ++ [2 .. r - 1])     handleRest [x, y] "zip" = Just $ \desc ->       mapM (letSubExp "zip_copy" . BasicOp . Replicate mempty . I.Var)         =<< ( (++)@@ -1884,8 +1903,8 @@             "length of index and value array does not match"             loc         certifying c $-          letExp (baseString sv ++ "_write_sv") . I.BasicOp $-            I.Reshape I.ReshapeCoerce (reshapeOuter (I.Shape [si_w]) 1 sv_shape) sv+          letExp (baseString sv ++ "_write_sv") $+            shapeCoerce (I.shapeDims (reshapeOuter (I.Shape [si_w]) 1 sv_shape)) sv        indexType <- fmap rowType <$> mapM lookupType si'       indexName <- mapM (\_ -> newVName "write_index") indexType
src/Futhark/Internalise/Monomorphise.hs view
@@ -322,7 +322,8 @@         Just prev ->           pure $ MonoKnown prev         Nothing -> do-          put (i + 1, M.insert d i m)+          -- Ensure that each instance of anySize is treated distinctly.+          put (i + 1, if d == anySize then m else M.insert d i m)           pure $ MonoKnown i  -- Mapping from function name and instance list to a new function name in case
src/Futhark/Internalise/ReplaceRecords.hs view
@@ -182,7 +182,12 @@   pure $ Lambda params' body' retdecl ret loc transformExp e = astMap m e   where-    m = identityMapper {mapOnExp = transformExp}+    m =+      identityMapper+        { mapOnExp = transformExp,+          mapOnStructType = transformStructType,+          mapOnParamType = transformParamType+        }  onValBind :: ValBind -> RecordM ValBind onValBind vb = do
src/Futhark/Optimise/ArrayLayout/Transform.hs view
@@ -236,7 +236,7 @@      manifest perm array =       letExp (baseString array ++ "_coalesced") $-        BasicOp (Manifest perm array)+        BasicOp (Manifest array perm)  lookupPermutation :: LayoutTable -> VName -> IndexExprName -> VName -> Maybe Permutation lookupPermutation perm_table seg_name idx_name arr_name =
src/Futhark/Optimise/ArrayShortCircuiting/MemRefAggreg.hs view
@@ -127,7 +127,7 @@   let ws = mapMaybe (getDirAliasedIxfn td_env coal_tab . patElemName) ys       rs = mapMaybe (getDirAliasedIxfn td_env coal_tab) (a : bs)    in Just (ws, ws ++ rs)-getUseSumFromStm td_env coal_tab (Let (Pat ys) _ (BasicOp (Manifest _perm x))) =+getUseSumFromStm td_env coal_tab (Let (Pat ys) _ (BasicOp (Manifest x _perm))) =   let ws = mapMaybe (getDirAliasedIxfn td_env coal_tab . patElemName) ys       rs = mapMaybe (getDirAliasedIxfn td_env coal_tab) [x]    in Just (ws, ws ++ rs)
src/Futhark/Optimise/ArrayShortCircuiting/TopdownAnalysis.hs view
@@ -71,10 +71,12 @@ getDirAliasFromExp :: Exp (Aliases rep) -> Maybe (VName, DirAlias) getDirAliasFromExp (BasicOp (SubExp (Var x))) = Just (x, Just) getDirAliasFromExp (BasicOp (Opaque _ (Var x))) = Just (x, Just)-getDirAliasFromExp (BasicOp (Reshape ReshapeCoerce shp x)) =-  Just (x, Just . (`LMAD.coerce` shapeDims (fmap pe64 shp)))-getDirAliasFromExp (BasicOp (Reshape ReshapeArbitrary shp x)) =-  Just (x, (`LMAD.reshape` shapeDims (fmap pe64 shp)))+getDirAliasFromExp (BasicOp (Reshape x shp)) =+  case reshapeKind shp of+    ReshapeCoerce ->+      Just (x, Just . (`LMAD.coerce` fmap pe64 (shapeDims $ newShape shp)))+    ReshapeArbitrary ->+      Just (x, (`LMAD.reshape` fmap pe64 (shapeDims $ newShape shp))) getDirAliasFromExp (BasicOp (Rearrange _ _)) =   Nothing getDirAliasFromExp (BasicOp (Index x slc)) =@@ -109,7 +111,7 @@ getInvAliasFromExp (BasicOp (SubExp (Var _))) = Just id getInvAliasFromExp (BasicOp (Opaque _ (Var _))) = Just id getInvAliasFromExp (BasicOp Update {}) = Just id-getInvAliasFromExp (BasicOp (Rearrange perm _)) =+getInvAliasFromExp (BasicOp (Rearrange _ perm)) =   Just (`LMAD.permute` rearrangeInverse perm) getInvAliasFromExp _ = Nothing 
src/Futhark/Optimise/BlkRegTiling.hs view
@@ -48,13 +48,9 @@  isInnerCoal :: Env -> VName -> Stm GPU -> Bool isInnerCoal (_, ixfn_env) slc_X (Let (Pat [pe]) _ (BasicOp (Index x _)))-  | slc_X == patElemName pe,-    Nothing <- M.lookup x ixfn_env =-      True -- if not in the table, we assume not-transposed!-isInnerCoal (_, ixfn_env) slc_X (Let (Pat [pe]) _ (BasicOp (Index x _)))-  | slc_X == patElemName pe,-    Just lmad <- M.lookup x ixfn_env =-      innerHasStride1 lmad+  | slc_X == patElemName pe =+      -- if not in the table, we assume not-transposed!+      maybe True innerHasStride1 $ M.lookup x ixfn_env   where     innerHasStride1 lmad =       let lmad_dims = LMAD.dims lmad@@ -626,7 +622,7 @@                   ones = map (const $ intConst Int64 1) rem_outer_dims                   new_shape = Shape $ concat [ones, block_dims, ones, rest_dims]               letExp "res_reshaped" . BasicOp $-                Reshape ReshapeArbitrary new_shape epilogue_res+                Reshape epilogue_res (reshapeAll (arrayShape epilogue_t) new_shape)         pure [RegTileReturns mempty regtile_ret_dims epilogue_res'] mmBlkRegTilingNrm _ _ = pure Nothing @@ -1278,7 +1274,7 @@                     ones = map (const se1) rem_outer_dims                     new_shape = Shape $ concat [ones, block_dims, ones, rest_dims]                 letExp "res_reshaped" . BasicOp $-                  Reshape ReshapeArbitrary new_shape res+                  Reshape res (reshapeAll (arrayShape res_tp') new_shape)            pure $ map (RegTileReturns mempty regtile_ret_dims) epilogue_res'         -- END (ret_seggroup, stms_seggroup) <- runBuilder $ do@@ -1312,7 +1308,7 @@               arr_tp <- lookupType arr_nm               let perm = [i + 1 .. arrayRank arr_tp - 1] ++ [0 .. i]               let arr_tr_str = baseString arr_nm ++ "_transp"-              arr_tr_nm <- letExp arr_tr_str $ BasicOp $ Manifest perm arr_nm+              arr_tr_nm <- letExp arr_tr_str $ BasicOp $ Manifest arr_nm perm               let e_ind' = BasicOp $ Index arr_tr_nm slc               let stm' = Let patt yy e_ind'               pure (tab_inn, M.insert p_nm (ptp, stm') tab_out)
src/Futhark/Optimise/EntryPointMem.hs view
@@ -42,7 +42,7 @@   where     table = consts_table <> mkTable (bodyStms (funDefBody fd))     mkSubst (Var v0)-      | Just (MemArray _ _ _ (ArrayIn mem0 lmad0), BasicOp (Manifest _ v1)) <-+      | Just (MemArray _ _ _ (ArrayIn mem0 lmad0), BasicOp (Manifest v1 _)) <-           varInfo v0 table,         Just (MemArray _ _ _ (ArrayIn mem1 lmad1), _) <-           varInfo v1 table,
src/Futhark/Optimise/Fusion.hs view
@@ -92,8 +92,8 @@       letBindNames [output] . BasicOp . SubExp . Var =<< H.applyTransforms ots v   ResNode _ -> pure mempty   TransNode output tr ia -> do-    (cs, e) <- H.transformToExp tr ia-    runBuilder_ $ certifying cs $ letBindNames [output] e+    (aux, e) <- H.transformToExp tr ia+    runBuilder_ $ auxing aux $ letBindNames [output] e   FreeNode _ -> pure mempty   DoNode stm lst -> do     lst' <- mapM (finalizeNode . fst) lst
src/Futhark/Optimise/Fusion/GraphRep.hs view
@@ -297,7 +297,7 @@     pure $ MatchNode s []   e     | [output] <- patNames pat,-      Just (ia, tr) <- H.transformFromExp (stmAuxCerts aux) e ->+      Just (ia, tr) <- H.transformFromExp aux e ->         pure $ TransNode output tr ia   _ -> pure n nodeToSoacNode n = pure n
src/Futhark/Optimise/Fusion/RulesWithAccs.hs view
@@ -170,15 +170,16 @@     getRepRshpArr :: ((H.Input, NodeT), LParam SOACS) -> Maybe (RshpInp, Certs)     getRepRshpArr ((H.Input outtrsf arr_nm arr_tp, _nt), farg)       | rshp_trsfm H.:< other_trsfms <- H.viewf outtrsf,-        (H.Reshape c ReshapeArbitrary shp_flat) <- rshp_trsfm,+        H.Reshape aux shp_flat <- rshp_trsfm,+        ReshapeArbitrary <- reshapeKind shp_flat,         other_trsfms == mempty,         eltp <- paramDec farg,-        Just shp_flat' <- checkShp eltp shp_flat,+        Just shp_flat' <- checkShp eltp $ newShape shp_flat,         Array _ptp shp_unflat _ <- arr_tp,         Just shp_unflat' <- checkShp eltp shp_unflat,         shapeRank shp_flat' == 1,         shapeRank shp_flat' < shapeRank shp_unflat' =-          Just (((arr_nm, farg), (shp_flat', shp_unflat', eltp)), c)+          Just (((arr_nm, farg), (shp_flat', shp_unflat', eltp)), stmAuxCerts aux)     getRepRshpArr _ = Nothing     --     checkShp (Prim _) shp_arr = Just shp_arr
src/Futhark/Optimise/Fusion/TryFusion.hs view
@@ -558,7 +558,7 @@   TryFusion (SOAC, SOAC.ArrayTransforms) iswim _ (SOAC.Screma w arrs form) ots   | Just [Futhark.Scan scan_fun nes] <- Futhark.isScanSOAC form,-    Just (map_pat, map_cs, map_w, map_fun) <- rwimPossible scan_fun,+    Just (map_pat, map_aux, map_w, map_fun) <- rwimPossible scan_fun,     Just nes_names <- mapM subExpVar nes = do       let nes_idents = zipWith Ident nes_names $ lambdaReturnType scan_fun           map_nes = map SOAC.identInput nes_idents@@ -594,7 +594,7 @@        pure         ( SOAC.Screma map_w map_arrs' (mapSOAC map_fun'),-          ots SOAC.|> SOAC.Rearrange map_cs perm+          ots SOAC.|> SOAC.Rearrange map_aux perm         ) iswim _ _ _ =   fail "ISWIM does not apply."@@ -768,7 +768,7 @@ pullReshape :: SOAC -> SOAC.ArrayTransforms -> TryFusion (SOAC, SOAC.ArrayTransforms) pullReshape soac ots = do   Just mapnest <- MapNest.fromSOAC soac-  SOAC.Reshape cs _kind newshape SOAC.:< ots' <- pure $ SOAC.viewf ots+  SOAC.Reshape cs newshape SOAC.:< ots' <- pure $ SOAC.viewf ots   -- This handles only the easy case where the underlying lambda is   -- scalar. The more complicated cases could also be handled, but   -- requires more tricky checks.@@ -776,7 +776,7 @@     all       ((== MapNest.depth mapnest) . arrayRank)       (MapNest.typeOf mapnest)-  mapnest' <- MapNest.reshape cs newshape mapnest+  mapnest' <- MapNest.reshape cs (newShape newshape) mapnest   soac' <- MapNest.toSOAC mapnest'   pure (soac', ots') 
src/Futhark/Optimise/GenRedOpt.hs view
@@ -261,7 +261,7 @@         ii /= length dims - 1,         perm <- [0 .. ii - 1] ++ [ii + 1 .. length dims - 1] ++ [ii] = do           (arr_tr, stms_tr) <- runBuilderT' $ do-            arr' <- letExp (baseString arr ++ "_trsp") $ BasicOp $ Rearrange perm arr -- Manifest [1,0] arr+            arr' <- letExp (baseString arr ++ "_trsp") $ BasicOp $ Rearrange arr perm             letExp (baseString arr' ++ "_opaque") $ BasicOp $ Opaque OpaqueNil $ Var arr'           let tab' = M.insert arr (perm, arr_tr, stms_tr) tab               slc' = Slice $ map (dims !!) perm
src/Futhark/Optimise/ReduceDeviceSyncs/MigrationTable.hs view
@@ -463,10 +463,10 @@       -- Can be replaced with 'graphHostOnly e' to disable migration.       -- A fix can be verified by enabling tests/migration/reuse4_scratch.fut       graphInefficientReturn s e-    BasicOp (Reshape _ s arr) -> do-      graphInefficientReturn (shapeDims s) e+    BasicOp (Reshape arr s) -> do+      graphInefficientReturn (shapeDims $ newShape s) e       one bs `reuses` arr-    BasicOp (Rearrange _ arr) -> do+    BasicOp (Rearrange arr _) -> do       graphInefficientReturn [] e       one bs `reuses` arr     -- Expressions with a cost linear to the size of their result arrays are
src/Futhark/Optimise/Simplify/Engine.hs view
@@ -1039,7 +1039,7 @@       _ -> pure v  instance (Simplifiable d) => Simplifiable (ShapeBase d) where-  simplify = fmap Shape . simplify . shapeDims+  simplify = traverse simplify  instance Simplifiable ExtSize where   simplify (Free se) = Free <$> simplify se
src/Futhark/Optimise/Simplify/Rules/BasicOp.hs view
@@ -86,11 +86,11 @@           letExp "concat_rearrange" $             BasicOp $               Concat 0 (x' :| xs') new_d-      letBind pat $ BasicOp $ Rearrange perm concat_rearrange+      letBind pat $ BasicOp $ Rearrange concat_rearrange perm   where     transposedBy perm1 v =       case ST.lookupExp v vtable of-        Just (BasicOp (Rearrange perm2 v'), vcs)+        Just (BasicOp (Rearrange v' perm2), vcs)           | perm1 == perm2 -> Just (v', vcs)         _ -> Nothing @@ -191,9 +191,11 @@     isFullSlice (arrayShape dest_t) is = Simplify . auxing aux $       case se of         Var v | not $ null $ sliceDims is -> do+          v_t <- lookupType v           v_reshaped <-             letSubExp (baseString v ++ "_reshaped") . BasicOp $-              Reshape ReshapeArbitrary (arrayShape dest_t) v+              Reshape v $+                reshapeAll (arrayShape v_t) (arrayShape dest_t)           letBind pat $ BasicOp $ Replicate mempty v_reshaped         _ -> letBind pat $ BasicOp $ ArrayLit [se] $ rowType dest_t ruleBasicOp vtable pat (StmAux cs1 attrs _) (Update safety1 dest1 is1 (Var v1))@@ -254,29 +256,24 @@          in letBind pat $ BasicOp $ Replicate (Shape [n]) se ruleBasicOp vtable pat aux (Index idd slice)   | Just inds <- sliceIndices slice,-    Just (BasicOp (Reshape k newshape idd2), idd_cs) <- ST.lookupExp idd vtable,-    length newshape == length inds =-      Simplify $-        case k of-          ReshapeCoerce ->-            certifying idd_cs . auxing aux . letBind pat . BasicOp $-              Index idd2 slice-          ReshapeArbitrary -> do-            -- Linearise indices and map to old index space.-            oldshape <- arrayDims <$> lookupType idd2-            let new_inds =-                  reshapeIndex-                    (map pe64 oldshape)-                    (map pe64 $ shapeDims newshape)-                    (map pe64 inds)-            new_inds' <--              mapM (toSubExp "new_index") new_inds-            certifying idd_cs . auxing aux $-              letBind pat $-                BasicOp $-                  Index idd2 $-                    Slice $-                      map DimFix new_inds'+    Just (BasicOp (Reshape idd2 newshape), idd_cs) <- ST.lookupExp idd vtable,+    shapeRank (newShape newshape) == length inds = Simplify $+      case reshapeKind newshape of+        ReshapeCoerce ->+          certifying idd_cs . auxing aux . letBind pat . BasicOp $+            Index idd2 slice+        ReshapeArbitrary -> do+          -- Linearise indices and map to old index space.+          oldshape <- arrayDims <$> lookupType idd2+          let new_inds =+                reshapeIndex+                  (map pe64 oldshape)+                  (map pe64 $ shapeDims $ newShape newshape)+                  (map pe64 inds)+          new_inds' <-+            mapM (toSubExp "new_index") new_inds+          certifying idd_cs . auxing aux . letBind pat . BasicOp $+            Index idd2 (Slice $ map DimFix new_inds')  -- Copying an iota is pointless; just make it an iota instead. ruleBasicOp vtable pat aux (Replicate (Shape []) (Var v))@@ -286,18 +283,16 @@           BasicOp $             Iota n x s it -- Handle identity permutation.-ruleBasicOp _ pat _ (Rearrange perm v)+ruleBasicOp _ pat _ (Rearrange v perm)   | sort perm == perm =       Simplify $ letBind pat $ BasicOp $ SubExp $ Var v-ruleBasicOp vtable pat aux (Rearrange perm v)-  | Just (BasicOp (Rearrange perm2 e), v_cs) <- ST.lookupExp v vtable =+ruleBasicOp vtable pat aux (Rearrange v perm)+  | Just (BasicOp (Rearrange e perm2), v_cs) <- ST.lookupExp v vtable =       -- Rearranging a rearranging: compose the permutations.-      Simplify . certifying v_cs . auxing aux $-        letBind pat $-          BasicOp $-            Rearrange (perm `rearrangeCompose` perm2) e+      Simplify . certifying v_cs . auxing aux . letBind pat . BasicOp $+        Rearrange e (perm `rearrangeCompose` perm2) -- Rearranging a replicate where the outer dimension is left untouched.-ruleBasicOp vtable pat aux (Rearrange perm v1)+ruleBasicOp vtable pat aux (Rearrange v1 perm)   | Just (BasicOp (Replicate dims (Var v2)), v1_cs) <- ST.lookupExp v1 vtable,     num_dims <- shapeRank dims,     (rep_perm, rest_perm) <- splitAt num_dims perm,@@ -307,9 +302,8 @@         certifying v1_cs $           auxing aux $ do             v <--              letSubExp "rearrange_replicate" $-                BasicOp $-                  Rearrange (map (subtract num_dims) rest_perm) v2+              letSubExp "rearrange_replicate" . BasicOp $+                Rearrange v2 (map (subtract num_dims) rest_perm)             letBind pat $ BasicOp $ Replicate dims v  -- Simplify away 0<=i when 'i' is from a loop of form 'for i < n'.@@ -357,15 +351,55 @@       Simplify . auxing aux $ letBind pat $ BasicOp $ SubExp $ Var acc -- Manifest of a a copy (or another Manifest) can be simplified to -- manifesting the original array, if it is still available.-ruleBasicOp vtable pat aux (Manifest perm v1)+ruleBasicOp vtable pat aux (Manifest v1 perm)   | Just (Replicate (Shape []) (Var v2), cs) <- ST.lookupBasicOp v1 vtable,     ST.available v2 vtable =       Simplify . auxing aux . certifying cs . letBind pat . BasicOp $-        Manifest perm v2-  | Just (Manifest _ v2, cs) <- ST.lookupBasicOp v1 vtable,+        Manifest v2 perm+  | Just (Manifest v2 _, cs) <- ST.lookupBasicOp v1 vtable,     ST.available v2 vtable =       Simplify . auxing aux . certifying cs . letBind pat . BasicOp $-        Manifest perm v2+        Manifest v2 perm+ruleBasicOp vtable pat aux (Reshape v2 v3_shape)+  | ReshapeArbitrary <- reshapeKind v3_shape,+    Just (Rearrange v1 perm, v2_cs) <- ST.lookupBasicOp v2 vtable,+    Just (Reshape v0 v1_shape, v1_cs) <- ST.lookupBasicOp v1 vtable,+    ReshapeArbitrary <- reshapeKind v1_shape,+    Just v0_shape <- arrayShape <$> ST.lookupType v0 vtable =+      case ( flipReshapeRearrange (shapeDims v0_shape) (shapeDims (newShape v1_shape)) perm,+             flipRearrangeReshape perm v3_shape+           ) of+        (Just perm', _) -> Simplify $ do+          v1' <- letExp (baseString v1) $ BasicOp $ Rearrange v0 perm'+          v1_shape' <- arrayShape <$> lookupType v1'+          auxing aux . certifying (v1_cs <> v2_cs) . letBind pat $+            BasicOp (Reshape v1' (reshapeAll v1_shape' (newShape v3_shape)))+        (_, Just (v3_shape', perm')) -> Simplify $ do+          v2' <-+            auxing aux . certifying (v1_cs <> v2_cs) . letExp (baseString v2) $+              BasicOp (Reshape v1 v3_shape')+          letBind pat $ BasicOp (Rearrange v2' perm')+        _ ->+          Skip+-- Reshaping or transposing a copy is almost always better done by copying the+-- result instead, because that improves the likelihood that the copy will be+-- eliminated.+ruleBasicOp vtable pat aux (Reshape v2 newshape)+  | Just (Replicate (Shape []) (Var v1), cs) <- ST.lookupBasicOp v2 vtable,+    ST.available v1 vtable =+      Simplify $ do+        v1' <-+          certifying cs . auxing aux . letExp (baseString v1) . BasicOp $+            Reshape v1 newshape+        letBind pat $ BasicOp $ Replicate (Shape []) (Var v1')+ruleBasicOp vtable pat aux (Rearrange v2 perm)+  | Just (Replicate (Shape []) (Var v1), cs) <- ST.lookupBasicOp v2 vtable,+    ST.available v1 vtable =+      Simplify $ do+        v1' <-+          certifying cs . auxing aux . letExp (baseString v1) . BasicOp $+            Rearrange v1 perm+        letBind pat $ BasicOp $ Replicate (Shape []) (Var v1') ruleBasicOp _ _ _ _ =   Skip 
src/Futhark/Optimise/Simplify/Rules/Index.hs view
@@ -56,6 +56,18 @@   Maybe (m IndexResult) simplifyIndexing vtable seType idd (Slice inds) consuming consumed =   case defOf idd of+    -- FIXME: This is a special case to avoid simplifying away a slice of a+    -- rearrange. This is because register tiling cannot otherwise properly+    -- detect what is going on.+    Just (Rearrange src perm, cs)+      | rearrangeReach perm <= length (takeWhile isIndex inds) ->+          let inds' = rearrangeShape (rearrangeInverse perm) inds+           in Just $ pure $ IndexResult cs src $ Slice inds'+      | any isIndex inds ->+          Nothing+      where+        isIndex DimFix {} = True+        isIndex _ = False     _       | Just t <- seType (Var idd),         Slice inds == fullSlice t [] ->@@ -76,6 +88,7 @@               <$> mapM (toSubExp "index_primexp") inds''       | Just (ST.IndexedArray cs arr inds'') <-           ST.index' idd (fixSlice (pe64 <$> Slice inds) (map fst matches)) vtable,+        length inds == length inds'',         all (worthInlining . untyped) inds'',         arr `ST.available` vtable,         all (`ST.elem` vtable) (unCerts cs),@@ -92,7 +105,7 @@                     =<< sequence inds'''               arr_sliced_tr <-                 letSubExp (baseString arr_sliced <> "_tr") $-                  BasicOp (Rearrange perm arr_sliced)+                  BasicOp (Rearrange arr_sliced perm)               pure $ SubExpResult mempty arr_sliced_tr       where         matches = zip fakeIndices $ zip [0 :: Int ..] $ sliceDims $ Slice inds@@ -164,13 +177,6 @@       where         index DimFix {} = Nothing         index (DimSlice _ n s) = Just (n, DimSlice (constant (0 :: Int64)) n s)-    Just (Rearrange perm src, cs)-      | rearrangeReach perm <= length (takeWhile isIndex inds) ->-          let inds' = rearrangeShape (rearrangeInverse perm) inds-           in Just $ pure $ IndexResult cs src $ Slice inds'-      where-        isIndex DimFix {} = True-        isIndex _ = False     Just (Replicate (Shape []) (Var src), cs)       | Just dims <- arrayDims <$> seType (Var src),         length inds == length dims,@@ -184,17 +190,19 @@         not consuming,         ST.available src vtable ->           Just $ pure $ IndexResult cs src $ Slice inds-    Just (Reshape ReshapeCoerce newshape src, cs)-      | Just olddims <- arrayDims <$> seType (Var src),-        changed_dims <- zipWith (/=) (shapeDims newshape) olddims,+    Just (Reshape src newshape, cs)+      | ReshapeCoerce <- reshapeKind newshape,+        Just olddims <- arrayDims <$> seType (Var src),+        changed_dims <- zipWith (/=) (shapeDims (newShape newshape)) olddims,         not $ or $ drop (length inds) changed_dims ->           Just $ pure $ IndexResult cs src $ Slice inds       | Just olddims <- arrayDims <$> seType (Var src),         length newshape == length inds,-        length olddims == length (shapeDims newshape) ->+        length olddims == length (shapeDims (newShape newshape)) ->           Just $ pure $ IndexResult cs src $ Slice inds-    Just (Reshape _ (Shape [_]) v2, cs)-      | Just [_] <- arrayDims <$> seType (Var v2) ->+    Just (Reshape v2 newshape, cs)+      | Shape [_] <- newShape newshape,+        Just [_] <- arrayDims <$> seType (Var v2) ->           Just $ pure $ IndexResult cs v2 $ Slice inds     Just (Concat d (x :| xs) _, cs)       | -- HACK: simplifying the indexing of an N-array concatenation
src/Futhark/Optimise/Simplify/Rules/Simple.hs view
@@ -268,54 +268,45 @@ simplifyAssert _ _ _ =   Nothing --- No-op reshape.-simplifyIdentityReshape :: SimpleRule rep-simplifyIdentityReshape _ seType (Reshape _ newshape v)+simplifyReshape :: SimpleRule rep+simplifyReshape defOf seType (Reshape v newshape)+  -- No-op reshape   | Just t <- seType $ Var v,-    newshape == arrayShape t =+    newShape newshape == arrayShape t =       resIsSubExp $ Var v-simplifyIdentityReshape _ _ _ = Nothing--simplifyReshapeReshape :: SimpleRule rep-simplifyReshapeReshape defOf _ (Reshape k1 newshape v)-  | Just (BasicOp (Reshape k2 _ v2), v_cs) <- defOf v =-      Just (Reshape (max k1 k2) newshape v2, v_cs)-simplifyReshapeReshape _ _ _ = Nothing--simplifyReshapeScratch :: SimpleRule rep-simplifyReshapeScratch defOf _ (Reshape _ newshape v)+  -- Simplifying a reshape+  | Just shape <- arrayShape <$> seType (Var v),+    Just newshape' <- simplifyNewShape shape newshape =+      Just (Reshape v newshape', mempty)+  -- Reshape-of-reshape+  | Just (BasicOp (Reshape v2 oldnewshape), v_cs) <- defOf v =+      Just (Reshape v2 (oldnewshape <> newshape), v_cs)+  -- Reshape-of-scratch   | Just (BasicOp (Scratch bt _), v_cs) <- defOf v =-      Just (Scratch bt $ shapeDims newshape, v_cs)-simplifyReshapeScratch _ _ _ = Nothing--simplifyReshapeReplicate :: SimpleRule rep-simplifyReshapeReplicate defOf seType (Reshape _ newshape v)+      Just (Scratch bt $ shapeDims $ newShape newshape, v_cs)+  -- Reshape-of-replicate   | Just (BasicOp (Replicate _ se), v_cs) <- defOf v,     Just oldshape <- arrayShape <$> seType se,-    shapeDims oldshape `isSuffixOf` shapeDims newshape =+    newshape' <- newShape newshape,+    shapeDims oldshape `isSuffixOf` shapeDims newshape' =       let new =-            take (length newshape - shapeRank oldshape) $-              shapeDims newshape+            take (shapeRank newshape' - shapeRank oldshape) $+              shapeDims newshape'        in Just (Replicate (Shape new) se, v_cs)-simplifyReshapeReplicate _ _ _ = Nothing--simplifyReshapeIota :: SimpleRule rep-simplifyReshapeIota defOf _ (Reshape _ newshape v)+  -- Reshape-of-iota   | Just (BasicOp (Iota _ offset stride it), v_cs) <- defOf v,-    [n] <- shapeDims newshape =+    [n] <- shapeDims (newShape newshape) =       Just (Iota n offset stride it, v_cs)-simplifyReshapeIota _ _ _ = Nothing--simplifyReshapeConcat :: SimpleRule rep-simplifyReshapeConcat defOf seType (Reshape ReshapeCoerce newshape v) = do-  (BasicOp (Concat d arrs _), v_cs) <- defOf v-  (bef, w', aft) <- focusNth d $ shapeDims newshape-  (arr_bef, _, arr_aft) <--    focusNth d <=< fmap arrayDims $ seType $ Var $ NE.head arrs-  guard $ arr_bef == bef-  guard $ arr_aft == aft-  Just (Concat d arrs w', v_cs)-simplifyReshapeConcat _ _ _ = Nothing+  -- Reshape-of-concat+  | ReshapeCoerce <- reshapeKind newshape = do+      (BasicOp (Concat d arrs _), v_cs) <- defOf v+      (bef, w', aft) <- focusNth d $ shapeDims $ newShape newshape+      (arr_bef, _, arr_aft) <-+        focusNth d <=< fmap arrayDims $ seType $ Var $ NE.head arrs+      guard $ arr_bef == bef+      guard $ arr_aft == aft+      Just (Concat d arrs w', v_cs)+simplifyReshape _ _ _ = Nothing  reshapeSlice :: [DimIndex d] -> [d] -> [DimIndex d] reshapeSlice (DimFix i : slice') scs =@@ -327,9 +318,10 @@ -- If we are size-coercing a slice, then we might as well just use a -- different slice instead. simplifyReshapeIndex :: SimpleRule rep-simplifyReshapeIndex defOf _ (Reshape ReshapeCoerce newshape v)-  | Just (BasicOp (Index v' slice), v_cs) <- defOf v,-    slice' <- Slice $ reshapeSlice (unSlice slice) $ shapeDims newshape,+simplifyReshapeIndex defOf _ (Reshape v newshape)+  | ReshapeCoerce <- reshapeKind newshape,+    Just (BasicOp (Index v' slice), v_cs) <- defOf v,+    slice' <- Slice $ reshapeSlice (unSlice slice) $ shapeDims $ newShape newshape,     slice' /= slice =       Just (Index v' slice', v_cs) simplifyReshapeIndex _ _ _ = Nothing@@ -338,7 +330,8 @@ -- instead use the original array and update the slice dimensions. simplifyUpdateReshape :: SimpleRule rep simplifyUpdateReshape defOf seType (Update safety dest slice (Var v))-  | Just (BasicOp (Reshape ReshapeCoerce _ v'), v_cs) <- defOf v,+  | Just (BasicOp (Reshape v' newshape), v_cs) <- defOf v,+    ReshapeCoerce <- reshapeKind newshape,     Just ds <- arrayDims <$> seType (Var v'),     slice' <- Slice $ reshapeSlice (unSlice slice) ds,     slice' /= slice =@@ -357,9 +350,9 @@       case defOf v of         Just (BasicOp Scratch {}, cs) ->           Just cs-        Just (BasicOp (Rearrange _ v'), cs) ->+        Just (BasicOp (Rearrange v' _), cs) ->           (cs <>) <$> isActuallyScratch v'-        Just (BasicOp (Reshape _ _ v'), cs) ->+        Just (BasicOp (Reshape v' _), cs) ->           (cs <>) <$> isActuallyScratch v'         _ -> Nothing repScratchToScratch _ _ _ =@@ -373,12 +366,7 @@     simplifyConvOp,     simplifyAssert,     repScratchToScratch,-    simplifyIdentityReshape,-    simplifyReshapeReshape,-    simplifyReshapeScratch,-    simplifyReshapeReplicate,-    simplifyReshapeIota,-    simplifyReshapeConcat,+    simplifyReshape,     simplifyReshapeIndex,     simplifyUpdateReshape   ]
src/Futhark/Optimise/TileLoops.hs view
@@ -31,7 +31,7 @@     onStms scope stms =       modifyNameSource $         runState $-          runReaderT (optimiseStms (M.empty, M.empty) stms) scope+          runReaderT (optimiseStms (M.empty, initialIxFnEnv scope) stms) scope  optimiseBody :: Env -> Body GPU -> TileM (Body GPU) optimiseBody env (Body () stms res) =@@ -741,7 +741,7 @@       else do         let new_shape = Shape $ unit_dims ++ arrayDims arr_t         letExp (baseString arr) . BasicOp $-          Reshape ReshapeArbitrary new_shape arr+          Reshape arr (reshapeAll (arrayShape arr_t) new_shape)   let tile_dims = zip (map snd dims_on_top) unit_dims ++ dims   pure $ TileReturns mempty tile_dims arr' 
src/Futhark/Optimise/TileLoops/Shared.hs view
@@ -13,6 +13,7 @@     varianceInStms,     isTileableRedomap,     changeEnv,+    initialIxFnEnv,     TileKind (..),   ) where@@ -275,6 +276,16 @@   ixfn_env' <- changeIxFnEnv ixfn_env y e   pure (with_env', ixfn_env') +-- | Construct an initial 'IxFnEnv' where it is assumed that every array+-- parameter in the scope has a row-major index function.+initialIxFnEnv :: Scope GPU -> IxFnEnv+initialIxFnEnv = M.mapMaybe f+  where+    f info =+      case typeOf info of+        Array _ shape _ -> Just $ LMAD.iota 0 $ map pe64 $ shapeDims shape+        _ -> Nothing+ changeWithEnv :: WithEnv -> Exp GPU -> TileM WithEnv changeWithEnv with_env (WithAcc accum_decs inner_lam) = do   let bindings = map mapfun accum_decs@@ -302,11 +313,13 @@         _ -> env  changeIxFnEnv :: IxFnEnv -> VName -> Exp GPU -> TileM IxFnEnv-changeIxFnEnv env y (BasicOp (Reshape ReshapeArbitrary shp_chg x)) =-  composeIxfuns env y x (`LMAD.reshape` fmap ExpMem.pe64 (shapeDims shp_chg))-changeIxFnEnv env y (BasicOp (Reshape ReshapeCoerce shp_chg x)) =-  composeIxfuns env y x (Just . (`LMAD.coerce` fmap ExpMem.pe64 (shapeDims shp_chg)))-changeIxFnEnv env y (BasicOp (Manifest perm x)) = do+changeIxFnEnv env y (BasicOp (Reshape x shp_chg)) =+  case reshapeKind shp_chg of+    ReshapeCoerce ->+      composeIxfuns env y x (Just . (`LMAD.coerce` fmap ExpMem.pe64 (shapeDims $ newShape shp_chg)))+    ReshapeArbitrary ->+      composeIxfuns env y x (`LMAD.reshape` fmap ExpMem.pe64 (shapeDims $ newShape shp_chg))+changeIxFnEnv env y (BasicOp (Manifest x perm)) = do   tp <- lookupType x   case tp of     Array _ptp shp _u -> do@@ -314,7 +327,7 @@       let ixfn = LMAD.permute (LMAD.iota 0 shp') perm       pure $ M.insert y ixfn env     _ -> error "In TileLoops/Shared.hs, changeIxFnEnv: manifest applied to a non-array!"-changeIxFnEnv env y (BasicOp (Rearrange perm x)) =+changeIxFnEnv env y (BasicOp (Rearrange x perm)) =   composeIxfuns env y x (Just . (`LMAD.permute` perm)) changeIxFnEnv env y (BasicOp (Index x slc)) =   composeIxfuns env y x (Just . (`LMAD.slice` Slice (map (fmap ExpMem.pe64) $ unSlice slc)))
src/Futhark/Pass/ExplicitAllocations.hs view
@@ -177,11 +177,11 @@   (Allocable fromrep torep inner) =>   Exp torep ->   AllocM fromrep torep (Exp torep)-repairExpression (BasicOp (Reshape k shape v)) = do+repairExpression (BasicOp (Reshape v shape)) = do   v_mem <- fst <$> lookupArraySummary v   space <- lookupMemSpace v_mem   v' <- snd <$> ensureDirectArray (Just space) v-  pure $ BasicOp $ Reshape k shape v'+  pure $ BasicOp $ Reshape v' shape repairExpression e =   error $ "repairExpression:\n" <> prettyString e @@ -535,7 +535,7 @@             MemArray pt shape u . ArrayIn mem $               LMAD.permute (LMAD.iota 0 $ map pe64 $ arrayDims t) perm           pat = Pat [PatElem v' info]-      addStm $ Let pat (defAux ()) $ BasicOp $ Manifest perm v+      addStm $ Let pat (defAux ()) $ BasicOp $ Manifest v perm       pure (mem, v')     _ ->       error $ "allocPermArray: " ++ prettyString t
src/Futhark/Pass/ExplicitAllocations/GPU.hs view
@@ -97,7 +97,7 @@   fmap (Inner . GPUBody ts) . buildBody_ . allocInStms stms $ pure res  kernelExpHints :: Exp GPUMem -> AllocM GPU GPUMem [ExpHint]-kernelExpHints (BasicOp (Manifest perm v)) = do+kernelExpHints (BasicOp (Manifest v perm)) = do   dims <- arrayDims <$> lookupType v   let perm_inv = rearrangeInverse perm       dims' = rearrangeShape perm dims
src/Futhark/Pass/ExtractKernels/DistributeNests.hs view
@@ -576,14 +576,14 @@         -- Move the to-be-replicated dimensions outermost.         arr_tr <-           letExp (baseString arr <> "_tr") . BasicOp $-            Rearrange ([nest_r .. arr_r - 1] ++ [0 .. nest_r - 1]) arr+            Rearrange arr ([nest_r .. arr_r - 1] ++ [0 .. nest_r - 1])         -- Replicate the now-outermost dimensions appropriately.         arr_tr_rep <-           letExp (baseString arr <> "_tr_rep") . BasicOp $             Replicate shape (Var arr_tr)         -- Move the replicated dimensions back where they belong.         letBind outerpat . BasicOp $-          Rearrange ([res_r - nest_r .. res_r - 1] ++ [0 .. res_r - nest_r - 1]) arr_tr_rep+          Rearrange arr_tr_rep ([res_r - nest_r .. res_r - 1] ++ [0 .. res_r - nest_r - 1]) maybeDistributeStm stm@(Let _ aux (BasicOp (Replicate shape v))) acc = do   distributeSingleStm acc stm >>= \case     Just (kernels, _, nest, acc')@@ -602,7 +602,7 @@   | not $ primType $ typeOf pe =       distributeSingleUnaryStm acc stm stm_arr $ \_ outerpat arr ->         pure $ oneStm $ Let outerpat aux $ BasicOp $ Replicate mempty $ Var arr-maybeDistributeStm stm@(Let _ aux (BasicOp (Rearrange perm stm_arr))) acc =+maybeDistributeStm stm@(Let _ aux (BasicOp (Rearrange stm_arr perm))) acc =   distributeSingleUnaryStm acc stm stm_arr $ \nest outerpat arr -> do     let r = length (snd nest) + 1         perm' = [0 .. r - 1] ++ map (+ r) perm@@ -613,12 +613,13 @@     pure $       stmsFromList         [ Let (Pat [PatElem arr' arr_t]) aux $ BasicOp $ Replicate mempty $ Var arr,-          Let outerpat aux $ BasicOp $ Rearrange perm' arr'+          Let outerpat aux $ BasicOp $ Rearrange arr' perm'         ]-maybeDistributeStm stm@(Let _ aux (BasicOp (Reshape k reshape stm_arr))) acc =+maybeDistributeStm stm@(Let _ aux (BasicOp (Reshape stm_arr reshape))) acc =   distributeSingleUnaryStm acc stm stm_arr $ \nest outerpat arr -> do-    let reshape' = Shape (kernelNestWidths nest) <> reshape-    pure $ oneStm $ Let outerpat aux $ BasicOp $ Reshape k reshape' arr+    let outer = Shape (kernelNestWidths nest)+        reshape' = reshapeCoerce outer <> newshapeInner outer reshape+    pure $ oneStm $ Let outerpat aux $ BasicOp $ Reshape arr reshape' maybeDistributeStm stm@(Let pat aux (BasicOp (Update _ arr slice (Var v)))) acc   | not $ null $ sliceDims slice =       distributeSingleStm acc stm >>= \case
src/Futhark/Pass/ExtractKernels/ISRWIM.hs view
@@ -24,7 +24,7 @@   [(SubExp, VName)] ->   Maybe (m ()) iswim res_pat w scan_fun scan_input-  | Just (map_pat, map_cs, map_w, map_fun) <- rwimPossible scan_fun = Just $ do+  | Just (map_pat, map_aux, map_w, map_fun) <- rwimPossible scan_fun = Just $ do       let (accs, arrs) = unzip scan_input       arrs' <- transposedArrays arrs       accs' <- mapM (letExp "acc" . BasicOp . SubExp) accs@@ -65,18 +65,14 @@           mapM (newIdent' (<> "_transposed") . transposeIdentType) $             patIdents res_pat -      addStm $-        Let res_pat' (StmAux map_cs mempty ()) $-          Op $-            Screma map_w map_arrs' (mapSOAC map_fun')+      addStm . Let res_pat' map_aux . Op $+        Screma map_w map_arrs' (mapSOAC map_fun')        forM_ (zip (patIdents res_pat) (patIdents res_pat')) $ \(to, from) -> do         let perm = [1, 0] ++ [2 .. arrayRank (identType from) - 1]         addStm $-          Let (basicPat [to]) (defAux ()) $-            BasicOp $-              Rearrange perm $-                identName from+          Let (basicPat [to]) (defAux ()) . BasicOp $+            Rearrange (identName from) perm   | otherwise = Nothing  -- | Interchange Reduce With Inner Map. Tries to turn a @reduce(map)@ into a@@ -90,7 +86,7 @@   [(SubExp, VName)] ->   Maybe (m ()) irwim res_pat w comm red_fun red_input-  | Just (map_pat, map_cs, map_w, map_fun) <- rwimPossible red_fun = Just $ do+  | Just (map_pat, map_aux, map_w, map_fun) <- rwimPossible red_fun = Just $ do       let (accs, arrs) = unzip red_input       arrs' <- transposedArrays arrs       -- FIXME?  Can we reasonably assume that the accumulator is a@@ -136,18 +132,15 @@        let map_fun' = Lambda map_params map_rettype map_body -      addStm $-        Let res_pat (StmAux map_cs mempty ()) $-          Op $-            Screma map_w arrs' $-              mapSOAC map_fun'+      addStm . Let res_pat map_aux . Op . Screma map_w arrs' $+        mapSOAC map_fun'   | otherwise = Nothing  -- | Does this reduce operator contain an inner map, and if so, what -- does that map look like? rwimPossible ::   Lambda SOACS ->-  Maybe (Pat Type, Certs, SubExp, Lambda SOACS)+  Maybe (Pat Type, StmAux (), SubExp, Lambda SOACS) rwimPossible fun   | Body _ stms res <- lambdaBody fun,     [stm] <- stmsToList stms, -- Body has a single binding@@ -156,7 +149,7 @@     Op (Screma map_w map_arrs form) <- stmExp stm,     Just map_fun <- isMapSOAC form,     map paramName (lambdaParams fun) == map_arrs =-      Just (map_pat, stmCerts stm, map_w, map_fun)+      Just (map_pat, stmAux stm, map_w, map_fun)   | otherwise =       Nothing @@ -164,7 +157,7 @@ transposedArrays arrs = forM arrs $ \arr -> do   t <- lookupType arr   let perm = [1, 0] ++ [2 .. arrayRank t - 1]-  letExp (baseString arr) $ BasicOp $ Rearrange perm arr+  letExp (baseString arr) $ BasicOp $ Rearrange arr perm  removeParamOuterDim :: LParam SOACS -> LParam SOACS removeParamOuterDim param =
src/Futhark/Pass/LiftAllocations.hs view
@@ -13,6 +13,7 @@ where  import Control.Monad.Reader+import Data.Map qualified as M import Data.Sequence (Seq (..)) import Futhark.Analysis.Alias (aliasAnalysis) import Futhark.IR.Aliases@@ -32,7 +33,7 @@     }   where     onFun f = f {funDefBody = onBody (funDefBody f)}-    onBody body = runReader (liftAllocationsInBody body) (Env onOp)+    onBody body = runReader (liftAllocationsInBody body) (Env onOp mempty)  liftAllocationsSeqMem :: Pass SeqMem SeqMem liftAllocationsSeqMem =@@ -49,8 +50,10 @@   Pass "lift allocations mc" "lift allocations mc" $     pure . liftInProg liftAllocationsInMCOp -newtype Env inner = Env-  {onInner :: inner -> LiftM inner inner}+data Env inner = Env+  { onInner :: inner -> LiftM inner inner,+    envAliases :: AliasesAndConsumed+  }  type LiftM inner a = Reader (Env inner) a @@ -59,7 +62,7 @@   Body rep ->   LiftM (inner rep) (Body rep) liftAllocationsInBody body = do-  stms <- liftAllocationsInStms (bodyStms body) mempty mempty mempty+  stms <- liftAllocationsInStms (bodyStms body)   pure $ body {bodyStms = stms}  liftInsideStm ::@@ -80,54 +83,65 @@ liftInsideStm stm = pure stm  liftAllocationsInStms ::+  forall rep inner.   (Mem rep inner, Aliased rep) =>-  -- | The input stms   Stms rep ->-  -- | The lifted allocations and associated statements-  Stms rep ->-  -- | The other statements processed so far-  Stms rep ->-  -- | (Names we need to lift, consumed names)-  (Names, Names) ->   LiftM (inner rep) (Stms rep)-liftAllocationsInStms Empty lifted acc _ = pure $ lifted <> acc-liftAllocationsInStms (stms :|> stm) lifted acc (to_lift, consumed) = do-  stm' <- liftInsideStm stm-  case stmExp stm' of-    BasicOp Assert {} -> liftStm stm'-    Op Alloc {} -> liftStm stm'-    _ -> do-      let pat_names = namesFromList $ patNames $ stmPat stm'-      if (pat_names `namesIntersect` to_lift)-        || namesIntersect consumed (freeIn stm)-        then liftStm stm'-        else dontLiftStm stm'-  where-    liftStm stm' =-      liftAllocationsInStms stms (stm' :<| lifted) acc (to_lift', consumed')-      where-        to_lift' =-          freeIn stm'-            <> (to_lift `namesSubtract` namesFromList (patNames (stmPat stm')))-        consumed' = consumed <> consumedInStm stm'-    dontLiftStm stm' =-      liftAllocationsInStms stms lifted (stm' :<| acc) (to_lift, consumed)+liftAllocationsInStms stms_orig = do+  outer_aliases <- asks envAliases+  let aliases = foldl trackAliases outer_aliases stms_orig+      go ::+        -- The input stms+        Stms rep ->+        -- The lifted allocations and associated statements+        Stms rep ->+        -- The other statements processed so far+        Stms rep ->+        -- (Names we need to lift, consumed names)+        (Names, Names) ->+        LiftM (inner rep) (Stms rep)+      go Empty lifted acc _ = pure $ lifted <> acc+      go (stms :|> stm) lifted acc (to_lift, consumed) = do+        stm' <- liftInsideStm stm+        case stmExp stm' of+          BasicOp Assert {} -> liftStm stm'+          Op Alloc {} -> liftStm stm'+          _ -> do+            let pat_names = namesFromList $ patNames $ stmPat stm'+                free_in_stm = freeIn stm+                expand v = maybe [v] namesToList $ M.lookup v $ fst aliases+            if (pat_names `namesIntersect` to_lift)+              || any (`nameIn` free_in_stm) (foldMap expand $ namesToList consumed)+              then liftStm stm'+              else dontLiftStm stm'+        where+          liftStm stm' =+            go stms (stm' :<| lifted) acc (to_lift', consumed')+            where+              to_lift' =+                freeIn stm'+                  <> (to_lift `namesSubtract` namesFromList (patNames (stmPat stm')))+              consumed' = consumed <> consumedInStm stm'+          dontLiftStm stm' =+            go stms lifted (stm' :<| acc) (to_lift, consumed)+  local (\env -> env {envAliases = aliases}) $+    go stms_orig mempty mempty mempty  liftAllocationsInSegOp ::   (Mem rep inner, Aliased rep) =>   SegOp lvl rep ->   LiftM (inner rep) (SegOp lvl rep) liftAllocationsInSegOp (SegMap lvl sp tps body) = do-  stms <- liftAllocationsInStms (kernelBodyStms body) mempty mempty mempty+  stms <- liftAllocationsInStms (kernelBodyStms body)   pure $ SegMap lvl sp tps $ body {kernelBodyStms = stms} liftAllocationsInSegOp (SegRed lvl sp tps body binops) = do-  stms <- liftAllocationsInStms (kernelBodyStms body) mempty mempty mempty+  stms <- liftAllocationsInStms (kernelBodyStms body)   pure $ SegRed lvl sp tps (body {kernelBodyStms = stms}) binops liftAllocationsInSegOp (SegScan lvl sp tps body binops) = do-  stms <- liftAllocationsInStms (kernelBodyStms body) mempty mempty mempty+  stms <- liftAllocationsInStms (kernelBodyStms body)   pure $ SegScan lvl sp tps (body {kernelBodyStms = stms}) binops liftAllocationsInSegOp (SegHist lvl sp tps body histops) = do-  stms <- liftAllocationsInStms (kernelBodyStms body) mempty mempty mempty+  stms <- liftAllocationsInStms (kernelBodyStms body)   pure $ SegHist lvl sp tps (body {kernelBodyStms = stms}) histops  liftAllocationsInHostOp ::
src/Futhark/Tools.hs view
@@ -146,8 +146,8 @@   -- Finally, the array parameters are set to the arrays (but reshaped   -- to make the types work out; this will be simplified rapidly).   forM_ (zip arr_params arrs) $ \(p, arr) ->-    letBindNames [paramName p] . BasicOp $-      Reshape ReshapeCoerce (arrayShape $ paramType p) arr+    letBindNames [paramName p] $+      shapeCoerce (arrayDims $ paramType p) arr    -- Then we just inline the lambda body.   mapM_ addStm $ bodyStms $ lambdaBody lam@@ -159,7 +159,7 @@     certifying cs $ case (arrayDims $ patElemType pe, se) of       (dims, Var v)         | not $ null dims ->-            letBindNames [patElemName pe] $ BasicOp $ Reshape ReshapeCoerce (Shape dims) v+            letBindNames [patElemName pe] $ shapeCoerce dims v       _ -> letBindNames [patElemName pe] $ BasicOp $ SubExp se  -- | Split the parameters of a stream reduction lambda into the chunk
src/Futhark/Transform/Substitute.hs view
@@ -142,8 +142,10 @@   substituteNames _ = id  instance (Substitute d) => Substitute (ShapeBase d) where-  substituteNames substs (Shape es) =-    Shape $ map (substituteNames substs) es+  substituteNames substs = fmap (substituteNames substs)++instance (Substitute d) => Substitute (NewShape d) where+  substituteNames substs = fmap (substituteNames substs)  instance (Substitute d) => Substitute (Ext d) where   substituteNames substs (Free x) = Free $ substituteNames substs x
src/Language/Futhark/Interpreter.hs view
@@ -161,12 +161,7 @@   pure x  extEnv :: EvalM Env-extEnv = valEnv . M.map f <$> getExts-  where-    f v =-      ( Nothing,-        v-      )+extEnv = valEnv . M.map (Nothing,) <$> getExts  valueStructType :: ValueType -> StructType valueStructType = first $ flip sizeFromInteger mempty . toInteger@@ -181,7 +176,7 @@   pretty (SizeClosure _ e) = pretty e  instance Pretty (F.Shape SizeClosure) where-  pretty = mconcat . map (braces . pretty) . shapeDims+  pretty = mconcat . map (brackets . pretty) . shapeDims  -- | A type where the sizes are unevaluated expressions. type EvalType = TypeBase SizeClosure NoUniqueness@@ -337,8 +332,9 @@ lookupInEnv onEnv qv env = f env $ qualQuals qv   where     f m (q : qs) =-      case M.lookup q $ envTerm m of-        Just (TermModule (Module mod)) -> f mod qs+      case (M.lookup (qualLeaf qv) $ onEnv m, M.lookup q $ envTerm m) of+        (Just x, _) -> Just x+        (Nothing, Just (TermModule (Module mod))) -> f mod qs         _ -> Nothing     f m [] = M.lookup (qualLeaf qv) $ onEnv m @@ -646,7 +642,7 @@           "Index ["             <> T.intercalate ", " (map prettyText is)             <> "] out of bounds for array of shape "-            <> prettyText (valueShape arr)+            <> prettyText (arrayValueShape arr)             <> "."   maybe oob pure $ indexArray is arr @@ -705,7 +701,7 @@       let free = fvVars $ freeInExp e        in not $ any (`S.member` bound) free || any (`S.member` outer_bound) free --- | Evaluate all sizes, and it better work. This implies it must be a+-- | Evaluate all sizes, and it better work. This implies it must not be a -- size-dependent function type, or one that has existentials. evalTypeFully :: EvalType -> EvalM ValueType evalTypeFully t = do@@ -755,7 +751,7 @@         env'' <- linkMissingSizes missing_sizes p v <$> matchPat env' p v         etaExpand (v : vs) env'' rt     etaExpand vs env' _ = do-      f <- localExts $ eval env' body+      f <- eval env' body       foldM (apply noLoc mempty) f $ reverse vs evalFunction env missing_sizes (p : ps) body rettype =   pure . ValueFun $ \v -> do@@ -1207,7 +1203,14 @@       let res_env = case res_mod of             Module x -> x             _ -> mempty-      pure (f_env <> e_env <> res_env, res_mod)+      -- The following environment handles the case where rsubst refers to names+      -- that are not actually defined in the module itself, but merely+      -- inherited from an outer environment (see #2273).+      let env_substs = (`Env` mempty) $ M.fromList $ do+            (to, from) <- M.toList rsubst+            x <- maybeToList $ M.lookup from $ envTerm env+            pure (to, x)+      pure (f_env <> e_env <> res_env <> env_substs, res_mod)     _ -> error "Expected ModuleFun."  evalDec :: Env -> Dec -> EvalM Env
src/Language/Futhark/Interpreter/Values.hs view
@@ -12,6 +12,7 @@     -- * Values     Value (..),     valueShape,+    arrayValueShape,     prettyValue,     valueText,     valueAccum,@@ -194,6 +195,15 @@ valueShape (ValueRecord fs) = ShapeRecord $ M.map valueShape fs valueShape (ValueSum shape _ _) = shape valueShape _ = ShapeLeaf++-- | Retrieve the part of the value shape that corresponds to outer array+-- dimensions. This is used for reporting shapes in those cases where the full+-- shape is not important, namely in indexing errors.+arrayValueShape :: Value m -> ValueShape+arrayValueShape = outer . valueShape+  where+    outer (ShapeDim d s) = ShapeDim d $ outer s+    outer _ = ShapeLeaf  -- TODO: Perhaps there is some clever way to reuse the code between -- valueAccum and valueAccumLM
src/Language/Futhark/Parser/Parser.y view
@@ -239,7 +239,7 @@         | ModTypeExp '->' ModTypeExp  { ModTypeArrow Nothing $1 $3 (srcspan $1 $>) }  TypeRef :: { TypeRefBase NoInfo Name }-         : QualName TypeParams '=' TypeExpTerm+         : QualName TypeParams '=' TypeExp            { TypeRef (fst $1) $2 $4 (srcspan (snd $1) $>) }  ModTypeBind :: { ModTypeBindBase NoInfo Name }@@ -301,6 +301,8 @@           in ValSpec name $3 $5 NoInfo Nothing (srcspan $1 $>) }       | val BindingBinOp TypeParams ':' TypeExp         { ValSpec $2 $3 $5 NoInfo Nothing (srcspan $1 $>) }+      | val '(' BindingBinOp ')' TypeParams ':' TypeExp+        { ValSpec $3 $5 $7 NoInfo Nothing (srcspan $1 $>) }       | TypeAbbr         { TypeAbbrSpec $1 } 
src/Language/Futhark/Pretty.hs view
@@ -6,6 +6,7 @@   ( prettyString,     prettyTuple,     leadingOperator,+    symbolName,     IsName (..),     prettyNameString,     Annot (..),@@ -37,7 +38,7 @@ -- with the tag.  To avoid erroneously using the 'Pretty' instance for -- VNames, we in fact only define it inside the modules for the core -- language (as an orphan instance).-class IsName v where+class (Eq v) => IsName v where   prettyName :: v -> Doc a   toName :: v -> Name @@ -204,7 +205,7 @@ hasArrayLit (TupLit es2 _) = any hasArrayLit es2 hasArrayLit _ = False -instance (Eq vn, IsName vn, Annot f) => Pretty (DimIndexBase f vn) where+instance (IsName vn, Annot f) => Pretty (DimIndexBase f vn) where   pretty (DimFix e) = pretty e   pretty (DimSlice i j (Just s)) =     maybe mempty pretty i@@ -223,12 +224,12 @@ instance (IsName vn) => Pretty (SizeBinder vn) where   pretty (SizeBinder v _) = brackets $ prettyName v -letBody :: (Eq vn, IsName vn, Annot f) => ExpBase f vn -> Doc a+letBody :: (IsName vn, Annot f) => ExpBase f vn -> Doc a letBody body@(AppExp LetPat {} _) = pretty body letBody body@(AppExp LetFun {} _) = pretty body letBody body = "in" <+> align (pretty body) -prettyAppExp :: (Eq vn, IsName vn, Annot f) => Int -> AppExpBase f vn -> Doc a+prettyAppExp :: (IsName vn, Annot f) => Int -> AppExpBase f vn -> Doc a prettyAppExp p (BinOp (bop, _) _ (x, _) (y, _) _) = prettyBinOp p bop x y prettyAppExp _ (Match e cs _) = "match" <+> pretty e </> (stack . map pretty) (NE.toList cs) prettyAppExp _ (Loop sizeparams pat initexp form loopbody _) =@@ -308,7 +309,7 @@     prettyExp 0 f       <+> hsep (map (prettyExp 10 . snd) $ NE.toList args) -instance (Eq vn, IsName vn, Annot f) => Pretty (AppExpBase f vn) where+instance (IsName vn, Annot f) => Pretty (AppExpBase f vn) where   pretty = prettyAppExp (-1)  prettyInst :: (Annot f, Pretty t) => f t -> Doc a@@ -322,17 +323,18 @@ prettyAttr :: (Pretty a) => a -> Doc ann prettyAttr attr = "#[" <> pretty attr <> "]" -operatorName :: Name -> Bool-operatorName = (`elem` opchars) . T.head . nameToText+-- | Does this name correspond to a symbol rather than an identifier?+symbolName :: Name -> Bool+symbolName = (`elem` opchars) . T.head . nameToText   where     opchars :: String     opchars = "+-*/%=!><|&^." -prettyExp :: (Eq vn, IsName vn, Annot f) => Int -> ExpBase f vn -> Doc a+prettyExp :: (IsName vn, Annot f) => Int -> ExpBase f vn -> Doc a prettyExp _ (Var name t _)   -- The first case occurs only for programs that have been normalised   -- by the compiler.-  | operatorName (toName (qualLeaf name)) = parens $ pretty name <> prettyInst t+  | symbolName (toName (qualLeaf name)) = parens $ pretty name <> prettyInst t   | otherwise = pretty name <> prettyInst t prettyExp _ (Hole t _) = "???" <> prettyInst t prettyExp _ (Parens e _) = align $ parens $ pretty e@@ -359,7 +361,7 @@   brackets (commasep $ map pretty es) <> prettyInst t prettyExp _ (StringLit s _) =   pretty $ show $ map (chr . fromIntegral) s-prettyExp _ (Project k e _ _) = pretty e <> "." <> pretty k+prettyExp _ (Project k e _ _) = prettyExp 11 e <> "." <> pretty k prettyExp _ (Negate e _) = "-" <> pretty e prettyExp _ (Not e _) = "!" <> pretty e prettyExp _ (Update src idxs ve _) =@@ -409,7 +411,7 @@         <> parens (pretty t <> "," <+> brackets (commasep $ map prettyName ext))   | otherwise = prettyAppExp i e -instance (Eq vn, IsName vn, Annot f) => Pretty (ExpBase f vn) where+instance (IsName vn, Annot f) => Pretty (ExpBase f vn) where   pretty = prettyExp (-1)  instance (IsName vn) => Pretty (AttrAtom vn) where@@ -420,18 +422,18 @@   pretty (AttrAtom attr _) = pretty attr   pretty (AttrComp f attrs _) = pretty f <> parens (commasep $ map pretty attrs) -instance (Eq vn, IsName vn, Annot f) => Pretty (FieldBase f vn) where+instance (IsName vn, Annot f) => Pretty (FieldBase f vn) where   pretty (RecordFieldExplicit (L _ name) e _) = pretty name <> equals <> pretty e   pretty (RecordFieldImplicit (L _ name) _ _) = prettyName name -instance (Eq vn, IsName vn, Annot f) => Pretty (CaseBase f vn) where+instance (IsName vn, Annot f) => Pretty (CaseBase f vn) where   pretty (CasePat p e _) = "case" <+> pretty p <+> "->" </> indent 2 (pretty e) -instance (Eq vn, IsName vn, Annot f) => Pretty (LoopInitBase f vn) where+instance (IsName vn, Annot f) => Pretty (LoopInitBase f vn) where   pretty (LoopInitImplicit e) = maybe "_" pretty $ unAnnot e   pretty (LoopInitExplicit e) = pretty e -instance (Eq vn, IsName vn, Annot f) => Pretty (LoopFormBase f vn) where+instance (IsName vn, Annot f) => Pretty (LoopFormBase f vn) where   pretty (For i ubound) =     "for" <+> pretty i <+> "<" <+> align (pretty ubound)   pretty (ForIn x e) =@@ -444,7 +446,7 @@   pretty (PatLitFloat f) = pretty f   pretty (PatLitPrim v) = pretty v -instance (Eq vn, IsName vn, Annot f, Pretty t) => Pretty (PatBase f vn t) where+instance (IsName vn, Annot f, Pretty t) => Pretty (PatBase f vn t) where   pretty (PatAscription p t _) = pretty p <> colon <+> align (pretty t)   pretty (PatParens p _) = parens $ pretty p   pretty (Id v t _) = case unAnnot t of@@ -465,10 +467,10 @@ ppAscription Nothing = mempty ppAscription (Just t) = colon <> align (pretty t) -instance (Eq vn, IsName vn, Annot f) => Pretty (ProgBase f vn) where+instance (IsName vn, Annot f) => Pretty (ProgBase f vn) where   pretty = stack . punctuate line . map pretty . progDecs -instance (Eq vn, IsName vn, Annot f) => Pretty (DecBase f vn) where+instance (IsName vn, Annot f) => Pretty (DecBase f vn) where   pretty (ValDec dec) = pretty dec   pretty (TypeDec dec) = pretty dec   pretty (ModTypeDec sig) = pretty sig@@ -477,7 +479,7 @@   pretty (LocalDec dec _) = "local" <+> pretty dec   pretty (ImportDec x _ _) = "import" <+> pretty x -prettyModExp :: (Eq vn, IsName vn, Annot f) => Int -> ModExpBase f vn -> Doc a+prettyModExp :: (IsName vn, Annot f) => Int -> ModExpBase f vn -> Doc a prettyModExp _ (ModVar v _) =   pretty v prettyModExp _ (ModParens e _) =@@ -502,7 +504,7 @@       Nothing -> mempty       Just (sig, _) -> colon <+> pretty sig -instance (Eq vn, IsName vn, Annot f) => Pretty (ModExpBase f vn) where+instance (IsName vn, Annot f) => Pretty (ModExpBase f vn) where   pretty = prettyModExp (-1)  instance Pretty Liftedness where@@ -510,7 +512,7 @@   pretty SizeLifted = "~"   pretty Lifted = "^" -instance (Eq vn, IsName vn, Annot f) => Pretty (TypeBindBase f vn) where+instance (IsName vn, Annot f) => Pretty (TypeBindBase f vn) where   pretty (TypeBind name l params te rt _ _) =     "type"       <> pretty l@@ -518,11 +520,11 @@         <+> equals         <+> maybe (pretty te) pretty (unAnnot rt) -instance (Eq vn, IsName vn) => Pretty (TypeParamBase vn) where+instance (IsName vn) => Pretty (TypeParamBase vn) where   pretty (TypeParamDim name _) = brackets $ prettyName name   pretty (TypeParamType l name _) = "'" <> pretty l <> prettyName name -instance (Eq vn, IsName vn, Annot f) => Pretty (ValBindBase f vn) where+instance (IsName vn, Annot f) => Pretty (ValBindBase f vn) where   pretty (ValBind entry name retdecl rettype tparams args body _ attrs _) =     mconcat (map ((<> line) . prettyAttr) attrs)       <> fun@@ -544,18 +546,23 @@         Just rettype' -> [colon <+> align rettype']         Nothing -> mempty -instance (Eq vn, IsName vn, Annot f) => Pretty (SpecBase f vn) where+instance (IsName vn, Annot f) => Pretty (SpecBase f vn) where   pretty (TypeAbbrSpec tpsig) = pretty tpsig   pretty (TypeSpec l name ps _ _) =     "type" <> pretty l <+> hsep (prettyName name : map pretty ps)   pretty (ValSpec name tparams vtype _ _ _) =-    "val" <+> hsep (prettyName name : map pretty tparams) <> colon <+> pretty vtype+    "val" <+> hsep (name' : map pretty tparams) <> colon <+> pretty vtype+    where+      name' =+        if symbolName $ toName name+          then parens $ prettyName name+          else prettyName name   pretty (ModSpec name sig _ _) =     "module" <+> prettyName name <> colon <+> pretty sig   pretty (IncludeSpec e _) =     "include" <+> pretty e -instance (Eq vn, IsName vn, Annot f) => Pretty (ModTypeExpBase f vn) where+instance (IsName vn, Annot f) => Pretty (ModTypeExpBase f vn) where   pretty (ModTypeVar v _ _) = pretty v   pretty (ModTypeParens e _) = parens $ pretty e   pretty (ModTypeSpecs ss _) = nestedBlock "{" "}" (stack $ punctuate line $ map pretty ss)@@ -566,15 +573,15 @@   pretty (ModTypeArrow Nothing e1 e2 _) =     pretty e1 <+> "->" <+> pretty e2 -instance (Eq vn, IsName vn, Annot f) => Pretty (ModTypeBindBase f vn) where+instance (IsName vn, Annot f) => Pretty (ModTypeBindBase f vn) where   pretty (ModTypeBind name e _ _) =     "module type" <+> prettyName name <+> equals <+> pretty e -instance (Eq vn, IsName vn, Annot f) => Pretty (ModParamBase f vn) where+instance (IsName vn, Annot f) => Pretty (ModParamBase f vn) where   pretty (ModParam pname psig _ _) =     parens (prettyName pname <> colon <+> pretty psig) -instance (Eq vn, IsName vn, Annot f) => Pretty (ModBindBase f vn) where+instance (IsName vn, Annot f) => Pretty (ModBindBase f vn) where   pretty (ModBind name ps sig e _ _) =     "module" <+> hsep (prettyName name : map pretty ps) <> sig' <> " =" <+> pretty e     where@@ -591,7 +598,7 @@     leading = leadingOperator $ toName $ qualLeaf bop  prettyBinOp ::-  (Eq vn, IsName vn, Annot f) =>+  (IsName vn, Annot f) =>   Int ->   QualName vn ->   ExpBase f vn ->
src/Language/Futhark/Semantic.hs view
@@ -28,7 +28,7 @@ import Language.Futhark import System.FilePath qualified as Native import System.FilePath.Posix qualified as Posix-import Prelude hiding (mod)+import Prelude hiding (abs, mod)  -- | Create an import name immediately from a file path specified by -- the user.@@ -158,7 +158,10 @@   mempty = Env mempty mempty mempty mempty mempty  instance Pretty MTy where-  pretty = pretty . mtyMod+  pretty (MTy abs mod) =+    "abstract" <> parens (hsep $ map p $ M.toList abs) </> pretty mod+    where+      p (v, l) = pretty l <> pretty v  instance Pretty Mod where   pretty (ModEnv e) = pretty e@@ -190,7 +193,7 @@         "val"           <+> prettyName name           <> mconcat (map ((" " <>) . pretty) tps)-          <> " ="+            <+> ":"             <+> pretty t       renderModType (name, _sig) =         "module type" <+> prettyName name
src/Language/Futhark/TypeChecker.hs view
@@ -331,25 +331,18 @@   (abs, s_abs, s_env, s') <- checkModTypeExpToEnv s   resolveTypeParams ps $ \ps' -> do     (ext, te', te_t, _) <- bindingTypeParams ps' $ checkTypeDecl te-    unless (null ext) $-      typeError te' mempty "Anonymous dimensions are not allowed here."-    (tname', s_abs', s_env') <- refineEnv loc s_abs s_env tname ps' te_t+    (tname', s_abs', s_env') <-+      refineEnv loc s_abs s_env tname ps' $ RetType ext te_t     pure (abs, MTy s_abs' $ ModEnv s_env', ModTypeWith s' (TypeRef tname' ps' te' trloc) loc) checkModTypeExp (ModTypeArrow maybe_pname e1 e2 loc) = do   (e1_abs, MTy s_abs e1_mod, e1') <- checkModTypeExp e1-  (env_for_e2, maybe_pname') <-+  (maybe_pname', (e2_abs, e2_mod, e2')) <-     case maybe_pname of       Just pname -> bindSpaced1 Term pname loc $ \pname' ->-        pure-          ( mempty-              { envNameMap = M.singleton (Term, pname) $ qualName pname',-                envModTable = M.singleton pname' e1_mod-              },-            Just pname'-          )+        localEnv (mempty {envModTable = M.singleton pname' e1_mod}) $+          (Just pname',) <$> checkModTypeExp e2       Nothing ->-        pure (mempty, Nothing)-  (e2_abs, e2_mod, e2') <- localEnv env_for_e2 $ checkModTypeExp e2+        (Nothing,) <$> checkModTypeExp e2   pure     ( e1_abs <> e2_abs,       MTy mempty $ ModFun $ FunModType s_abs e1_mod e2_mod,@@ -644,10 +637,9 @@   SrcLoc ->   [TypeParam] ->   [Pat ParamType] ->-  Maybe (TypeExp Exp VName) ->   ResRetType ->   TypeM ()-checkEntryPoint loc tparams params maybe_tdecl rettype+checkEntryPoint loc tparams params rettype   | any isTypeParam tparams =       typeError loc mempty $         withIndexLink@@ -674,16 +666,6 @@         "Entry point size parameter "           <> pretty p           <> " only used non-constructively."-  | p : _ <- filter nastyParameter params =-      warn p $-        "Entry point parameter\n"-          </> indent 2 (pretty p)-          </> "\nwill have an opaque type, so the entry point will likely not be callable."-  | nastyReturnType maybe_tdecl rettype_t =-      warn loc $-        "Entry point return type\n"-          </> indent 2 (pretty rettype)-          </> "\nwill have an opaque type, so the result will likely not be usable."   | otherwise =       pure ()   where@@ -708,7 +690,7 @@    let entry' = Info (entryPoint params' maybe_tdecl' rettype) <$ entry   case entry' of-    Just _ -> checkEntryPoint loc tparams' params' maybe_tdecl' rettype+    Just _ -> checkEntryPoint loc tparams' params' rettype     _ -> pure ()    let vb' = ValBind entry' fname maybe_tdecl' (Info rettype) tparams' params' body' doc attrs' loc@@ -721,44 +703,6 @@         },       vb'     )--nastyType :: (Monoid als) => TypeBase dim als -> Bool-nastyType (Scalar Prim {}) = False-nastyType t@Array {} = nastyType $ stripArray 1 t-nastyType _ = True--nastyReturnType :: (Monoid als) => Maybe (TypeExp Exp VName) -> TypeBase dim als -> Bool-nastyReturnType Nothing (Scalar (Arrow _ _ _ t1 (RetType _ t2))) =-  nastyType t1 || nastyReturnType Nothing t2-nastyReturnType (Just (TEArrow _ te1 te2 _)) (Scalar (Arrow _ _ _ t1 (RetType _ t2))) =-  (not (niceTypeExp te1) && nastyType t1)-    || nastyReturnType (Just te2) t2-nastyReturnType (Just te) _-  | niceTypeExp te = False-nastyReturnType te t-  | Just ts <- isTupleRecord t =-      case te of-        Just (TETuple tes _) -> or $ zipWith nastyType' (map Just tes) ts-        _ -> any nastyType ts-  | otherwise = nastyType' te t-  where-    nastyType' (Just te') _ | niceTypeExp te' = False-    nastyType' _ t' = nastyType t'--nastyParameter :: Pat ParamType -> Bool-nastyParameter p = nastyType (patternType p) && not (ascripted p)-  where-    ascripted (PatAscription _ te _) = niceTypeExp te-    ascripted (PatParens p' _) = ascripted p'-    ascripted _ = False--niceTypeExp :: TypeExp Exp VName -> Bool-niceTypeExp (TEVar (QualName [] _) _) = True-niceTypeExp (TEApply te TypeArgExpSize {} _) = niceTypeExp te-niceTypeExp (TEArray _ te _) = niceTypeExp te-niceTypeExp (TEUnique te _) = niceTypeExp te-niceTypeExp (TEDim _ te _) = niceTypeExp te-niceTypeExp _ = False  checkOneDec :: DecBase NoInfo Name -> TypeM (TySet, Env, DecBase Info VName) checkOneDec (ModDec struct) = do
src/Language/Futhark/TypeChecker/Modules.hs view
@@ -9,6 +9,7 @@ where  import Control.Monad+import Control.Monad.Identity import Data.Either import Data.Map.Strict qualified as M import Data.Maybe@@ -17,6 +18,7 @@ import Futhark.Util.Pretty import Language.Futhark import Language.Futhark.Semantic+import Language.Futhark.Traversals import Language.Futhark.TypeChecker.Monad import Language.Futhark.TypeChecker.Types import Language.Futhark.TypeChecker.Unify (doUnification)@@ -109,10 +111,21 @@         substitute v =           fromMaybe v $ M.lookup v substs -        -- For applySubst and friends.-        subst v =-          ExpSubst . flip sizeFromName mempty . qualName <$> M.lookup v substs+        substituteInExp :: Exp -> Exp+        substituteInExp = runIdentity . astMap mapper+          where+            mapper =+              ASTMapper+                { mapOnExp = pure . substituteInExp,+                  mapOnName = pure . substituteInQualName,+                  mapOnStructType = pure . substituteInType,+                  mapOnParamType = pure . substituteInType,+                  mapOnResRetType = pure . substituteInRetType+                } +        substituteInQualName (QualName qs v) =+          QualName (map substitute qs) (substitute v)+         substituteInMap f m =           let (ks, vs) = unzip $ M.toList m            in M.fromList $@@ -143,9 +156,8 @@           TypeParamType l (substitute p) loc          substituteInScalarType :: ScalarTypeBase Size u -> ScalarTypeBase Size u-        substituteInScalarType (TypeVar u (QualName qs v) targs) =-          TypeVar u (QualName (map substitute qs) $ substitute v) $-            map substituteInTypeArg targs+        substituteInScalarType (TypeVar u v targs) =+          TypeVar u (substituteInQualName v) $ map substituteInTypeArg targs         substituteInScalarType (Prim t) =           Prim t         substituteInScalarType (Record ts) =@@ -155,15 +167,18 @@         substituteInScalarType (Arrow als v d1 t1 (RetType dims t2)) =           Arrow als v d1 (substituteInType t1) $ RetType dims $ substituteInType t2 +        substituteInRetType :: RetTypeBase Size u -> RetTypeBase Size u+        substituteInRetType (RetType ext t) = RetType ext $ substituteInType t+         substituteInType :: TypeBase Size u -> TypeBase Size u         substituteInType (Scalar t) = Scalar $ substituteInScalarType t         substituteInType (Array u shape t) =           Array u (substituteInShape shape) $ substituteInScalarType t -        substituteInShape (Shape ds) = Shape $ map (applySubst subst) ds+        substituteInShape (Shape ds) = Shape $ map substituteInExp ds          substituteInTypeArg (TypeArgDim e) =-          TypeArgDim $ applySubst subst e+          TypeArgDim $ substituteInExp e         substituteInTypeArg (TypeArgType t) =           TypeArgType $ substituteInType t @@ -182,13 +197,19 @@     <> (mconcat . map modTypeAbbrs . M.elems . envModTable) env  -- | Refine the given type name in the given env.+--+-- XXX: we do not check whether this results in a meaningful module type. In+-- particular, we may refine a nonlifted type to contain a function or+-- existentially quantified sizes. However, it is still not possible to+-- construct a module that matches such malformed module types, so this is not a+-- soundness issue, merely an ergonomic issue. refineEnv ::   SrcLoc ->   TySet ->   Env ->   QualName Name ->   [TypeParam] ->-  StructType ->+  StructRetType ->   TypeM (QualName VName, TySet, Env) refineEnv loc tset env tname ps t   | Just (tname', TypeAbbr _ cur_ps (RetType _ (Scalar (TypeVar _ (QualName qs v) _)))) <-@@ -202,8 +223,8 @@               substituteTypesInEnv                 ( flip M.lookup $                     M.fromList-                      [ (qualLeaf tname', Subst cur_ps $ RetType [] t),-                        (v, Subst ps $ RetType [] t)+                      [ (qualLeaf tname', Subst cur_ps t),+                        (v, Subst ps t)                       ]                 )                 env
src/Language/Futhark/TypeChecker/Terms.hs view
@@ -958,10 +958,11 @@ checkOneExp :: ExpBase NoInfo VName -> TypeM ([TypeParam], Exp) checkOneExp e = runTermTypeM checkExp $ do   e' <- checkExp e-  let t = typeOf e'-  (tparams, _, _) <--    letGeneralise (nameFromString "<exp>") (srclocOf e) [] [] $ toRes Nonunique t-  fixOverloadedTypes $ typeVars t+  (tparams, _, RetType _ t') <-+    letGeneralise (nameFromString "<exp>") (srclocOf e) [] [] $+      toRes Nonunique $+        typeOf e'+  fixOverloadedTypes $ typeVars t'   e'' <- normTypeFully e'   localChecks e''   causalityCheck e''@@ -1606,10 +1607,18 @@           loc           (filter (`elem` hidden) $ foldMap patNames params)           body_t--      let usage = mkUsage body "return type annotation"-      onFailure (CheckingReturn rettype body_t') $-        unify usage (toStruct rettype) body_t'+      case find (`elem` hidden) $ fvVars $ freeInType rettype of+        Just v ->+          typeError loc mempty $+            "The return type annotation"+              </> indent 2 (align (pretty rettype))+              </> "refers to the name"+              <+> dquotes (prettyName v)+              <+> "which is bound to an inner component of a function parameter."+        Nothing -> do+          let usage = mkUsage body "return type annotation"+          onFailure (CheckingReturn rettype body_t') $+            unify usage (toStruct rettype) body_t'     Nothing -> pure ()    pure body'
src/Language/Futhark/TypeChecker/Types.hs view
@@ -258,13 +258,16 @@           <+> pretty (length targs)           <> "."     else do-      (targs', dims, substs) <- unzip3 <$> zipWithM checkArgApply ps targs+      (targs', dims, substs, targs_ls) <-+        L.unzip4 <$> zipWithM checkArgApply ps targs       pure         ( foldl (\x y -> TEApply x y tloc) (TEVar tname tname_loc) targs',           [],           RetType (t_dims ++ mconcat dims) $             applySubst (`M.lookup` mconcat substs) t,-          l+          -- XXX: this is an overapproximation of the liftedness in case one of+          -- these type parameters is a phantom type.+          maximum $ l : targs_ls         )   where     tloc = srclocOf ote@@ -294,13 +297,14 @@      checkArgApply (TypeParamDim pv _) (TypeArgExpSize d) = do       (d', svars, subst) <- checkSizeExp d-      pure (d', svars, M.singleton pv subst)+      pure (d', svars, M.singleton pv subst, Unlifted)     checkArgApply (TypeParamType _ pv _) (TypeArgExpType te) = do-      (te', svars, RetType dims st, _) <- evalTypeExp df te+      (te', svars, RetType dims st, te_l) <- evalTypeExp df te       pure         ( TypeArgExpType te',           svars ++ dims,-          M.singleton pv $ Subst [] $ RetType [] $ toStruct st+          M.singleton pv $ Subst [] $ RetType [] $ toStruct st,+          te_l         )     checkArgApply p a =       typeError tloc mempty $
src/Language/Futhark/TypeChecker/Unify.hs view
@@ -557,7 +557,7 @@     not (anyBound bound e1) || (qualLeaf v2 `elem` bound) =       linkVarToDim usage bcs (qualLeaf v2) lvl2 e1 unifySizes usage bcs _ _ e1 e2 = do-  notes <- (<>) <$> dimNotes usage e2 <*> dimNotes usage e2+  notes <- (<>) <$> dimNotes usage e1 <*> dimNotes usage e2   unifyError usage notes bcs $     "Sizes"       <+> dquotes (pretty e1)
unittests/Futhark/IR/Prop/ReshapeTests.hs view
@@ -5,12 +5,17 @@   ) where +import Data.List qualified as L import Futhark.IR.Prop.Constants import Futhark.IR.Prop.Reshape import Futhark.IR.Syntax+import Futhark.IR.SyntaxTests () import Test.Tasty import Test.Tasty.HUnit +intShape :: [Int] -> Shape+intShape = Shape . map (intConst Int32 . toInteger)+ reshapeOuterTests :: [TestTree] reshapeOuterTests =   [ testCase (unwords ["reshapeOuter", show sc, show n, show shape, "==", show sc_res]) $@@ -35,10 +40,197 @@         ]   ] -intShape :: [Int] -> Shape-intShape = Shape . map (intConst Int32 . toInteger)+dimFlatten :: Int -> Int -> d -> DimSplice d+dimFlatten i k w = DimSplice i k (Shape [w]) +dimUnflatten :: Int -> [d] -> DimSplice d+dimUnflatten i ws = DimSplice i 1 (Shape ws)++dimCoerce :: Int -> d -> DimSplice d+dimCoerce i w = DimSplice i 1 (Shape [w])++dimSplice :: Int -> Int -> [d] -> DimSplice d+dimSplice i n s = DimSplice i n $ Shape s++flipReshapeRearrangeTests :: [TestTree]+flipReshapeRearrangeTests =+  [ testCase+      ( unwords+          [ "flipReshapeRearrange",+            show v0_shape,+            show v1_shape,+            show perm+          ]+      )+      $ flipReshapeRearrange v0_shape v1_shape perm @?= res+    | (v0_shape :: [String], v1_shape, perm, res) <-+        [ ( ["A", "B", "C"],+            ["A", "BC"],+            [1, 0],+            Just [1, 2, 0]+          ),+          ( ["A", "B", "C", "D"],+            ["A", "BCD"],+            [1, 0],+            Just [1, 2, 3, 0]+          ),+          ( ["A"],+            ["B", "C"],+            [1, 0],+            Nothing+          ),+          ( ["A", "B", "C"],+            ["AB", "C"],+            [1, 0],+            Just [2, 0, 1]+          ),+          ( ["A", "B", "C", "D"],+            ["ABC", "D"],+            [1, 0],+            Just [3, 0, 1, 2]+          )+        ]+  ]++flipRearrangeReshapeTests :: [TestTree]+flipRearrangeReshapeTests =+  [ testCase+      ( unwords+          [ "flipRearrangeReshape",+            show perm,+            prettyStringOneLine newshape+          ]+      )+      $ flipRearrangeReshape perm newshape @?= res+    | (perm, newshape :: NewShape String, res) <-+        [ ( [1, 0],+            NewShape+              [dimUnflatten 1 ["B", "C"]]+              (Shape ["A", "B", "C"]),+            Just+              ( NewShape+                  [dimUnflatten 0 ["B", "C"]]+                  (Shape ["B", "C", "A"]),+                [2, 0, 1]+              )+          ),+          ( [1, 0],+            NewShape+              [dimFlatten 0 2 "AB"]+              (Shape ["AB"]),+            Nothing+          )+        ]+  ]++simplifyTests :: TestTree+simplifyTests =+  testGroup+    "simplifyNewShape"+    [ testCase "Inverse flatten and unflatten - simple case" $+        lhs+          ["A", "B"]+          [dimFlatten 0 2 "AB", dimUnflatten 0 ["A", "B"]]+          @?= Just [],+      testCase "Non-inverse flatten and unflatten - simple case" $+        lhs+          ["A", "B"]+          [dimFlatten 0 2 "AB", dimUnflatten 0 ["C", "D"]]+          @?= Just [dimSplice 0 2 ["C", "D"]],+      testCase "Inverse flatten and unflatten - separated by coercion" $+        lhs+          ["A", "B"]+          [ dimFlatten 0 2 "AB",+            dimCoerce 0 "CD",+            dimUnflatten 0 ["C", "D"]+          ]+          @?= Just [dimSplice 0 2 ["C", "D"]],+      testCase "Two unflattens - simple case" $+        lhs+          ["ABC"]+          [dimUnflatten 0 ["A", "BC"], dimUnflatten 1 ["B", "C"]]+          @?= Just [dimUnflatten 0 ["A", "B", "C"]],+      testCase "Two unflattens with unchanged prefix" $+        lhs+          ["A", "B", "C", "D", "E"]+          [ DimSplice 3 2 $ Shape ["DE"],+            DimSplice 2 2 $ Shape ["CDE"]+          ]+          @?= Just [dimFlatten 2 3 "CDE"],+      testCase "Identity coerce" $+        lhs+          ["A", "B", "C"]+          [dimCoerce 1 "B", dimCoerce 2 "C"]+          @?= Just [],+      testCase "Identity coerce (multiple dimensions)" $+        lhs+          ["A", "B", "C"]+          [DimSplice 1 2 (Shape ["B", "C"])]+          @?= Just [],+      testCase "Identity coerce (with non-identity stuff afterwards)" $+        lhs+          ["B", "CD"]+          [dimCoerce 0 "B", dimUnflatten 1 ["C", "D"]]+          @?= Just [dimUnflatten 1 ["C", "D"]],+      testCase "Get rid of a coerce before an unflatten" $+        lhs+          ["CD"]+          [dimCoerce 0 "AB", dimUnflatten 0 ["A", "B"]]+          @?= Just [dimUnflatten 0 ["A", "B"]],+      testCase "Get rid of a coerce after a flatten" $+        lhs+          ["A", "B", "C"]+          [dimFlatten 0 2 "ABC", dimCoerce 0 "K"]+          @?= Just [dimFlatten 0 2 "K"],+      testCase "Flatten and unflatten (invariant suffix)" $+        lhs+          ["A", "B", "C"]+          [dimFlatten 0 3 "ABC", dimUnflatten 0 ["D", "E", "C"]]+          @?= Just [dimSplice 0 2 ["D", "E"]],+      testCase "Flatten and unflatten (invariant prefix)" $+        lhs+          ["A", "B", "C"]+          [dimFlatten 0 3 "ABC", dimUnflatten 0 ["A", "D", "E"]]+          @?= Just [dimSplice 1 2 ["D", "E"]],+      testCase "Invariant part of splice" $+        lhs+          ["A", "B", "C", "D"]+          [DimSplice 1 3 $ Shape ["BC", "D"]]+          @?= Just [DimSplice 1 2 $ Shape ["BC"]],+      testCase "Necessary coercion" $+        lhs+          ["A", "B"]+          [dimCoerce 0 "C", dimCoerce 1 "D"]+          @?= Nothing,+      testCase "Another necessary coercion" $+        lhs+          ["A", "B", "C"]+          [dimCoerce 0 "A'", dimCoerce 1 "A'", dimCoerce 2 "A'"]+          @?= Nothing,+      testCase "Long with redundancies" $+        lhs+          ["A", "B", "C", "D"]+          [ DimSplice 1 3 $ Shape ["BC", "D"],+            dimCoerce 1 "BC",+            dimCoerce 2 "D",+            dimFlatten 1 2 "BCD",+            dimFlatten 0 2 "ABCD"+          ]+          @?= Just [dimFlatten 0 4 "ABCD"]+    ]+  where+    lhs orig_shape ss =+      let res_shape :: ShapeBase String =+            L.foldl' applySplice (Shape orig_shape) ss+       in dimSplices+            <$> simplifyNewShape (Shape orig_shape) (NewShape ss res_shape)+ tests :: TestTree tests =-  testGroup "ReshapeTests" $-    reshapeOuterTests ++ reshapeInnerTests+  testGroup "ReshapeTests" . mconcat $+    [ reshapeOuterTests,+      reshapeInnerTests,+      flipReshapeRearrangeTests,+      flipRearrangeReshapeTests,+      [simplifyTests]+    ]